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