summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry.cc227
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry.h83
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc134
-rw-r--r--chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.cc1
-rw-r--r--chrome/browser/profiles/profile_impl.cc3
-rw-r--r--chrome/browser/ui/tab_contents/tab_contents_wrapper.cc6
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/pref_names.cc13
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--chrome/test/testing_profile.cc3
10 files changed, 426 insertions, 47 deletions
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc
index 067c21a..1e93ca57 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -5,8 +5,11 @@
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "base/memory/scoped_ptr.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/custom_handlers/protocol_handler.h"
#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h"
#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
#include "content/browser/child_process_security_policy.h"
#include "net/base/network_delegate.h"
@@ -15,36 +18,104 @@
// ProtocolHandlerRegistry -----------------------------------------------------
-ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile)
- :profile_(profile) {
+ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
+ Delegate* delegate)
+ : profile_(profile),
+ delegate_(delegate),
+ enabled_(true) {
+}
+
+ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
+ STLDeleteContainerPairSecondPointers(protocol_handlers_.begin(),
+ protocol_handlers_.end());
+ STLDeleteContainerPointers(ignored_protocol_handlers_.begin(),
+ ignored_protocol_handlers_.end());
+}
+
+static void RemoveAndDelete(ProtocolHandlerMap& handlers,
+ const std::string& scheme) {
+ ProtocolHandlerMap::iterator p = handlers.find(scheme);
+ if (p != handlers.end()) {
+ ProtocolHandler* removed_handler = p->second;
+ handlers.erase(p);
+ delete removed_handler;
+ }
}
void ProtocolHandlerRegistry::RegisterProtocolHandler(
ProtocolHandler* handler) {
- if (protocolHandlers_.find(handler->protocol()) == protocolHandlers_.end()) {
- ChildProcessSecurityPolicy* policy =
- ChildProcessSecurityPolicy::GetInstance();
- if (!policy->IsWebSafeScheme(handler->protocol())) {
- policy->RegisterWebSafeScheme(handler->protocol());
+ DCHECK(CanSchemeBeOverridden(handler->protocol()));
+ if (enabled_) {
+ delegate_->RegisterExternalHandler(handler->protocol());
+ }
+ RemoveAndDelete(protocol_handlers_, handler->protocol());
+ protocol_handlers_[handler->protocol()] = handler;
+}
+
+void ProtocolHandlerRegistry::IgnoreProtocolHandler(ProtocolHandler* handler) {
+ ignored_protocol_handlers_.push_back(handler);
+}
+
+void ProtocolHandlerRegistry::Enable() {
+ if (enabled_) {
+ return;
+ }
+ enabled_ = true;
+ for (ProtocolHandlerMap::const_iterator p = protocol_handlers_.begin();
+ p != protocol_handlers_.end(); p++) {
+ delegate_->RegisterExternalHandler(p->first);
+ }
+}
+
+void ProtocolHandlerRegistry::Disable() {
+ if (!enabled_) {
+ return;
+ }
+ enabled_ = false;
+ for (ProtocolHandlerMap::const_iterator p = protocol_handlers_.begin();
+ p != protocol_handlers_.end(); p++) {
+ delegate_->DeregisterExternalHandler(p->first);
+ }
+}
+
+ProtocolHandlerList ProtocolHandlerRegistry::GetHandlersFromPref(
+ const char* pref_name) {
+ ProtocolHandlerList result;
+ PrefService* prefs = profile_->GetPrefs();
+ if (!prefs->HasPrefPath(pref_name)) {
+ return result;
+ }
+
+ const ListValue* handlers = prefs->GetList(pref_name);
+ if (handlers) {
+ for (size_t i = 0; i < handlers->GetSize(); i++) {
+ DictionaryValue* dict;
+ handlers->GetDictionary(i, &dict);
+ ProtocolHandler* handler = ProtocolHandler::CreateProtocolHandler(dict);
+ if (handler) {
+ result.push_back(handler);
+ }
}
- net::URLRequest::RegisterProtocolFactory(handler->protocol(),
- &ProtocolHandlerRegistry::Factory);
}
- protocolHandlers_[handler->protocol()] = handler;
+ return result;
}
void ProtocolHandlerRegistry::Load() {
PrefService* prefs = profile_->GetPrefs();
- if (!prefs->HasPrefPath(prefs::kRegisteredProtocolHandlers)) {
- return;
+ if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) {
+ enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled);
}
- const ListValue* protocolHandlers =
- prefs->GetList(prefs::kRegisteredProtocolHandlers);
-
- for (size_t i = 0; i < protocolHandlers->GetSize(); i++) {
- DictionaryValue* dict;
- protocolHandlers->GetDictionary(i, &dict);
- RegisterHandlerFromValue(dict);
+ ProtocolHandlerList registered_handlers =
+ GetHandlersFromPref(prefs::kRegisteredProtocolHandlers);
+ for (ProtocolHandlerList::iterator p = registered_handlers.begin();
+ p != registered_handlers.end(); p++) {
+ RegisterProtocolHandler(*p);
+ }
+ ProtocolHandlerList ignored_handlers =
+ GetHandlersFromPref(prefs::kIgnoredProtocolHandlers);
+ for (ProtocolHandlerList::iterator p = ignored_handlers.begin();
+ p != ignored_handlers.end(); p++) {
+ IgnoreProtocolHandler(*p);
}
}
@@ -57,36 +128,84 @@ void ProtocolHandlerRegistry::RegisterHandlerFromValue(
}
void ProtocolHandlerRegistry::Save() {
- scoped_ptr<Value> value(Encode());
- profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, *value);
+ scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers());
+ scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers());
+ scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_));
+ profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
+ *registered_protocol_handlers);
+ profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
+ *ignored_protocol_handlers);
+ profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled);
profile_->GetPrefs()->ScheduleSavePersistentPrefs();
}
ProtocolHandler* ProtocolHandlerRegistry::GetHandlerFor(
const std::string& scheme) const {
- ProtocolHandlerMap::const_iterator i = protocolHandlers_.find(scheme);
- return i == protocolHandlers_.end() ? NULL : i->second;
+ ProtocolHandlerMap::const_iterator i = protocol_handlers_.find(scheme);
+ return i == protocol_handlers_.end() ? NULL : i->second;
}
bool ProtocolHandlerRegistry::CanSchemeBeOverridden(
const std::string& scheme) const {
return GetHandlerFor(scheme) != NULL ||
- !net::URLRequest::IsHandledProtocol(scheme);
+ !delegate_->IsExternalHandlerRegistered(scheme);
+}
+
+void ProtocolHandlerRegistry::GetHandledProtocols(
+ std::vector<std::string>* output) {
+ ProtocolHandlerMap::iterator p;
+ for (p = protocol_handlers_.begin(); p != protocol_handlers_.end(); p++) {
+ output->push_back(p->first);
+ }
}
-bool ProtocolHandlerRegistry::IsAlreadyRegistered(
+void ProtocolHandlerRegistry::RemoveHandlerFor(const std::string& scheme) {
+ RemoveAndDelete(protocol_handlers_, scheme);
+ net::URLRequest::RegisterProtocolFactory(scheme, NULL);
+ Save();
+}
+
+void ProtocolHandlerRegistry::RemoveIgnoredHandler(ProtocolHandler* handler) {
+ for (ProtocolHandlerList::iterator p = ignored_protocol_handlers_.begin();
+ p != ignored_protocol_handlers_.end(); p++) {
+ if (*handler == **p) {
+ ProtocolHandler* removed_handler = *p;
+ ignored_protocol_handlers_.erase(p);
+ delete removed_handler;
+ break;
+ }
+ }
+}
+
+bool ProtocolHandlerRegistry::IsRegistered(
const ProtocolHandler* handler) const {
ProtocolHandler* currentHandler = GetHandlerFor(handler->protocol());
return currentHandler && *currentHandler == *handler;
}
+bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler* handler) const {
+ ProtocolHandlerList::const_iterator i;
+ for (i = ignored_protocol_handlers_.begin();
+ i != ignored_protocol_handlers_.end(); i++) {
+ if (**i == *handler) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool ProtocolHandlerRegistry::IsHandledProtocol(
+ const std::string& scheme) const {
+ return GetHandlerFor(scheme);
+}
+
net::URLRequestJob* ProtocolHandlerRegistry::Factory(net::URLRequest* request,
const std::string& scheme) {
return request->context()->network_delegate()->MaybeCreateURLRequestJob(
request);
}
-
net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
net::URLRequest* request) const {
ProtocolHandler* handler = GetHandlerFor(request->url().scheme());
@@ -104,16 +223,24 @@ net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
return new net::URLRequestRedirectJob(request, translated_url);
}
-ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {}
+Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() {
+ ListValue* protocol_handlers = new ListValue();
-Value* ProtocolHandlerRegistry::Encode() {
- ListValue* protocolHandlers = new ListValue();
+ for (ProtocolHandlerMap::iterator i = protocol_handlers_.begin();
+ i != protocol_handlers_.end(); ++i) {
+ protocol_handlers->Append(i->second->Encode());
+ }
+ return protocol_handlers;
+}
- for (ProtocolHandlerMap::iterator i = protocolHandlers_.begin();
- i != protocolHandlers_.end(); ++i) {
- protocolHandlers->Append(i->second->Encode());
+Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() {
+ ListValue* handlers = new ListValue();
+
+ for (ProtocolHandlerList::iterator i = ignored_protocol_handlers_.begin();
+ i != ignored_protocol_handlers_.end(); ++i) {
+ handlers->Append((*i)->Encode());
}
- return protocolHandlers;
+ return handlers;
}
void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
@@ -126,6 +253,40 @@ void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
ProtocolHandler* handler) {
}
+void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler(
+ ProtocolHandler* handler) {
+ IgnoreProtocolHandler(handler);
+ Save();
+}
+
void ProtocolHandlerRegistry::RegisterPrefs(PrefService* prefService) {
prefService->RegisterListPref(prefs::kRegisteredProtocolHandlers);
+ prefService->RegisterListPref(prefs::kIgnoredProtocolHandlers);
+ prefService->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true);
+}
+
+// Delegate --------------------------------------------------------------------
+
+ProtocolHandlerRegistry::Delegate::~Delegate() {
+}
+
+void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler(
+ const std::string& protocol) {
+ ChildProcessSecurityPolicy* policy =
+ ChildProcessSecurityPolicy::GetInstance();
+ if (!policy->IsWebSafeScheme(protocol)) {
+ policy->RegisterWebSafeScheme(protocol);
+ }
+ net::URLRequest::RegisterProtocolFactory(protocol,
+ &ProtocolHandlerRegistry::Factory);
+}
+
+void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler(
+ const std::string& protocol) {
+ net::URLRequest::RegisterProtocolFactory(protocol, NULL);
+}
+
+bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered(
+ const std::string& protocol) {
+ return net::URLRequest::IsHandledProtocol(protocol);
}
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.h b/chrome/browser/custom_handlers/protocol_handler_registry.h
index 9ae3cfc..868bd2b 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.h
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.h
@@ -6,18 +6,21 @@
#define CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_
#pragma once
-#include <string>
#include <map>
+#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
-#include "chrome/browser/custom_handlers/protocol_handler.h"
#include "chrome/browser/profiles/profile.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
+class ProtocolHandler;
+typedef std::map<std::string, ProtocolHandler*> ProtocolHandlerMap;
+typedef std::vector<ProtocolHandler*> ProtocolHandlerList;
// This is where handlers for protocols registered with
// navigator.registerProtocolHandler() are registered. Each Profile owns an
@@ -28,7 +31,10 @@
class ProtocolHandlerRegistry
: public base::RefCountedThreadSafe<ProtocolHandlerRegistry> {
public:
- explicit ProtocolHandlerRegistry(Profile* profile);
+ class Delegate;
+
+ ProtocolHandlerRegistry(Profile* profile, Delegate* delegate);
+ ~ProtocolHandlerRegistry();
// Called when the user accepts the registration of a given protocol handler.
void OnAcceptRegisterProtocolHandler(ProtocolHandler* handler);
@@ -36,6 +42,10 @@ class ProtocolHandlerRegistry
// Called when the user denies the registration of a given protocol handler.
void OnDenyRegisterProtocolHandler(ProtocolHandler* handler);
+ // Called when the user indicates that they don't want to be asked about the
+ // given protocol handler again.
+ void OnIgnoreRegisterProtocolHandler(ProtocolHandler* handler);
+
// Loads a user's registered protocol handlers.
void Load();
@@ -45,12 +55,27 @@ class ProtocolHandlerRegistry
// Returns the handler for this protocol.
ProtocolHandler* GetHandlerFor(const std::string& scheme) const;
+ // Yields a list of the protocols handled by this registry.
+ void GetHandledProtocols(std::vector<std::string>* output);
+
// Returns true if we allow websites to register handlers for the given
// scheme.
bool CanSchemeBeOverridden(const std::string& scheme) const;
// Returns true if an identical protocol handler has already been registered.
- bool IsAlreadyRegistered(const ProtocolHandler* handler) const;
+ bool IsRegistered(const ProtocolHandler* handler) const;
+
+ // Returns true if the protocol handler is being ignored.
+ bool IsIgnored(const ProtocolHandler* handler) const;
+
+ // Returns true if the protocol has a registered protocol handler.
+ bool IsHandledProtocol(const std::string& scheme) const;
+
+ // Removes any existing protocol handler for the given protocol.
+ void RemoveHandlerFor(const std::string& scheme);
+
+ // Causes the given protocol handler to not be ignored anymore.
+ void RemoveIgnoredHandler(ProtocolHandler* handler);
// URLRequestFactory for use with URLRequest::RegisterProtocolFactory().
// Redirects any URLRequests for which there is a matching protocol handler.
@@ -64,28 +89,68 @@ class ProtocolHandlerRegistry
// protocol handler, returns NULL otherwise.
net::URLRequestJob* MaybeCreateJob(net::URLRequest* request) const;
+ // Puts this registry in the enabled state - registered protocol handlers
+ // will handle requests.
+ void Enable();
+
+ // Puts this registry in the disabled state - registered protocol handlers
+ // will not handle requests.
+ void Disable();
+
+ bool enabled() { return enabled_; }
+
+ class Delegate {
+ public:
+ virtual ~Delegate();
+ virtual void RegisterExternalHandler(const std::string& protocol);
+ virtual void DeregisterExternalHandler(const std::string& protocol);
+ virtual bool IsExternalHandlerRegistered(const std::string& protocol);
+ };
+
private:
- typedef std::map<std::string, ProtocolHandler*> ProtocolHandlerMap;
friend class base::RefCountedThreadSafe<ProtocolHandlerRegistry>;
- ~ProtocolHandlerRegistry();
- // Returns a JSON dictionary of protocols to protocol handlers. The caller is
+ // Returns a JSON list of protocol handlers. The caller is responsible for
+ // deleting this Value.
+ Value* EncodeRegisteredHandlers();
+
+ // Returns a JSON list of ignored protocol handlers. The caller is
// responsible for deleting this Value.
- Value* Encode();
+ Value* EncodeIgnoredHandlers();
// Registers a new protocol handler.
void RegisterProtocolHandler(ProtocolHandler* handler);
+ // Get the ProtocolHandlers stored under the given pref name. The caller owns
+ // the returned ProtocolHandlers and is responsible for deleting them.
+ ProtocolHandlerList GetHandlersFromPref(const char* pref_name);
+
+ // Ignores future requests to register the given protocol handler.
+ void IgnoreProtocolHandler(ProtocolHandler* handler);
+
// Registers a new protocol handler from a JSON dictionary.
void RegisterHandlerFromValue(const DictionaryValue* value);
+ // Register
+ void IgnoreHandlerFromValue(const DictionaryValue* value);
+
// Map from protocols (strings) to protocol handlers.
- ProtocolHandlerMap protocolHandlers_;
+ ProtocolHandlerMap protocol_handlers_;
+
+ // Protocol handlers that the user has told us to ignore.
+ ProtocolHandlerList ignored_protocol_handlers_;
// The Profile that owns this ProtocolHandlerRegistry.
Profile* profile_;
+ // The Delegate that registers / deregisters external handlers on our behalf.
+ scoped_ptr<Delegate> delegate_;
+
+ // If false then registered protocol handlers will not be used to handle
+ // requests.
+ bool enabled_;
+
DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerRegistry);
};
#endif // CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
new file mode 100644
index 0000000..1503ddd
--- /dev/null
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+
+#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/test/testing_browser_process.h"
+#include "chrome/test/testing_browser_process_test.h"
+#include "chrome/browser/custom_handlers/protocol_handler.h"
+#include "chrome/test/testing_browser_process_test.h"
+#include "chrome/test/testing_pref_service.h"
+#include "chrome/test/testing_profile.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
+#include "content/common/notification_service.h"
+
+class FakeDelegate : public ProtocolHandlerRegistry::Delegate {
+ public:
+ virtual ~FakeDelegate() { }
+ virtual void RegisterExternalHandler(const std::string& protocol) {
+ registered_protocols_.insert(protocol);
+ }
+ virtual void DeregisterExternalHandler(const std::string& protocol) {
+ registered_protocols_.erase(protocol);
+ }
+
+ bool IsExternalHandlerRegistered(const std::string& protocol) {
+ return registered_protocols_.find(protocol) != registered_protocols_.end();
+ }
+
+ void Reset() {
+ registered_protocols_.clear();
+ }
+
+ private:
+ std::set<std::string> registered_protocols_;
+};
+
+
+class ProtocolHandlerRegistryTest : public testing::Test {
+ public:
+ FakeDelegate* delegate() const { return delegate_; }
+ TestingProfile* profile() const { return profile_.get(); }
+ PrefService* pref_service() const { return profile_->GetPrefs(); }
+ ProtocolHandlerRegistry* registry() const { return registry_.get(); }
+
+ ProtocolHandler* CreateProtocolHandler(const std::string& protocol,
+ const GURL& url,
+ const std::string& title) {
+ return ProtocolHandler::CreateProtocolHandler(protocol, url,
+ UTF8ToUTF16(title));
+ }
+
+ ProtocolHandler* MakeProtocolHandler(const std::string& protocol) {
+ return CreateProtocolHandler(protocol, GURL("http://blah.com/%s"),
+ protocol);
+ }
+
+ ProtocolHandler* TestProtocolHandler() {
+ return CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test");
+ }
+
+ void ReloadProtocolHandlerRegistry() {
+ delegate_ = new FakeDelegate(*delegate_); // Copy across the delegate.
+ registry_ = new ProtocolHandlerRegistry(profile(), delegate());
+ registry_->Load();
+ }
+
+ private:
+ virtual void SetUp() {
+ profile_.reset(new TestingProfile());
+ profile_->SetPrefService(new TestingPrefService());
+ delegate_ = new FakeDelegate();
+ registry_ = new ProtocolHandlerRegistry(profile(), delegate());
+ registry_->Load();
+
+ ProtocolHandlerRegistry::RegisterPrefs(pref_service());
+ }
+
+ FakeDelegate* delegate_;
+ scoped_ptr<TestingProfile> profile_;
+ scoped_refptr<ProtocolHandlerRegistry> registry_;
+};
+
+TEST_F(ProtocolHandlerRegistryTest, AcceptProtocolHandlerHandlesProtocol) {
+ ASSERT_FALSE(registry()->IsHandledProtocol("test"));
+ registry()->OnAcceptRegisterProtocolHandler(TestProtocolHandler());
+ ASSERT_TRUE(registry()->IsHandledProtocol("test"));
+}
+
+TEST_F(ProtocolHandlerRegistryTest, DisableDeregistersProtocolHandlers) {
+ ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test"));
+ registry()->OnAcceptRegisterProtocolHandler(TestProtocolHandler());
+ ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test"));
+
+ registry()->Disable();
+ ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test"));
+ registry()->Enable();
+ ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test"));
+}
+
+TEST_F(ProtocolHandlerRegistryTest, IgnoreProtocolHandler) {
+ registry()->OnIgnoreRegisterProtocolHandler(TestProtocolHandler());
+ ASSERT_TRUE(registry()->IsIgnored(TestProtocolHandler()));
+ registry()->RemoveIgnoredHandler(TestProtocolHandler());
+ ASSERT_FALSE(registry()->IsIgnored(TestProtocolHandler()));
+}
+
+TEST_F(ProtocolHandlerRegistryTest, SaveAndLoad) {
+ registry()->OnAcceptRegisterProtocolHandler(TestProtocolHandler());
+ registry()->OnIgnoreRegisterProtocolHandler(MakeProtocolHandler("stuff"));
+
+ ASSERT_TRUE(registry()->IsHandledProtocol("test"));
+ ASSERT_TRUE(registry()->IsIgnored(MakeProtocolHandler("stuff")));
+ delegate()->Reset();
+ ReloadProtocolHandlerRegistry();
+ ASSERT_TRUE(registry()->IsHandledProtocol("test"));
+ ASSERT_TRUE(registry()->IsIgnored(MakeProtocolHandler("stuff")));
+}
+
+TEST_F(ProtocolHandlerRegistryTest, TestEnabledDisabled) {
+ registry()->Disable();
+ ASSERT_FALSE(registry()->enabled());
+ registry()->Enable();
+ ASSERT_TRUE(registry()->enabled());
+}
+
+TEST_F(ProtocolHandlerRegistryTest,
+ DisallowRegisteringExternallyHandledProtocols) {
+ delegate()->RegisterExternalHandler("test");
+ ASSERT_FALSE(registry()->CanSchemeBeOverridden("test"));
+}
diff --git a/chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.cc b/chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.cc
index 3d12986..9bd9176 100644
--- a/chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.cc
+++ b/chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/custom_handlers/protocol_handler.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 4a71f99..8b472cd 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -504,7 +504,8 @@ void ProfileImpl::InitPromoResources() {
void ProfileImpl::InitRegisteredProtocolHandlers() {
if (protocol_handler_registry_)
return;
- protocol_handler_registry_ = new ProtocolHandlerRegistry(this);
+ protocol_handler_registry_ = new ProtocolHandlerRegistry(this,
+ new ProtocolHandlerRegistry::Delegate());
protocol_handler_registry_->Load();
}
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
index 1b7ad45..86031ec 100644
--- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/automation/automation_tab_helper.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/custom_handlers/protocol_handler.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h"
#include "chrome/browser/extensions/extension_tab_helper.h"
@@ -288,11 +289,14 @@ void TabContentsWrapper::OnRegisterProtocolHandler(const std::string& protocol,
const GURL& url,
const string16& title) {
ProtocolHandlerRegistry* registry = profile()->GetProtocolHandlerRegistry();
+ if (!registry->enabled()) {
+ return;
+ }
ProtocolHandler* handler =
ProtocolHandler::CreateProtocolHandler(protocol, url, title);
if ((handler != NULL) &&
registry->CanSchemeBeOverridden(handler->protocol())) {
- tab_contents()->AddInfoBar(registry->IsAlreadyRegistered(handler) ?
+ tab_contents()->AddInfoBar(registry->IsRegistered(handler) ?
static_cast<InfoBarDelegate*>(new SimpleAlertInfoBarDelegate(
tab_contents(), NULL, l10n_util::GetStringFUTF16(
IDS_REGISTER_PROTOCOL_HANDLER_ALREADY_REGISTERED,
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 2f04c4f..06c0812 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1303,6 +1303,7 @@
'browser/content_settings/stub_settings_observer.cc',
'browser/content_settings/stub_settings_observer.h',
'browser/cookies_tree_model_unittest.cc',
+ 'browser/custom_handlers/protocol_handler_registry_unittest.cc',
'browser/debugger/devtools_manager_unittest.cc',
'browser/debugger/devtools_remote_listen_socket_unittest.cc',
'browser/debugger/devtools_remote_listen_socket_unittest.h',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 04c6f3a6..2a022ec 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1289,6 +1289,15 @@ const char kManagedPopupsBlockedForUrls[] =
// needs to acknowledge this page.
const char kKnownBackgroundPages[] = "background_pages.known";
-// Dictionary that maps URL schemes (protocols) to URL handlers.
-const char kRegisteredProtocolHandlers[] = "registered_protocol_handlers";
+// List of protocol handlers.
+const char kRegisteredProtocolHandlers[] =
+ "custom_handlers.registered_protocol_handlers";
+
+// List of protocol handlers the user has requested not to be asked about again.
+const char kIgnoredProtocolHandlers[] =
+ "custom_handlers.ignored_protocol_handlers";
+
+// Whether user-specified handlers for protocols and content types can be
+// specified.
+const char kCustomHandlersEnabled[] = "custom_handlers.enabled";
} // namespace prefs
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 32ad145..fd1da77 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -475,6 +475,8 @@ extern const char kGSSAPILibraryName[];
extern const char kKnownBackgroundPages[];
extern const char kRegisteredProtocolHandlers[];
+extern const char kIgnoredProtocolHandlers[];
+extern const char kCustomHandlersEnabled[];
} // namespace prefs
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index cab23da..f426c98 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -292,7 +292,8 @@ void TestingProfile::CreateAutocompleteClassifier() {
}
void TestingProfile::CreateProtocolHandlerRegistry() {
- protocol_handler_registry_ = new ProtocolHandlerRegistry(this);
+ protocol_handler_registry_ = new ProtocolHandlerRegistry(this,
+ new ProtocolHandlerRegistry::Delegate());
}
void TestingProfile::CreateWebDataService(bool delete_file) {