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