| Index: chrome/browser/extensions/extension_dom_ui.cc
|
| diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
|
| index ed5abb9624c0cc6fd38f49477aa674addedbe2bd..044a28a714cdae1bfed224b4e98483457679696f 100644
|
| --- a/chrome/browser/extensions/extension_dom_ui.cc
|
| +++ b/chrome/browser/extensions/extension_dom_ui.cc
|
| @@ -5,8 +5,16 @@
|
| #include "chrome/browser/extensions/extension_dom_ui.h"
|
|
|
| #include "chrome/browser/browser.h"
|
| +#include "chrome/browser/browser_list.h"
|
| +#include "chrome/browser/profile.h"
|
| #include "chrome/browser/tab_contents/tab_contents.h"
|
| #include "chrome/common/bindings_policy.h"
|
| +#include "chrome/common/pref_service.h"
|
| +#include "chrome/common/url_constants.h"
|
| +
|
| +namespace {
|
| +const wchar_t kExtensionURLOverrides[] = L"extensions.chrome_url_overrides";
|
| +}
|
|
|
| ExtensionDOMUI::ExtensionDOMUI(TabContents* tab_contents)
|
| : DOMUI(tab_contents) {
|
| @@ -14,18 +22,35 @@ ExtensionDOMUI::ExtensionDOMUI(TabContents* tab_contents)
|
| hide_favicon_ = true;
|
| should_hide_url_ = true;
|
| bindings_ = BindingsPolicy::EXTENSION;
|
| +
|
| + // For chrome:// overrides, some of the defaults are a little different.
|
| + GURL url = tab_contents->GetURL();
|
| + if (url.SchemeIs(chrome::kChromeUIScheme)) {
|
| + if (url.host() == chrome::kChromeUINewTabHost) {
|
| + focus_location_bar_by_default_ = true;
|
| + } else {
|
| + // Current behavior of other chrome:// pages is to display the URL.
|
| + should_hide_url_ = false;
|
| + }
|
| + }
|
| }
|
|
|
| -void ExtensionDOMUI::RenderViewCreated(RenderViewHost* render_view_host) {
|
| +void ExtensionDOMUI::ResetExtensionFunctionDispatcher(
|
| + RenderViewHost* render_view_host) {
|
| + // Use the NavigationController to get the URL rather than the TabContents
|
| + // since this is the real underlying URL (see HandleChromeURLOverride).
|
| + NavigationController& controller = tab_contents()->controller();
|
| + const GURL& url = controller.pending_entry()->url();
|
| extension_function_dispatcher_.reset(
|
| - new ExtensionFunctionDispatcher(render_view_host, this,
|
| - tab_contents()->GetURL()));
|
| + new ExtensionFunctionDispatcher(render_view_host, this, url));
|
| +}
|
| +
|
| +void ExtensionDOMUI::RenderViewCreated(RenderViewHost* render_view_host) {
|
| + ResetExtensionFunctionDispatcher(render_view_host);
|
| }
|
|
|
| void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) {
|
| - extension_function_dispatcher_.reset(
|
| - new ExtensionFunctionDispatcher(render_view_host, this,
|
| - tab_contents()->GetURL()));
|
| + ResetExtensionFunctionDispatcher(render_view_host);
|
| }
|
|
|
| void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message,
|
| @@ -39,3 +64,188 @@ void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message,
|
| Browser* ExtensionDOMUI::GetBrowser() {
|
| return static_cast<Browser*>(tab_contents()->delegate());
|
| }
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// chrome:// URL overrides
|
| +
|
| +// static
|
| +void ExtensionDOMUI::RegisterUserPrefs(PrefService* prefs) {
|
| + prefs->RegisterDictionaryPref(kExtensionURLOverrides);
|
| +}
|
| +
|
| +// static
|
| +bool ExtensionDOMUI::HandleChromeURLOverride(GURL* url, Profile* profile) {
|
| + if (!url->SchemeIs(chrome::kChromeUIScheme))
|
| + return false;
|
| +
|
| + // Even when the extensions service is enabled by default, it's still
|
| + // disabled in incognito mode.
|
| + ExtensionsService* service = profile->GetExtensionsService();
|
| + if (!service)
|
| + return false;
|
| +
|
| + const DictionaryValue* overrides =
|
| + profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
|
| + std::string page = url->host();
|
| + ListValue* url_list;
|
| + if (!overrides || !overrides->GetList(UTF8ToWide(page), &url_list))
|
| + return false;
|
| +
|
| + if (!service->is_ready()) {
|
| + // TODO(erikkay) So far, it looks like extensions load before the new tab
|
| + // page. I don't know if we have anything that enforces this, so add this
|
| + // check for safety.
|
| + NOTREACHED() << "Chrome URL override requested before extensions loaded";
|
| + return false;
|
| + }
|
| +
|
| + while (url_list->GetSize()) {
|
| + Value* val;
|
| + url_list->Get(0, &val);
|
| +
|
| + // Verify that the override value is good. If not, unregister it and find
|
| + // the next one.
|
| + std::string override;
|
| + if (!val->GetAsString(&override)) {
|
| + NOTREACHED();
|
| + UnregisterChromeURLOverride(page, profile, val);
|
| + continue;
|
| + }
|
| + GURL extension_url(override);
|
| + if (!extension_url.is_valid()) {
|
| + NOTREACHED();
|
| + UnregisterChromeURLOverride(page, profile, val);
|
| + continue;
|
| + }
|
| +
|
| + // Verify that the extension that's being referred to actually exists.
|
| + Extension* extension = service->GetExtensionByURL(extension_url);
|
| + if (!extension) {
|
| + // This can currently happen if you use --load-extension one run, and
|
| + // then don't use it the next. It could also happen if an extension
|
| + // were deleted directly from the filesystem, etc.
|
| + LOG(WARNING) << "chrome URL override present for non-existant extension";
|
| + UnregisterChromeURLOverride(page, profile, val);
|
| + continue;
|
| + }
|
| +
|
| + *url = extension_url;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// static
|
| +void ExtensionDOMUI::RegisterChromeURLOverrides(
|
| + Profile* profile, const DictionaryValue* new_overrides) {
|
| + if (!new_overrides)
|
| + return;
|
| +
|
| + PrefService* prefs = profile->GetPrefs();
|
| + DictionaryValue* all_overrides =
|
| + prefs->GetMutableDictionary(kExtensionURLOverrides);
|
| +
|
| + // For each override provided by the extension, add it to the front of
|
| + // the override list if it's not already in the list.
|
| + DictionaryValue::key_iterator iter = new_overrides->begin_keys();
|
| + for (;iter != new_overrides->end_keys(); ++iter) {
|
| + Value* val;
|
| + new_overrides->Get(*iter, &val);
|
| + std::string string_val;
|
| + if (!val->GetAsString(&string_val)) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| + ListValue* page_overrides;
|
| + if (!all_overrides->GetList(*iter, &page_overrides)) {
|
| + page_overrides = new ListValue();
|
| + all_overrides->Set(*iter, page_overrides);
|
| + } else {
|
| + // Verify that the override isn't already in the list.
|
| + ListValue::iterator i = page_overrides->begin();
|
| + for (; i != page_overrides->end(); ++i) {
|
| + std::string override_val;
|
| + if (!(*i)->GetAsString(&override_val)) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| + if (override_val == string_val)
|
| + break;
|
| + }
|
| + // This value is already in the list, leave it alone.
|
| + if (i != page_overrides->end())
|
| + continue;
|
| + }
|
| + // Insert the override at the front of the list. Last registered override
|
| + // wins.
|
| + page_overrides->Insert(0, val->DeepCopy());
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void ExtensionDOMUI::UnregisterAndReplaceOverride(const std::string& page,
|
| + Profile* profile, ListValue* list, Value* override) {
|
| + int index = list->Remove(*override);
|
| + if (index == 0) {
|
| + // This is the active override, so we need to find all existing
|
| + // tabs for this override and get them to reload the original URL.
|
| + for (TabContentsIterator iterator; !iterator.done(); iterator++) {
|
| + TabContents* tab = *iterator;
|
| + if (tab->profile() != profile)
|
| + continue;
|
| +
|
| + GURL url = tab->GetURL();
|
| + if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page)
|
| + continue;
|
| +
|
| + // Don't use Reload() since |url| isn't the same as the internal URL
|
| + // that NavigationController has.
|
| + tab->controller().LoadURL(url, url, PageTransition::RELOAD);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void ExtensionDOMUI::UnregisterChromeURLOverride(const std::string& page,
|
| + Profile* profile, Value* override) {
|
| + if (!override)
|
| + return;
|
| + PrefService* prefs = profile->GetPrefs();
|
| + DictionaryValue* all_overrides =
|
| + prefs->GetMutableDictionary(kExtensionURLOverrides);
|
| + ListValue* page_overrides;
|
| + if (!all_overrides->GetList(UTF8ToWide(page), &page_overrides)) {
|
| + // If it's being unregistered, it should already be in the list.
|
| + NOTREACHED();
|
| + return;
|
| + } else {
|
| + UnregisterAndReplaceOverride(page, profile, page_overrides, override);
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void ExtensionDOMUI::UnregisterChromeURLOverrides(
|
| + Profile* profile, const DictionaryValue* new_overrides) {
|
| + if (!new_overrides)
|
| + return;
|
| + PrefService* prefs = profile->GetPrefs();
|
| + DictionaryValue* all_overrides =
|
| + prefs->GetMutableDictionary(kExtensionURLOverrides);
|
| + DictionaryValue::key_iterator iter = new_overrides->begin_keys();
|
| + for (; iter != new_overrides->end_keys(); ++iter) {
|
| + Value* val;
|
| + if (!new_overrides->Get(*iter, &val)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + ListValue* page_overrides;
|
| + if (!all_overrides->GetList(*iter, &page_overrides)) {
|
| + // If it's being unregistered, it should already be in the list.
|
| + NOTREACHED();
|
| + continue;
|
| + } else {
|
| + UnregisterAndReplaceOverride(WideToUTF8(*iter), profile, page_overrides,
|
| + val);
|
| + }
|
| + }
|
| +}
|
|
|