Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1674)

Unified Diff: chrome/browser/shell_integration.cc

Issue 1397563002: Setting chrome as the default browser is now fixed on Windows 10 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2526
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/shell_integration.h ('k') | chrome/browser/shell_integration_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/shell_integration.cc
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 25e8ec7c55a6a087273821b26f6a3be7c7bb0be8..d8c5b8dcf38352aab3c7937c875c333fd463e3f6 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -7,10 +7,12 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/prefs/pref_service.h"
#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"
@@ -42,6 +44,11 @@ bool ShellIntegration::SetAsDefaultBrowserInteractive() {
}
// static
+bool ShellIntegration::IsSetAsDefaultAsynchronous() {
+ return false;
+}
+
+// static
bool ShellIntegration::SetAsDefaultProtocolClientInteractive(
const std::string& protocol) {
return false;
@@ -53,7 +60,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;
}
#if !defined(OS_WIN)
@@ -162,51 +173,67 @@ 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_) {
+ if (set_as_default_initialized_) {
+ FinalizeSetAsDefault();
+ set_as_default_initialized_ = false;
+ }
+
+ ReportAttemptResult(AttemptResult::RETRY);
+ }
+
+ set_as_default_in_progress_ = true;
bool interactive_permitted = false;
if (observer_) {
observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
+
+ // The initialization is only useful when there is an observer.
+ set_as_default_initialized_ = InitializeSetAsDefault();
}
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this,
- interactive_permitted));
+
+ // Remember the start time.
+ start_time_ = base::TimeTicks::Now();
+
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DefaultWebClientWorker::SetAsDefault,
+ this, interactive_permitted));
}
void ShellIntegration::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_ = NULL;
+ observer_ = nullptr;
+
+ if (set_as_default_initialized_) {
+ FinalizeSetAsDefault();
+ set_as_default_initialized_ = false;
+ }
+
+ if (set_as_default_in_progress_)
+ ReportAttemptResult(AttemptResult::ABANDONED);
}
///////////////////////////////////////////////////////////////////////////////
// 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);
@@ -214,29 +241,89 @@ void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault(
// if we own it.
if (observer_ && observer_->IsOwnedByWorker()) {
delete observer_;
- observer_ = NULL;
+ observer_ = nullptr;
}
}
-void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault(
- bool interactive_permitted) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+void ShellIntegration::DefaultWebClientWorker::OnSetAsDefaultAttemptComplete(
+ AttemptResult result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // 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;
+
+ if (set_as_default_initialized_) {
+ FinalizeSetAsDefault();
+ set_as_default_initialized_ = false;
+ }
+ if (observer_) {
+ bool succeeded = result == AttemptResult::SUCCESS ||
+ result == AttemptResult::ALREADY_DEFAULT;
+ observer_->OnSetAsDefaultConcluded(succeeded);
+ }
- bool result = SetAsDefault(interactive_permitted);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result));
+ ReportAttemptResult(result);
+
+ // 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::CompleteSetAsDefault(
- 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();
+void ShellIntegration::DefaultWebClientWorker::ReportAttemptResult(
+ AttemptResult result) {
+ if (!ShouldReportAttemptResults())
+ return;
+
+ UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.AsyncSetAsDefault.Result", result,
+ AttemptResult::NUM_ATTEMPT_RESULT_TYPES);
+
+ switch (result) {
+ case SUCCESS:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DefaultBrowser.AsyncSetAsDefault.Duration_Success",
+ base::TimeTicks::Now() - start_time_);
+ break;
+ case FAILURE:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DefaultBrowser.AsyncSetAsDefault.Duration_Failure",
+ base::TimeTicks::Now() - start_time_);
+ break;
+ case ABANDONED:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DefaultBrowser.AsyncSetAsDefault.Duration_Abandoned",
+ base::TimeTicks::Now() - start_time_);
+ break;
+ case RETRY:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DefaultBrowser.AsyncSetAsDefault.Duration_Retry",
+ base::TimeTicks::Now() - start_time_);
+ break;
+ default:
+ break;
+ }
+}
+
+bool ShellIntegration::DefaultWebClientWorker::InitializeSetAsDefault() {
+ return true;
+}
+
+void ShellIntegration::DefaultWebClientWorker::FinalizeSetAsDefault() {}
+
+#if !defined(OS_WIN)
+// static
+bool ShellIntegration::DefaultWebClientWorker::ShouldReportAttemptResults() {
+ return false;
}
+#endif // !defined(OS_WIN)
void ShellIntegration::DefaultWebClientWorker::UpdateUI(
DefaultWebClientState state) {
@@ -266,30 +353,59 @@ ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
: DefaultWebClientWorker(observer) {
}
+ShellIntegration::DefaultBrowserWorker::~DefaultBrowserWorker() {}
+
///////////////////////////////////////////////////////////////////////////////
// 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();
+ AttemptResult result = AttemptResult::FAILURE;
+ switch (CanSetAsDefaultBrowser()) {
+ case SET_DEFAULT_NOT_ALLOWED:
+ NOTREACHED();
break;
- case ShellIntegration::SET_DEFAULT_INTERACTIVE:
- if (interactive_permitted)
- result = ShellIntegration::SetAsDefaultBrowserInteractive();
+ case SET_DEFAULT_UNATTENDED:
+ if (SetAsDefaultBrowser())
+ result = AttemptResult::SUCCESS;
break;
- default:
+ case SET_DEFAULT_INTERACTIVE:
+ if (interactive_permitted && SetAsDefaultBrowserInteractive())
+ result = AttemptResult::SUCCESS;
+ break;
+ 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 = AttemptResult::ALREADY_DEFAULT;
+ break;
+ }
+ // This function will cause OnSetAsDefaultAttemptComplete() to be called
+ // asynchronously via a filter established in InitializeSetAsDefault().
+ if (!SetAsDefaultBrowserAsynchronous()) {
+ result = AttemptResult::LAUNCH_FAILURE;
+ break;
+ }
+ return;
+#else
NOTREACHED();
+ break;
+#endif
}
-
- return result;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this,
+ result));
}
///////////////////////////////////////////////////////////////////////////////
@@ -305,28 +421,39 @@ 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;
+ AttemptResult result = AttemptResult::FAILURE;
+ 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:
+ if (SetAsDefaultProtocolClient(protocol_))
+ result = AttemptResult::SUCCESS;
break;
- case ShellIntegration::SET_DEFAULT_INTERACTIVE:
- if (interactive_permitted) {
- result = ShellIntegration::SetAsDefaultProtocolClientInteractive(
- protocol_);
+ case SET_DEFAULT_INTERACTIVE:
+ if (interactive_permitted &&
+ SetAsDefaultProtocolClientInteractive(protocol_)) {
+ result = AttemptResult::SUCCESS;
}
break;
+ case SET_DEFAULT_ASYNCHRONOUS:
+ NOTREACHED();
+ break;
}
-
- return result;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DefaultProtocolClientWorker::OnSetAsDefaultAttemptComplete,
+ this, result));
}
« no previous file with comments | « chrome/browser/shell_integration.h ('k') | chrome/browser/shell_integration_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698