summaryrefslogtreecommitdiffstats
path: root/chrome/browser/custom_handlers
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/custom_handlers')
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry.cc273
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry.h66
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry_factory.cc61
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry_factory.h47
-rw-r--r--chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc229
5 files changed, 198 insertions, 478 deletions
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc
index 712f791..5a6dfae 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h"
#include "chrome/browser/net/chrome_url_request_context.h"
@@ -22,30 +21,14 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/notification_service.h"
-#include "grit/generated_resources.h"
#include "net/base/network_delegate.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_redirect_job.h"
-#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
using content::ChildProcessSecurityPolicy;
namespace {
-const ProtocolHandler& LookupHandler(
- const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
- const std::string& scheme) {
- ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p =
- handler_map.find(scheme);
-
- if (p != handler_map.end())
- return p->second;
-
- return ProtocolHandler::EmptyProtocolHandler();
-}
-
// If true default protocol handlers will be removed if the OS level
// registration for a protocol is no longer Chrome.
bool ShouldRemoveHandlersNotInOS() {
@@ -61,165 +44,17 @@ bool ShouldRemoveHandlersNotInOS() {
#endif
}
-void InstallDefaultProtocolHandlers(ProtocolHandlerRegistry* registry) {
- // Only chromeos has default protocol handlers at this point.
- #if defined(OS_CHROMEOS)
- registry->AddPredefinedHandler(
- ProtocolHandler::CreateProtocolHandler(
- "mailto",
- GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_MAILTO_HANDLER_URL)),
- l10n_util::GetStringUTF16(IDS_GOOGLE_MAILTO_HANDLER_NAME)));
- registry->AddPredefinedHandler(
- ProtocolHandler::CreateProtocolHandler(
- "webcal",
- GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_WEBCAL_HANDLER_URL)),
- l10n_util::GetStringUTF16(IDS_GOOGLE_WEBCAL_HANDLER_NAME)));
- #endif
-}
-
-} // namespace
-
-// Core ------------------------------------------------------------------------
-
-// Core is an IO thread specific object. Access to the class should all
-// be done via the IO thread. The registry living on the UI thread makes
-// a best effort to update the IO object after local updates are completed.
-class ProtocolHandlerRegistry::Core
- : public base::RefCountedThreadSafe<ProtocolHandlerRegistry::Core> {
- public:
-
- // Creates a new instance. If |enabled| is true the registry is considered
- // enabled on the IO thread.
- explicit Core(bool enabled);
-
- // Returns true if the protocol has a default protocol handler.
- // Should be called only from the IO thread.
- bool IsHandledProtocol(const std::string& scheme) const;
-
- // Clears the default for the provided protocol.
- // Should be called only from the IO thread.
- void ClearDefault(const std::string& scheme);
-
- // Makes this ProtocolHandler the default handler for its protocol.
- // Should be called only from the IO thread.
- void SetDefault(const ProtocolHandler& handler);
-
- // Creates a URL request job for the given request if there is a matching
- // protocol handler, returns NULL otherwise.
- net::URLRequestJob* MaybeCreateJob(net::URLRequest* request) const;
-
- // Indicate that the registry has been enabled in the IO thread's
- // copy of the data.
- void Enable() { enabled_ = true; }
-
- // Indicate that the registry has been disabled in the IO thread's copy of
- // the data.
- void Disable() { enabled_ = false; }
-
- private:
- friend class base::RefCountedThreadSafe<Core>;
- virtual ~Core();
-
- // Copy of protocol handlers use only on the IO thread.
- ProtocolHandlerRegistry::ProtocolHandlerMap default_handlers_;
-
- // Is the registry enabled on the IO thread.
- bool enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-ProtocolHandlerRegistry::Core::Core(bool) : enabled_(true) {}
-ProtocolHandlerRegistry::Core::~Core() {}
-
-bool ProtocolHandlerRegistry::Core::IsHandledProtocol(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return enabled_ && !LookupHandler(default_handlers_, scheme).IsEmpty();
-}
-
-void ProtocolHandlerRegistry::Core::ClearDefault(const std::string& scheme) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- default_handlers_.erase(scheme);
-}
-
-void ProtocolHandlerRegistry::Core::SetDefault(const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ClearDefault(handler.protocol());
- default_handlers_.insert(std::make_pair(handler.protocol(), handler));
-}
-
-// Create a new job for the supplied |URLRequest| if a default handler
-// is registered and the associated handler is able to interpret
-// the url from |request|.
-net::URLRequestJob* ProtocolHandlerRegistry::Core::MaybeCreateJob(
- net::URLRequest* request) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- ProtocolHandler handler = LookupHandler(default_handlers_,
- request->url().scheme());
- if (handler.IsEmpty())
- return NULL;
-
- GURL translated_url(handler.TranslateUrl(request->url()));
- if (!translated_url.is_valid())
- return NULL;
-
- return new net::URLRequestRedirectJob(request, translated_url);
-}
-
-// URLInterceptor ------------------------------------------------------------
-
-// Instances of this class are produced for ownership by the IO
-// thread where it handler URL requests. We should never hold
-// any pointers on this class, only produce them in response to
-// requests via |ProtocolHandlerRegistry::CreateURLInterceptor|.
-class ProtocolHandlerRegistry::URLInterceptor
- : public net::URLRequestJobFactory::Interceptor {
- public:
- explicit URLInterceptor(Core* core);
- virtual ~URLInterceptor();
-
- virtual net::URLRequestJob* MaybeIntercept(
- net::URLRequest* request) const OVERRIDE;
-
- virtual bool WillHandleProtocol(const std::string& protocol) const OVERRIDE;
-
- virtual net::URLRequestJob* MaybeInterceptRedirect(
- const GURL& url, net::URLRequest* request) const OVERRIDE {
- return NULL;
- }
+} // namespace
- virtual net::URLRequestJob* MaybeInterceptResponse(
- net::URLRequest* request) const OVERRIDE {
- return NULL;
+static const ProtocolHandler& LookupHandler(
+ const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
+ const std::string& scheme) {
+ ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p =
+ handler_map.find(scheme);
+ if (p != handler_map.end()) {
+ return p->second;
}
-
- private:
- scoped_refptr<Core> core_;
- DISALLOW_COPY_AND_ASSIGN(URLInterceptor);
-};
-
-ProtocolHandlerRegistry::URLInterceptor::URLInterceptor(Core* core)
- : core_(core) {
- DCHECK(core_);
-}
-
-ProtocolHandlerRegistry::URLInterceptor::~URLInterceptor() {
-}
-
-net::URLRequestJob* ProtocolHandlerRegistry::URLInterceptor::MaybeIntercept(
- net::URLRequest* request) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- return core_->MaybeCreateJob(request);
-}
-
-bool ProtocolHandlerRegistry::URLInterceptor::WillHandleProtocol(
- const std::string& protocol) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- return core_->IsHandledProtocol(protocol);
+ return ProtocolHandler::EmptyProtocolHandler();
}
// DefaultClientObserver ------------------------------------------------------
@@ -241,7 +76,8 @@ ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() {
registry_->default_client_observers_.erase(iter);
}
-void ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
+void
+ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
ShellIntegration::DefaultWebClientUIState state) {
if (worker_) {
if (ShouldRemoveHandlersNotInOS() &&
@@ -315,9 +151,9 @@ ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
: profile_(profile),
delegate_(delegate),
enabled_(true),
+ enabled_io_(enabled_),
is_loading_(false),
- is_loaded_(false),
- core_(new Core(enabled_)){
+ is_loaded_(false) {
}
bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest(
@@ -397,12 +233,11 @@ ProtocolHandlerRegistry::GetReplacedHandlers(
void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
default_handlers_.erase(scheme);
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&Core::ClearDefault, core_, scheme));
+ base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme));
Save();
NotifyChanged();
}
@@ -413,23 +248,19 @@ bool ProtocolHandlerRegistry::IsDefault(
return GetHandlerFor(handler.protocol()) == handler;
}
-void ProtocolHandlerRegistry::InitProtocolSettings() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // Default protocol handlers must be installed first.
- InstallDefaultProtocolHandlers(this);
-
+void ProtocolHandlerRegistry::Load() {
// Any further default additions to the table will get rejected from now on.
is_loaded_ = true;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
is_loading_ = true;
-
PrefService* prefs = profile_->GetPrefs();
if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) {
- if (prefs->GetBoolean(prefs::kCustomHandlersEnabled)) {
- Enable();
- } else {
- Disable();
- }
+ enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(enabled_ ? &ProtocolHandlerRegistry::EnableIO :
+ &ProtocolHandlerRegistry::DisableIO, this));
}
std::vector<const DictionaryValue*> registered_handlers =
GetHandlersFromPref(prefs::kRegisteredProtocolHandlers);
@@ -597,6 +428,12 @@ bool ProtocolHandlerRegistry::IsHandledProtocol(
return enabled_ && !GetHandlerFor(scheme).IsEmpty();
}
+bool ProtocolHandlerRegistry::IsHandledProtocolIO(
+ const std::string& scheme) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty();
+}
+
void ProtocolHandlerRegistry::RemoveHandler(
const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -615,8 +452,8 @@ void ProtocolHandlerRegistry::RemoveHandler(
} else {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&Core::ClearDefault, core_, q->second.protocol()));
-
+ base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this,
+ q->second.protocol()));
default_handlers_.erase(q);
}
}
@@ -641,6 +478,21 @@ const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
return LookupHandler(default_handlers_, scheme);
}
+net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
+ net::URLRequest* request) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ProtocolHandler handler = LookupHandler(default_handlers_io_,
+ request->url().scheme());
+ if (handler.IsEmpty()) {
+ return NULL;
+ }
+ GURL translated_url(handler.TranslateUrl(request->url()));
+ if (!translated_url.is_valid()) {
+ return NULL;
+ }
+ return new net::URLRequestRedirectJob(request, translated_url);
+}
+
void ProtocolHandlerRegistry::Enable() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (enabled_) {
@@ -650,8 +502,7 @@ void ProtocolHandlerRegistry::Enable() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&Core::Enable, core_));
-
+ base::Bind(&ProtocolHandlerRegistry::EnableIO, this));
ProtocolHandlerMap::const_iterator p;
for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
delegate_->RegisterExternalHandler(p->first);
@@ -669,8 +520,7 @@ void ProtocolHandlerRegistry::Disable() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&Core::Disable, core_));
-
+ base::Bind(&ProtocolHandlerRegistry::DisableIO, this));
ProtocolHandlerMap::const_iterator p;
for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
delegate_->DeregisterExternalHandler(p->first);
@@ -679,7 +529,7 @@ void ProtocolHandlerRegistry::Disable() {
NotifyChanged();
}
-void ProtocolHandlerRegistry::Shutdown() {
+void ProtocolHandlerRegistry::Finalize() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
delegate_.reset(NULL);
// We free these now in case there are any outstanding workers running. If
@@ -703,7 +553,7 @@ void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) {
}
ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(default_client_observers_.empty());
}
@@ -717,6 +567,17 @@ void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) {
list.insert(list.begin(), handler);
}
+void ProtocolHandlerRegistry::ClearDefaultIO(const std::string& scheme) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ default_handlers_io_.erase(scheme);
+}
+
+void ProtocolHandlerRegistry::SetDefaultIO(const ProtocolHandler& handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ClearDefaultIO(handler.protocol());
+ default_handlers_io_.insert(std::make_pair(handler.protocol(), handler));
+}
+
void ProtocolHandlerRegistry::Save() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (is_loading_) {
@@ -757,7 +618,7 @@ void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&Core::SetDefault, core_, handler));
+ base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler));
}
void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
@@ -854,16 +715,10 @@ void ProtocolHandlerRegistry::IgnoreProtocolHandler(
void ProtocolHandlerRegistry::AddPredefinedHandler(
const ProtocolHandler& handler) {
- DCHECK(!is_loaded_); // Must be called prior InitProtocolSettings.
+ // If called after the load command was issued this function will fail.
+ DCHECK(!is_loaded_);
RegisterProtocolHandler(handler);
SetDefault(handler);
}
-net::URLRequestJobFactory::Interceptor*
- ProtocolHandlerRegistry::CreateURLInterceptor() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // this is always created on the UI thread (in profile_io's
- // InitializeOnUIThread. Any method calls must be done
- // on the IO thread (this is checked).
- return new URLInterceptor(core_);
-}
+
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.h b/chrome/browser/custom_handlers/protocol_handler_registry.h
index 82f608db..a74a765 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.h
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.h
@@ -20,18 +20,17 @@
#include "content/public/browser/notification_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory.h"
// This is where handlers for protocols registered with
// navigator.registerProtocolHandler() are registered. Each Profile owns an
// instance of this class, which is initialized on browser start through
// Profile::InitRegisteredProtocolHandlers(), and they should be the only
// instances of this class.
-class ProtocolHandlerRegistry : public ProfileKeyedService {
+class ProtocolHandlerRegistry
+ : public base::RefCountedThreadSafe<
+ ProtocolHandlerRegistry, content::BrowserThread::DeleteOnIOThread> {
public:
- // Provides notification of when the OS level user agent settings
- // are changed.
class DefaultClientObserver
: public ShellIntegration::DefaultWebClientObserver {
public:
@@ -60,9 +59,9 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
DISALLOW_COPY_AND_ASSIGN(DefaultClientObserver);
};
- // |Delegate| provides an interface for interacting asynchronously
- // with the underlying OS for the purposes of registering Chrome
- // as the default handler for specific protocols.
+ // TODO(koz): Refactor this to eliminate the unnecessary virtuals. All that
+ // should be needed is a way to ensure that the list of websafe protocols is
+ // updated.
class Delegate {
public:
virtual ~Delegate();
@@ -84,14 +83,7 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
typedef std::map<std::string, ProtocolHandlerList> ProtocolHandlerMultiMap;
typedef std::vector<DefaultClientObserver*> DefaultClientObserverList;
- // Creates a new instance. Assumes ownership of |delegate|.
ProtocolHandlerRegistry(Profile* profile, Delegate* delegate);
- virtual ~ProtocolHandlerRegistry();
-
- // Returns a net::URLRequestJobFactory::Interceptor suitable
- // for use on the IO thread, but is initialized on the UI thread.
- // Callers assume responsibility for deleting this object.
- net::URLRequestJobFactory::Interceptor* CreateURLInterceptor();
// Called when a site tries to register as a protocol handler. If the request
// can be handled silently by the registry - either to ignore the request
@@ -124,10 +116,8 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// Returns true if this handler is the default handler for its protocol.
bool IsDefault(const ProtocolHandler& handler) const;
- // Initializes default protocol settings and loads them from prefs.
- // This method must be called to complete initialization of the
- // registry after creation, and prior to use.
- void InitProtocolSettings();
+ // Loads a user's registered protocol handlers.
+ void Load();
// Returns the offset in the list of handlers for a protocol of the default
// handler for that protocol.
@@ -165,6 +155,10 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// Returns true if the protocol has a default protocol handler.
bool IsHandledProtocol(const std::string& scheme) const;
+ // Returns true if the protocol has a default protocol handler.
+ // Should be called only from the IO thread.
+ bool IsHandledProtocolIO(const std::string& scheme) const;
+
// Removes the given protocol handler from the registry.
void RemoveHandler(const ProtocolHandler& handler);
@@ -175,6 +169,10 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// exists.
const ProtocolHandler& GetHandlerFor(const std::string& scheme) const;
+ // Creates a URL request job for the given request if there is a matching
+ // 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();
@@ -185,7 +183,7 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// This is called by the UI thread when the system is shutting down. This
// does finalization which must be done on the UI thread.
- virtual void Shutdown() OVERRIDE;
+ void Finalize();
// Registers the preferences that we store registered protocol handlers in.
static void RegisterPrefs(PrefService* prefService);
@@ -203,14 +201,28 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
friend class ProtocolHandlerRegistryTest;
friend class RegisterProtocolHandlerBrowserTest;
- // Forward declaration of the internal implementation classes.
- class Core;
- class URLInterceptor;
+ ~ProtocolHandlerRegistry();
// Puts the given handler at the top of the list of handlers for its
// protocol.
void PromoteHandler(const ProtocolHandler& handler);
+ // Clears the default for the provided protocol.
+ // Should be called only from the IO thread.
+ void ClearDefaultIO(const std::string& scheme);
+
+ // Makes this ProtocolHandler the default handler for its protocol.
+ // Should be called only from the IO thread.
+ void SetDefaultIO(const ProtocolHandler& handler);
+
+ // Indicate that the registry has been enabled in the IO thread's copy of the
+ // data.
+ void EnableIO() { enabled_io_ = true; }
+
+ // Indicate that the registry has been disabled in the IO thread's copy of
+ // the data.
+ void DisableIO() { enabled_io_ = false; }
+
// Saves a user's registered protocol handlers.
void Save();
@@ -265,6 +277,9 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// requests.
bool enabled_;
+ // Copy of enabled_ that is only accessed on the IO thread.
+ bool enabled_io_;
+
// Whether or not we are loading.
bool is_loading_;
@@ -272,12 +287,11 @@ class ProtocolHandlerRegistry : public ProfileKeyedService {
// AddPredefinedHandler will be rejected.
bool is_loaded_;
- // Copy of registry data for use on the IO thread. Changes to the registry
- // are posted to the IO thread where updates are applied to this object.
- scoped_refptr<Core> core_;
-
DefaultClientObserverList default_client_observers_;
+ // Copy of default_handlers_ that is only accessed on the IO thread.
+ ProtocolHandlerMap default_handlers_io_;
+
DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerRegistry);
};
#endif // CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc b/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc
deleted file mode 100644
index 63a3548..0000000
--- a/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 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_factory.h"
-
-#include "base/memory/singleton.h"
-#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
-#include "chrome/browser/extensions/extension_system_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_dependency_manager.h"
-
-// static
-ProtocolHandlerRegistryFactory* ProtocolHandlerRegistryFactory::GetInstance() {
- return Singleton<ProtocolHandlerRegistryFactory>::get();
-}
-
-// static
-ProtocolHandlerRegistry* ProtocolHandlerRegistryFactory::GetForProfile(
- Profile* profile) {
- return static_cast<ProtocolHandlerRegistry*>(
- GetInstance()->GetServiceForProfile(profile, true));
-}
-
-ProtocolHandlerRegistryFactory::ProtocolHandlerRegistryFactory()
- : ProfileKeyedServiceFactory("ProtocolHandlerRegistry",
- ProfileDependencyManager::GetInstance()) {
-}
-
-ProtocolHandlerRegistryFactory::~ProtocolHandlerRegistryFactory() {
-}
-
-// Will be created when initializing profile_io_data, so we might
-// as well have the framework create this along with other
-// PKSs to preserve orderly civic conduct :)
-bool ProtocolHandlerRegistryFactory::ServiceIsCreatedWithProfile() {
- return true;
-}
-
-// Allows the produced registry to be used in incognito mode.
-bool ProtocolHandlerRegistryFactory::ServiceRedirectedInIncognito() {
- return true;
-}
-
-// Do not create this service for tests. MANY tests will fail
-// due to the threading requirements of this service. ALSO,
-// not creating this increases test isolation (which is GOOD!)
-bool ProtocolHandlerRegistryFactory::ServiceIsNULLWhileTesting() {
- return true;
-}
-
-ProfileKeyedService* ProtocolHandlerRegistryFactory::BuildServiceInstanceFor(
- Profile* profile) const {
- ProtocolHandlerRegistry* registry = new ProtocolHandlerRegistry(
- profile, new ProtocolHandlerRegistry::Delegate());
-
- // Must be called as a part of the creation process.
- registry->InitProtocolSettings();
-
- return registry;
-}
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_factory.h b/chrome/browser/custom_handlers/protocol_handler_registry_factory.h
deleted file mode 100644
index 343303f..0000000
--- a/chrome/browser/custom_handlers/protocol_handler_registry_factory.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_FACTORY_H_
-#define CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_FACTORY_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/profiles/profile_keyed_service_factory.h"
-
-class Profile;
-class ProtocolHandlerRegistry;
-template <typename T> struct DefaultSingletonTraits;
-
-// Singleton that owns all ProtocolHandlerRegistrys and associates them with
-// Profiles. Listens for the Profile's destruction notification and cleans up
-// the associated ProtocolHandlerRegistry.
-class ProtocolHandlerRegistryFactory : public ProfileKeyedServiceFactory {
- public:
- // Returns the singleton instance of the ProtocolHandlerRegistryFactory.
- static ProtocolHandlerRegistryFactory* GetInstance();
-
- // Returns the ProtocolHandlerRegistry that provides intent registration for
- // |profile|. Ownership stays with this factory object.
- static ProtocolHandlerRegistry* GetForProfile(Profile* profile);
-
- protected:
- // ProfileKeyedServiceFactory implementation.
- virtual bool ServiceIsCreatedWithProfile() OVERRIDE;
- virtual bool ServiceRedirectedInIncognito() OVERRIDE;
- virtual bool ServiceIsNULLWhileTesting() OVERRIDE;
-
- private:
- friend struct DefaultSingletonTraits<ProtocolHandlerRegistryFactory>;
-
- ProtocolHandlerRegistryFactory();
- virtual ~ProtocolHandlerRegistryFactory();
-
- // ProfileKeyedServiceFactory implementation.
- virtual ProfileKeyedService* BuildServiceInstanceFor(
- Profile* profile) const OVERRIDE;
-
- DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerRegistryFactory);
-};
-
-#endif // CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_FACTORY_H_
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
index 029e99d1..1330661 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -8,7 +8,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/custom_handlers/protocol_handler.h"
@@ -22,56 +21,11 @@
#include "content/public/test/test_renderer_host.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
namespace {
-void AssertInterceptedIO(
- const GURL& url,
- net::URLRequestJobFactory::Interceptor* interceptor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- net::URLRequestContext context;
- net::URLRequest request(url, NULL, &context);
- scoped_refptr<net::URLRequestJob> job = interceptor->MaybeIntercept(&request);
- ASSERT_TRUE(job.get() != NULL);
-}
-
-void AssertIntercepted(
- const GURL& url,
- net::URLRequestJobFactory::Interceptor* interceptor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(AssertInterceptedIO,
- url,
- base::Unretained(interceptor)));
- MessageLoop::current()->RunAllPending();
-}
-
-void AssertWillHandleIO(
- const std::string& scheme,
- bool expected,
- net::URLRequestJobFactory::Interceptor* interceptor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ASSERT_EQ(expected, interceptor->WillHandleProtocol(scheme));
-}
-
-void AssertWillHandle(
- const std::string& scheme,
- bool expected,
- net::URLRequestJobFactory::Interceptor* interceptor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(AssertWillHandleIO,
- scheme,
- expected,
- base::Unretained(interceptor)));
- MessageLoop::current()->RunAllPending();
-}
-
class FakeDelegate : public ProtocolHandlerRegistry::Delegate {
public:
FakeDelegate() : force_os_failure_(false) {}
@@ -220,7 +174,7 @@ class QueryProtocolHandlerOnChange
public:
QueryProtocolHandlerOnChange(Profile* profile,
ProtocolHandlerRegistry* registry)
- : local_registry_(registry),
+ : registry_(registry),
called_(false),
notification_registrar_() {
notification_registrar_.Add(this,
@@ -232,53 +186,26 @@ class QueryProtocolHandlerOnChange
const content::NotificationSource& source,
const content::NotificationDetails& details) {
std::vector<std::string> output;
- local_registry_->GetRegisteredProtocols(&output);
+ registry_->GetRegisteredProtocols(&output);
called_ = true;
}
- ProtocolHandlerRegistry* local_registry_;
+ ProtocolHandlerRegistry* registry_;
bool called_;
content::NotificationRegistrar notification_registrar_;
};
-// URLRequest DCHECKS that the current MessageLoop is IO. It does this because
-// it can't check the thread id (since net can't depend on content.) We want
-// to harness our tests so all threads use the same loop allowing us to
-// guarantee all messages are processed.) By overriding the IsType method
-// we basically ignore the supplied message loop type, and instead infer
-// our type based on the current thread. GO DEPENDENCY INJECTION!
-class TestMessageLoop : public MessageLoop {
- public:
- TestMessageLoop() : MessageLoop(MessageLoop::TYPE_DEFAULT) {}
- ~TestMessageLoop() {}
- virtual bool IsType(MessageLoop::Type type) const OVERRIDE {
- switch (type) {
- case MessageLoop::TYPE_UI:
- return BrowserThread::CurrentlyOn(BrowserThread::UI);
- case MessageLoop::TYPE_IO:
- return BrowserThread::CurrentlyOn(BrowserThread::IO);
- case MessageLoop::TYPE_DEFAULT:
- return !BrowserThread::CurrentlyOn(BrowserThread::UI) &&
- !BrowserThread::CurrentlyOn(BrowserThread::IO);
- }
- return false;
- }
-};
-
} // namespace
class ProtocolHandlerRegistryTest : public testing::Test {
protected:
ProtocolHandlerRegistryTest()
- : ui_thread_(BrowserThread::UI, &loop_),
- file_thread_(BrowserThread::FILE, &loop_),
- io_thread_(BrowserThread::IO, &loop_),
- test_protocol_handler_(CreateProtocolHandler("test", "test")) {}
+ : test_protocol_handler_(CreateProtocolHandler("test", "test")) {}
FakeDelegate* delegate() const { return delegate_; }
- ProtocolHandlerRegistry* registry() { return registry_.get(); }
TestingProfile* profile() const { return profile_.get(); }
PrefService* pref_service() const { return profile_->GetPrefs(); }
+ ProtocolHandlerRegistry* registry() const { return registry_.get(); }
const ProtocolHandler& test_protocol_handler() const {
return test_protocol_handler_;
}
@@ -296,48 +223,68 @@ class ProtocolHandlerRegistryTest : public testing::Test {
name);
}
- void RecreateRegistry(bool initialize) {
- TeadDownRegistry();
- SetUpRegistry(initialize);
- }
-
- // Returns a new registry, initializing it if |initialize| is true.
- // Caller assumes ownership for the object
- void SetUpRegistry(bool initialize) {
+ void ReloadProtocolHandlerRegistry() {
delegate_ = new FakeDelegate();
- registry_.reset(new ProtocolHandlerRegistry(profile(), delegate()));
- if (initialize) registry_->InitProtocolSettings();
+ registry_->Finalize();
+ registry_ = NULL;
+ registry_ = new ProtocolHandlerRegistry(profile(), delegate());
+ registry_->Load();
}
- void TeadDownRegistry() {
- registry_->Shutdown();
- registry_.reset();
- // Registry owns the delegate_ it handles deletion of that object.
+ void ReloadProtocolHandlerRegistryAndInstallDefaultHandler() {
+ delegate_ = new FakeDelegate();
+ registry_->Finalize();
+ registry_ = NULL;
+ registry_ = new ProtocolHandlerRegistry(profile(), delegate());
+ registry_->AddPredefinedHandler(CreateProtocolHandler(
+ "test", GURL("http://test.com/%s"), "Test"));
+ registry_->Load();
}
virtual void SetUp() {
+ ui_message_loop_.reset(new MessageLoopForUI());
+ ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI,
+ MessageLoop::current()));
+ io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO));
+ io_thread_->StartIOThread();
+
+ file_thread_.reset(new content::TestBrowserThread(BrowserThread::FILE));
+ file_thread_->Start();
+
profile_.reset(new TestingProfile());
profile_->SetPrefService(new TestingPrefService());
- SetUpRegistry(true);
+ delegate_ = new FakeDelegate();
+ registry_ = new ProtocolHandlerRegistry(profile(), delegate());
+ registry_->Load();
test_protocol_handler_ =
CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test");
+
ProtocolHandlerRegistry::RegisterPrefs(pref_service());
}
virtual void TearDown() {
- TeadDownRegistry();
+ registry_->Finalize();
+ registry_ = NULL;
+ io_thread_->Stop();
+ io_thread_.reset(NULL);
+ file_thread_->Stop();
+ file_thread_.reset(NULL);
+ ui_thread_.reset(NULL);
+ ui_message_loop_.reset(NULL);
}
- TestMessageLoop loop_;
+ bool enabled_io() {
+ return registry()->enabled_io_;
+ }
- private:
- content::TestBrowserThread ui_thread_;
- content::TestBrowserThread file_thread_;
- content::TestBrowserThread io_thread_;
+ scoped_ptr<MessageLoopForUI> ui_message_loop_;
+ scoped_ptr<content::TestBrowserThread> ui_thread_;
+ scoped_ptr<content::TestBrowserThread> io_thread_;
+ scoped_ptr<content::TestBrowserThread> file_thread_;
+ FakeDelegate* delegate_;
scoped_ptr<TestingProfile> profile_;
- FakeDelegate* delegate_; // Registry assumes ownership of delegate_.
- scoped_ptr<ProtocolHandlerRegistry> registry_;
+ scoped_refptr<ProtocolHandlerRegistry> registry_;
ProtocolHandler test_protocol_handler_;
};
@@ -436,7 +383,7 @@ TEST_F(ProtocolHandlerRegistryTest, SaveAndLoad) {
ASSERT_TRUE(registry()->IsHandledProtocol("test"));
ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler));
delegate()->Reset();
- RecreateRegistry(true);
+ ReloadProtocolHandlerRegistry();
ASSERT_TRUE(registry()->IsHandledProtocol("test"));
ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler));
}
@@ -522,14 +469,14 @@ TEST_F(ProtocolHandlerRegistryTest, TestDefaultSaveLoad) {
registry()->OnAcceptRegisterProtocolHandler(ph2);
registry()->Disable();
- RecreateRegistry(true);
+ ReloadProtocolHandlerRegistry();
ASSERT_FALSE(registry()->enabled());
registry()->Enable();
ASSERT_FALSE(registry()->IsDefault(ph1));
ASSERT_TRUE(registry()->IsDefault(ph2));
- RecreateRegistry(true);
+ ReloadProtocolHandlerRegistry();
ASSERT_TRUE(registry()->enabled());
}
@@ -689,10 +636,6 @@ TEST_F(ProtocolHandlerRegistryTest, TestDisablePreventsHandling) {
ASSERT_FALSE(registry()->IsHandledProtocol("test"));
}
-// TODO(smckay): This is much more appropriately an integration
-// test. Make that so, then update the
-// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully
-// isolate this test from the FILE thread.
TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) {
ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1");
ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2");
@@ -703,7 +646,7 @@ TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) {
registry()->OnAcceptRegisterProtocolHandler(ph_do1);
registry()->OnDenyRegisterProtocolHandler(ph_dont);
- MessageLoop::current()->Run(); // FILE thread needs to run.
+ MessageLoop::current()->Run();
ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do"));
ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont"));
@@ -721,10 +664,6 @@ TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) {
#define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure
#endif
-// TODO(smckay): This is much more appropriately an integration
-// test. Make that so, then update the
-// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully
-// isolate this test from the FILE thread.
TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) {
ProtocolHandler ph_do = CreateProtocolHandler("do", "test1");
ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test");
@@ -733,24 +672,40 @@ TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) {
ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
registry()->OnAcceptRegisterProtocolHandler(ph_do);
- MessageLoop::current()->Run(); // FILE thread needs to run.
+ MessageLoop::current()->Run();
delegate()->set_force_os_failure(true);
registry()->OnAcceptRegisterProtocolHandler(ph_dont);
- MessageLoop::current()->Run(); // FILE thread needs to run.
+ MessageLoop::current()->Run();
ASSERT_TRUE(registry()->IsHandledProtocol("do"));
ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size());
ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size());
}
+static void MakeRequest(const GURL& url, ProtocolHandlerRegistry* registry) {
+ net::URLRequestContext context;
+ net::URLRequest request(url, NULL, &context);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ MessageLoop::QuitClosure());
+ scoped_refptr<net::URLRequestJob> job(registry->MaybeCreateJob(&request));
+ ASSERT_TRUE(job.get() != NULL);
+}
+
TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) {
ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1");
registry()->OnAcceptRegisterProtocolHandler(ph1);
GURL url("mailto:someone@something.com");
- net::URLRequestJobFactory::Interceptor* interceptor =
- registry()->CreateURLInterceptor();
+ scoped_refptr<ProtocolHandlerRegistry> r(registry());
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(MakeRequest, url, r));
+ MessageLoop::current()->Run();
+}
- AssertIntercepted(url, interceptor);
+static void CheckIsHandled(const std::string& scheme, bool expected,
+ ProtocolHandlerRegistry* registry) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ MessageLoop::QuitClosure());
+ ASSERT_EQ(expected, registry->IsHandledProtocolIO(scheme));
}
TEST_F(ProtocolHandlerRegistryTest,
@@ -758,10 +713,11 @@ TEST_F(ProtocolHandlerRegistryTest,
std::string scheme("mailto");
ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1");
registry()->OnAcceptRegisterProtocolHandler(ph1);
- net::URLRequestJobFactory::Interceptor* interceptor =
- registry()->CreateURLInterceptor();
-
- AssertWillHandle(scheme, true, interceptor);
+ scoped_refptr<ProtocolHandlerRegistry> r(registry());
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(CheckIsHandled, scheme, true, r));
}
TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultFallsBackToOldDefault) {
@@ -805,20 +761,26 @@ TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestClearDefaultGetsPropagatedToIO) {
ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1");
registry()->OnAcceptRegisterProtocolHandler(ph1);
registry()->ClearDefault(scheme);
- net::URLRequestJobFactory::Interceptor* interceptor =
- registry()->CreateURLInterceptor();
+ scoped_refptr<ProtocolHandlerRegistry> r(registry());
- AssertWillHandle(scheme, false, interceptor);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(CheckIsHandled, scheme, false, r));
}
-TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) {
- std::string mailto("mailto");
- ProtocolHandler ph1 = CreateProtocolHandler(mailto, "MailtoHandler");
- registry()->OnAcceptRegisterProtocolHandler(ph1);
+static void QuitUILoop() {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ MessageLoop::QuitClosure());
+}
- AssertWillHandle(mailto, true, registry()->CreateURLInterceptor());
+TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) {
registry()->Disable();
- AssertWillHandle(mailto, false, registry()->CreateURLInterceptor());
+ ReloadProtocolHandlerRegistry();
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(QuitUILoop));
+ MessageLoop::current()->Run();
+ ASSERT_FALSE(enabled_io());
}
TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) {
@@ -882,10 +844,7 @@ TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) {
}
TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestInstallDefaultHandler) {
- RecreateRegistry(false);
- registry()->AddPredefinedHandler(CreateProtocolHandler(
- "test", GURL("http://test.com/%s"), "Test"));
- registry()->InitProtocolSettings();
+ ReloadProtocolHandlerRegistryAndInstallDefaultHandler();
std::vector<std::string> protocols;
registry()->GetRegisteredProtocols(&protocols);
ASSERT_EQ(static_cast<size_t>(1), protocols.size());