function _showDialog() {
        var dialog,
            $dlg,
            views   = [],
            $search,
            $searchClear,
            $modalDlg,
            context = { Strings: Strings, showRegistry: !!brackets.config.extension_registry },
            models  = [];

        // Load registry only if the registry URL exists
        if (context.showRegistry) {
            models.push(new ExtensionManagerViewModel.RegistryViewModel());
            models.push(new ExtensionManagerViewModel.ThemesViewModel());
        }

        models.push(new ExtensionManagerViewModel.InstalledViewModel());
        models.push(new ExtensionManagerViewModel.DefaultViewModel());

        function updateSearchDisabled() {
            var model           = models[_activeTabIndex],
                searchDisabled  = ($search.val() === "") &&
                                  (!model.filterSet || model.filterSet.length === 0);

            $search.prop("disabled", searchDisabled);
            $searchClear.prop("disabled", searchDisabled);

            return searchDisabled;
        }

        function clearSearch() {
            $search.val("");
            views.forEach(function (view, index) {
                view.filter("");
                $modalDlg.scrollTop(0);
            });

            if (!updateSearchDisabled()) {
                $search.focus();
            }
        }

        // Open the dialog
        dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(dialogTemplate, context));

        // On dialog close: clean up listeners & models, and commit changes
        dialog.done(function () {
            $(window.document).off(".extensionManager");

            models.forEach(function (model) {
                model.dispose();
            });

            _performChanges();
        });

        // Create the view.
        $dlg = dialog.getElement();
        $search = $(".search", $dlg);
        $searchClear = $(".search-clear", $dlg);
        $modalDlg = $(".modal-body", $dlg);

        function setActiveTab($tab) {
            if (models[_activeTabIndex]) {
                models[_activeTabIndex].scrollPos = $modalDlg.scrollTop();
            }
            $tab.tab("show");
            if (models[_activeTabIndex]) {
                $modalDlg.scrollTop(models[_activeTabIndex].scrollPos || 0);
                clearSearch();
                if (_activeTabIndex === 2) {
                    $(".ext-sort-group").hide();
                } else {
                    $(".ext-sort-group").show();
                }
            }
        }

        // Dialog tabs
        $dlg.find(".nav-tabs a")
            .on("click", function (event) {
                setActiveTab($(this));
            });

        // Navigate through tabs via Ctrl-(Shift)-Tab
        // (focus may be on document.body if text in extension listing clicked - see #9511)
        $(window.document).on("keyup.extensionManager", function (event) {
            if (event.keyCode === KeyEvent.DOM_VK_TAB && event.ctrlKey) {
                var $tabs = $(".nav-tabs a", $dlg),
                    tabIndex = _activeTabIndex;

                if (event.shiftKey) {
                    tabIndex--;
                } else {
                    tabIndex++;
                }
                tabIndex %= $tabs.length;
                setActiveTab($tabs.eq(tabIndex));
            }
        });

        // Update & hide/show the notification overlay on a tab's icon, based on its model's notifyCount
        function updateNotificationIcon(index) {
            var model = models[index],
                $notificationIcon = $dlg.find(".nav-tabs li").eq(index).find(".notification");
            if (model.notifyCount) {
                $notificationIcon.text(model.notifyCount);
                $notificationIcon.show();
            } else {
                $notificationIcon.hide();
            }
        }

        // Initialize models and create a view for each model
        var modelInitPromise = Async.doInParallel(models, function (model, index) {
            var view    = new ExtensionManagerView(),
                promise = view.initialize(model),
                lastNotifyCount;

            promise.always(function () {
                views[index] = view;

                lastNotifyCount = model.notifyCount;
                updateNotificationIcon(index);
            });

            model.on("change", function () {
                if (lastNotifyCount !== model.notifyCount) {
                    lastNotifyCount = model.notifyCount;
                    updateNotificationIcon(index);
                }
            });

            return promise;
        }, true);

        modelInitPromise.always(function () {
            $(".spinner", $dlg).remove();

            views.forEach(function (view) {
                view.$el.appendTo($modalDlg);
            });

            // Update search UI before new tab is shown
            $("a[data-toggle='tab']", $dlg).each(function (index, tabElement) {
                $(tabElement).on("show", function (event) {
                    _activeTabIndex = index;

                    // Focus the search input
                    if (!updateSearchDisabled()) {
                        $dlg.find(".search").focus();
                    }
                });
            });

            // Filter the views when the user types in the search field.
            var searchTimeoutID;
            $dlg.on("input", ".search", function (e) {
                clearTimeout(searchTimeoutID);
                var query = $(this).val();
                searchTimeoutID = setTimeout(function () {
                    views[_activeTabIndex].filter(query);
                    $modalDlg.scrollTop(0);
                }, 200);
            }).on("click", ".search-clear", clearSearch);
            
            // Sort the extension list based on the current selected sorting criteria
            $dlg.on("change", ".sort-extensions", function (e) {
                var sortBy = $(this).val();
                PreferencesManager.set("extensions.sort", sortBy);
                models.forEach(function (model, index) {
                    if (index <= 1) {
                        model._setSortedExtensionList(ExtensionManager.extensions, index === 1);
                        views[index].filter($(".search").val());
                    }
                });
            });

            // Disable the search field when there are no items in the model
            models.forEach(function (model, index) {
                model.on("change", function () {
                    if (_activeTabIndex === index) {
                        updateSearchDisabled();
                    }
                });
            });

            var $activeTab = $dlg.find(".nav-tabs li.active a");
            if ($activeTab.length) { // If there's already a tab selected, show it
                $activeTab.parent().removeClass("active"); // workaround for bootstrap-tab
                $activeTab.tab("show");
            } else if ($("#toolbar-extension-manager").hasClass('updatesAvailable')) {
                // Open dialog to Installed tab if extension updates are available
                $dlg.find(".nav-tabs a.installed").tab("show");
            } else { // Otherwise show the first tab
                $dlg.find(".nav-tabs a:first").tab("show");
            }
            // If activeTab was explicitly selected by user,
            // then check for the selection
            // Or if there was an update available since activeTab.length would be 0,
            // then check for updatesAvailable class in toolbar-extension-manager
            if (($activeTab.length && $activeTab.hasClass("installed")) || (!$activeTab.length && $("#toolbar-extension-manager").hasClass('updatesAvailable'))) {
                $(".ext-sort-group").hide();
            } else {
                $(".ext-sort-group").show();
            }
        });

        // Handle the 'Install from URL' button.
        $(".extension-manager-dialog .install-from-url")
            .click(function () {
                InstallExtensionDialog.showDialog().done(ExtensionManager.updateFromDownload);
            });

        // Handle the drag/drop zone
        var $dropzone = $("#install-drop-zone"),
            $dropmask = $("#install-drop-zone-mask");

        $dropzone
            .on("dragover", function (event) {
                _stopEvent(event);

                if (!event.originalEvent.dataTransfer.files) {
                    return;
                }

                var items = event.originalEvent.dataTransfer.items,
                    isValidDrop = false;

                isValidDrop = _.every(items, function (item) {
                    if (item.kind === "file") {
                        var entry = item.webkitGetAsEntry(),
                            extension = FileUtils.getFileExtension(entry.fullPath);

                        return entry.isFile && extension === "zip";
                    }

                    return false;
                });

                if (isValidDrop) {
                    // Set an absolute width to stabilize the button size
                    $dropzone.width($dropzone.width());

                    // Show drop styling and message
                    $dropzone.removeClass("drag");
                    $dropzone.addClass("drop");
                } else {
                    event.originalEvent.dataTransfer.dropEffect = "none";
                }
            })
            .on("drop", _stopEvent);

        $dropmask
            .on("dragover", function (event) {
                _stopEvent(event);
                event.originalEvent.dataTransfer.dropEffect = "copy";
            })
            .on("dragleave", function () {
                $dropzone.removeClass("drop");
                $dropzone.addClass("drag");
            })
            .on("drop", function (event) {
                _stopEvent(event);

                if (event.originalEvent.dataTransfer.files) {
                    // Attempt install
                    _installUsingDragAndDrop().fail(function (errorArray) {
                        var message = Strings.INSTALL_EXTENSION_DROP_ERROR;

                        message += "<ul class='dialog-list'>";
                        errorArray.forEach(function (info) {
                            message += "<li><span class='dialog-filename'>";
                            message += StringUtils.breakableUrl(info.item);
                            message += "</span>: " + info.error + "</li>";
                        });
                        message += "</ul>";

                        Dialogs.showModalDialog(
                            DefaultDialogs.DIALOG_ID_ERROR,
                            Strings.EXTENSION_MANAGER_TITLE,
                            message
                        );
                    }).always(function () {
                        $dropzone.removeClass("validating");
                        $dropzone.addClass("drag");
                    });

                    // While installing, show validating message
                    $dropzone.removeClass("drop");
                    $dropzone.addClass("validating");
                }
            });

        return new $.Deferred().resolve(dialog).promise();
    }
@private
Show a dialog that allows the user to browse and manage extensions.