protocol_handler_registry.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_ 6#define CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_ 7 8#include <map> 9#include <string> 10#include <vector> 11 12#include "base/basictypes.h" 13#include "base/memory/ref_counted.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/sequenced_task_runner_helpers.h" 16#include "base/values.h" 17#include "chrome/browser/profiles/profile.h" 18#include "chrome/browser/profiles/profile_keyed_service.h" 19#include "chrome/browser/shell_integration.h" 20#include "chrome/common/custom_handlers/protocol_handler.h" 21#include "content/public/browser/browser_thread.h" 22#include "content/public/browser/notification_service.h" 23#include "net/url_request/url_request.h" 24#include "net/url_request/url_request_job.h" 25#include "net/url_request/url_request_job_factory.h" 26 27namespace user_prefs { 28class PrefRegistrySyncable; 29} 30 31// This is where handlers for protocols registered with 32// navigator.registerProtocolHandler() are registered. Each Profile owns an 33// instance of this class, which is initialized on browser start through 34// Profile::InitRegisteredProtocolHandlers(), and they should be the only 35// instances of this class. 36class ProtocolHandlerRegistry : public ProfileKeyedService { 37 38 public: 39 // Provides notification of when the OS level user agent settings 40 // are changed. 41 class DefaultClientObserver 42 : public ShellIntegration::DefaultWebClientObserver { 43 public: 44 explicit DefaultClientObserver(ProtocolHandlerRegistry* registry); 45 virtual ~DefaultClientObserver(); 46 47 // Get response from the worker regarding whether Chrome is the default 48 // handler for the protocol. 49 virtual void SetDefaultWebClientUIState( 50 ShellIntegration::DefaultWebClientUIState state) OVERRIDE; 51 52 virtual bool IsInteractiveSetDefaultPermitted() OVERRIDE; 53 54 // Give the observer a handle to the worker, so we can find out the protocol 55 // when we're called and also tell the worker if we get deleted. 56 void SetWorker(ShellIntegration::DefaultProtocolClientWorker* worker); 57 58 protected: 59 ShellIntegration::DefaultProtocolClientWorker* worker_; 60 61 private: 62 virtual bool IsOwnedByWorker() OVERRIDE; 63 64 // This is a raw pointer, not reference counted, intentionally. In general 65 // subclasses of DefaultWebClientObserver are not able to be refcounted 66 // e.g. the browser options page 67 ProtocolHandlerRegistry* registry_; 68 69 DISALLOW_COPY_AND_ASSIGN(DefaultClientObserver); 70 }; 71 72 // |Delegate| provides an interface for interacting asynchronously 73 // with the underlying OS for the purposes of registering Chrome 74 // as the default handler for specific protocols. 75 class Delegate { 76 public: 77 virtual ~Delegate(); 78 virtual void RegisterExternalHandler(const std::string& protocol); 79 virtual void DeregisterExternalHandler(const std::string& protocol); 80 virtual bool IsExternalHandlerRegistered(const std::string& protocol); 81 virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker( 82 ShellIntegration::DefaultWebClientObserver* observer, 83 const std::string& protocol); 84 virtual DefaultClientObserver* CreateShellObserver( 85 ProtocolHandlerRegistry* registry); 86 virtual void RegisterWithOSAsDefaultClient( 87 const std::string& protocol, 88 ProtocolHandlerRegistry* registry); 89 }; 90 91 // Forward declaration of the internal implementation class. 92 class IOThreadDelegate; 93 94 // JobInterceptorFactory intercepts URLRequestJob creation for URLRequests the 95 // ProtocolHandlerRegistry is registered to handle. When no handler is 96 // registered, the URLRequest is passed along to the chained 97 // URLRequestJobFactory (set with |JobInterceptorFactory::Chain|). 98 // JobInterceptorFactory's are created via 99 // |ProtocolHandlerRegistry::CreateJobInterceptorFactory|. 100 class JobInterceptorFactory : public net::URLRequestJobFactory { 101 public: 102 // |io_thread_delegate| is used to perform actual job creation work. 103 explicit JobInterceptorFactory(IOThreadDelegate* io_thread_delegate); 104 virtual ~JobInterceptorFactory(); 105 106 // |job_factory| is set as the URLRequestJobFactory where requests are 107 // forwarded if JobInterceptorFactory decides to pass on them. 108 void Chain(scoped_ptr<net::URLRequestJobFactory> job_factory); 109 110 // URLRequestJobFactory implementation. 111 virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler( 112 const std::string& scheme, 113 net::URLRequest* request, 114 net::NetworkDelegate* network_delegate) const OVERRIDE; 115 virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE; 116 virtual bool IsHandledURL(const GURL& url) const OVERRIDE; 117 118 private: 119 // When JobInterceptorFactory decides to pass on particular requests, 120 // they're forwarded to the chained URLRequestJobFactory, |job_factory_|. 121 scoped_ptr<URLRequestJobFactory> job_factory_; 122 // |io_thread_delegate_| performs the actual job creation decisions by 123 // mirroring the ProtocolHandlerRegistry on the IO thread. 124 scoped_refptr<IOThreadDelegate> io_thread_delegate_; 125 126 DISALLOW_COPY_AND_ASSIGN(JobInterceptorFactory); 127 }; 128 129 typedef std::map<std::string, ProtocolHandler> ProtocolHandlerMap; 130 typedef std::vector<ProtocolHandler> ProtocolHandlerList; 131 typedef std::map<std::string, ProtocolHandlerList> ProtocolHandlerMultiMap; 132 typedef std::vector<DefaultClientObserver*> DefaultClientObserverList; 133 134 // Creates a new instance. Assumes ownership of |delegate|. 135 ProtocolHandlerRegistry(Profile* profile, Delegate* delegate); 136 virtual ~ProtocolHandlerRegistry(); 137 138 // Returns a net::URLRequestJobFactory suitable for use on the IO thread, but 139 // is initialized on the UI thread. 140 scoped_ptr<JobInterceptorFactory> CreateJobInterceptorFactory(); 141 142 // Called when a site tries to register as a protocol handler. If the request 143 // can be handled silently by the registry - either to ignore the request 144 // or to update an existing handler - the request will succeed. If this 145 // function returns false the user needs to be prompted for confirmation. 146 bool SilentlyHandleRegisterHandlerRequest(const ProtocolHandler& handler); 147 148 // Called when the user accepts the registration of a given protocol handler. 149 void OnAcceptRegisterProtocolHandler(const ProtocolHandler& handler); 150 151 // Called when the user denies the registration of a given protocol handler. 152 void OnDenyRegisterProtocolHandler(const ProtocolHandler& handler); 153 154 // Called when the user indicates that they don't want to be asked about the 155 // given protocol handler again. 156 void OnIgnoreRegisterProtocolHandler(const ProtocolHandler& handler); 157 158 // Removes all handlers that have the same origin and protocol as the given 159 // one and installs the given handler. Returns true if any protocol handlers 160 // were replaced. 161 bool AttemptReplace(const ProtocolHandler& handler); 162 163 // Returns a list of protocol handlers that can be replaced by the given 164 // handler. 165 ProtocolHandlerList GetReplacedHandlers(const ProtocolHandler& handler) const; 166 167 // Clears the default for the provided protocol. 168 void ClearDefault(const std::string& scheme); 169 170 // Returns true if this handler is the default handler for its protocol. 171 bool IsDefault(const ProtocolHandler& handler) const; 172 173 // Initializes default protocol settings and loads them from prefs. 174 // This method must be called to complete initialization of the 175 // registry after creation, and prior to use. 176 void InitProtocolSettings(); 177 178 // Returns the offset in the list of handlers for a protocol of the default 179 // handler for that protocol. 180 int GetHandlerIndex(const std::string& scheme) const; 181 182 // Get the list of protocol handlers for the given scheme. 183 ProtocolHandlerList GetHandlersFor(const std::string& scheme) const; 184 185 // Get the list of ignored protocol handlers. 186 ProtocolHandlerList GetIgnoredHandlers(); 187 188 // Yields a list of the protocols that have handlers registered in this 189 // registry. 190 void GetRegisteredProtocols(std::vector<std::string>* output) const; 191 192 // Returns true if we allow websites to register handlers for the given 193 // scheme. 194 bool CanSchemeBeOverridden(const std::string& scheme) const; 195 196 // Returns true if an identical protocol handler has already been registered. 197 bool IsRegistered(const ProtocolHandler& handler) const; 198 199 // Returns true if an identical protocol handler is being ignored. 200 bool IsIgnored(const ProtocolHandler& handler) const; 201 202 // Returns true if an equivalent protocol handler has already been registered. 203 bool HasRegisteredEquivalent(const ProtocolHandler& handler) const; 204 205 // Returns true if an equivalent protocol handler is being ignored. 206 bool HasIgnoredEquivalent(const ProtocolHandler& handler) const; 207 208 // Causes the given protocol handler to not be ignored anymore. 209 void RemoveIgnoredHandler(const ProtocolHandler& handler); 210 211 // Returns true if the protocol has a default protocol handler. 212 bool IsHandledProtocol(const std::string& scheme) const; 213 214 // Removes the given protocol handler from the registry. 215 void RemoveHandler(const ProtocolHandler& handler); 216 217 // Remove the default handler for the given protocol. 218 void RemoveDefaultHandler(const std::string& scheme); 219 220 // Returns the default handler for this protocol, or an empty handler if none 221 // exists. 222 const ProtocolHandler& GetHandlerFor(const std::string& scheme) const; 223 224 // Puts this registry in the enabled state - registered protocol handlers 225 // will handle requests. 226 void Enable(); 227 228 // Puts this registry in the disabled state - registered protocol handlers 229 // will not handle requests. 230 void Disable(); 231 232 // This is called by the UI thread when the system is shutting down. This 233 // does finalization which must be done on the UI thread. 234 virtual void Shutdown() OVERRIDE; 235 236 // Registers the preferences that we store registered protocol handlers in. 237 static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry); 238 239 bool enabled() const { return enabled_; } 240 241 // Add a predefined protocol handler. This has to be called before the first 242 // load command was issued, otherwise the command will be ignored. 243 void AddPredefinedHandler(const ProtocolHandler& handler); 244 245 private: 246 friend class base::DeleteHelper<ProtocolHandlerRegistry>; 247 friend struct content::BrowserThread::DeleteOnThread< 248 content::BrowserThread::IO>; 249 250 // for access to InstallDefaultsForChromeOS 251 friend class ProtocolHandlerRegistryFactory; 252 253 friend class ProtocolHandlerRegistryTest; 254 friend class RegisterProtocolHandlerBrowserTest; 255 256 // Puts the given handler at the top of the list of handlers for its 257 // protocol. 258 void PromoteHandler(const ProtocolHandler& handler); 259 260 // Saves a user's registered protocol handlers. 261 void Save(); 262 263 // Returns a pointer to the list of handlers registered for the given scheme, 264 // or NULL if there are none. 265 const ProtocolHandlerList* GetHandlerList(const std::string& scheme) const; 266 267 // Install default protocol handlers for chromeos which must be done 268 // prior to calling InitProtocolSettings. 269 void InstallDefaultsForChromeOS(); 270 271 // Makes this ProtocolHandler the default handler for its protocol. 272 void SetDefault(const ProtocolHandler& handler); 273 274 // Insert the given ProtocolHandler into the registry. 275 void InsertHandler(const ProtocolHandler& handler); 276 277 // Returns a JSON list of protocol handlers. The caller is responsible for 278 // deleting this Value. 279 Value* EncodeRegisteredHandlers(); 280 281 // Returns a JSON list of ignored protocol handlers. The caller is 282 // responsible for deleting this Value. 283 Value* EncodeIgnoredHandlers(); 284 285 // Sends a notification of the given type to the NotificationService. 286 void NotifyChanged(); 287 288 // Registers a new protocol handler. 289 void RegisterProtocolHandler(const ProtocolHandler& handler); 290 291 // Get the DictionaryValues stored under the given pref name that are valid 292 // ProtocolHandler values. 293 std::vector<const DictionaryValue*> GetHandlersFromPref( 294 const char* pref_name) const; 295 296 // Ignores future requests to register the given protocol handler. 297 void IgnoreProtocolHandler(const ProtocolHandler& handler); 298 299 // Map from protocols (strings) to protocol handlers. 300 ProtocolHandlerMultiMap protocol_handlers_; 301 302 // Protocol handlers that the user has told us to ignore. 303 ProtocolHandlerList ignored_protocol_handlers_; 304 305 // Protocol handlers that are the defaults for a given protocol. 306 ProtocolHandlerMap default_handlers_; 307 308 // The Profile that owns this ProtocolHandlerRegistry. 309 Profile* profile_; 310 311 // The Delegate that registers / deregisters external handlers on our behalf. 312 scoped_ptr<Delegate> delegate_; 313 314 // If false then registered protocol handlers will not be used to handle 315 // requests. 316 bool enabled_; 317 318 // Whether or not we are loading. 319 bool is_loading_; 320 321 // When the table gets loaded this flag will be set and any further calls to 322 // AddPredefinedHandler will be rejected. 323 bool is_loaded_; 324 325 // Copy of registry data for use on the IO thread. Changes to the registry 326 // are posted to the IO thread where updates are applied to this object. 327 scoped_refptr<IOThreadDelegate> io_thread_delegate_; 328 329 DefaultClientObserverList default_client_observers_; 330 331 DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerRegistry); 332}; 333#endif // CHROME_BROWSER_CUSTOM_HANDLERS_PROTOCOL_HANDLER_REGISTRY_H_ 334