Index: chrome/browser/shell_integration.cc |
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc |
index 2ac4b5896e9b7a6900d43331a66bd853698a581f..5460a53fa8fa3806904ac4db47e3f8ab1b1c0694 100644 |
--- a/chrome/browser/shell_integration.cc |
+++ b/chrome/browser/shell_integration.cc |
@@ -11,6 +11,7 @@ |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/threading/thread_restrictions.h" |
+#include "base/timer/timer.h" |
#include "chrome/browser/policy/policy_path_parser.h" |
#include "chrome/common/chrome_paths.h" |
#include "chrome/common/chrome_switches.h" |
@@ -34,7 +35,11 @@ ShellIntegration::DefaultWebClientSetPermission |
ShellIntegration::CanSetAsDefaultProtocolClient() { |
// Allowed as long as the browser can become the operating system default |
// browser. |
- return CanSetAsDefaultBrowser(); |
+ DefaultWebClientSetPermission permission = CanSetAsDefaultBrowser(); |
+ |
+ // Set as default asynchronous is only supported for default web browser. |
+ return (permission == SET_DEFAULT_ASYNCHRONOUS) ? SET_DEFAULT_INTERACTIVE |
+ : permission; |
} |
static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL; |
@@ -124,6 +129,13 @@ bool ShellIntegration::SetAsDefaultBrowserInteractive() { |
return false; |
} |
+#if !defined(OS_WIN) |
+// static |
+bool ShellIntegration::IsSetAsDefaultAsynchronous() { |
+ return false; |
+} |
+#endif // !defined(OS_WIN) |
+ |
// static |
bool ShellIntegration::SetAsDefaultProtocolClientInteractive( |
const std::string& protocol) { |
@@ -152,29 +164,34 @@ bool ShellIntegration::DefaultWebClientObserver:: |
ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker( |
DefaultWebClientObserver* observer) |
- : observer_(observer) { |
-} |
+ : observer_(observer) {} |
void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() { |
if (observer_) { |
observer_->SetDefaultWebClientUIState(STATE_PROCESSING); |
BrowserThread::PostTask( |
BrowserThread::FILE, FROM_HERE, |
- base::Bind( |
- &DefaultWebClientWorker::ExecuteCheckIsDefault, this)); |
+ base::Bind(&DefaultWebClientWorker::CheckIsDefault, this)); |
} |
} |
void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() { |
+ // Cancel the already running process if another start is requested. |
+ if (set_as_default_in_progress_) |
grt (UTC plus 2)
2015/09/30 17:22:32
in looking at how set_as_default_in_progress_ is u
Patrick Monette
2015/10/01 21:12:50
Done.
|
+ OnSetAsDefaultAttemptComplete(false); |
+ |
+ set_as_default_in_progress_ = true; |
bool interactive_permitted = false; |
if (observer_) { |
observer_->SetDefaultWebClientUIState(STATE_PROCESSING); |
interactive_permitted = observer_->IsInteractiveSetDefaultPermitted(); |
+ |
+ InitializeSetAsDefault(); |
} |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this, |
- interactive_permitted)); |
+ |
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&DefaultWebClientWorker::SetAsDefault, |
+ this, interactive_permitted)); |
} |
void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() { |
@@ -182,21 +199,20 @@ void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() { |
// our worker thread returns after the view is dead. |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
observer_ = NULL; |
+ // If an attempt to set the default browser is already in progress, its result |
+ // won't be posted to any observers. Manually invoke |
+ // OnSetAsDefaultAttemptComplete() to ensure we free the default browser |
grt (UTC plus 2)
2015/09/30 17:22:32
nit: "free" -> "clear"?
Patrick Monette
2015/10/01 21:12:51
Done.
|
+ // callback and timer. |
+ if (set_as_default_in_progress_) |
+ OnSetAsDefaultAttemptComplete(false); |
} |
/////////////////////////////////////////////////////////////////////////////// |
// DefaultWebClientWorker, private: |
-void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() { |
- DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
- DefaultWebClientState state = CheckIsDefault(); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind( |
- &DefaultWebClientWorker::CompleteCheckIsDefault, this, state)); |
-} |
+ShellIntegration::DefaultWebClientWorker::~DefaultWebClientWorker() {} |
-void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault( |
+void ShellIntegration::DefaultWebClientWorker::OnCheckIsDefaultComplete( |
DefaultWebClientState state) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
UpdateUI(state); |
@@ -208,26 +224,36 @@ void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault( |
} |
} |
-void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault( |
- bool interactive_permitted) { |
- DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
- |
- bool result = SetAsDefault(interactive_permitted); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result)); |
-} |
- |
-void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault( |
+void ShellIntegration::DefaultWebClientWorker::OnSetAsDefaultAttemptComplete( |
bool succeeded) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- // First tell the observer what the SetAsDefault call has returned. |
- if (observer_) |
- observer_->OnSetAsDefaultConcluded(succeeded); |
- // Set as default completed, check again to make sure it stuck... |
- StartCheckIsDefault(); |
+ // Hold on to a reference because if this was called via the default browser |
+ // callback in StartupBrowserCreator, clearing the callback in |
+ // FinalizeSetAsDefault would otherwise remove the last reference and delete |
+ // us in the middle of this function. |
+ scoped_refptr<DefaultWebClientWorker> scoped_ref(this); |
+ |
+ if (set_as_default_in_progress_) { |
+ set_as_default_in_progress_ = false; |
+ |
+ FinalizeSetAsDefault(succeeded); |
+ if (observer_) |
+ observer_->OnSetAsDefaultConcluded(succeeded); |
+ |
+ // Start the default browser check which will notify the observer as to |
+ // whether Chrome is really the default browser. This is needed because |
+ // detecting that the process was successful is not 100% sure. |
+ // For example, on Windows 10+, the user might have unchecked the "Always |
+ // use this app" checkbox which can't be detected. |
+ StartCheckIsDefault(); |
+ } |
} |
+void ShellIntegration::DefaultWebClientWorker::InitializeSetAsDefault() {} |
+ |
+void ShellIntegration::DefaultWebClientWorker::FinalizeSetAsDefault( |
+ bool succeeded) {} |
+ |
void ShellIntegration::DefaultWebClientWorker::UpdateUI( |
DefaultWebClientState state) { |
if (observer_) { |
@@ -256,30 +282,58 @@ ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker( |
: DefaultWebClientWorker(observer) { |
} |
+ShellIntegration::DefaultBrowserWorker::~DefaultBrowserWorker() { |
+ if (set_as_default_in_progress_) |
+ OnSetAsDefaultAttemptComplete(false); |
grt (UTC plus 2)
2015/09/30 17:22:32
i don't think this could ever happen. the object c
Patrick Monette
2015/10/01 21:12:50
SGTM. Done.
|
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// DefaultBrowserWorker, private: |
-ShellIntegration::DefaultWebClientState |
-ShellIntegration::DefaultBrowserWorker::CheckIsDefault() { |
- return ShellIntegration::GetDefaultBrowser(); |
+void ShellIntegration::DefaultBrowserWorker::CheckIsDefault() { |
+ DefaultWebClientState state = GetDefaultBrowser(); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state)); |
} |
-bool ShellIntegration::DefaultBrowserWorker::SetAsDefault( |
+void ShellIntegration::DefaultBrowserWorker::SetAsDefault( |
bool interactive_permitted) { |
bool result = false; |
- switch (ShellIntegration::CanSetAsDefaultBrowser()) { |
- case ShellIntegration::SET_DEFAULT_UNATTENDED: |
- result = ShellIntegration::SetAsDefaultBrowser(); |
+ switch (CanSetAsDefaultBrowser()) { |
+ case SET_DEFAULT_NOT_ALLOWED: |
+ NOTREACHED(); |
+ break; |
+ case SET_DEFAULT_UNATTENDED: |
+ result = SetAsDefaultBrowser(); |
break; |
- case ShellIntegration::SET_DEFAULT_INTERACTIVE: |
+ case SET_DEFAULT_INTERACTIVE: |
if (interactive_permitted) |
- result = ShellIntegration::SetAsDefaultBrowserInteractive(); |
+ result = SetAsDefaultBrowserInteractive(); |
break; |
- default: |
+ case SET_DEFAULT_ASYNCHRONOUS: |
+#if defined(OS_WIN) |
+ if (!interactive_permitted) |
+ break; |
+ if (GetDefaultBrowser() == IS_DEFAULT) { |
+ // Don't start the asynchronous operation since it could result in |
+ // losing the default browser status. |
+ result = true; |
+ break; |
+ } |
+ // This function will cause OnSetAsDefaultAttemptComplete() to be called |
+ // asynchronously via a filter established in InitializeSetAsDefault(). |
+ SetAsDefaultBrowserAsynchronous(); |
+ return; |
+#else |
NOTREACHED(); |
+ break; |
+#endif |
} |
- |
- return result; |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this, |
+ result)); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -295,28 +349,37 @@ ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker( |
/////////////////////////////////////////////////////////////////////////////// |
// DefaultProtocolClientWorker, private: |
-ShellIntegration::DefaultWebClientState |
-ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() { |
- return ShellIntegration::IsDefaultProtocolClient(protocol_); |
+ShellIntegration::DefaultProtocolClientWorker::~DefaultProtocolClientWorker() {} |
+ |
+void ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() { |
+ DefaultWebClientState state = IsDefaultProtocolClient(protocol_); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&DefaultProtocolClientWorker::OnCheckIsDefaultComplete, this, |
+ state)); |
} |
-bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault( |
+void ShellIntegration::DefaultProtocolClientWorker::SetAsDefault( |
bool interactive_permitted) { |
bool result = false; |
- switch (ShellIntegration::CanSetAsDefaultProtocolClient()) { |
- case ShellIntegration::SET_DEFAULT_NOT_ALLOWED: |
- result = false; |
+ switch (CanSetAsDefaultProtocolClient()) { |
+ case SET_DEFAULT_NOT_ALLOWED: |
+ // Not allowed, do nothing. |
break; |
- case ShellIntegration::SET_DEFAULT_UNATTENDED: |
- result = ShellIntegration::SetAsDefaultProtocolClient(protocol_); |
+ case SET_DEFAULT_UNATTENDED: |
+ result = SetAsDefaultProtocolClient(protocol_); |
break; |
- case ShellIntegration::SET_DEFAULT_INTERACTIVE: |
+ case SET_DEFAULT_INTERACTIVE: |
if (interactive_permitted) { |
- result = ShellIntegration::SetAsDefaultProtocolClientInteractive( |
- protocol_); |
+ result = SetAsDefaultProtocolClientInteractive(protocol_); |
} |
break; |
+ case SET_DEFAULT_ASYNCHRONOUS: |
+ NOTREACHED(); |
+ break; |
} |
- |
- return result; |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&DefaultProtocolClientWorker::OnSetAsDefaultAttemptComplete, |
+ this, result)); |
} |