Commit 5fafa5aa authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

[Extensions] Fix chrome url override settings

Previously, chrome url overrides were added and removed at extension load and
unload. They should instead be added at install time, updated when the extension
is unloaded, and removed when the extension is uninstalled. Change the pref from
a string (of the url) to a dictionary with { entry: <url>, active: <bool> } to
allow for inactive, but retained, entries.

Also add regression tests.

BUG=571429

Review URL: https://codereview.chromium.org/1543923002

Cr-Commit-Position: refs/heads/master@{#367137}
parent c670faf4
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "chrome/browser/extensions/dev_mode_bubble_delegate.h" #include "chrome/browser/extensions/dev_mode_bubble_delegate.h"
#include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_web_ui_override_registrar.h"
#include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h" #include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h"
#include "chrome/browser/extensions/proxy_overridden_bubble_delegate.h" #include "chrome/browser/extensions/proxy_overridden_bubble_delegate.h"
#include "chrome/browser/extensions/settings_api_bubble_delegate.h" #include "chrome/browser/extensions/settings_api_bubble_delegate.h"
...@@ -45,6 +46,12 @@ const char kId1[] = "iccfkkhkfiphcjdakkmcjmkfboccmndk"; ...@@ -45,6 +46,12 @@ const char kId1[] = "iccfkkhkfiphcjdakkmcjmkfboccmndk";
const char kId2[] = "ajjhifimiemdpmophmkkkcijegphclbl"; const char kId2[] = "ajjhifimiemdpmophmkkkcijegphclbl";
const char kId3[] = "ioibbbfddncmmabjmpokikkeiofalaek"; const char kId3[] = "ioibbbfddncmmabjmpokikkeiofalaek";
scoped_ptr<KeyedService> BuildOverrideRegistrar(
content::BrowserContext* context) {
return make_scoped_ptr(
new extensions::ExtensionWebUIOverrideRegistrar(context));
}
} // namespace } // namespace
namespace extensions { namespace extensions {
...@@ -289,6 +296,11 @@ class ExtensionMessageBubbleTest : public BrowserWithTestWindowTest { ...@@ -289,6 +296,11 @@ class ExtensionMessageBubbleTest : public BrowserWithTestWindowTest {
base::FilePath(), false); base::FilePath(), false);
service_ = ExtensionSystem::Get(profile())->extension_service(); service_ = ExtensionSystem::Get(profile())->extension_service();
service_->Init(); service_->Init();
extensions::ExtensionWebUIOverrideRegistrar::GetFactoryInstance()->
SetTestingFactory(profile(), &BuildOverrideRegistrar);
extensions::ExtensionWebUIOverrideRegistrar::GetFactoryInstance()->Get(
profile());
} }
~ExtensionMessageBubbleTest() override {} ~ExtensionMessageBubbleTest() override {}
......
...@@ -48,16 +48,31 @@ class ExtensionWebUI : public content::WebUIController { ...@@ -48,16 +48,31 @@ class ExtensionWebUI : public content::WebUIController {
static bool HandleChromeURLOverrideReverse( static bool HandleChromeURLOverrideReverse(
GURL* url, content::BrowserContext* browser_context); GURL* url, content::BrowserContext* browser_context);
// Register and unregister a dictionary of one or more overrides. // Initialize the Chrome URL overrides. This must happen *before* any further
// Page names are the keys, and chrome-extension: URLs are the values. // calls for URL overrides!
// (e.g. { "newtab": "chrome-extension://<id>/my_new_tab.html" } static void InitializeChromeURLOverrides(Profile* profile);
static void RegisterChromeURLOverrides(Profile* profile,
// Validate the Chrome URL overrides, ensuring that each is valid and points
// to an existing extension. To be called once all extensions are loaded.
static void ValidateChromeURLOverrides(Profile* profile);
// Add new Chrome URL overrides. If an entry exists, it is marked as active.
// If one doesn't exist, it is added at the beginning of the list of
// overrides (meaning it has priority).
static void RegisterOrActivateChromeURLOverrides(
Profile* profile,
const extensions::URLOverrides::URLOverrideMap& overrides); const extensions::URLOverrides::URLOverrideMap& overrides);
static void UnregisterChromeURLOverrides(Profile* profile,
// Deactivate overrides without removing them from the list or modifying their
// positions in the list.
static void DeactivateChromeURLOverrides(
Profile* profile,
const extensions::URLOverrides::URLOverrideMap& overrides); const extensions::URLOverrides::URLOverrideMap& overrides);
static void UnregisterChromeURLOverride(const std::string& page,
// Completely unregister overrides, removing them from the list.
static void UnregisterChromeURLOverrides(
Profile* profile, Profile* profile,
const base::Value* override); const extensions::URLOverrides::URLOverrideMap& overrides);
// Called from BrowserPrefs // Called from BrowserPrefs
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
......
...@@ -8,13 +8,23 @@ ...@@ -8,13 +8,23 @@
#include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/extensions/extension_web_ui.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/one_shot_event.h"
namespace extensions { namespace extensions {
ExtensionWebUIOverrideRegistrar::ExtensionWebUIOverrideRegistrar( ExtensionWebUIOverrideRegistrar::ExtensionWebUIOverrideRegistrar(
content::BrowserContext* context) content::BrowserContext* context)
: extension_registry_observer_(this) { : extension_registry_observer_(this),
weak_factory_(this) {
ExtensionWebUI::InitializeChromeURLOverrides(
Profile::FromBrowserContext(context));
extension_registry_observer_.Add(ExtensionRegistry::Get(context)); extension_registry_observer_.Add(ExtensionRegistry::Get(context));
ExtensionSystem::Get(context)->ready().Post(
FROM_HERE,
base::Bind(&ExtensionWebUIOverrideRegistrar::OnExtensionSystemReady,
weak_factory_.GetWeakPtr(),
context));
} }
ExtensionWebUIOverrideRegistrar::~ExtensionWebUIOverrideRegistrar() { ExtensionWebUIOverrideRegistrar::~ExtensionWebUIOverrideRegistrar() {
...@@ -23,7 +33,7 @@ ExtensionWebUIOverrideRegistrar::~ExtensionWebUIOverrideRegistrar() { ...@@ -23,7 +33,7 @@ ExtensionWebUIOverrideRegistrar::~ExtensionWebUIOverrideRegistrar() {
void ExtensionWebUIOverrideRegistrar::OnExtensionLoaded( void ExtensionWebUIOverrideRegistrar::OnExtensionLoaded(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const Extension* extension) { const Extension* extension) {
ExtensionWebUI::RegisterChromeURLOverrides( ExtensionWebUI::RegisterOrActivateChromeURLOverrides(
Profile::FromBrowserContext(browser_context), Profile::FromBrowserContext(browser_context),
URLOverrides::GetChromeURLOverrides(extension)); URLOverrides::GetChromeURLOverrides(extension));
} }
...@@ -32,11 +42,26 @@ void ExtensionWebUIOverrideRegistrar::OnExtensionUnloaded( ...@@ -32,11 +42,26 @@ void ExtensionWebUIOverrideRegistrar::OnExtensionUnloaded(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const Extension* extension, const Extension* extension,
UnloadedExtensionInfo::Reason reason) { UnloadedExtensionInfo::Reason reason) {
ExtensionWebUI::DeactivateChromeURLOverrides(
Profile::FromBrowserContext(browser_context),
URLOverrides::GetChromeURLOverrides(extension));
}
void ExtensionWebUIOverrideRegistrar::OnExtensionUninstalled(
content::BrowserContext* browser_context,
const Extension* extension,
UninstallReason reason) {
ExtensionWebUI::UnregisterChromeURLOverrides( ExtensionWebUI::UnregisterChromeURLOverrides(
Profile::FromBrowserContext(browser_context), Profile::FromBrowserContext(browser_context),
URLOverrides::GetChromeURLOverrides(extension)); URLOverrides::GetChromeURLOverrides(extension));
} }
void ExtensionWebUIOverrideRegistrar::OnExtensionSystemReady(
content::BrowserContext* context) {
ExtensionWebUI::ValidateChromeURLOverrides(
Profile::FromBrowserContext(context));
}
static base::LazyInstance< static base::LazyInstance<
BrowserContextKeyedAPIFactory<ExtensionWebUIOverrideRegistrar> > g_factory = BrowserContextKeyedAPIFactory<ExtensionWebUIOverrideRegistrar> > g_factory =
LAZY_INSTANCE_INITIALIZER; LAZY_INSTANCE_INITIALIZER;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEB_UI_OVERRIDE_REGISTRAR_H_ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEB_UI_OVERRIDE_REGISTRAR_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/extension_registry_observer.h"
...@@ -36,16 +37,24 @@ class ExtensionWebUIOverrideRegistrar : public BrowserContextKeyedAPI, ...@@ -36,16 +37,24 @@ class ExtensionWebUIOverrideRegistrar : public BrowserContextKeyedAPI,
void OnExtensionUnloaded(content::BrowserContext* browser_context, void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension, const Extension* extension,
UnloadedExtensionInfo::Reason reason) override; UnloadedExtensionInfo::Reason reason) override;
void OnExtensionUninstalled(content::BrowserContext* browser_context,
const Extension* extension,
UninstallReason reason) override;
void OnExtensionSystemReady(content::BrowserContext* context);
// BrowserContextKeyedAPI implementation. // BrowserContextKeyedAPI implementation.
static const char* service_name() { static const char* service_name() {
return "ExtensionWebUIOverrideRegistrar"; return "ExtensionWebUIOverrideRegistrar";
} }
static const bool kServiceIsNULLWhileTesting = true;
// Listen to extension load, unloaded notifications. // Listen to extension load, unloaded notifications.
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_; extension_registry_observer_;
base::WeakPtrFactory<ExtensionWebUIOverrideRegistrar> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ExtensionWebUIOverrideRegistrar); DISALLOW_COPY_AND_ASSIGN(ExtensionWebUIOverrideRegistrar);
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/extensions/extension_web_ui.h"
#include "chrome/browser/extensions/extension_web_ui_override_registrar.h"
#include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h" #include "content/public/test/test_browser_thread.h"
...@@ -24,6 +25,15 @@ ...@@ -24,6 +25,15 @@
namespace extensions { namespace extensions {
namespace {
scoped_ptr<KeyedService> BuildOverrideRegistrar(
content::BrowserContext* context) {
return make_scoped_ptr(new ExtensionWebUIOverrideRegistrar(context));
}
} // namespace
class ExtensionWebUITest : public testing::Test { class ExtensionWebUITest : public testing::Test {
public: public:
ExtensionWebUITest() ExtensionWebUITest()
...@@ -36,6 +46,9 @@ class ExtensionWebUITest : public testing::Test { ...@@ -36,6 +46,9 @@ class ExtensionWebUITest : public testing::Test {
static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_.get())); static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_.get()));
extension_service_ = system->CreateExtensionService( extension_service_ = system->CreateExtensionService(
base::CommandLine::ForCurrentProcess(), base::FilePath(), false); base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
ExtensionWebUIOverrideRegistrar::GetFactoryInstance()->SetTestingFactory(
profile_.get(), &BuildOverrideRegistrar);
ExtensionWebUIOverrideRegistrar::GetFactoryInstance()->Get(profile_.get());
} }
void TearDown() override { void TearDown() override {
...@@ -110,7 +123,7 @@ TEST_F(ExtensionWebUITest, ExtensionURLOverride) { ...@@ -110,7 +123,7 @@ TEST_F(ExtensionWebUITest, ExtensionURLOverride) {
// This time the non-component extension was registered more recently and // This time the non-component extension was registered more recently and
// should still take precedence. // should still take precedence.
ExtensionWebUI::RegisterChromeURLOverrides( ExtensionWebUI::RegisterOrActivateChromeURLOverrides(
profile_.get(), URLOverrides::GetChromeURLOverrides(ext_unpacked.get())); profile_.get(), URLOverrides::GetChromeURLOverrides(ext_unpacked.get()));
url = GURL("chrome://bookmarks"); url = GURL("chrome://bookmarks");
EXPECT_TRUE(ExtensionWebUI::HandleChromeURLOverride(&url, profile_.get())); EXPECT_TRUE(ExtensionWebUI::HandleChromeURLOverride(&url, profile_.get()));
......
{ {
"name": "New tab override test", "name": "New tab override test, number 1",
"version": "0.1", "version": "0.1",
"manifest_version": 2, "manifest_version": 2,
"description": "Test chrome://newtab override", "description": "Test chrome://newtab override",
"background": {
"scripts": ["background.js"]
},
"permissions": [ "permissions": [
"tabs" "tabs"
], ],
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
chrome.test.notifyPass(); chrome.test.sendMessage('controlled by first');
{
"name": "New tab override test, number 2",
"version": "0.1",
"manifest_version": 2,
"description": "Test chrome://newtab override",
"permissions": [
"tabs"
],
"chrome_url_overrides": {
"newtab": "override.html"
}
}
<!doctype html>
<html>
<script src="override.js"></script>
This is a tab override.
</html>
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
chrome.test.notifyPass(); chrome.test.sendMessage('controlled by second');
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment