diff options
| author | pmonette <pmonette@chromium.org> | 2016-03-07 11:50:37 -0800 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2016-03-07 19:51:34 +0000 |
| commit | 586ab5b351a279069a635c5ee6fab7cef834ef5c (patch) | |
| tree | bc56731a90bc2d5a42c63fab8ecfa1742b8d9aa7 | |
| parent | 701f238b27019e76f57af621f52ad7f5a53456d3 (diff) | |
| download | chromium_src-586ab5b351a279069a635c5ee6fab7cef834ef5c.zip chromium_src-586ab5b351a279069a635c5ee6fab7cef834ef5c.tar.gz chromium_src-586ab5b351a279069a635c5ee6fab7cef834ef5c.tar.bz2 | |
Replaced DefaultWebClientObserver with a single callback
This simplifies the usage of the default worker classes and removes the
complicated ownership model for the observer.
Review URL: https://codereview.chromium.org/1701183002
Cr-Commit-Position: refs/heads/master@{#379616}
19 files changed, 377 insertions, 579 deletions
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 12512d5..d1b356c 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -1211,10 +1211,9 @@ void BrowserProcessImpl::ApplyDefaultBrowserPolicy() { // The worker pointer is reference counted. While it is running, the // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. - scoped_refptr<shell_integration::DefaultWebClientWorker> - set_browser_worker = new shell_integration::DefaultBrowserWorker( - nullptr, - /*delete_observer=*/false); + scoped_refptr<shell_integration::DefaultBrowserWorker> set_browser_worker = + new shell_integration::DefaultBrowserWorker( + shell_integration::DefaultWebClientWorkerCallback()); // The user interaction must always be disabled when applying the default // browser policy since it is done at each browser startup and the result // of the interaction cannot be forced. diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc index c0e69ac..7cd1ce2 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc @@ -69,7 +69,6 @@ class ProtocolHandlerRegistry::IOThreadDelegate : public base::RefCountedThreadSafe< ProtocolHandlerRegistry::IOThreadDelegate> { public: - // Creates a new instance. If |enabled| is true the registry is considered // enabled on the IO thread. explicit IOThreadDelegate(bool enabled); @@ -230,42 +229,6 @@ bool ProtocolHandlerRegistry::JobInterceptorFactory::IsSafeRedirectTarget( return job_factory_->IsSafeRedirectTarget(location); } -// DefaultClientObserver ------------------------------------------------------ - -ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver( - ProtocolHandlerRegistry* registry) - : worker_(NULL), - registry_(registry) { - DCHECK(registry_); -} - -ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() { - if (worker_) - worker_->ObserverDestroyed(); - - DefaultClientObserverList::iterator iter = std::find( - registry_->default_client_observers_.begin(), - registry_->default_client_observers_.end(), this); - registry_->default_client_observers_.erase(iter); -} - -void ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) { - if (worker_) { - if (ShouldRemoveHandlersNotInOS() && - (state == shell_integration::STATE_NOT_DEFAULT)) { - registry_->ClearDefault(worker_->protocol()); - } - } else { - NOTREACHED(); - } -} - -void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker( - shell_integration::DefaultProtocolClientWorker* worker) { - worker_ = worker; -} - // Delegate -------------------------------------------------------------------- ProtocolHandlerRegistry::Delegate::~Delegate() {} @@ -290,44 +253,34 @@ bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered( return ProfileIOData::IsHandledProtocol(protocol); } -shell_integration::DefaultProtocolClientWorker* +scoped_refptr<shell_integration::DefaultProtocolClientWorker> ProtocolHandlerRegistry::Delegate::CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol) { - return new shell_integration::DefaultProtocolClientWorker( - observer, protocol, /*delete_observer=*/true); -} - -ProtocolHandlerRegistry::DefaultClientObserver* -ProtocolHandlerRegistry::Delegate::CreateShellObserver( - ProtocolHandlerRegistry* registry) { - return new DefaultClientObserver(registry); + return new shell_integration::DefaultProtocolClientWorker(callback, protocol); } void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient( const std::string& protocol, ProtocolHandlerRegistry* registry) { - DefaultClientObserver* observer = CreateShellObserver(registry); // The worker pointer is reference counted. While it is running, the // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. - scoped_refptr<shell_integration::DefaultProtocolClientWorker> worker; - worker = CreateShellWorker(observer, protocol); - observer->SetWorker(worker.get()); - registry->default_client_observers_.push_back(observer); - worker->StartSetAsDefault(); + CreateShellWorker(registry->GetDefaultWebClientCallback(protocol), protocol) + ->StartSetAsDefault(); } // ProtocolHandlerRegistry ----------------------------------------------------- ProtocolHandlerRegistry::ProtocolHandlerRegistry( - content::BrowserContext* context, Delegate* delegate) + content::BrowserContext* context, + Delegate* delegate) : context_(context), delegate_(delegate), enabled_(true), is_loading_(false), is_loaded_(false), - io_thread_delegate_(new IOThreadDelegate(enabled_)){ -} + io_thread_delegate_(new IOThreadDelegate(enabled_)), + weak_ptr_factory_(this) {} bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( const ProtocolHandler& handler) { @@ -468,12 +421,13 @@ void ProtocolHandlerRegistry::InitProtocolSettings() { for (ProtocolHandlerMap::const_iterator p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { ProtocolHandler handler = p->second; - DefaultClientObserver* observer = delegate_->CreateShellObserver(this); - scoped_refptr<shell_integration::DefaultProtocolClientWorker> worker; - worker = delegate_->CreateShellWorker(observer, handler.protocol()); - observer->SetWorker(worker.get()); - default_client_observers_.push_back(observer); - worker->StartCheckIsDefault(); + // The worker pointer is reference counted. While it is running the + // message loops of the FILE and UI thread will hold references to it + // and it will be automatically freed once all its tasks have finished. + delegate_ + ->CreateShellWorker(GetDefaultWebClientCallback(handler.protocol()), + handler.protocol()) + ->StartSetAsDefault(); } } } @@ -709,14 +663,8 @@ void ProtocolHandlerRegistry::Disable() { void ProtocolHandlerRegistry::Shutdown() { DCHECK_CURRENTLY_ON(BrowserThread::UI); delegate_.reset(NULL); - // We free these now in case there are any outstanding workers running. If - // we didn't free them they could respond to workers and try to update the - // protocol handler registry after it was deleted. - // Observers remove themselves from this list when they are deleted; so - // we delete the last item until none are left in the list. - while (!default_client_observers_.empty()) { - delete default_client_observers_.back(); - } + + weak_ptr_factory_.InvalidateWeakPtrs(); } // static @@ -731,7 +679,6 @@ void ProtocolHandlerRegistry::RegisterProfilePrefs( ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(default_client_observers_.empty()); } void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { @@ -949,6 +896,15 @@ void ProtocolHandlerRegistry::EraseHandler(const ProtocolHandler& handler, list->erase(std::find(list->begin(), list->end(), handler)); } +void ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished( + const std::string& protocol, + shell_integration::DefaultWebClientUIState state) { + if (ShouldRemoveHandlersNotInOS() && + state == shell_integration::STATE_NOT_DEFAULT) { + ClearDefault(protocol); + } +} + void ProtocolHandlerRegistry::AddPredefinedHandler( const ProtocolHandler& handler) { DCHECK(!is_loaded_); // Must be called prior InitProtocolSettings. @@ -956,6 +912,14 @@ void ProtocolHandlerRegistry::AddPredefinedHandler( SetDefault(handler); } +shell_integration::DefaultWebClientWorkerCallback +ProtocolHandlerRegistry::GetDefaultWebClientCallback( + const std::string& protocol) { + return base::Bind( + &ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished, + weak_ptr_factory_.GetWeakPtr(), protocol); +} + scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> ProtocolHandlerRegistry::CreateJobInterceptorFactory() { DCHECK_CURRENTLY_ON(BrowserThread::UI); diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.h b/chrome/browser/custom_handlers/protocol_handler_registry.h index a2dcc07..c540c98 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry.h +++ b/chrome/browser/custom_handlers/protocol_handler_registry.h @@ -10,8 +10,8 @@ #include <vector> #include "base/macros.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner_helpers.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" @@ -34,40 +34,11 @@ class PrefRegistrySyncable; // Profile::InitRegisteredProtocolHandlers(), and they should be the only // instances of this class. class ProtocolHandlerRegistry : public KeyedService { - public: enum HandlerSource { USER, // The handler was installed by user POLICY, // The handler was installed by policy }; - // Provides notification of when the OS level user agent settings - // are changed. - class DefaultClientObserver - : public shell_integration::DefaultWebClientObserver { - public: - explicit DefaultClientObserver(ProtocolHandlerRegistry* registry); - ~DefaultClientObserver() override; - - // Get response from the worker regarding whether Chrome is the default - // handler for the protocol. - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override; - - // Give the observer a handle to the worker, so we can find out the protocol - // when we're called and also tell the worker if we get deleted. - void SetWorker(shell_integration::DefaultProtocolClientWorker* worker); - - protected: - shell_integration::DefaultProtocolClientWorker* worker_; - - private: - // This is a raw pointer, not reference counted, intentionally. In general - // subclasses of DefaultWebClientObserver are not able to be refcounted - // e.g. the browser options page - ProtocolHandlerRegistry* registry_; - - DISALLOW_COPY_AND_ASSIGN(DefaultClientObserver); - }; // |Delegate| provides an interface for interacting asynchronously // with the underlying OS for the purposes of registering Chrome @@ -78,11 +49,10 @@ class ProtocolHandlerRegistry : public KeyedService { virtual void RegisterExternalHandler(const std::string& protocol); virtual void DeregisterExternalHandler(const std::string& protocol); virtual bool IsExternalHandlerRegistered(const std::string& protocol); - virtual shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + virtual scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol); - virtual DefaultClientObserver* CreateShellObserver( - ProtocolHandlerRegistry* registry); virtual void RegisterWithOSAsDefaultClient( const std::string& protocol, ProtocolHandlerRegistry* registry); @@ -140,7 +110,6 @@ class ProtocolHandlerRegistry : public KeyedService { typedef std::map<std::string, ProtocolHandler> ProtocolHandlerMap; typedef std::vector<ProtocolHandler> ProtocolHandlerList; typedef std::map<std::string, ProtocolHandlerList> ProtocolHandlerMultiMap; - typedef std::vector<DefaultClientObserver*> DefaultClientObserverList; // Creates a new instance. Assumes ownership of |delegate|. ProtocolHandlerRegistry(content::BrowserContext* context, Delegate* delegate); @@ -261,6 +230,11 @@ class ProtocolHandlerRegistry : public KeyedService { // load command was issued, otherwise the command will be ignored. void AddPredefinedHandler(const ProtocolHandler& handler); + // Gets the callback for DefaultProtocolClientWorker. Allows the Delegate to + // create the worker on behalf of ProtocolHandlerRegistry. + shell_integration::DefaultWebClientWorkerCallback GetDefaultWebClientCallback( + const std::string& protocol); + private: friend class base::DeleteHelper<ProtocolHandlerRegistry>; friend struct content::BrowserThread::DeleteOnThread< @@ -340,6 +314,12 @@ class ProtocolHandlerRegistry : public KeyedService { // Erases the handler that is guaranteed to exist from the list. void EraseHandler(const ProtocolHandler& handler, ProtocolHandlerList* list); + // Called with the default state when the default protocol client worker is + // done. + void OnSetAsDefaultProtocolClientFinished( + const std::string& protocol, + shell_integration::DefaultWebClientUIState state); + // Map from protocols (strings) to protocol handlers. ProtocolHandlerMultiMap protocol_handlers_; @@ -384,7 +364,9 @@ class ProtocolHandlerRegistry : public KeyedService { // are posted to the IO thread where updates are applied to this object. scoped_refptr<IOThreadDelegate> io_thread_delegate_; - DefaultClientObserverList default_client_observers_; + // Makes it possible to invalidate the callback for the + // DefaultProtocolClientWorker. + base::WeakPtrFactory<ProtocolHandlerRegistry> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerRegistry); }; diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc index 2ddfae0..8dfd2f7 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc @@ -136,6 +136,42 @@ base::DictionaryValue* GetProtocolHandlerValueWithDefault(std::string protocol, return value; } +class FakeProtocolClientWorker + : public shell_integration::DefaultProtocolClientWorker { + public: + FakeProtocolClientWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, + const std::string& protocol, + bool force_failure) + : shell_integration::DefaultProtocolClientWorker(callback, protocol), + force_failure_(force_failure) {} + + private: + ~FakeProtocolClientWorker() override {} + + void CheckIsDefault() override { + shell_integration::DefaultWebClientState state = + shell_integration::IS_DEFAULT; + if (force_failure_) + state = shell_integration::NOT_DEFAULT; + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&FakeProtocolClientWorker::OnCheckIsDefaultComplete, this, + state)); + } + + void SetAsDefault() override { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&FakeProtocolClientWorker::OnSetAsDefaultAttemptComplete, + this, AttemptResult::SUCCESS)); + } + + private: + bool force_failure_; +}; + class FakeDelegate : public ProtocolHandlerRegistry::Delegate { public: FakeDelegate() : force_os_failure_(false) {} @@ -150,20 +186,17 @@ class FakeDelegate : public ProtocolHandlerRegistry::Delegate { registered_protocols_.erase(protocol); } - shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, - const std::string& protocol) override; + scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, + const std::string& protocol) override { + return new FakeProtocolClientWorker(callback, protocol, force_os_failure_); + } - ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver( + void RegisterWithOSAsDefaultClient( + const std::string& protocol, ProtocolHandlerRegistry* registry) override; - void RegisterWithOSAsDefaultClient(const std::string& protocol, - ProtocolHandlerRegistry* reg) override { - ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(protocol, - reg); - ASSERT_FALSE(IsFakeRegisteredWithOS(protocol)); - } - bool IsExternalHandlerRegistered(const std::string& protocol) override { return registered_protocols_.find(protocol) != registered_protocols_.end(); } @@ -193,78 +226,29 @@ class FakeDelegate : public ProtocolHandlerRegistry::Delegate { bool force_os_failure_; }; -class FakeClientObserver - : public ProtocolHandlerRegistry::DefaultClientObserver { - public: - FakeClientObserver(ProtocolHandlerRegistry* registry, - FakeDelegate* registry_delegate) - : ProtocolHandlerRegistry::DefaultClientObserver(registry), - delegate_(registry_delegate) {} - - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override { - ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( - state); - if (state == shell_integration::STATE_IS_DEFAULT) { - delegate_->FakeRegisterWithOS(worker_->protocol()); - } - if (state != shell_integration::STATE_PROCESSING) { - base::MessageLoop::current()->QuitWhenIdle(); - } - } - - private: - FakeDelegate* delegate_; -}; - -class FakeProtocolClientWorker - : public shell_integration::DefaultProtocolClientWorker { - public: - FakeProtocolClientWorker( - shell_integration::DefaultWebClientObserver* observer, - const std::string& protocol, - bool force_failure) - : shell_integration::DefaultProtocolClientWorker( - observer, - protocol, - /*delete_observer*/ true), - force_failure_(force_failure) {} - - private: - ~FakeProtocolClientWorker() override {} - - void CheckIsDefault() override { - shell_integration::DefaultWebClientState state = - shell_integration::IS_DEFAULT; - if (force_failure_) - state = shell_integration::NOT_DEFAULT; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&FakeProtocolClientWorker::OnCheckIsDefaultComplete, this, - state)); +void OnShellWorkerFinished(ProtocolHandlerRegistry* registry, + FakeDelegate* delegate, + const std::string& protocol, + shell_integration::DefaultWebClientUIState state) { + registry->GetDefaultWebClientCallback(protocol).Run(state); + if (state == shell_integration::STATE_IS_DEFAULT) { + delegate->FakeRegisterWithOS(protocol); } - - void SetAsDefault() override { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&FakeProtocolClientWorker::OnSetAsDefaultAttemptComplete, - this, AttemptResult::SUCCESS)); + if (state != shell_integration::STATE_PROCESSING) { + base::MessageLoop::current()->QuitWhenIdle(); } - - private: - bool force_failure_; -}; - -ProtocolHandlerRegistry::DefaultClientObserver* - FakeDelegate::CreateShellObserver(ProtocolHandlerRegistry* registry) { - return new FakeClientObserver(registry, this); } -shell_integration::DefaultProtocolClientWorker* FakeDelegate::CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, - const std::string& protocol) { - return new FakeProtocolClientWorker(observer, protocol, force_os_failure_); +void FakeDelegate::RegisterWithOSAsDefaultClient( + const std::string& protocol, + ProtocolHandlerRegistry* registry) { + // The worker pointer is reference counted. While it is running, the + // message loops of the FILE and UI thread will hold references to it + // and it will be automatically freed once all its tasks have finished. + CreateShellWorker(base::Bind(OnShellWorkerFinished, registry, this, protocol), + protocol) + ->StartSetAsDefault(); + ASSERT_FALSE(IsFakeRegisteredWithOS(protocol)); } class NotificationCounter : public content::NotificationObserver { @@ -333,8 +317,8 @@ class TestMessageLoop : public base::MessageLoop { case base::MessageLoop::TYPE_IO: return BrowserThread::CurrentlyOn(BrowserThread::IO); #if defined(OS_ANDROID) - case base::MessageLoop::TYPE_JAVA: // fall-through -#endif // defined(OS_ANDROID) + case base::MessageLoop::TYPE_JAVA: // fall-through +#endif // defined(OS_ANDROID) case base::MessageLoop::TYPE_CUSTOM: case base::MessageLoop::TYPE_DEFAULT: return !BrowserThread::CurrentlyOn(BrowserThread::UI) && @@ -753,7 +737,7 @@ TEST_F(ProtocolHandlerRegistryTest, TestDisablePreventsHandling) { // TODO(smckay): This is much more appropriately an integration // test. Make that so, then update the -// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully +// ShellIntegretion{Delegate,Callback,Worker} test classes we use to fully // isolate this test from the FILE thread. TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) { ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1"); @@ -785,7 +769,7 @@ TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) { // TODO(smckay): This is much more appropriately an integration // test. Make that so, then update the -// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully +// ShellIntegretion{Delegate,Callback,Worker} test classes we use to fully // isolate this test from the FILE thread. TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) { ProtocolHandler ph_do = CreateProtocolHandler("do", "test1"); diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc index 5fa8ddc..66449d1 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.cc +++ b/chrome/browser/external_protocol/external_protocol_handler.cc @@ -38,18 +38,15 @@ static bool g_accept_requests = true; namespace { // Functions enabling unit testing. Using a NULL delegate will use the default -// behavior; if a delegate is provided it will be used instead. Also, Ownership -// of |observer| is passed to the new worker. -shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, +// behavior; if a delegate is provided it will be used instead. +scoped_refptr<shell_integration::DefaultProtocolClientWorker> CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol, ExternalProtocolHandler::Delegate* delegate) { - if (!delegate) - return new shell_integration::DefaultProtocolClientWorker( - observer, protocol, - /*delete_observer=*/true); + if (delegate) + return delegate->CreateShellWorker(callback, protocol); - return delegate->CreateShellWorker(observer, protocol); + return new shell_integration::DefaultProtocolClientWorker(callback, protocol); } ExternalProtocolHandler::BlockState GetBlockStateWithDelegate( @@ -92,71 +89,49 @@ void LaunchUrlWithoutSecurityCheckWithDelegate( } } -// When we are about to launch a URL with the default OS level application, -// we check if that external application will be us. If it is we just ignore -// the request. -class ExternalDefaultProtocolObserver - : public shell_integration::DefaultWebClientObserver { - public: - ExternalDefaultProtocolObserver(const GURL& escaped_url, - int render_process_host_id, - int tab_contents_id, - bool prompt_user, - ui::PageTransition page_transition, - bool has_user_gesture, - ExternalProtocolHandler::Delegate* delegate) - : delegate_(delegate), - escaped_url_(escaped_url), - render_process_host_id_(render_process_host_id), - tab_contents_id_(tab_contents_id), - prompt_user_(prompt_user), - page_transition_(page_transition), - has_user_gesture_(has_user_gesture) {} - - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override { - DCHECK(base::MessageLoopForUI::IsCurrent()); - - // If we are still working out if we're the default, or we've found - // out we definately are the default, we end here. - if (state == shell_integration::STATE_PROCESSING) { - return; - } +// When we are about to launch a URL with the default OS level application, we +// check if the external application will be us. If it is we just ignore the +// request. +void OnDefaultProtocolClientWorkerFinished( + const GURL& escaped_url, + int render_process_host_id, + int tab_contents_id, + bool prompt_user, + ui::PageTransition page_transition, + bool has_user_gesture, + ExternalProtocolHandler::Delegate* delegate, + shell_integration::DefaultWebClientUIState state) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) - delegate_->FinishedProcessingCheck(); + // If we are still working out if we're the default, or we've found + // out we definately are the default, we end here. + if (state == shell_integration::STATE_PROCESSING) + return; - if (state == shell_integration::STATE_IS_DEFAULT) { - if (delegate_) - delegate_->BlockRequest(); - return; - } + if (delegate) + delegate->FinishedProcessingCheck(); - // If we get here, either we are not the default or we cannot work out - // what the default is, so we proceed. - if (prompt_user_) { - // Ask the user if they want to allow the protocol. This will call - // LaunchUrlWithoutSecurityCheck if the user decides to accept the - // protocol. - RunExternalProtocolDialogWithDelegate( - escaped_url_, render_process_host_id_, tab_contents_id_, - page_transition_, has_user_gesture_, delegate_); - return; - } + if (state == shell_integration::STATE_IS_DEFAULT) { + if (delegate) + delegate->BlockRequest(); + return; + } - LaunchUrlWithoutSecurityCheckWithDelegate( - escaped_url_, render_process_host_id_, tab_contents_id_, delegate_); + // If we get here, either we are not the default or we cannot work out + // what the default is, so we proceed. + if (prompt_user) { + // Ask the user if they want to allow the protocol. This will call + // LaunchUrlWithoutSecurityCheck if the user decides to accept the + // protocol. + RunExternalProtocolDialogWithDelegate(escaped_url, render_process_host_id, + tab_contents_id, page_transition, + has_user_gesture, delegate); + return; } - private: - ExternalProtocolHandler::Delegate* delegate_; - const GURL escaped_url_; - const int render_process_host_id_; - const int tab_contents_id_; - const bool prompt_user_; - const ui::PageTransition page_transition_; - const bool has_user_gesture_; -}; + LaunchUrlWithoutSecurityCheckWithDelegate(escaped_url, render_process_host_id, + tab_contents_id, delegate); +} } // namespace @@ -289,19 +264,17 @@ void ExternalProtocolHandler::LaunchUrlWithDelegate( g_accept_requests = false; // The worker creates tasks with references to itself and puts them into - // message loops. When no tasks are left it will delete the observer and - // eventually be deleted itself. - shell_integration::DefaultWebClientObserver* observer = - new ExternalDefaultProtocolObserver( - url, render_process_host_id, tab_contents_id, block_state == UNKNOWN, - page_transition, has_user_gesture, delegate); - scoped_refptr<shell_integration::DefaultProtocolClientWorker> worker = - CreateShellWorker(observer, escaped_url.scheme(), delegate); + // message loops. + shell_integration::DefaultWebClientWorkerCallback callback = base::Bind( + &OnDefaultProtocolClientWorkerFinished, url, render_process_host_id, + tab_contents_id, block_state == UNKNOWN, page_transition, + has_user_gesture, delegate); // Start the check process running. This will send tasks to the FILE thread - // and when the answer is known will send the result back to the observer on - // the UI thread. - worker->StartCheckIsDefault(); + // and when the answer is known will send the result back to + // OnDefaultProtocolClientWorkerFinished(). + CreateShellWorker(callback, escaped_url.scheme(), delegate) + ->StartCheckIsDefault(); } // static diff --git a/chrome/browser/external_protocol/external_protocol_handler.h b/chrome/browser/external_protocol/external_protocol_handler.h index 4759805..692f2dd 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.h +++ b/chrome/browser/external_protocol/external_protocol_handler.h @@ -29,8 +29,9 @@ class ExternalProtocolHandler { // Delegate to allow unit testing to provide different behavior. class Delegate { public: - virtual shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + virtual scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol) = 0; virtual BlockState GetBlockState(const std::string& scheme) = 0; virtual void BlockRequest() = 0; diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc index b631125..aa09a9f 100644 --- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc +++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc @@ -14,13 +14,10 @@ class FakeExternalProtocolHandlerWorker : public shell_integration::DefaultProtocolClientWorker { public: FakeExternalProtocolHandlerWorker( - shell_integration::DefaultWebClientObserver* observer, + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol, shell_integration::DefaultWebClientState os_state) - : shell_integration::DefaultProtocolClientWorker( - observer, - protocol, - /*delete_observer=*/true), + : shell_integration::DefaultProtocolClientWorker(callback, protocol), os_state_(os_state) {} private: @@ -54,10 +51,11 @@ class FakeExternalProtocolHandlerDelegate has_prompted_(false), has_blocked_(false) {} - shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol) override { - return new FakeExternalProtocolHandlerWorker(observer, protocol, os_state_); + return new FakeExternalProtocolHandlerWorker(callback, protocol, os_state_); } ExternalProtocolHandler::BlockState GetBlockState( diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 5e6cb29..fa527e2 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -1068,8 +1068,9 @@ class NeverRunsExternalProtocolHandlerDelegate : public ExternalProtocolHandler::Delegate { public: // ExternalProtocolHandler::Delegate implementation. - shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol) override { NOTREACHED(); // This will crash, but it shouldn't get this far with BlockState::BLOCK diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc index db54a75..4e49b1c 100644 --- a/chrome/browser/shell_integration.cc +++ b/chrome/browser/shell_integration.cc @@ -151,13 +151,11 @@ base::string16 GetAppShortcutsSubdirName() { // DefaultWebClientWorker::DefaultWebClientWorker( - DefaultWebClientObserver* observer, - bool delete_observer) - : observer_(observer), delete_observer_(delete_observer) {} + const DefaultWebClientWorkerCallback& callback) + : callback_(callback) {} void DefaultWebClientWorker::StartCheckIsDefault() { - if (observer_) - observer_->SetDefaultWebClientUIState(STATE_PROCESSING); + RunCallback(STATE_PROCESSING); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, @@ -176,8 +174,7 @@ void DefaultWebClientWorker::StartSetAsDefault() { } set_as_default_in_progress_ = true; - if (observer_) - observer_->SetDefaultWebClientUIState(STATE_PROCESSING); + RunCallback(STATE_PROCESSING); set_as_default_initialized_ = InitializeSetAsDefault(); @@ -189,21 +186,6 @@ void DefaultWebClientWorker::StartSetAsDefault() { base::Bind(&DefaultWebClientWorker::SetAsDefault, this)); } -void DefaultWebClientWorker::ObserverDestroyed() { - // Our associated view has gone away, so we shouldn't call back to it if - // our worker thread returns after the view is dead. - DCHECK_CURRENTLY_ON(BrowserThread::UI); - observer_ = nullptr; - - if (set_as_default_initialized_) { - FinalizeSetAsDefault(); - set_as_default_initialized_ = false; - } - - if (set_as_default_in_progress_) - ReportAttemptResult(AttemptResult::ABANDONED); -} - /////////////////////////////////////////////////////////////////////////////// // DefaultWebClientWorker, private: @@ -221,13 +203,6 @@ void DefaultWebClientWorker::OnCheckIsDefaultComplete( ? AttemptResult::SUCCESS : AttemptResult::NO_ERRORS_NOT_DEFAULT); } - - // The worker has finished everything it needs to do, so free the observer - // if we own it. - if (observer_ && delete_observer_) { - delete observer_; - observer_ = nullptr; - } } void DefaultWebClientWorker::OnSetAsDefaultAttemptComplete( @@ -253,12 +228,17 @@ void DefaultWebClientWorker::OnSetAsDefaultAttemptComplete( if (!check_default_should_report_success_) ReportAttemptResult(result); - // Start the default browser check which will notify the observer as to - // whether Chrome was sucessfully set as the default web client. + // Start the default browser check. The default state will be reported to + // the caller via the |callback_|. StartCheckIsDefault(); } } +void DefaultWebClientWorker::RunCallback(DefaultWebClientUIState state) { + if (!callback_.is_null()) + callback_.Run(state); +} + void DefaultWebClientWorker::ReportAttemptResult(AttemptResult result) { const char* histogram_prefix = GetHistogramPrefix(); @@ -288,27 +268,24 @@ bool DefaultWebClientWorker::InitializeSetAsDefault() { void DefaultWebClientWorker::FinalizeSetAsDefault() {} void DefaultWebClientWorker::UpdateUI(DefaultWebClientState state) { - if (observer_) { - switch (state) { - case NOT_DEFAULT: - observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT); - break; - case IS_DEFAULT: - observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT); - break; - case UNKNOWN_DEFAULT: - observer_->SetDefaultWebClientUIState(STATE_UNKNOWN); - break; - default: - break; - } + switch (state) { + case NOT_DEFAULT: + RunCallback(STATE_NOT_DEFAULT); + break; + case IS_DEFAULT: + RunCallback(STATE_IS_DEFAULT); + break; + case UNKNOWN_DEFAULT: + RunCallback(STATE_UNKNOWN); + break; + case NUM_DEFAULT_STATES: + break; } } bool DefaultWebClientWorker::ShouldReportDurationForResult( AttemptResult result) { - return result == SUCCESS || result == FAILURE || result == ABANDONED || - result == RETRY; + return result == SUCCESS || result == FAILURE || result == RETRY; } const char* DefaultWebClientWorker::AttemptResultToString( @@ -320,8 +297,6 @@ const char* DefaultWebClientWorker::AttemptResultToString( return "AlreadyDefault"; case FAILURE: return "Failure"; - case ABANDONED: - return "Abandoned"; case LAUNCH_FAILURE: return "LaunchFailure"; case OTHER_WORKER: @@ -341,9 +316,9 @@ const char* DefaultWebClientWorker::AttemptResultToString( // DefaultBrowserWorker // -DefaultBrowserWorker::DefaultBrowserWorker(DefaultWebClientObserver* observer, - bool delete_observer) - : DefaultWebClientWorker(observer, delete_observer) {} +DefaultBrowserWorker::DefaultBrowserWorker( + const DefaultWebClientWorkerCallback& callback) + : DefaultWebClientWorker(callback) {} DefaultBrowserWorker::~DefaultBrowserWorker() {} @@ -408,10 +383,9 @@ const char* DefaultBrowserWorker::GetHistogramPrefix() { // DefaultProtocolClientWorker::DefaultProtocolClientWorker( - DefaultWebClientObserver* observer, - const std::string& protocol, - bool delete_observer) - : DefaultWebClientWorker(observer, delete_observer), protocol_(protocol) {} + const DefaultWebClientWorkerCallback& callback, + const std::string& protocol) + : DefaultWebClientWorker(callback), protocol_(protocol) {} /////////////////////////////////////////////////////////////////////////////// // DefaultProtocolClientWorker, private: diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h index 556747b6..8d2b536 100644 --- a/chrome/browser/shell_integration.h +++ b/chrome/browser/shell_integration.h @@ -7,6 +7,7 @@ #include <string> +#include "base/callback.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -189,12 +190,10 @@ enum DefaultWebClientUIState { STATE_UNKNOWN }; -class DefaultWebClientObserver { - public: - virtual ~DefaultWebClientObserver() {} - // Updates the UI state to reflect the current default browser state. - virtual void SetDefaultWebClientUIState(DefaultWebClientUIState state) = 0; -}; +// The type of callback used to communicate processing state to consumers of +// DefaultBrowserWorker and DefaultProtocolClientWorker. +using DefaultWebClientWorkerCallback = + base::Callback<void(DefaultWebClientUIState)>; // Helper objects that handle checking if Chrome is the default browser // or application for a url protocol on Windows and Linux, and also setting @@ -208,11 +207,8 @@ class DefaultWebClientObserver { class DefaultWebClientWorker : public base::RefCountedThreadSafe<DefaultWebClientWorker> { public: - // Constructor. The worker will post updates to |observer|. If - // |delete_observer| is true, the worker owns the observer and it will be - // freed in the destructor. - DefaultWebClientWorker(DefaultWebClientObserver* observer, - bool delete_observer); + explicit DefaultWebClientWorker( + const DefaultWebClientWorkerCallback& callback); // Controls whether the worker can use user interaction to set the default // web client. If false, the set-as-default operation will fail on OS where @@ -221,19 +217,16 @@ class DefaultWebClientWorker interactive_permitted_ = interactive_permitted; } - // Checks to see if Chrome is the default web client application. The result - // will be passed back to the observer via the SetDefaultWebClientUIState - // function. If there is no observer, this function does not do anything. + // Checks to see if Chrome is the default web client application. The + // instance's callback will be run to communicate the default state to the + // caller. void StartCheckIsDefault(); - // Sets Chrome as the default web client application. If there is an - // observer, once the operation has completed the new default will be - // queried and the current status reported via SetDefaultWebClientUIState. + // Sets Chrome as the default web client application. Once done, it will + // trigger a check for the default state using StartCheckIsDefault() to return + // the default state to the caller. void StartSetAsDefault(); - // Called to notify the worker that the view is gone. - void ObserverDestroyed(); - protected: friend class base::RefCountedThreadSafe<DefaultWebClientWorker>; @@ -241,43 +234,47 @@ class DefaultWebClientWorker // Do not modify the ordering as it is important for UMA. enum AttemptResult { // Chrome was set as the default web client. - SUCCESS, + SUCCESS = 0, // Chrome was already the default web client. This counts as a successful // attempt. - ALREADY_DEFAULT, + ALREADY_DEFAULT = 1, // Chrome was not set as the default web client. - FAILURE, + FAILURE = 2, // The attempt was abandoned because the observer was destroyed. - ABANDONED, + // Note: This result is no longer used since the removal of + // DefaultWebClientObserver. + // ABANDONED = 3, // Failed to launch the process to set Chrome as the default web client // asynchronously. - LAUNCH_FAILURE, + LAUNCH_FAILURE = 4, // Another worker is already in progress to make Chrome the default web // client. - OTHER_WORKER, + OTHER_WORKER = 5, // The user initiated another attempt while the asynchronous operation was // already in progress. - RETRY, + RETRY = 6, // No errors were encountered yet Chrome is still not the default web // client. - NO_ERRORS_NOT_DEFAULT, + NO_ERRORS_NOT_DEFAULT = 7, NUM_ATTEMPT_RESULT_TYPES }; virtual ~DefaultWebClientWorker(); - // Communicates the result to the observer. In contrast to + // Communicates the result via the |callback_|. In contrast to // OnSetAsDefaultAttemptComplete(), this should not be called multiple // times. void OnCheckIsDefaultComplete(DefaultWebClientState state); // Called when the set as default operation is completed. This then invokes - // FinalizeSetAsDefault() and, if an observer is present, starts the check - // is default process. + // FinalizeSetAsDefault() and starts the check is default process. // It is safe to call this multiple times. Only the first call is processed // after StartSetAsDefault() is invoked. void OnSetAsDefaultAttemptComplete(AttemptResult result); + // Runs the callback but only if it is not null. + void RunCallback(DefaultWebClientUIState state); + // Returns true if FinalizeSetAsDefault() will be called. bool set_as_default_initialized() const { return set_as_default_initialized_; @@ -288,7 +285,7 @@ class DefaultWebClientWorker bool interactive_permitted_ = true; // Flag that indicates if the set-as-default operation is in progess to - // prevent multiple notifications to the observer. + // prevent multiple notifications to the |callback_|. bool set_as_default_in_progress_ = false; private: @@ -328,10 +325,8 @@ class DefaultWebClientWorker // Returns a string based on |result|. This is used for UMA reports. static const char* AttemptResultToString(AttemptResult result); - DefaultWebClientObserver* observer_; - - // Indicates if the the observer will be automatically freed by the worker. - bool delete_observer_; + // Called with the default state after the worker is done. + DefaultWebClientWorkerCallback callback_; // Flag that indicates the return value of InitializeSetAsDefault(). If // true, FinalizeSetAsDefault() will be called to clear what was @@ -351,11 +346,7 @@ class DefaultWebClientWorker // Worker for checking and setting the default browser. class DefaultBrowserWorker : public DefaultWebClientWorker { public: - // Constructor. The worker will post updates to |observer|. If - // |delete_observer| is true, the worker owns the observer and it will be - // freed in the destructor. - DefaultBrowserWorker(DefaultWebClientObserver* observer, - bool delete_observer); + explicit DefaultBrowserWorker(const DefaultWebClientWorkerCallback& callback); private: ~DefaultBrowserWorker() override; @@ -395,12 +386,8 @@ class DefaultBrowserWorker : public DefaultWebClientWorker { // multiple protocols you should use multiple worker objects. class DefaultProtocolClientWorker : public DefaultWebClientWorker { public: - // Constructor. The worker will post updates to |observer|. If - // |delete_observer| is true, the worker owns the observer and it will be - // freed in the destructor. - DefaultProtocolClientWorker(DefaultWebClientObserver* observer, - const std::string& protocol, - bool delete_observer); + DefaultProtocolClientWorker(const DefaultWebClientWorkerCallback& callback, + const std::string& protocol); const std::string& protocol() const { return protocol_; } diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index 8b95570..b38b5f1 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc @@ -646,8 +646,8 @@ bool DefaultBrowserWorker::InitializeSetAsDefault() { // instead call OnSetAsDefaultAttemptComplete(), passing true to indicate // success. // 5. If Chrome is not selected, the url is opened in the selected browser. - // After a certain amount of time, we notify the observer that the - // process failed. + // After a certain amount of time, we notify the caller via the |callback_| + // that the process failed. if (!StartupBrowserCreator::SetDefaultBrowserCallback( base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this, diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc index 7977f45..419d1be 100644 --- a/chrome/browser/ui/apps/chrome_app_delegate.cc +++ b/chrome/browser/ui/apps/chrome_app_delegate.cc @@ -79,42 +79,29 @@ content::WebContents* OpenURLFromTabInternal( return new_tab_params.target_contents; } -// Helper class that opens a URL based on if this browser instance is the -// default system browser. If it is the default, open the URL directly instead -// of asking the system to open it. -class OpenURLFromTabBasedOnBrowserDefault - : public shell_integration::DefaultWebClientObserver { - public: - OpenURLFromTabBasedOnBrowserDefault(scoped_ptr<content::WebContents> source, - const content::OpenURLParams& params) - : source_(std::move(source)), params_(params) {} - - // Opens a URL when called with the result of if this is the default system - // browser or not. - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override { - Profile* profile = - Profile::FromBrowserContext(source_->GetBrowserContext()); - DCHECK(profile); - if (!profile) - return; - switch (state) { - case shell_integration::STATE_PROCESSING: - break; - case shell_integration::STATE_IS_DEFAULT: - OpenURLFromTabInternal(profile, params_); - break; - case shell_integration::STATE_NOT_DEFAULT: - case shell_integration::STATE_UNKNOWN: - platform_util::OpenExternal(profile, params_.url); - break; - } +void OnCheckIsDefaultBrowserFinished( + content::WebContents* source, + const content::OpenURLParams& params, + shell_integration::DefaultWebClientUIState state) { + // Open a URL based on if this browser instance is the default system browser. + // If it is the default, open the URL directly instead of asking the system to + // open it. + Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); + DCHECK(profile); + if (!profile) + return; + switch (state) { + case shell_integration::STATE_PROCESSING: + break; + case shell_integration::STATE_IS_DEFAULT: + OpenURLFromTabInternal(profile, params); + break; + case shell_integration::STATE_NOT_DEFAULT: + case shell_integration::STATE_UNKNOWN: + platform_util::OpenExternal(profile, params.url); + break; } - - private: - scoped_ptr<content::WebContents> source_; - const content::OpenURLParams params_; -}; +} } // namespace @@ -147,22 +134,13 @@ ChromeAppDelegate::NewWindowContentsDelegate::OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) { if (source) { - // This NewWindowContentsDelegate was given ownership of the incoming - // WebContents by being assigned as its delegate within - // ChromeAppDelegate::AddNewContents, but this is the first time - // NewWindowContentsDelegate actually sees the WebContents. - // Here it is captured for deletion. - scoped_ptr<content::WebContents> owned_source(source); - scoped_refptr<shell_integration::DefaultWebClientWorker> + // Object lifetime notes: StartCheckIsDefault() takes lifetime ownership of + // check_if_default_browser_worker and will clean up after the asynchronous + // tasks. + scoped_refptr<shell_integration::DefaultBrowserWorker> check_if_default_browser_worker = - new shell_integration::DefaultBrowserWorker( - new OpenURLFromTabBasedOnBrowserDefault(std::move(owned_source), - params), - /*delete_observer=*/true); - // Object lifetime notes: The OpenURLFromTabBasedOnBrowserDefault is owned - // by check_if_default_browser_worker. StartCheckIsDefault() takes lifetime - // ownership of check_if_default_browser_worker and will clean up after - // the asynchronous tasks. + new shell_integration::DefaultBrowserWorker(base::Bind( + &OnCheckIsDefaultBrowserFinished, base::Owned(source), params)); check_if_default_browser_worker->StartCheckIsDefault(); } return NULL; diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index a858f2b..10cae39 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc @@ -876,18 +876,14 @@ class FakeDelegate : public ProtocolHandlerRegistry::Delegate { // side effects on other tests. } - shell_integration::DefaultProtocolClientWorker* CreateShellWorker( - shell_integration::DefaultWebClientObserver* observer, + scoped_refptr<shell_integration::DefaultProtocolClientWorker> + CreateShellWorker( + const shell_integration::DefaultWebClientWorkerCallback& callback, const std::string& protocol) override { VLOG(1) << "CreateShellWorker"; return NULL; } - ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver( - ProtocolHandlerRegistry* registry) override { - return NULL; - } - void RegisterWithOSAsDefaultClient( const std::string& protocol, ProtocolHandlerRegistry* registry) override { diff --git a/chrome/browser/ui/startup/default_browser_prompt.cc b/chrome/browser/ui/startup/default_browser_prompt.cc index 4249abe..268c76f 100644 --- a/chrome/browser/ui/startup/default_browser_prompt.cc +++ b/chrome/browser/ui/startup/default_browser_prompt.cc @@ -180,8 +180,8 @@ bool DefaultBrowserInfoBarDelegate::Accept() { // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. scoped_refptr<shell_integration::DefaultBrowserWorker>( - new shell_integration::DefaultBrowserWorker(nullptr, - /*delete_observer=*/false)) + new shell_integration::DefaultBrowserWorker( + shell_integration::DefaultWebClientWorkerCallback())) ->StartSetAsDefault(); return true; } @@ -198,61 +198,14 @@ bool DefaultBrowserInfoBarDelegate::Cancel() { return true; } -// A shell_integration::DefaultWebClientObserver that handles the check to -// determine whether or not to show the default browser prompt. If Chrome is the -// default browser, then the kCheckDefaultBrowser pref is reset. Otherwise, the -// prompt is shown. -class CheckDefaultBrowserObserver - : public shell_integration::DefaultWebClientObserver { - public: - CheckDefaultBrowserObserver(const base::FilePath& profile_path, - bool show_prompt); - ~CheckDefaultBrowserObserver() override; - - private: - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override; - - void ResetCheckDefaultBrowserPref(); - void ShowPrompt(); - - // The path to the profile for which the prompt is to be shown. - base::FilePath profile_path_; - - // True if the prompt is to be shown if Chrome is not the default browser. - bool show_prompt_; - - DISALLOW_COPY_AND_ASSIGN(CheckDefaultBrowserObserver); -}; - -CheckDefaultBrowserObserver::CheckDefaultBrowserObserver( - const base::FilePath& profile_path, - bool show_prompt) - : profile_path_(profile_path), show_prompt_(show_prompt) {} - -CheckDefaultBrowserObserver::~CheckDefaultBrowserObserver() {} - -void CheckDefaultBrowserObserver::SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) { - if (state == shell_integration::STATE_IS_DEFAULT) { - // Notify the user in the future if Chrome ceases to be the user's chosen - // default browser. - ResetCheckDefaultBrowserPref(); - } else if (show_prompt_ && state == shell_integration::STATE_NOT_DEFAULT && - shell_integration::CanSetAsDefaultBrowser() != - shell_integration::SET_DEFAULT_NOT_ALLOWED) { - ShowPrompt(); - } -} - -void CheckDefaultBrowserObserver::ResetCheckDefaultBrowserPref() { +void ResetCheckDefaultBrowserPref(const base::FilePath& profile_path) { Profile* profile = - g_browser_process->profile_manager()->GetProfileByPath(profile_path_); + g_browser_process->profile_manager()->GetProfileByPath(profile_path); if (profile) profile->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true); } -void CheckDefaultBrowserObserver::ShowPrompt() { +void ShowPrompt() { Browser* browser = chrome::FindLastActive(); if (!browser) return; // Reached during ui tests. @@ -270,6 +223,21 @@ void CheckDefaultBrowserObserver::ShowPrompt() { ->GetPrefs()); } +void OnCheckIsDefaultBrowserFinished( + const base::FilePath& profile_path, + bool show_prompt, + shell_integration::DefaultWebClientUIState state) { + if (state == shell_integration::STATE_IS_DEFAULT) { + // Notify the user in the future if Chrome ceases to be the user's chosen + // default browser. + ResetCheckDefaultBrowserPref(profile_path); + } else if (show_prompt && state == shell_integration::STATE_NOT_DEFAULT && + shell_integration::CanSetAsDefaultBrowser() != + shell_integration::SET_DEFAULT_NOT_ALLOWED) { + ShowPrompt(); + } +} + } // namespace namespace chrome { @@ -314,9 +282,8 @@ void ShowDefaultBrowserPrompt(Profile* profile) { } scoped_refptr<shell_integration::DefaultBrowserWorker>( - new shell_integration::DefaultBrowserWorker( - new CheckDefaultBrowserObserver(profile->GetPath(), show_prompt), - /*delete_observer=*/true)) + new shell_integration::DefaultBrowserWorker(base::Bind( + &OnCheckIsDefaultBrowserFinished, profile->GetPath(), show_prompt))) ->StartCheckIsDefault(); } diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index 1e56c52..fbf5f2d 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc @@ -7,8 +7,6 @@ #include <stddef.h> #include <set> -#include <string> -#include <vector> #include "base/bind.h" #include "base/bind_helpers.h" @@ -197,8 +195,9 @@ BrowserOptionsHandler::BrowserOptionsHandler() // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. default_browser_worker_ = new shell_integration::DefaultBrowserWorker( - this, /*delete_observer=*/false); -#endif + base::Bind(&BrowserOptionsHandler::OnDefaultBrowserWorkerFinished, + weak_ptr_factory_.GetWeakPtr())); +#endif // !defined(OS_CHROMEOS) #if defined(ENABLE_SERVICE_DISCOVERY) cloud_print_mdns_ui_enabled_ = true; @@ -211,10 +210,6 @@ BrowserOptionsHandler::~BrowserOptionsHandler() { if (sync_service) sync_service->RemoveObserver(this); -#if !defined(OS_CHROMEOS) - if (default_browser_worker_.get()) - default_browser_worker_->ObserverDestroyed(); -#endif if (template_url_service_) template_url_service_->RemoveObserver(this); // There may be pending file dialogs, we need to tell them that we've gone @@ -1106,6 +1101,7 @@ bool BrowserOptionsHandler::ShouldAllowAdvancedSettings() { } #if !defined(OS_CHROMEOS) + void BrowserOptionsHandler::UpdateDefaultBrowserState() { default_browser_worker_->StartCheckIsDefault(); } @@ -1128,7 +1124,7 @@ void BrowserOptionsHandler::BecomeDefaultBrowser(const base::ListValue* args) { prefs->SetBoolean(prefs::kCheckDefaultBrowser, true); } -void BrowserOptionsHandler::SetDefaultWebClientUIState( +void BrowserOptionsHandler::OnDefaultBrowserWorkerFinished( shell_integration::DefaultWebClientUIState state) { int status_string_id; diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h index edeced0..465e503 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.h +++ b/chrome/browser/ui/webui/options/browser_options_handler.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_BROWSER_OPTIONS_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_OPTIONS_BROWSER_OPTIONS_HANDLER_H_ +#include <string> #include <vector> #include "base/compiler_specific.h" @@ -61,9 +62,6 @@ class BrowserOptionsHandler public sync_driver::SyncServiceObserver, public SigninManagerBase::Observer, public ui::SelectFileDialog::Listener, -#if !defined(OS_CHROMEOS) - public shell_integration::DefaultWebClientObserver, -#endif #if defined(OS_CHROMEOS) public chromeos::system::PointerDeviceObserver::Observer, public policy::ConsumerManagementService::Observer, @@ -177,9 +175,9 @@ class BrowserOptionsHandler // Makes this the default browser. Called from WebUI. void BecomeDefaultBrowser(const base::ListValue* args); - // shell_integration::DefaultWebClientObserver implementation. - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override; + // Receives the default browser state when the worker is done. + void OnDefaultBrowserWorkerFinished( + shell_integration::DefaultWebClientUIState state); // Updates the UI with the given state for the default browser. void SetDefaultBrowserUIString(int status_string_id); diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui.cc b/chrome/browser/ui/webui/set_as_default_browser_ui.cc index 6938596..2aeb4d8 100644 --- a/chrome/browser/ui/webui/set_as_default_browser_ui.cc +++ b/chrome/browser/ui/webui/set_as_default_browser_ui.cc @@ -4,6 +4,9 @@ #include "chrome/browser/ui/webui/set_as_default_browser_ui.h" +#include <string> +#include <vector> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" @@ -93,22 +96,14 @@ class ResponseDelegate { // Event handler for SetAsDefaultBrowserUI. Capable of setting Chrome as the // default browser on button click, closing itself and triggering Chrome // restart. -class SetAsDefaultBrowserHandler - : public WebUIMessageHandler, - public base::SupportsWeakPtr<SetAsDefaultBrowserHandler>, - public shell_integration::DefaultWebClientObserver { +class SetAsDefaultBrowserHandler : public WebUIMessageHandler { public: explicit SetAsDefaultBrowserHandler( const base::WeakPtr<ResponseDelegate>& response_delegate); - ~SetAsDefaultBrowserHandler() override; // WebUIMessageHandler implementation. void RegisterMessages() override; - // shell_integration::DefaultWebClientObserver implementation. - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override; - private: // Handler for the 'Next' (or 'make Chrome the Metro browser') button. void HandleLaunchSetDefaultBrowserFlow(const base::ListValue* args); @@ -116,6 +111,9 @@ class SetAsDefaultBrowserHandler // Close this web ui. void ConcludeInteraction(MakeChromeDefaultResult interaction_result); + void OnDefaultBrowserWorkerFinished( + shell_integration::DefaultWebClientUIState state); + // The worker pointer is reference counted. While it is running, the // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. @@ -123,18 +121,18 @@ class SetAsDefaultBrowserHandler default_browser_worker_; base::WeakPtr<ResponseDelegate> response_delegate_; + // Used to invalidate the DefaultBrowserWorker callback. + base::WeakPtrFactory<SetAsDefaultBrowserHandler> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(SetAsDefaultBrowserHandler); }; SetAsDefaultBrowserHandler::SetAsDefaultBrowserHandler( const base::WeakPtr<ResponseDelegate>& response_delegate) - : default_browser_worker_(new shell_integration::DefaultBrowserWorker( - this, - /*delete_observer=*/false)), - response_delegate_(response_delegate) {} - -SetAsDefaultBrowserHandler::~SetAsDefaultBrowserHandler() { - default_browser_worker_->ObserverDestroyed(); + : response_delegate_(response_delegate), weak_ptr_factory_(this) { + default_browser_worker_ = new shell_integration::DefaultBrowserWorker( + base::Bind(&SetAsDefaultBrowserHandler::OnDefaultBrowserWorkerFinished, + weak_ptr_factory_.GetWeakPtr())); } void SetAsDefaultBrowserHandler::RegisterMessages() { @@ -144,22 +142,6 @@ void SetAsDefaultBrowserHandler::RegisterMessages() { base::Unretained(this))); } -void SetAsDefaultBrowserHandler::SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) { - // The callback is expected to be invoked once the procedure has completed. - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (state == shell_integration::STATE_NOT_DEFAULT) { - // The operation concluded, but Chrome is still not the default. This - // suggests the user has decided not to make Chrome the default. - ConcludeInteraction(MAKE_CHROME_DEFAULT_REGRETTED); - } else if (state == shell_integration::STATE_IS_DEFAULT) { - ConcludeInteraction(MAKE_CHROME_DEFAULT_ACCEPTED); - } - - // Otherwise, keep the dialog open since the user probably didn't make a - // choice. -} - void SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow( const base::ListValue* args) { default_browser_worker_->StartSetAsDefault(); @@ -181,6 +163,22 @@ void SetAsDefaultBrowserHandler::ConcludeInteraction( } } +void SetAsDefaultBrowserHandler::OnDefaultBrowserWorkerFinished( + shell_integration::DefaultWebClientUIState state) { + // The callback is expected to be invoked once the procedure has completed. + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (state == shell_integration::STATE_NOT_DEFAULT) { + // The operation concluded, but Chrome is still not the default. This + // suggests the user has decided not to make Chrome the default. + ConcludeInteraction(MAKE_CHROME_DEFAULT_REGRETTED); + } else if (state == shell_integration::STATE_IS_DEFAULT) { + ConcludeInteraction(MAKE_CHROME_DEFAULT_ACCEPTED); + } + + // Otherwise, keep the dialog open since the user probably didn't make a + // choice. +} + // A web dialog delegate implementation for when 'Make Chrome Metro' UI // is displayed on a dialog. class SetAsDefaultBrowserDialogImpl : public ui::WebDialogDelegate, diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc index fa60315..881be4d 100644 --- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc @@ -21,18 +21,17 @@ bool IsDisabledByPolicy(const BooleanPrefMember& pref) { } // namespace DefaultBrowserHandler::DefaultBrowserHandler(content::WebUI* webui) - : default_browser_worker_(new shell_integration::DefaultBrowserWorker( - this, - /*delete_observer=*/false)) { + : weak_ptr_factory_(this) { + default_browser_worker_ = new shell_integration::DefaultBrowserWorker( + base::Bind(&DefaultBrowserHandler::OnDefaultBrowserWorkerFinished, + weak_ptr_factory_.GetWeakPtr())); default_browser_policy_.Init( prefs::kDefaultBrowserSettingEnabled, g_browser_process->local_state(), base::Bind(&DefaultBrowserHandler::RequestDefaultBrowserState, base::Unretained(this), nullptr)); } -DefaultBrowserHandler::~DefaultBrowserHandler() { - default_browser_worker_->ObserverDestroyed(); -} +DefaultBrowserHandler::~DefaultBrowserHandler() {} void DefaultBrowserHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( @@ -45,7 +44,23 @@ void DefaultBrowserHandler::RegisterMessages() { base::Unretained(this))); } -void DefaultBrowserHandler::SetDefaultWebClientUIState( +void DefaultBrowserHandler::RequestDefaultBrowserState( + const base::ListValue* /*args*/) { + default_browser_worker_->StartCheckIsDefault(); +} + +void DefaultBrowserHandler::SetAsDefaultBrowser(const base::ListValue* args) { + CHECK(!IsDisabledByPolicy(default_browser_policy_)); + + default_browser_worker_->StartSetAsDefault(); + + // If the user attempted to make Chrome the default browser, notify + // them when this changes. + Profile::FromWebUI(web_ui())->GetPrefs()->SetBoolean( + prefs::kCheckDefaultBrowser, true); +} + +void DefaultBrowserHandler::OnDefaultBrowserWorkerFinished( shell_integration::DefaultWebClientUIState state) { if (state == shell_integration::STATE_PROCESSING) return; @@ -69,20 +84,4 @@ void DefaultBrowserHandler::SetDefaultWebClientUIState( is_default, can_be_default); } -void DefaultBrowserHandler::RequestDefaultBrowserState( - const base::ListValue* /*args*/) { - default_browser_worker_->StartCheckIsDefault(); -} - -void DefaultBrowserHandler::SetAsDefaultBrowser(const base::ListValue* args) { - CHECK(!IsDisabledByPolicy(default_browser_policy_)); - - default_browser_worker_->StartSetAsDefault(); - - // If the user attempted to make Chrome the default browser, notify - // them when this changes. - Profile::FromWebUI(web_ui())->GetPrefs()->SetBoolean( - prefs::kCheckDefaultBrowser, true); -} - } // namespace settings diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h index 9aa4dfe..25c63a6 100644 --- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h +++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_DEFAULT_BROWSER_HANDLER_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/shell_integration.h" #include "chrome/browser/ui/webui/settings/md_settings_ui.h" @@ -24,9 +25,7 @@ namespace settings { // The application used by the OS to open web documents (e.g. *.html) // is the "default browser". This class is an API for the JavaScript // settings code to change the default browser settings. -class DefaultBrowserHandler - : public SettingsPageUIHandler, - public shell_integration::DefaultWebClientObserver { +class DefaultBrowserHandler : public SettingsPageUIHandler { public: explicit DefaultBrowserHandler(content::WebUI* webui); ~DefaultBrowserHandler() override; @@ -34,10 +33,6 @@ class DefaultBrowserHandler // SettingsPageUIHandler implementation. void RegisterMessages() override; - // shell_integration::DefaultWebClientObserver implementation. - void SetDefaultWebClientUIState( - shell_integration::DefaultWebClientUIState state) override; - private: // Called from WebUI to request the current state. void RequestDefaultBrowserState(const base::ListValue* args); @@ -45,6 +40,11 @@ class DefaultBrowserHandler // Makes this the default browser. Called from WebUI. void SetAsDefaultBrowser(const base::ListValue* args); + // Called with the default browser state when the DefaultBrowserWorker is + // done. + void OnDefaultBrowserWorkerFinished( + shell_integration::DefaultWebClientUIState state); + // Reference to a background worker that handles default browser settings. scoped_refptr<shell_integration::DefaultBrowserWorker> default_browser_worker_; @@ -52,6 +52,9 @@ class DefaultBrowserHandler // Policy setting to determine if default browser setting is managed. BooleanPrefMember default_browser_policy_; + // Used to invalidate the DefaultBrowserWorker callback. + base::WeakPtrFactory<DefaultBrowserHandler> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(DefaultBrowserHandler); }; |
