diff options
Diffstat (limited to 'chrome/browser')
3 files changed, 107 insertions, 25 deletions
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index 7599108..4fc76cb 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc @@ -7,6 +7,7 @@ #include "apps/app_window.h" #include "apps/app_window_registry.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "chrome/browser/extensions/api/tabs/tabs_constants.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/tab_helper.h" @@ -19,6 +20,7 @@ #include "chrome/browser/ui/browser_iterator.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" +#include "chrome/browser/ui/singleton_tabs.h" #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/extensions/api/tabs.h" @@ -31,6 +33,7 @@ #include "extensions/common/constants.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" +#include "extensions/common/feature_switch.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/incognito_info.h" #include "extensions/common/permissions/api_permission.h" @@ -566,16 +569,33 @@ void ExtensionTabUtil::OpenOptionsPage(const Extension* extension, browser = displayer->browser(); } - content::OpenURLParams params(ManifestURL::GetOptionsPage(extension), - content::Referrer(), - SINGLETON_TAB, - content::PAGE_TRANSITION_LINK, - false); - browser->OpenURL(params); - browser->window()->Show(); - WebContents* web_contents = - browser->tab_strip_model()->GetActiveWebContents(); - web_contents->GetDelegate()->ActivateContents(web_contents); + if (FeatureSwitch::embedded_extension_options()->IsEnabled()) { + // If embedded extension options are enabled, open chrome://extensions + // in a new tab and show the extension options in an embedded popup. + chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams( + browser, GURL(chrome::kChromeUIExtensionsURL))); + params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE; + + GURL::Replacements replacements; + std::string query = + base::StringPrintf("options=%s", extension->id().c_str()); + replacements.SetQueryStr(query); + params.url = params.url.ReplaceComponents(replacements); + + chrome::ShowSingletonTabOverwritingNTP(browser, params); + } else { + // Otherwise open a new tab with the extension's options page + content::OpenURLParams params(ManifestURL::GetOptionsPage(extension), + content::Referrer(), + SINGLETON_TAB, + content::PAGE_TRANSITION_LINK, + false); + browser->OpenURL(params); + browser->window()->Show(); + WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + web_contents->GetDelegate()->ActivateContents(web_contents); + } } } // namespace extensions diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js index 012bc87..ecea6c1 100644 --- a/chrome/browser/resources/extensions/extension_list.js +++ b/chrome/browser/resources/extensions/extension_list.js @@ -33,6 +33,15 @@ cr.define('options', function() { ExtensionsList.prototype = { __proto__: HTMLDivElement.prototype, + /** + * Indicates whether an embedded options page that was navigated to through + * the '?options=' URL query has been shown to the user. This is necessary + * to prevent showExtensionNodes_ from opening the options more than once. + * @type {boolean} + * @private + */ + optionsShown_: false, + /** @override */ decorate: function() { this.textContent = ''; @@ -44,6 +53,10 @@ cr.define('options', function() { return parseQueryParams(document.location)['id']; }, + getOptionsQueryParam_: function() { + return parseQueryParams(document.location)['options']; + }, + /** * Creates all extension items from scratch. * @private @@ -53,16 +66,12 @@ cr.define('options', function() { this.data_.extensions.forEach(this.createNode_, this); var idToHighlight = this.getIdQueryParam_(); - if (idToHighlight && $(idToHighlight)) { - // Scroll offset should be calculated slightly higher than the actual - // offset of the element being scrolled to, so that it ends up not all - // the way at the top. That way it is clear that there are more elements - // above the element being scrolled to. - var scrollFudge = 1.2; - var scrollTop = $(idToHighlight).offsetTop - scrollFudge * - $(idToHighlight).clientHeight; - setScrollTopForDocument(document, scrollTop); - } + if (idToHighlight && $(idToHighlight)) + this.scrollToNode_(idToHighlight); + + var idToOpenOptions = this.getOptionsQueryParam_(); + if (idToOpenOptions && $(idToOpenOptions)) + this.showEmbeddedExtensionOptions_(idToOpenOptions, true); if (this.data_.extensions.length == 0) this.classList.add('empty-extension-list'); @@ -71,6 +80,22 @@ cr.define('options', function() { }, /** + * Scrolls the page down to the extension node with the given id. + * @param {string} extensionId The id of the extension to scroll to. + * @private + */ + scrollToNode_: function(extensionId) { + // Scroll offset should be calculated slightly higher than the actual + // offset of the element being scrolled to, so that it ends up not all + // the way at the top. That way it is clear that there are more elements + // above the element being scrolled to. + var scrollFudge = 1.2; + var scrollTop = $(extensionId).offsetTop - scrollFudge * + $(extensionId).clientHeight; + setScrollTopForDocument(document, scrollTop); + }, + + /** * Synthesizes and initializes an HTML element for the extension metadata * given in |extension|. * @param {Object} extension A dictionary of extension metadata. @@ -194,10 +219,7 @@ cr.define('options', function() { var options = node.querySelector('.options-link'); options.addEventListener('click', function(e) { if (this.data_.enableEmbeddedExtensionOptions) { - extensions.ExtensionOptionsOverlay.getInstance(). - setExtensionAndShowOverlay(extension.id, - extension.name, - extension.icon); + this.showEmbeddedExtensionOptions_(extension.id, false); } else { chrome.send('extensionSettingsOptions', [extension.id]); } @@ -417,6 +439,43 @@ cr.define('options', function() { setScrollTopForDocument(document, topScroll); } }, + + /** + * Opens the extension options overlay for the extension with the given id. + * @param {string} extensionId The id of extension whose options page should + * be displayed. + * @param {boolean} scroll Whether the page should scroll to the extension + * @private + */ + showEmbeddedExtensionOptions_: function(extensionId, scroll) { + if (this.optionsShown_) + return; + + // Get the extension from the given id. + var extension = this.data_.extensions.filter(function(extension) { + return extension.id == extensionId; + })[0]; + + if (!extension) + return; + + if (scroll) + this.scrollToNode_(extensionId); + // Add the options query string. Corner case: the 'options' query string + // will clobber the 'id' query string if the options link is clicked when + // 'id' is in the URL, or if both query strings are in the URL. + uber.replaceState({}, '?options=' + extensionId); + + extensions.ExtensionOptionsOverlay.getInstance(). + setExtensionAndShowOverlay(extensionId, + extension.name, + extension.icon); + + this.optionsShown_ = true; + $('overlay').addEventListener('cancelOverlay', function() { + this.optionsShown_ = false; + }.bind(this)); + }, }; return { diff --git a/chrome/browser/resources/extensions/extension_options_overlay.js b/chrome/browser/resources/extensions/extension_options_overlay.js index b9614f3..e51e1fe 100644 --- a/chrome/browser/resources/extensions/extension_options_overlay.js +++ b/chrome/browser/resources/extensions/extension_options_overlay.js @@ -55,6 +55,9 @@ cr.define('extensions', function() { $('extension-options-overlay-guest').removeChild(extensionoptions); $('extension-options-overlay-icon').removeAttribute('src'); + + // Remove the options query string. + uber.replaceState({}, ''); }, /** @@ -94,7 +97,7 @@ cr.define('extensions', function() { extensionoptions.setDeferAutoSize(true); extensionoptions.onclose = function() { - this.handleDismiss_(); + cr.dispatchSimpleEvent($('overlay'), 'cancelOverlay'); }.bind(this); // Resize the overlay if the <extensionoptions> changes size. |