function _openInlineWidget(editor, providers, defaultErrorMsg) {
        PerfUtils.markStart(PerfUtils.INLINE_WIDGET_OPEN);

        // Run through inline-editor providers until one responds
        var pos = editor.getCursorPos(),
            inlinePromise,
            i,
            result = new $.Deferred(),
            errorMsg,
            providerRet;

        // Query each provider in priority order. Provider may return:
        // 1. `null` to indicate it does not apply to current cursor position
        // 2. promise that should resolve to an InlineWidget
        // 3. string which indicates provider does apply to current cursor position,
        //    but reason it could not create InlineWidget
        //
        // Keep looping until a provider is found. If a provider is not found,
        // display the highest priority error message that was found, otherwise display
        // default error message
        for (i = 0; i < providers.length && !inlinePromise; i++) {
            var provider = providers[i].provider;
            providerRet = provider(editor, pos);
            if (providerRet) {
                if (providerRet.hasOwnProperty("done")) {
                    inlinePromise = providerRet;
                } else if (!errorMsg && typeof (providerRet) === "string") {
                    errorMsg = providerRet;
                }
            }
        }

        // Use default error message if none other provided
        errorMsg = errorMsg || defaultErrorMsg;

        // If one of them will provide a widget, show it inline once ready
        if (inlinePromise) {
            inlinePromise.done(function (inlineWidget) {
                editor.addInlineWidget(pos, inlineWidget).done(function () {
                    PerfUtils.addMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
                    result.resolve();
                });
            }).fail(function () {
                // terminate timer that was started above
                PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
                editor.displayErrorMessageAtCursor(errorMsg);
                result.reject();
            });
        } else {
            // terminate timer that was started above
            PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
            editor.displayErrorMessageAtCursor(errorMsg);
            result.reject();
        }

        return result.promise();
    }
@private
Finds an inline widget provider from the given list that can offer a widget for the current cursor
position, and once the widget has been created inserts it into the editor.

@param {!Editor} editor The host editor
@param {Array.<{priority:number, provider:function(...)}>} providers
     prioritized list of providers
@param {string=} defaultErrorMsg Default message to display if no providers return non-null
@return {$.Promise} a promise that will be resolved when an InlineWidget
     is created or rejected if no inline providers have offered one.