protocol_handler_registry.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/custom_handlers/protocol_handler_registry.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utility> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/net/chrome_url_request_context.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile_io_data.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/custom_handlers/protocol_handler.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/child_process_security_policy.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "grit/generated_resources.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/network_delegate.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_redirect_job.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::ChildProcessSecurityPolicy; 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const ProtocolHandler& LookupHandler( 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& scheme) { 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) handler_map.find(scheme); 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (p != handler_map.end()) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return p->second; 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ProtocolHandler::EmptyProtocolHandler(); 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If true default protocol handlers will be removed if the OS level 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// registration for a protocol is no longer Chrome. 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldRemoveHandlersNotInOS() { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_LINUX) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We don't do this on Linux as the OS registration there is not reliable, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and Chrome OS doesn't have any notion of OS registration. 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(benwells): When Linux support is more reliable remove this 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // difference (http://crbug.com/88255). 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ShellIntegration::CanSetAsDefaultProtocolClient() != 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShellIntegration::SET_DEFAULT_NOT_ALLOWED; 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// IOThreadDelegate ------------------------------------------------------------ 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// IOThreadDelegate is an IO thread specific object. Access to the class should 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// all be done via the IO thread. The registry living on the UI thread makes 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// a best effort to update the IO object after local updates are completed. 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ProtocolHandlerRegistry::IOThreadDelegate 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public base::RefCountedThreadSafe< 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerRegistry::IOThreadDelegate> { 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Creates a new instance. If |enabled| is true the registry is considered 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // enabled on the IO thread. 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit IOThreadDelegate(bool enabled); 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Returns true if the protocol has a default protocol handler. 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should be called only from the IO thread. 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool IsHandledProtocol(const std::string& scheme) const; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Clears the default for the provided protocol. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should be called only from the IO thread. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ClearDefault(const std::string& scheme); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Makes this ProtocolHandler the default handler for its protocol. 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should be called only from the IO thread. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetDefault(const ProtocolHandler& handler); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Creates a URL request job for the given request if there is a matching 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // protocol handler, returns NULL otherwise. 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestJob* MaybeCreateJob( 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) const; 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Indicate that the registry has been enabled in the IO thread's 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // copy of the data. 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Enable() { enabled_ = true; } 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Indicate that the registry has been disabled in the IO thread's copy of 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the data. 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Disable() { enabled_ = false; } 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class base::RefCountedThreadSafe<IOThreadDelegate>; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~IOThreadDelegate(); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Copy of protocol handlers use only on the IO thread. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerRegistry::ProtocolHandlerMap default_handlers_; 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Is the registry enabled on the IO thread. 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool enabled_; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(IOThreadDelegate); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::IOThreadDelegate::IOThreadDelegate(bool) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : enabled_(true) {} 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::IOThreadDelegate::~IOThreadDelegate() {} 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::IOThreadDelegate::IsHandledProtocol( 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& scheme) const { 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return enabled_ && !LookupHandler(default_handlers_, scheme).IsEmpty(); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::IOThreadDelegate::ClearDefault( 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& scheme) { 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_handlers_.erase(scheme); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::IOThreadDelegate::SetDefault( 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandler& handler) { 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ClearDefault(handler.protocol()); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_handlers_.insert(std::make_pair(handler.protocol(), handler)); 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Create a new job for the supplied |URLRequest| if a default handler 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// is registered and the associated handler is able to interpret 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the url from |request|. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)net::URLRequestJob* ProtocolHandlerRegistry::IOThreadDelegate::MaybeCreateJob( 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) const { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandler handler = LookupHandler(default_handlers_, 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request->url().scheme()); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (handler.IsEmpty()) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL translated_url(handler.TranslateUrl(request->url())); 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!translated_url.is_valid()) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new net::URLRequestRedirectJob( 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request, network_delegate, translated_url, 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Protocol Handler Registry"); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// JobInterceptorFactory ------------------------------------------------------- 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Instances of JobInterceptorFactory are produced for ownership by the IO 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// thread where it handler URL requests. We should never hold 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// any pointers on this class, only produce them in response to 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// requests via |ProtocolHandlerRegistry::CreateJobInterceptorFactory|. 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::JobInterceptorFactory::JobInterceptorFactory( 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IOThreadDelegate* io_thread_delegate) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : io_thread_delegate_(io_thread_delegate) { 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(io_thread_delegate_.get()); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DetachFromThread(); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::JobInterceptorFactory::~JobInterceptorFactory() { 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::JobInterceptorFactory::Chain( 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<net::URLRequestJobFactory> job_factory) { 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) job_factory_ = job_factory.Pass(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)net::URLRequestJob* 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::JobInterceptorFactory:: 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MaybeCreateJobWithProtocolHandler( 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& scheme, 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequest* request, 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::NetworkDelegate* network_delegate) const { 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestJob* job = io_thread_delegate_->MaybeCreateJob( 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request, network_delegate); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (job) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return job; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return job_factory_->MaybeCreateJobWithProtocolHandler( 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scheme, request, network_delegate); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::JobInterceptorFactory::IsHandledProtocol( 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& scheme) const { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return io_thread_delegate_->IsHandledProtocol(scheme) || 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) job_factory_->IsHandledProtocol(scheme); 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::JobInterceptorFactory::IsHandledURL( 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& url) const { 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (url.is_valid() && 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_thread_delegate_->IsHandledProtocol(url.scheme())) || 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) job_factory_->IsHandledURL(url); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::JobInterceptorFactory::IsSafeRedirectTarget( 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& location) const { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return job_factory_->IsSafeRedirectTarget(location); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// DefaultClientObserver ------------------------------------------------------ 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver( 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerRegistry* registry) 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : worker_(NULL), 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry_(registry) { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(registry_); 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() { 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (worker_) 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker_->ObserverDestroyed(); 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DefaultClientObserverList::iterator iter = std::find( 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry_->default_client_observers_.begin(), 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry_->default_client_observers_.end(), this); 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry_->default_client_observers_.erase(iter); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShellIntegration::DefaultWebClientUIState state) { 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (worker_) { 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldRemoveHandlersNotInOS() && 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (state == ShellIntegration::STATE_NOT_DEFAULT)) { 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry_->ClearDefault(worker_->protocol()); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::DefaultClientObserver:: 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IsInteractiveSetDefaultPermitted() { 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker( 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShellIntegration::DefaultProtocolClientWorker* worker) { 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker_ = worker; 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::DefaultClientObserver::IsOwnedByWorker() { 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Delegate -------------------------------------------------------------------- 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::Delegate::~Delegate() {} 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler( 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& protocol) { 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChildProcessSecurityPolicy* policy = 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChildProcessSecurityPolicy::GetInstance(); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!policy->IsWebSafeScheme(protocol)) { 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) policy->RegisterWebSafeScheme(protocol); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler( 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& protocol) { 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered( 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& protocol) { 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // NOTE(koz): This function is safe to call from any thread, despite living 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // in ProfileIOData. 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ProfileIOData::IsHandledProtocol(protocol); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ShellIntegration::DefaultProtocolClientWorker* 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::Delegate::CreateShellWorker( 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShellIntegration::DefaultWebClientObserver* observer, 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& protocol) { 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new ShellIntegration::DefaultProtocolClientWorker(observer, protocol); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::DefaultClientObserver* 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::Delegate::CreateShellObserver( 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerRegistry* registry) { 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new DefaultClientObserver(registry); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient( 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& protocol, ProtocolHandlerRegistry* registry) { 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DefaultClientObserver* observer = CreateShellObserver(registry); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The worker pointer is reference counted. While it is running the 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // message loops of the FILE and UI thread will hold references to it 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and it will be automatically freed once all its tasks have finished. 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker = CreateShellWorker(observer, protocol); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer->SetWorker(worker.get()); 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->default_client_observers_.push_back(observer); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker->StartSetAsDefault(); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ProtocolHandlerRegistry ----------------------------------------------------- 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile, 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Delegate* delegate) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_(delegate), 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_(true), 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_loading_(false), 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_loaded_(false), 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_thread_delegate_(new IOThreadDelegate(enabled_)){ 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandler& handler) { 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol())) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler)) 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (AttemptReplace(handler)) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler( 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandler& handler) { 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterProtocolHandler(handler, USER); 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetDefault(handler); 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Save(); 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyChanged(); 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler( 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandler& handler) { 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterProtocolHandler(handler, USER); 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Save(); 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyChanged(); 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler( 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ProtocolHandler& handler) { 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IgnoreProtocolHandler(handler, USER); 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Save(); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyChanged(); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) { 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandler old_default = GetHandlerFor(handler.protocol()); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool make_new_handler_default = handler.IsSameOrigin(old_default); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProtocolHandlerList to_replace(GetReplacedHandlers(handler)); 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (to_replace.empty()) 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ProtocolHandlerList::iterator p = to_replace.begin(); 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) p != to_replace.end(); ++p) { 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RemoveHandler(*p); 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (make_new_handler_default) { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnAcceptRegisterProtocolHandler(handler); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InsertHandler(handler); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyChanged(); 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProtocolHandlerRegistry::ProtocolHandlerList 382ProtocolHandlerRegistry::GetReplacedHandlers( 383 const ProtocolHandler& handler) const { 384 ProtocolHandlerList replaced_handlers; 385 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol()); 386 if (!handlers) 387 return replaced_handlers; 388 for (ProtocolHandlerList::const_iterator p = handlers->begin(); 389 p != handlers->end(); p++) { 390 if (handler.IsSameOrigin(*p)) { 391 replaced_handlers.push_back(*p); 392 } 393 } 394 return replaced_handlers; 395} 396 397void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) { 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 399 400 default_handlers_.erase(scheme); 401 BrowserThread::PostTask( 402 BrowserThread::IO, 403 FROM_HERE, 404 base::Bind(&IOThreadDelegate::ClearDefault, io_thread_delegate_, scheme)); 405 Save(); 406 NotifyChanged(); 407} 408 409bool ProtocolHandlerRegistry::IsDefault( 410 const ProtocolHandler& handler) const { 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 412 return GetHandlerFor(handler.protocol()) == handler; 413} 414 415void ProtocolHandlerRegistry::InstallDefaultsForChromeOS() { 416#if defined(OS_CHROMEOS) 417 // Only chromeos has default protocol handlers at this point. 418 AddPredefinedHandler( 419 ProtocolHandler::CreateProtocolHandler( 420 "mailto", 421 GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_MAILTO_HANDLER_URL)))); 422 AddPredefinedHandler( 423 ProtocolHandler::CreateProtocolHandler( 424 "webcal", 425 GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_WEBCAL_HANDLER_URL)))); 426#else 427 NOTREACHED(); // this method should only ever be called in chromeos. 428#endif 429} 430 431void ProtocolHandlerRegistry::InitProtocolSettings() { 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 433 434 // Any further default additions to the table will get rejected from now on. 435 is_loaded_ = true; 436 is_loading_ = true; 437 438 PrefService* prefs = profile_->GetPrefs(); 439 if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { 440 if (prefs->GetBoolean(prefs::kCustomHandlersEnabled)) { 441 Enable(); 442 } else { 443 Disable(); 444 } 445 } 446 447 RegisterProtocolHandlersFromPref(prefs::kPolicyRegisteredProtocolHandlers, 448 POLICY); 449 RegisterProtocolHandlersFromPref(prefs::kRegisteredProtocolHandlers, USER); 450 IgnoreProtocolHandlersFromPref(prefs::kPolicyIgnoredProtocolHandlers, POLICY); 451 IgnoreProtocolHandlersFromPref(prefs::kIgnoredProtocolHandlers, USER); 452 453 is_loading_ = false; 454 455 // For each default protocol handler, check that we are still registered 456 // with the OS as the default application. 457 if (ShouldRemoveHandlersNotInOS()) { 458 for (ProtocolHandlerMap::const_iterator p = default_handlers_.begin(); 459 p != default_handlers_.end(); ++p) { 460 ProtocolHandler handler = p->second; 461 DefaultClientObserver* observer = delegate_->CreateShellObserver(this); 462 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; 463 worker = delegate_->CreateShellWorker(observer, handler.protocol()); 464 observer->SetWorker(worker.get()); 465 default_client_observers_.push_back(observer); 466 worker->StartCheckIsDefault(); 467 } 468 } 469} 470 471int ProtocolHandlerRegistry::GetHandlerIndex(const std::string& scheme) const { 472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 473 const ProtocolHandler& handler = GetHandlerFor(scheme); 474 if (handler.IsEmpty()) 475 return -1; 476 const ProtocolHandlerList* handlers = GetHandlerList(scheme); 477 if (!handlers) 478 return -1; 479 480 ProtocolHandlerList::const_iterator p; 481 int i; 482 for (i = 0, p = handlers->begin(); p != handlers->end(); ++p, ++i) { 483 if (*p == handler) 484 return i; 485 } 486 return -1; 487} 488 489ProtocolHandlerRegistry::ProtocolHandlerList 490ProtocolHandlerRegistry::GetHandlersFor( 491 const std::string& scheme) const { 492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 493 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme); 494 if (p == protocol_handlers_.end()) { 495 return ProtocolHandlerList(); 496 } 497 return p->second; 498} 499 500ProtocolHandlerRegistry::ProtocolHandlerList 501ProtocolHandlerRegistry::GetIgnoredHandlers() { 502 return ignored_protocol_handlers_; 503} 504 505void ProtocolHandlerRegistry::GetRegisteredProtocols( 506 std::vector<std::string>* output) const { 507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 508 ProtocolHandlerMultiMap::const_iterator p; 509 for (p = protocol_handlers_.begin(); p != protocol_handlers_.end(); ++p) { 510 if (!p->second.empty()) 511 output->push_back(p->first); 512 } 513} 514 515bool ProtocolHandlerRegistry::CanSchemeBeOverridden( 516 const std::string& scheme) const { 517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 518 const ProtocolHandlerList* handlers = GetHandlerList(scheme); 519 // If we already have a handler for this scheme, we can add more. 520 if (handlers != NULL && !handlers->empty()) 521 return true; 522 // Don't override a scheme if it already has an external handler. 523 return !delegate_->IsExternalHandlerRegistered(scheme); 524} 525 526bool ProtocolHandlerRegistry::IsRegistered( 527 const ProtocolHandler& handler) const { 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 529 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol()); 530 if (!handlers) { 531 return false; 532 } 533 return std::find(handlers->begin(), handlers->end(), handler) != 534 handlers->end(); 535} 536 537bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const { 538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 539 ProtocolHandlerList::const_iterator i; 540 for (i = ignored_protocol_handlers_.begin(); 541 i != ignored_protocol_handlers_.end(); ++i) { 542 if (*i == handler) { 543 return true; 544 } 545 } 546 return false; 547} 548 549bool ProtocolHandlerRegistry::HasRegisteredEquivalent( 550 const ProtocolHandler& handler) const { 551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 552 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol()); 553 if (!handlers) { 554 return false; 555 } 556 ProtocolHandlerList::const_iterator i; 557 for (i = handlers->begin(); i != handlers->end(); ++i) { 558 if (handler.IsEquivalent(*i)) { 559 return true; 560 } 561 } 562 return false; 563} 564 565bool ProtocolHandlerRegistry::HasIgnoredEquivalent( 566 const ProtocolHandler& handler) const { 567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 568 ProtocolHandlerList::const_iterator i; 569 for (i = ignored_protocol_handlers_.begin(); 570 i != ignored_protocol_handlers_.end(); ++i) { 571 if (handler.IsEquivalent(*i)) { 572 return true; 573 } 574 } 575 return false; 576} 577 578void ProtocolHandlerRegistry::RemoveIgnoredHandler( 579 const ProtocolHandler& handler) { 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 581 bool should_notify = false; 582 if (HandlerExists(handler, ignored_protocol_handlers_) && 583 HandlerExists(handler, user_ignored_protocol_handlers_)) { 584 EraseHandler(handler, &user_ignored_protocol_handlers_); 585 Save(); 586 if (!HandlerExists(handler, policy_ignored_protocol_handlers_)) { 587 EraseHandler(handler, &ignored_protocol_handlers_); 588 should_notify = true; 589 } 590 } 591 if (should_notify) 592 NotifyChanged(); 593} 594 595bool ProtocolHandlerRegistry::IsHandledProtocol( 596 const std::string& scheme) const { 597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 598 return enabled_ && !GetHandlerFor(scheme).IsEmpty(); 599} 600 601void ProtocolHandlerRegistry::RemoveHandler( 602 const ProtocolHandler& handler) { 603 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 604 ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()]; 605 bool erase_success = false; 606 if (HandlerExists(handler, handlers) && 607 HandlerExists(handler, &user_protocol_handlers_)) { 608 EraseHandler(handler, &user_protocol_handlers_); 609 if (!HandlerExists(handler, &policy_protocol_handlers_)) { 610 erase_success = true; 611 EraseHandler(handler, &protocol_handlers_); 612 } 613 } 614 ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); 615 if (erase_success && q != default_handlers_.end() && q->second == handler) { 616 // Make the new top handler in the list the default. 617 if (!handlers.empty()) { 618 // NOTE We pass a copy because SetDefault() modifies handlers. 619 SetDefault(ProtocolHandler(handlers[0])); 620 } else { 621 BrowserThread::PostTask( 622 BrowserThread::IO, FROM_HERE, 623 base::Bind(&IOThreadDelegate::ClearDefault, io_thread_delegate_, 624 q->second.protocol())); 625 626 default_handlers_.erase(q); 627 } 628 } 629 630 if (erase_success && !IsHandledProtocol(handler.protocol())) { 631 delegate_->DeregisterExternalHandler(handler.protocol()); 632 } 633 Save(); 634 if (erase_success) 635 NotifyChanged(); 636} 637 638void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) { 639 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 640 ProtocolHandler current_default = GetHandlerFor(scheme); 641 if (!current_default.IsEmpty()) 642 RemoveHandler(current_default); 643} 644 645const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor( 646 const std::string& scheme) const { 647 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 648 return LookupHandler(default_handlers_, scheme); 649} 650 651void ProtocolHandlerRegistry::Enable() { 652 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 653 if (enabled_) { 654 return; 655 } 656 enabled_ = true; 657 BrowserThread::PostTask( 658 BrowserThread::IO, 659 FROM_HERE, 660 base::Bind(&IOThreadDelegate::Enable, io_thread_delegate_)); 661 662 ProtocolHandlerMap::const_iterator p; 663 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { 664 delegate_->RegisterExternalHandler(p->first); 665 } 666 Save(); 667 NotifyChanged(); 668} 669 670void ProtocolHandlerRegistry::Disable() { 671 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 672 if (!enabled_) { 673 return; 674 } 675 enabled_ = false; 676 BrowserThread::PostTask( 677 BrowserThread::IO, 678 FROM_HERE, 679 base::Bind(&IOThreadDelegate::Disable, io_thread_delegate_)); 680 681 ProtocolHandlerMap::const_iterator p; 682 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { 683 delegate_->DeregisterExternalHandler(p->first); 684 } 685 Save(); 686 NotifyChanged(); 687} 688 689void ProtocolHandlerRegistry::Shutdown() { 690 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 691 delegate_.reset(NULL); 692 // We free these now in case there are any outstanding workers running. If 693 // we didn't free them they could respond to workers and try to update the 694 // protocol handler registry after it was deleted. 695 // Observers remove themselves from this list when they are deleted; so 696 // we delete the last item until none are left in the list. 697 while (!default_client_observers_.empty()) { 698 delete default_client_observers_.back(); 699 } 700} 701 702// static 703void ProtocolHandlerRegistry::RegisterProfilePrefs( 704 user_prefs::PrefRegistrySyncable* registry) { 705 registry->RegisterListPref(prefs::kRegisteredProtocolHandlers, 706 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 707 registry->RegisterListPref(prefs::kIgnoredProtocolHandlers, 708 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 709 registry->RegisterListPref(prefs::kPolicyRegisteredProtocolHandlers, 710 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 711 registry->RegisterListPref(prefs::kPolicyIgnoredProtocolHandlers, 712 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 713 registry->RegisterBooleanPref( 714 prefs::kCustomHandlersEnabled, 715 true, 716 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 717} 718 719ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { 720 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 721 DCHECK(default_client_observers_.empty()); 722} 723 724void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { 725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 726 DCHECK(IsRegistered(handler)); 727 ProtocolHandlerMultiMap::iterator p = 728 protocol_handlers_.find(handler.protocol()); 729 ProtocolHandlerList& list = p->second; 730 list.erase(std::find(list.begin(), list.end(), handler)); 731 list.insert(list.begin(), handler); 732} 733 734void ProtocolHandlerRegistry::Save() { 735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 736 if (is_loading_) { 737 return; 738 } 739 scoped_ptr<base::Value> registered_protocol_handlers( 740 EncodeRegisteredHandlers()); 741 scoped_ptr<base::Value> ignored_protocol_handlers(EncodeIgnoredHandlers()); 742 scoped_ptr<base::Value> enabled(base::Value::CreateBooleanValue(enabled_)); 743 profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, 744 *registered_protocol_handlers); 745 profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers, 746 *ignored_protocol_handlers); 747 profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled); 748} 749 750const ProtocolHandlerRegistry::ProtocolHandlerList* 751ProtocolHandlerRegistry::GetHandlerList( 752 const std::string& scheme) const { 753 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 754 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme); 755 if (p == protocol_handlers_.end()) { 756 return NULL; 757 } 758 return &p->second; 759} 760 761void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) { 762 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 763 ProtocolHandlerMap::const_iterator p = default_handlers_.find( 764 handler.protocol()); 765 // If we're not loading, and we are setting a default for a new protocol, 766 // register with the OS. 767 if (!is_loading_ && p == default_handlers_.end()) 768 delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this); 769 default_handlers_.erase(handler.protocol()); 770 default_handlers_.insert(std::make_pair(handler.protocol(), handler)); 771 PromoteHandler(handler); 772 BrowserThread::PostTask( 773 BrowserThread::IO, 774 FROM_HERE, 775 base::Bind(&IOThreadDelegate::SetDefault, io_thread_delegate_, handler)); 776} 777 778void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) { 779 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 780 ProtocolHandlerMultiMap::iterator p = 781 protocol_handlers_.find(handler.protocol()); 782 783 if (p != protocol_handlers_.end()) { 784 p->second.push_back(handler); 785 return; 786 } 787 788 ProtocolHandlerList new_list; 789 new_list.push_back(handler); 790 protocol_handlers_[handler.protocol()] = new_list; 791} 792 793base::Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() { 794 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 795 base::ListValue* protocol_handlers = new base::ListValue(); 796 for (ProtocolHandlerMultiMap::iterator i = user_protocol_handlers_.begin(); 797 i != user_protocol_handlers_.end(); 798 ++i) { 799 for (ProtocolHandlerList::iterator j = i->second.begin(); 800 j != i->second.end(); ++j) { 801 base::DictionaryValue* encoded = j->Encode(); 802 if (IsDefault(*j)) { 803 encoded->Set("default", base::Value::CreateBooleanValue(true)); 804 } 805 protocol_handlers->Append(encoded); 806 } 807 } 808 return protocol_handlers; 809} 810 811base::Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() { 812 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 813 base::ListValue* handlers = new base::ListValue(); 814 for (ProtocolHandlerList::iterator i = 815 user_ignored_protocol_handlers_.begin(); 816 i != user_ignored_protocol_handlers_.end(); 817 ++i) { 818 handlers->Append(i->Encode()); 819 } 820 return handlers; 821} 822 823void ProtocolHandlerRegistry::NotifyChanged() { 824 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 825 content::NotificationService::current()->Notify( 826 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, 827 content::Source<Profile>(profile_), 828 content::NotificationService::NoDetails()); 829} 830 831void ProtocolHandlerRegistry::RegisterProtocolHandler( 832 const ProtocolHandler& handler, 833 const HandlerSource source) { 834 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 835 DCHECK(CanSchemeBeOverridden(handler.protocol())); 836 DCHECK(!handler.IsEmpty()); 837 ProtocolHandlerMultiMap& map = 838 (source == POLICY) ? policy_protocol_handlers_ : user_protocol_handlers_; 839 ProtocolHandlerList& list = map[handler.protocol()]; 840 if (!HandlerExists(handler, list)) 841 list.push_back(handler); 842 if (IsRegistered(handler)) { 843 return; 844 } 845 if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol())) 846 delegate_->RegisterExternalHandler(handler.protocol()); 847 InsertHandler(handler); 848} 849 850std::vector<const base::DictionaryValue*> 851ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const { 852 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 853 std::vector<const base::DictionaryValue*> result; 854 PrefService* prefs = profile_->GetPrefs(); 855 if (!prefs->HasPrefPath(pref_name)) { 856 return result; 857 } 858 859 const base::ListValue* handlers = prefs->GetList(pref_name); 860 if (handlers) { 861 for (size_t i = 0; i < handlers->GetSize(); ++i) { 862 const base::DictionaryValue* dict; 863 if (!handlers->GetDictionary(i, &dict)) 864 continue; 865 if (ProtocolHandler::IsValidDict(dict)) { 866 result.push_back(dict); 867 } 868 } 869 } 870 return result; 871} 872 873void ProtocolHandlerRegistry::RegisterProtocolHandlersFromPref( 874 const char* pref_name, 875 const HandlerSource source) { 876 std::vector<const base::DictionaryValue*> registered_handlers = 877 GetHandlersFromPref(pref_name); 878 for (std::vector<const base::DictionaryValue*>::const_iterator p = 879 registered_handlers.begin(); 880 p != registered_handlers.end(); 881 ++p) { 882 ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(*p); 883 RegisterProtocolHandler(handler, source); 884 bool is_default = false; 885 if ((*p)->GetBoolean("default", &is_default) && is_default) { 886 SetDefault(handler); 887 } 888 } 889} 890 891void ProtocolHandlerRegistry::IgnoreProtocolHandler( 892 const ProtocolHandler& handler, 893 const HandlerSource source) { 894 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 895 ProtocolHandlerList& list = (source == POLICY) 896 ? policy_ignored_protocol_handlers_ 897 : user_ignored_protocol_handlers_; 898 if (!HandlerExists(handler, list)) 899 list.push_back(handler); 900 if (HandlerExists(handler, ignored_protocol_handlers_)) 901 return; 902 ignored_protocol_handlers_.push_back(handler); 903} 904 905void ProtocolHandlerRegistry::IgnoreProtocolHandlersFromPref( 906 const char* pref_name, 907 const HandlerSource source) { 908 std::vector<const base::DictionaryValue*> ignored_handlers = 909 GetHandlersFromPref(pref_name); 910 for (std::vector<const base::DictionaryValue*>::const_iterator p = 911 ignored_handlers.begin(); 912 p != ignored_handlers.end(); 913 ++p) { 914 IgnoreProtocolHandler(ProtocolHandler::CreateProtocolHandler(*p), source); 915 } 916} 917 918bool ProtocolHandlerRegistry::HandlerExists(const ProtocolHandler& handler, 919 ProtocolHandlerMultiMap* map) { 920 return HandlerExists(handler, (*map)[handler.protocol()]); 921} 922 923bool ProtocolHandlerRegistry::HandlerExists(const ProtocolHandler& handler, 924 const ProtocolHandlerList& list) { 925 return std::find(list.begin(), list.end(), handler) != list.end(); 926} 927 928void ProtocolHandlerRegistry::EraseHandler(const ProtocolHandler& handler, 929 ProtocolHandlerMultiMap* map) { 930 EraseHandler(handler, &(*map)[handler.protocol()]); 931} 932 933void ProtocolHandlerRegistry::EraseHandler(const ProtocolHandler& handler, 934 ProtocolHandlerList* list) { 935 list->erase(std::find(list->begin(), list->end(), handler)); 936} 937 938void ProtocolHandlerRegistry::AddPredefinedHandler( 939 const ProtocolHandler& handler) { 940 DCHECK(!is_loaded_); // Must be called prior InitProtocolSettings. 941 RegisterProtocolHandler(handler, USER); 942 SetDefault(handler); 943} 944 945scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 946ProtocolHandlerRegistry::CreateJobInterceptorFactory() { 947 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 948 // this is always created on the UI thread (in profile_io's 949 // InitializeOnUIThread. Any method calls must be done 950 // on the IO thread (this is checked). 951 return scoped_ptr<JobInterceptorFactory>( 952 new JobInterceptorFactory(io_thread_delegate_.get())); 953} 954