| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" |    5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" | 
|    6  |    6  | 
|    7 #include <utility> |    7 #include <utility> | 
|    8  |    8  | 
|    9 #include "base/bind.h" |    9 #include "base/bind.h" | 
|   10 #include "base/command_line.h" |   10 #include "base/command_line.h" | 
|   11 #include "base/logging.h" |   11 #include "base/logging.h" | 
 |   12 #include "base/memory/ref_counted.h" | 
|   12 #include "base/memory/scoped_ptr.h" |   13 #include "base/memory/scoped_ptr.h" | 
|   13 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg
     ate.h" |   14 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg
     ate.h" | 
|   14 #include "chrome/browser/net/chrome_url_request_context.h" |   15 #include "chrome/browser/net/chrome_url_request_context.h" | 
|   15 #include "chrome/browser/prefs/pref_service.h" |   16 #include "chrome/browser/prefs/pref_service.h" | 
|   16 #include "chrome/browser/profiles/profile_io_data.h" |   17 #include "chrome/browser/profiles/profile_io_data.h" | 
|   17 #include "chrome/common/chrome_notification_types.h" |   18 #include "chrome/common/chrome_notification_types.h" | 
|   18 #include "chrome/common/chrome_switches.h" |   19 #include "chrome/common/chrome_switches.h" | 
|   19 #include "chrome/common/custom_handlers/protocol_handler.h" |   20 #include "chrome/common/custom_handlers/protocol_handler.h" | 
|   20 #include "chrome/common/pref_names.h" |   21 #include "chrome/common/pref_names.h" | 
|   21 #include "content/public/browser/browser_thread.h" |   22 #include "content/public/browser/browser_thread.h" | 
|   22 #include "content/public/browser/child_process_security_policy.h" |   23 #include "content/public/browser/child_process_security_policy.h" | 
|   23 #include "content/public/browser/notification_service.h" |   24 #include "content/public/browser/notification_service.h" | 
 |   25 #include "grit/generated_resources.h" | 
|   24 #include "net/base/network_delegate.h" |   26 #include "net/base/network_delegate.h" | 
 |   27 #include "net/url_request/url_request.h" | 
 |   28 #include "net/url_request/url_request_job.h" | 
|   25 #include "net/url_request/url_request_redirect_job.h" |   29 #include "net/url_request/url_request_redirect_job.h" | 
 |   30 #include "ui/base/l10n/l10n_util.h" | 
|   26  |   31  | 
|   27 using content::BrowserThread; |   32 using content::BrowserThread; | 
|   28 using content::ChildProcessSecurityPolicy; |   33 using content::ChildProcessSecurityPolicy; | 
|   29  |   34  | 
|   30 namespace { |   35 namespace { | 
|   31  |   36  | 
 |   37 const ProtocolHandler& LookupHandler( | 
 |   38     const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, | 
 |   39     const std::string& scheme) { | 
 |   40   ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = | 
 |   41       handler_map.find(scheme); | 
 |   42  | 
 |   43   if (p != handler_map.end()) | 
 |   44     return p->second; | 
 |   45  | 
 |   46   return ProtocolHandler::EmptyProtocolHandler(); | 
 |   47 } | 
 |   48  | 
|   32 // If true default protocol handlers will be removed if the OS level |   49 // If true default protocol handlers will be removed if the OS level | 
|   33 // registration for a protocol is no longer Chrome. |   50 // registration for a protocol is no longer Chrome. | 
|   34 bool ShouldRemoveHandlersNotInOS() { |   51 bool ShouldRemoveHandlersNotInOS() { | 
|   35 #if defined(OS_LINUX) |   52 #if defined(OS_LINUX) | 
|   36   // We don't do this on Linux as the OS registration there is not reliable, |   53   // We don't do this on Linux as the OS registration there is not reliable, | 
|   37   // and Chrome OS doesn't have any notion of OS registration. |   54   // and Chrome OS doesn't have any notion of OS registration. | 
|   38   // TODO(benwells): When Linux support is more reliable remove this |   55   // TODO(benwells): When Linux support is more reliable remove this | 
|   39   // difference (http://crbug.com/88255). |   56   // difference (http://crbug.com/88255). | 
|   40   return false; |   57   return false; | 
|   41 #else |   58 #else | 
|   42   return ShellIntegration::CanSetAsDefaultProtocolClient() != |   59   return ShellIntegration::CanSetAsDefaultProtocolClient() != | 
|   43       ShellIntegration::SET_DEFAULT_NOT_ALLOWED; |   60       ShellIntegration::SET_DEFAULT_NOT_ALLOWED; | 
|   44 #endif |   61 #endif | 
|   45 } |   62 } | 
|   46  |   63  | 
|   47 } // namespace |   64 }  // namespace | 
|   48  |   65  | 
|   49 static const ProtocolHandler& LookupHandler( |   66 // Core ------------------------------------------------------------------------ | 
|   50     const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, |   67  | 
|   51     const std::string& scheme) { |   68 // Core is an IO thread specific object. Access to the class should all | 
|   52   ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = |   69 // be done via the IO thread. The registry living on the UI thread makes | 
|   53       handler_map.find(scheme); |   70 // a best effort to update the IO object after local updates are completed. | 
|   54   if (p != handler_map.end()) { |   71 class ProtocolHandlerRegistry::Core | 
|   55     return p->second; |   72     : public base::RefCountedThreadSafe<ProtocolHandlerRegistry::Core> { | 
 |   73  public: | 
 |   74  | 
 |   75   // Creates a new instance. If |enabled| is true the registry is considered | 
 |   76   // enabled on the IO thread. | 
 |   77   explicit Core(bool enabled); | 
 |   78  | 
 |   79   // Returns true if the protocol has a default protocol handler. | 
 |   80   // Should be called only from the IO thread. | 
 |   81   bool IsHandledProtocol(const std::string& scheme) const; | 
 |   82  | 
 |   83   // Clears the default for the provided protocol. | 
 |   84   // Should be called only from the IO thread. | 
 |   85   void ClearDefault(const std::string& scheme); | 
 |   86  | 
 |   87   // Makes this ProtocolHandler the default handler for its protocol. | 
 |   88   // Should be called only from the IO thread. | 
 |   89   void SetDefault(const ProtocolHandler& handler); | 
 |   90  | 
 |   91   // Creates a URL request job for the given request if there is a matching | 
 |   92   // protocol handler, returns NULL otherwise. | 
 |   93   net::URLRequestJob* MaybeCreateJob(net::URLRequest* request) const; | 
 |   94  | 
 |   95   // Indicate that the registry has been enabled in the IO thread's | 
 |   96   // copy of the data. | 
 |   97   void Enable() { enabled_ = true; } | 
 |   98  | 
 |   99   // Indicate that the registry has been disabled in the IO thread's copy of | 
 |  100   // the data. | 
 |  101   void Disable() { enabled_ = false; } | 
 |  102  | 
 |  103  private: | 
 |  104   friend class base::RefCountedThreadSafe<Core>; | 
 |  105   virtual ~Core(); | 
 |  106  | 
 |  107   // Copy of protocol handlers use only on the IO thread. | 
 |  108   ProtocolHandlerRegistry::ProtocolHandlerMap default_handlers_; | 
 |  109  | 
 |  110   // Is the registry enabled on the IO thread. | 
 |  111   bool enabled_; | 
 |  112  | 
 |  113   DISALLOW_COPY_AND_ASSIGN(Core); | 
 |  114 }; | 
 |  115  | 
 |  116 ProtocolHandlerRegistry::Core::Core(bool) : enabled_(true) {} | 
 |  117 ProtocolHandlerRegistry::Core::~Core() {} | 
 |  118  | 
 |  119 bool ProtocolHandlerRegistry::Core::IsHandledProtocol( | 
 |  120     const std::string& scheme) const { | 
 |  121   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  122   return enabled_ && !LookupHandler(default_handlers_, scheme).IsEmpty(); | 
 |  123 } | 
 |  124  | 
 |  125 void ProtocolHandlerRegistry::Core::ClearDefault(const std::string& scheme) { | 
 |  126   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  127   default_handlers_.erase(scheme); | 
 |  128 } | 
 |  129  | 
 |  130 void ProtocolHandlerRegistry::Core::SetDefault(const ProtocolHandler& handler) { | 
 |  131   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  132   ClearDefault(handler.protocol()); | 
 |  133   default_handlers_.insert(std::make_pair(handler.protocol(), handler)); | 
 |  134 } | 
 |  135  | 
 |  136 // Create a new job for the supplied |URLRequest| if a default handler | 
 |  137 // is registered and the associated handler is able to interpret | 
 |  138 // the url from |request|. | 
 |  139 net::URLRequestJob* ProtocolHandlerRegistry::Core::MaybeCreateJob( | 
 |  140     net::URLRequest* request) const { | 
 |  141   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  142  | 
 |  143   ProtocolHandler handler = LookupHandler(default_handlers_, | 
 |  144                                           request->url().scheme()); | 
 |  145   if (handler.IsEmpty()) | 
 |  146     return NULL; | 
 |  147  | 
 |  148   GURL translated_url(handler.TranslateUrl(request->url())); | 
 |  149   if (!translated_url.is_valid()) | 
 |  150     return NULL; | 
 |  151  | 
 |  152   return new net::URLRequestRedirectJob(request, translated_url); | 
 |  153 } | 
 |  154  | 
 |  155 // URLInterceptor ------------------------------------------------------------ | 
 |  156  | 
 |  157 // Instances of this class are produced for ownership by the IO | 
 |  158 // thread where it handler URL requests. We should never hold | 
 |  159 // any pointers on this class, only produce them in response to | 
 |  160 // requests via |ProtocolHandlerRegistry::CreateURLInterceptor|. | 
 |  161 class ProtocolHandlerRegistry::URLInterceptor | 
 |  162     : public net::URLRequestJobFactory::Interceptor { | 
 |  163  public: | 
 |  164   explicit URLInterceptor(Core* core); | 
 |  165   virtual ~URLInterceptor(); | 
 |  166  | 
 |  167   virtual net::URLRequestJob* MaybeIntercept( | 
 |  168       net::URLRequest* request) const OVERRIDE; | 
 |  169  | 
 |  170   virtual bool WillHandleProtocol(const std::string& protocol) const OVERRIDE; | 
 |  171  | 
 |  172   virtual net::URLRequestJob* MaybeInterceptRedirect( | 
 |  173       const GURL& url, net::URLRequest* request) const OVERRIDE { | 
 |  174     return NULL; | 
|   56   } |  175   } | 
|   57   return ProtocolHandler::EmptyProtocolHandler(); |  176  | 
 |  177   virtual net::URLRequestJob* MaybeInterceptResponse( | 
 |  178       net::URLRequest* request) const OVERRIDE { | 
 |  179     return NULL; | 
 |  180   } | 
 |  181  | 
 |  182  private: | 
 |  183   scoped_refptr<Core> core_; | 
 |  184   DISALLOW_COPY_AND_ASSIGN(URLInterceptor); | 
 |  185 }; | 
 |  186  | 
 |  187 ProtocolHandlerRegistry::URLInterceptor::URLInterceptor(Core* core) | 
 |  188     : core_(core) { | 
 |  189   DCHECK(core_); | 
 |  190 } | 
 |  191  | 
 |  192 ProtocolHandlerRegistry::URLInterceptor::~URLInterceptor() { | 
 |  193 } | 
 |  194  | 
 |  195 net::URLRequestJob* ProtocolHandlerRegistry::URLInterceptor::MaybeIntercept( | 
 |  196     net::URLRequest* request) const { | 
 |  197   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  198  | 
 |  199   return core_->MaybeCreateJob(request); | 
 |  200 } | 
 |  201  | 
 |  202 bool ProtocolHandlerRegistry::URLInterceptor::WillHandleProtocol( | 
 |  203     const std::string& protocol) const { | 
 |  204   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
 |  205  | 
 |  206   return core_->IsHandledProtocol(protocol); | 
|   58 } |  207 } | 
|   59  |  208  | 
|   60 // DefaultClientObserver ------------------------------------------------------ |  209 // DefaultClientObserver ------------------------------------------------------ | 
|   61  |  210  | 
|   62 ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver( |  211 ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver( | 
|   63     ProtocolHandlerRegistry* registry) |  212     ProtocolHandlerRegistry* registry) | 
|   64     : worker_(NULL), |  213     : worker_(NULL), | 
|   65       registry_(registry) { |  214       registry_(registry) { | 
|   66   DCHECK(registry_); |  215   DCHECK(registry_); | 
|   67 } |  216 } | 
|   68  |  217  | 
|   69 ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() { |  218 ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() { | 
|   70   if (worker_) |  219   if (worker_) | 
|   71     worker_->ObserverDestroyed(); |  220     worker_->ObserverDestroyed(); | 
|   72  |  221  | 
|   73   DefaultClientObserverList::iterator iter = std::find( |  222   DefaultClientObserverList::iterator iter = std::find( | 
|   74       registry_->default_client_observers_.begin(), |  223       registry_->default_client_observers_.begin(), | 
|   75       registry_->default_client_observers_.end(), this); |  224       registry_->default_client_observers_.end(), this); | 
|   76   registry_->default_client_observers_.erase(iter); |  225   registry_->default_client_observers_.erase(iter); | 
|   77 } |  226 } | 
|   78  |  227  | 
|   79 void |  228 void ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( | 
|   80 ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( |  | 
|   81     ShellIntegration::DefaultWebClientUIState state) { |  229     ShellIntegration::DefaultWebClientUIState state) { | 
|   82   if (worker_) { |  230   if (worker_) { | 
|   83     if (ShouldRemoveHandlersNotInOS() && |  231     if (ShouldRemoveHandlersNotInOS() && | 
|   84         (state == ShellIntegration::STATE_NOT_DEFAULT)) { |  232         (state == ShellIntegration::STATE_NOT_DEFAULT)) { | 
|   85       registry_->ClearDefault(worker_->protocol()); |  233       registry_->ClearDefault(worker_->protocol()); | 
|   86     } |  234     } | 
|   87   } else { |  235   } else { | 
|   88     NOTREACHED(); |  236     NOTREACHED(); | 
|   89   } |  237   } | 
|   90 } |  238 } | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  144   worker->StartSetAsDefault(); |  292   worker->StartSetAsDefault(); | 
|  145 } |  293 } | 
|  146  |  294  | 
|  147 // ProtocolHandlerRegistry ----------------------------------------------------- |  295 // ProtocolHandlerRegistry ----------------------------------------------------- | 
|  148  |  296  | 
|  149 ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile, |  297 ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile, | 
|  150     Delegate* delegate) |  298     Delegate* delegate) | 
|  151     : profile_(profile), |  299     : profile_(profile), | 
|  152       delegate_(delegate), |  300       delegate_(delegate), | 
|  153       enabled_(true), |  301       enabled_(true), | 
|  154       enabled_io_(enabled_), |  | 
|  155       is_loading_(false), |  302       is_loading_(false), | 
|  156       is_loaded_(false) { |  303       is_loaded_(false), | 
 |  304       core_(new Core(enabled_)){ | 
|  157 } |  305 } | 
|  158  |  306  | 
|  159 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( |  307 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( | 
|  160     const ProtocolHandler& handler) { |  308     const ProtocolHandler& handler) { | 
|  161   if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol())) |  309   if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol())) | 
|  162     return true; |  310     return true; | 
|  163  |  311  | 
|  164   if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler)) |  312   if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler)) | 
|  165     return true; |  313     return true; | 
|  166  |  314  | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  226        p != handlers->end(); p++) { |  374        p != handlers->end(); p++) { | 
|  227     if (handler.IsSameOrigin(*p)) { |  375     if (handler.IsSameOrigin(*p)) { | 
|  228       replaced_handlers.push_back(*p); |  376       replaced_handlers.push_back(*p); | 
|  229     } |  377     } | 
|  230   } |  378   } | 
|  231   return replaced_handlers; |  379   return replaced_handlers; | 
|  232 } |  380 } | 
|  233  |  381  | 
|  234 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) { |  382 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) { | 
|  235   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  383   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  384  | 
|  236   default_handlers_.erase(scheme); |  385   default_handlers_.erase(scheme); | 
|  237   BrowserThread::PostTask( |  386   BrowserThread::PostTask( | 
|  238       BrowserThread::IO, |  387       BrowserThread::IO, | 
|  239       FROM_HERE, |  388       FROM_HERE, | 
|  240       base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme)); |  389       base::Bind(&Core::ClearDefault, core_, scheme)); | 
|  241   Save(); |  390   Save(); | 
|  242   NotifyChanged(); |  391   NotifyChanged(); | 
|  243 } |  392 } | 
|  244  |  393  | 
|  245 bool ProtocolHandlerRegistry::IsDefault( |  394 bool ProtocolHandlerRegistry::IsDefault( | 
|  246     const ProtocolHandler& handler) const { |  395     const ProtocolHandler& handler) const { | 
|  247   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  396   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  248   return GetHandlerFor(handler.protocol()) == handler; |  397   return GetHandlerFor(handler.protocol()) == handler; | 
|  249 } |  398 } | 
|  250  |  399  | 
|  251 void ProtocolHandlerRegistry::Load() { |  400 void ProtocolHandlerRegistry::InstallDefaultsForChromeOS() { | 
 |  401 #if defined(OS_CHROMEOS) | 
 |  402   // Only chromeos has default protocol handlers at this point. | 
 |  403   AddPredefinedHandler( | 
 |  404       ProtocolHandler::CreateProtocolHandler( | 
 |  405           "mailto", | 
 |  406           GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_MAILTO_HANDLER_URL)), | 
 |  407           l10n_util::GetStringUTF16(IDS_GOOGLE_MAILTO_HANDLER_NAME))); | 
 |  408   AddPredefinedHandler( | 
 |  409       ProtocolHandler::CreateProtocolHandler( | 
 |  410           "webcal", | 
 |  411           GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_WEBCAL_HANDLER_URL)), | 
 |  412           l10n_util::GetStringUTF16(IDS_GOOGLE_WEBCAL_HANDLER_NAME))); | 
 |  413 #else | 
 |  414   NOTREACHED();  // this method should only ever be called in chromeos. | 
 |  415 #endif | 
 |  416 } | 
 |  417  | 
 |  418 void ProtocolHandlerRegistry::InitProtocolSettings() { | 
 |  419   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  420  | 
|  252   // Any further default additions to the table will get rejected from now on. |  421   // Any further default additions to the table will get rejected from now on. | 
|  253   is_loaded_ = true; |  422   is_loaded_ = true; | 
|  254   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  | 
|  255   is_loading_ = true; |  423   is_loading_ = true; | 
 |  424  | 
|  256   PrefService* prefs = profile_->GetPrefs(); |  425   PrefService* prefs = profile_->GetPrefs(); | 
|  257   if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { |  426   if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { | 
|  258     enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled); |  427     if (prefs->GetBoolean(prefs::kCustomHandlersEnabled)) { | 
|  259     BrowserThread::PostTask( |  428       Enable(); | 
|  260         BrowserThread::IO, |  429     } else { | 
|  261         FROM_HERE, |  430       Disable(); | 
|  262         base::Bind(enabled_ ? &ProtocolHandlerRegistry::EnableIO : |  431     } | 
|  263                    &ProtocolHandlerRegistry::DisableIO, this)); |  | 
|  264   } |  432   } | 
|  265   std::vector<const DictionaryValue*> registered_handlers = |  433   std::vector<const DictionaryValue*> registered_handlers = | 
|  266       GetHandlersFromPref(prefs::kRegisteredProtocolHandlers); |  434       GetHandlersFromPref(prefs::kRegisteredProtocolHandlers); | 
|  267   for (std::vector<const DictionaryValue*>::const_iterator p = |  435   for (std::vector<const DictionaryValue*>::const_iterator p = | 
|  268        registered_handlers.begin(); |  436        registered_handlers.begin(); | 
|  269        p != registered_handlers.end(); ++p) { |  437        p != registered_handlers.end(); ++p) { | 
|  270     ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(*p); |  438     ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(*p); | 
|  271     RegisterProtocolHandler(handler); |  439     RegisterProtocolHandler(handler); | 
|  272     bool is_default = false; |  440     bool is_default = false; | 
|  273     if ((*p)->GetBoolean("default", &is_default) && is_default) { |  441     if ((*p)->GetBoolean("default", &is_default) && is_default) { | 
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  421   if (should_notify) |  589   if (should_notify) | 
|  422     NotifyChanged(); |  590     NotifyChanged(); | 
|  423 } |  591 } | 
|  424  |  592  | 
|  425 bool ProtocolHandlerRegistry::IsHandledProtocol( |  593 bool ProtocolHandlerRegistry::IsHandledProtocol( | 
|  426     const std::string& scheme) const { |  594     const std::string& scheme) const { | 
|  427   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  595   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  428   return enabled_ && !GetHandlerFor(scheme).IsEmpty(); |  596   return enabled_ && !GetHandlerFor(scheme).IsEmpty(); | 
|  429 } |  597 } | 
|  430  |  598  | 
|  431 bool ProtocolHandlerRegistry::IsHandledProtocolIO( |  | 
|  432     const std::string& scheme) const { |  | 
|  433   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |  | 
|  434   return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty(); |  | 
|  435 } |  | 
|  436  |  | 
|  437 void ProtocolHandlerRegistry::RemoveHandler( |  599 void ProtocolHandlerRegistry::RemoveHandler( | 
|  438     const ProtocolHandler& handler) { |  600     const ProtocolHandler& handler) { | 
|  439   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  601   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  440   ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()]; |  602   ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()]; | 
|  441   ProtocolHandlerList::iterator p = |  603   ProtocolHandlerList::iterator p = | 
|  442       std::find(handlers.begin(), handlers.end(), handler); |  604       std::find(handlers.begin(), handlers.end(), handler); | 
|  443   if (p != handlers.end()) { |  605   if (p != handlers.end()) { | 
|  444     handlers.erase(p); |  606     handlers.erase(p); | 
|  445   } |  607   } | 
|  446   ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); |  608   ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); | 
|  447   if (q != default_handlers_.end() && q->second == handler) { |  609   if (q != default_handlers_.end() && q->second == handler) { | 
|  448     // Make the new top handler in the list the default. |  610     // Make the new top handler in the list the default. | 
|  449     if (!handlers.empty()) { |  611     if (!handlers.empty()) { | 
|  450       // NOTE We pass a copy because SetDefault() modifies handlers. |  612       // NOTE We pass a copy because SetDefault() modifies handlers. | 
|  451       SetDefault(ProtocolHandler(handlers[0])); |  613       SetDefault(ProtocolHandler(handlers[0])); | 
|  452     } else { |  614     } else { | 
|  453       BrowserThread::PostTask( |  615       BrowserThread::PostTask( | 
|  454           BrowserThread::IO, FROM_HERE, |  616           BrowserThread::IO, FROM_HERE, | 
|  455           base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, |  617           base::Bind(&Core::ClearDefault, core_, q->second.protocol())); | 
|  456                      q->second.protocol())); |  618  | 
|  457       default_handlers_.erase(q); |  619       default_handlers_.erase(q); | 
|  458     } |  620     } | 
|  459   } |  621   } | 
|  460  |  622  | 
|  461   if (!IsHandledProtocol(handler.protocol())) { |  623   if (!IsHandledProtocol(handler.protocol())) { | 
|  462     delegate_->DeregisterExternalHandler(handler.protocol()); |  624     delegate_->DeregisterExternalHandler(handler.protocol()); | 
|  463   } |  625   } | 
|  464   Save(); |  626   Save(); | 
|  465   NotifyChanged(); |  627   NotifyChanged(); | 
|  466 } |  628 } | 
|  467  |  629  | 
|  468 void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) { |  630 void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) { | 
|  469   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  631   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  470   ProtocolHandler current_default = GetHandlerFor(scheme); |  632   ProtocolHandler current_default = GetHandlerFor(scheme); | 
|  471   if (!current_default.IsEmpty()) |  633   if (!current_default.IsEmpty()) | 
|  472     RemoveHandler(current_default); |  634     RemoveHandler(current_default); | 
|  473 } |  635 } | 
|  474  |  636  | 
|  475 const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor( |  637 const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor( | 
|  476     const std::string& scheme) const { |  638     const std::string& scheme) const { | 
|  477   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  639   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  478   return LookupHandler(default_handlers_, scheme); |  640   return LookupHandler(default_handlers_, scheme); | 
|  479 } |  641 } | 
|  480  |  642  | 
|  481 net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob( |  | 
|  482     net::URLRequest* request) const { |  | 
|  483   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |  | 
|  484   ProtocolHandler handler = LookupHandler(default_handlers_io_, |  | 
|  485                                           request->url().scheme()); |  | 
|  486   if (handler.IsEmpty()) { |  | 
|  487     return NULL; |  | 
|  488   } |  | 
|  489   GURL translated_url(handler.TranslateUrl(request->url())); |  | 
|  490   if (!translated_url.is_valid()) { |  | 
|  491     return NULL; |  | 
|  492   } |  | 
|  493   return new net::URLRequestRedirectJob(request, translated_url); |  | 
|  494 } |  | 
|  495  |  | 
|  496 void ProtocolHandlerRegistry::Enable() { |  643 void ProtocolHandlerRegistry::Enable() { | 
|  497   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  644   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  498   if (enabled_) { |  645   if (enabled_) { | 
|  499     return; |  646     return; | 
|  500   } |  647   } | 
|  501   enabled_ = true; |  648   enabled_ = true; | 
|  502   BrowserThread::PostTask( |  649   BrowserThread::PostTask( | 
|  503       BrowserThread::IO, |  650       BrowserThread::IO, | 
|  504       FROM_HERE, |  651       FROM_HERE, | 
|  505       base::Bind(&ProtocolHandlerRegistry::EnableIO, this)); |  652       base::Bind(&Core::Enable, core_)); | 
 |  653  | 
|  506   ProtocolHandlerMap::const_iterator p; |  654   ProtocolHandlerMap::const_iterator p; | 
|  507   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { |  655   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { | 
|  508     delegate_->RegisterExternalHandler(p->first); |  656     delegate_->RegisterExternalHandler(p->first); | 
|  509   } |  657   } | 
|  510   Save(); |  658   Save(); | 
|  511   NotifyChanged(); |  659   NotifyChanged(); | 
|  512 } |  660 } | 
|  513  |  661  | 
|  514 void ProtocolHandlerRegistry::Disable() { |  662 void ProtocolHandlerRegistry::Disable() { | 
|  515   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  663   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  516   if (!enabled_) { |  664   if (!enabled_) { | 
|  517     return; |  665     return; | 
|  518   } |  666   } | 
|  519   enabled_ = false; |  667   enabled_ = false; | 
|  520   BrowserThread::PostTask( |  668   BrowserThread::PostTask( | 
|  521       BrowserThread::IO, |  669       BrowserThread::IO, | 
|  522       FROM_HERE, |  670       FROM_HERE, | 
|  523       base::Bind(&ProtocolHandlerRegistry::DisableIO, this)); |  671       base::Bind(&Core::Disable, core_)); | 
 |  672  | 
|  524   ProtocolHandlerMap::const_iterator p; |  673   ProtocolHandlerMap::const_iterator p; | 
|  525   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { |  674   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { | 
|  526     delegate_->DeregisterExternalHandler(p->first); |  675     delegate_->DeregisterExternalHandler(p->first); | 
|  527   } |  676   } | 
|  528   Save(); |  677   Save(); | 
|  529   NotifyChanged(); |  678   NotifyChanged(); | 
|  530 } |  679 } | 
|  531  |  680  | 
|  532 void ProtocolHandlerRegistry::Finalize() { |  681 void ProtocolHandlerRegistry::Shutdown() { | 
|  533   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  682   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  534   delegate_.reset(NULL); |  683   delegate_.reset(NULL); | 
|  535   // We free these now in case there are any outstanding workers running. If |  684   // We free these now in case there are any outstanding workers running. If | 
|  536   // we didn't free them they could respond to workers and try to update the |  685   // we didn't free them they could respond to workers and try to update the | 
|  537   // protocol handler registry after it was deleted. |  686   // protocol handler registry after it was deleted. | 
|  538   // Observers remove themselves from this list when they are deleted; so |  687   // Observers remove themselves from this list when they are deleted; so | 
|  539   // we delete the last item until none are left in the list. |  688   // we delete the last item until none are left in the list. | 
|  540   while (!default_client_observers_.empty()) { |  689   while (!default_client_observers_.empty()) { | 
|  541     delete default_client_observers_.back(); |  690     delete default_client_observers_.back(); | 
|  542   } |  691   } | 
|  543 } |  692 } | 
|  544  |  693  | 
|  545 // static |  694 // static | 
|  546 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) { |  695 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) { | 
|  547   pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers, |  696   pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers, | 
|  548                                  PrefService::UNSYNCABLE_PREF); |  697                                  PrefService::UNSYNCABLE_PREF); | 
|  549   pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers, |  698   pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers, | 
|  550                                  PrefService::UNSYNCABLE_PREF); |  699                                  PrefService::UNSYNCABLE_PREF); | 
|  551   pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true, |  700   pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true, | 
|  552                                     PrefService::UNSYNCABLE_PREF); |  701                                     PrefService::UNSYNCABLE_PREF); | 
|  553 } |  702 } | 
|  554  |  703  | 
|  555 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { |  704 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { | 
|  556   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |  705   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  557   DCHECK(default_client_observers_.empty()); |  706   DCHECK(default_client_observers_.empty()); | 
|  558 } |  707 } | 
|  559  |  708  | 
|  560 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { |  709 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { | 
|  561   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  710   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  562   DCHECK(IsRegistered(handler)); |  711   DCHECK(IsRegistered(handler)); | 
|  563   ProtocolHandlerMultiMap::iterator p = |  712   ProtocolHandlerMultiMap::iterator p = | 
|  564       protocol_handlers_.find(handler.protocol()); |  713       protocol_handlers_.find(handler.protocol()); | 
|  565   ProtocolHandlerList& list = p->second; |  714   ProtocolHandlerList& list = p->second; | 
|  566   list.erase(std::find(list.begin(), list.end(), handler)); |  715   list.erase(std::find(list.begin(), list.end(), handler)); | 
|  567   list.insert(list.begin(), handler); |  716   list.insert(list.begin(), handler); | 
|  568 } |  717 } | 
|  569  |  718  | 
|  570 void ProtocolHandlerRegistry::ClearDefaultIO(const std::string& scheme) { |  | 
|  571   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |  | 
|  572   default_handlers_io_.erase(scheme); |  | 
|  573 } |  | 
|  574  |  | 
|  575 void ProtocolHandlerRegistry::SetDefaultIO(const ProtocolHandler& handler) { |  | 
|  576   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |  | 
|  577   ClearDefaultIO(handler.protocol()); |  | 
|  578   default_handlers_io_.insert(std::make_pair(handler.protocol(), handler)); |  | 
|  579 } |  | 
|  580  |  | 
|  581 void ProtocolHandlerRegistry::Save() { |  719 void ProtocolHandlerRegistry::Save() { | 
|  582   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  720   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  583   if (is_loading_) { |  721   if (is_loading_) { | 
|  584     return; |  722     return; | 
|  585   } |  723   } | 
|  586   scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers()); |  724   scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers()); | 
|  587   scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers()); |  725   scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers()); | 
|  588   scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_)); |  726   scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_)); | 
|  589   profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, |  727   profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, | 
|  590       *registered_protocol_handlers); |  728       *registered_protocol_handlers); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  611   // If we're not loading, and we are setting a default for a new protocol, |  749   // If we're not loading, and we are setting a default for a new protocol, | 
|  612   // register with the OS. |  750   // register with the OS. | 
|  613   if (!is_loading_ && p == default_handlers_.end()) |  751   if (!is_loading_ && p == default_handlers_.end()) | 
|  614       delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this); |  752       delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this); | 
|  615   default_handlers_.erase(handler.protocol()); |  753   default_handlers_.erase(handler.protocol()); | 
|  616   default_handlers_.insert(std::make_pair(handler.protocol(), handler)); |  754   default_handlers_.insert(std::make_pair(handler.protocol(), handler)); | 
|  617   PromoteHandler(handler); |  755   PromoteHandler(handler); | 
|  618   BrowserThread::PostTask( |  756   BrowserThread::PostTask( | 
|  619       BrowserThread::IO, |  757       BrowserThread::IO, | 
|  620       FROM_HERE, |  758       FROM_HERE, | 
|  621       base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler)); |  759       base::Bind(&Core::SetDefault, core_, handler)); | 
|  622 } |  760 } | 
|  623  |  761  | 
|  624 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) { |  762 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) { | 
|  625   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  763   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  626   ProtocolHandlerMultiMap::iterator p = |  764   ProtocolHandlerMultiMap::iterator p = | 
|  627       protocol_handlers_.find(handler.protocol()); |  765       protocol_handlers_.find(handler.protocol()); | 
|  628  |  766  | 
|  629   if (p != protocol_handlers_.end()) { |  767   if (p != protocol_handlers_.end()) { | 
|  630     p->second.push_back(handler); |  768     p->second.push_back(handler); | 
|  631     return; |  769     return; | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  708 } |  846 } | 
|  709  |  847  | 
|  710 void ProtocolHandlerRegistry::IgnoreProtocolHandler( |  848 void ProtocolHandlerRegistry::IgnoreProtocolHandler( | 
|  711     const ProtocolHandler& handler) { |  849     const ProtocolHandler& handler) { | 
|  712   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |  850   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  713   ignored_protocol_handlers_.push_back(handler); |  851   ignored_protocol_handlers_.push_back(handler); | 
|  714 } |  852 } | 
|  715  |  853  | 
|  716 void ProtocolHandlerRegistry::AddPredefinedHandler( |  854 void ProtocolHandlerRegistry::AddPredefinedHandler( | 
|  717     const ProtocolHandler& handler) { |  855     const ProtocolHandler& handler) { | 
|  718   // If called after the load command was issued this function will fail. |  856   DCHECK(!is_loaded_);  // Must be called prior InitProtocolSettings. | 
|  719   DCHECK(!is_loaded_); |  | 
|  720   RegisterProtocolHandler(handler); |  857   RegisterProtocolHandler(handler); | 
|  721   SetDefault(handler); |  858   SetDefault(handler); | 
|  722 } |  859 } | 
|  723  |  860  | 
|  724  |  861 net::URLRequestJobFactory::Interceptor* | 
 |  862     ProtocolHandlerRegistry::CreateURLInterceptor() { | 
 |  863   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
 |  864   // this is always created on the UI thread (in profile_io's | 
 |  865   // InitializeOnUIThread. Any method calls must be done | 
 |  866   // on the IO thread (this is checked). | 
 |  867   return new URLInterceptor(core_); | 
 |  868 } | 
| OLD | NEW |