Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3864)

Unified Diff: chrome/browser/extensions/extension_dom_ui.cc

Issue 174277: override chrome:// URLs via extensions. (Closed)
Patch Set: fix linux errors Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/extensions/extension_dom_ui.h ('k') | chrome/browser/extensions/extension_host.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
+ }
+ }
+}
« no previous file with comments | « chrome/browser/extensions/extension_dom_ui.h ('k') | chrome/browser/extensions/extension_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698