protocol_handler_registry.h revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
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 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
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