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