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