Chromium Code Reviews| Index: chrome/browser/ui/startup/default_browser_prompt.cc |
| diff --git a/chrome/browser/ui/startup/default_browser_prompt.cc b/chrome/browser/ui/startup/default_browser_prompt.cc |
| index 67199bf78eebac98fb2960f5c88f74f681ae8266..b2cf97cfd64e18b5d53e81ad7e91aebf29e4118d 100644 |
| --- a/chrome/browser/ui/startup/default_browser_prompt.cc |
| +++ b/chrome/browser/ui/startup/default_browser_prompt.cc |
| @@ -8,14 +8,13 @@ |
| #include "base/location.h" |
| #include "base/memory/weak_ptr.h" |
| -#include "base/metrics/histogram.h" |
| +#include "base/metrics/histogram_macros.h" |
| #include "base/prefs/pref_registry_simple.h" |
| #include "base/prefs/pref_service.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/thread_task_runner_handle.h" |
| #include "base/version.h" |
| #include "chrome/browser/browser_process.h" |
| -#include "chrome/browser/first_run/first_run.h" |
| #include "chrome/browser/infobars/infobar_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| @@ -26,12 +25,9 @@ |
| #include "chrome/common/pref_names.h" |
| #include "chrome/grit/chromium_strings.h" |
| #include "chrome/grit/generated_resources.h" |
| -#include "chrome/installer/util/master_preferences.h" |
| -#include "chrome/installer/util/master_preferences_constants.h" |
| #include "components/infobars/core/confirm_infobar_delegate.h" |
| #include "components/infobars/core/infobar.h" |
| #include "components/version_info/version_info.h" |
| -#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/web_contents.h" |
| #include "grit/theme_resources.h" |
| @@ -40,39 +36,80 @@ |
| namespace { |
| -// Calls the appropriate function for setting Chrome as the default browser. |
| -// This requires IO access (registry) and may result in interaction with a |
| -// modal system UI. |
| -void SetChromeAsDefaultBrowser(bool interactive_flow, PrefService* prefs) { |
| - if (interactive_flow) { |
| +// A ShellIntegration::DefaultWebClientObserver that records user metrics for |
| +// the result of making Chrome the default browser. |
| +class SetDefaultBrowserObserver |
| + : public ShellIntegration::DefaultWebClientObserver { |
| + public: |
| + SetDefaultBrowserObserver(); |
| + ~SetDefaultBrowserObserver() override; |
| + |
| + void SetDefaultWebClientUIState( |
|
Peter Kasting
2015/09/22 21:17:25
Nit: I would make these private if they aren't cal
grt (UTC plus 2)
2015/09/23 13:57:49
Done here and in CheckDefaultBrowserObserver.
|
| + ShellIntegration::DefaultWebClientUIState state) override; |
| + void OnSetAsDefaultConcluded(bool succeeded) override; |
| + bool IsOwnedByWorker() override; |
| + bool IsInteractiveSetDefaultPermitted() override; |
| + |
| + private: |
| + // True if an interactive flow will be used (i.e., Windows 8+). |
| + bool interactive_; |
| + |
| + // The result of the call to ShellIntegration::SetAsDefaultBrowser() or |
| + // ShellIntegration::SetAsDefaultBrowserInteractive(). |
| + bool interaction_succeeded_ = false; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SetDefaultBrowserObserver); |
| +}; |
| + |
| +SetDefaultBrowserObserver::SetDefaultBrowserObserver() |
| + : interactive_(ShellIntegration::CanSetAsDefaultBrowser() == |
| + ShellIntegration::SET_DEFAULT_INTERACTIVE) { |
| + // Log that an attempt is about to be made to set one way or the other. |
| + if (interactive_) |
| UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.SetAsDefaultUI", true); |
| - if (!ShellIntegration::SetAsDefaultBrowserInteractive()) { |
| - UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.SetAsDefaultUIFailed", true); |
| - } else if (ShellIntegration::GetDefaultBrowser() == |
| - ShellIntegration::NOT_DEFAULT) { |
| - // If the interaction succeeded but we are still not the default browser |
| - // it likely means the user simply selected another browser from the |
| - // panel. We will respect this choice and write it down as 'no, thanks'. |
| - UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.DontSetAsDefault", true); |
| - } |
| - } else { |
| + else |
| UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.SetAsDefault", true); |
| - ShellIntegration::SetAsDefaultBrowser(); |
| +} |
| + |
| +SetDefaultBrowserObserver::~SetDefaultBrowserObserver() {} |
| + |
| +void SetDefaultBrowserObserver::SetDefaultWebClientUIState( |
| + ShellIntegration::DefaultWebClientUIState state) { |
| + if (interactive_ && interaction_succeeded_ && |
| + state == ShellIntegration::STATE_NOT_DEFAULT) { |
| + // The interactive flow succeeded, yet Chrome is not the default browser. |
| + // This likely means that the user selected another browser from the panel. |
| + // Consider this the same as canceling the infobar. |
| + UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.DontSetAsDefault", true); |
| + } |
| +} |
| + |
| +void SetDefaultBrowserObserver::OnSetAsDefaultConcluded(bool succeeded) { |
| + interaction_succeeded_ = succeeded; |
| + if (interactive_ && !succeeded) { |
| + // Log that the interactive flow failed. |
| + UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.SetAsDefaultUIFailed", true); |
| } |
| } |
| +bool SetDefaultBrowserObserver::IsOwnedByWorker() { |
| + // Instruct the DefaultBrowserWorker to delete this instance when it is done. |
| + return true; |
| +} |
| + |
| +bool SetDefaultBrowserObserver::IsInteractiveSetDefaultPermitted() { |
| + return true; |
| +} |
| + |
| // The delegate for the infobar shown when Chrome is not the default browser. |
| class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate { |
| public: |
| // Creates a default browser infobar and delegate and adds the infobar to |
| // |infobar_service|. |
| - static void Create(InfoBarService* infobar_service, |
| - PrefService* prefs, |
| - bool interactive_flow_required); |
| + static void Create(InfoBarService* infobar_service, PrefService* prefs); |
| private: |
| - DefaultBrowserInfoBarDelegate(PrefService* prefs, |
| - bool interactive_flow_required); |
| + explicit DefaultBrowserInfoBarDelegate(PrefService* prefs); |
| ~DefaultBrowserInfoBarDelegate() override; |
| void AllowExpiry() { should_expire_ = true; } |
| @@ -95,10 +132,6 @@ class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate { |
| // Whether the info-bar should be dismissed on the next navigation. |
| bool should_expire_; |
| - // Whether changing the default application will require entering the |
| - // modal-UI flow. |
| - const bool interactive_flow_required_; |
| - |
| // Used to delay the expiration of the info-bar. |
| base::WeakPtrFactory<DefaultBrowserInfoBarDelegate> weak_factory_; |
| @@ -107,21 +140,17 @@ class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate { |
| // static |
| void DefaultBrowserInfoBarDelegate::Create(InfoBarService* infobar_service, |
| - PrefService* prefs, |
| - bool interactive_flow_required) { |
| - infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar( |
| - scoped_ptr<ConfirmInfoBarDelegate>(new DefaultBrowserInfoBarDelegate( |
| - prefs, interactive_flow_required)))); |
| + PrefService* prefs) { |
| + infobar_service->AddInfoBar( |
| + infobar_service->CreateConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate>( |
| + new DefaultBrowserInfoBarDelegate(prefs)))); |
| } |
| -DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate( |
| - PrefService* prefs, |
| - bool interactive_flow_required) |
| +DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate(PrefService* prefs) |
| : ConfirmInfoBarDelegate(), |
| prefs_(prefs), |
| action_taken_(false), |
| should_expire_(false), |
| - interactive_flow_required_(interactive_flow_required), |
| weak_factory_(this) { |
| // We want the info-bar to stick-around for few seconds and then be hidden |
| // on the next navigation after that. |
| @@ -165,11 +194,9 @@ bool DefaultBrowserInfoBarDelegate::OKButtonTriggersUACPrompt() const { |
| bool DefaultBrowserInfoBarDelegate::Accept() { |
| action_taken_ = true; |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::FILE, FROM_HERE, |
| - base::Bind(&SetChromeAsDefaultBrowser, interactive_flow_required_, |
| - prefs_)); |
| - |
| + scoped_refptr<ShellIntegration::DefaultBrowserWorker>( |
| + new ShellIntegration::DefaultBrowserWorker(new SetDefaultBrowserObserver)) |
| + ->StartSetAsDefault(); |
| return true; |
| } |
| @@ -181,8 +208,72 @@ bool DefaultBrowserInfoBarDelegate::Cancel() { |
| return true; |
| } |
| -void NotifyNotDefaultBrowserCallback(chrome::HostDesktopType desktop_type) { |
| - Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type); |
| +// A ShellIntegration::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 ShellIntegration::DefaultWebClientObserver { |
| + public: |
| + CheckDefaultBrowserObserver(const base::FilePath& profile_path, |
| + bool show_prompt, |
| + chrome::HostDesktopType desktop_type); |
| + ~CheckDefaultBrowserObserver() override; |
|
Peter Kasting
2015/09/22 21:17:25
Nit: Blank line below this for consistency with th
grt (UTC plus 2)
2015/09/23 13:57:49
Done.
|
| + void SetDefaultWebClientUIState( |
| + ShellIntegration::DefaultWebClientUIState state) override; |
| + bool IsOwnedByWorker() override; |
| + |
| + private: |
| + 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_; |
| + chrome::HostDesktopType desktop_type_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CheckDefaultBrowserObserver); |
| +}; |
| + |
| +CheckDefaultBrowserObserver::CheckDefaultBrowserObserver( |
| + const base::FilePath& profile_path, |
| + bool show_prompt, |
| + chrome::HostDesktopType desktop_type) |
| + : profile_path_(profile_path), |
| + show_prompt_(show_prompt), |
| + desktop_type_(desktop_type) {} |
| + |
| +CheckDefaultBrowserObserver::~CheckDefaultBrowserObserver() {} |
| + |
| +void CheckDefaultBrowserObserver::SetDefaultWebClientUIState( |
| + ShellIntegration::DefaultWebClientUIState state) { |
| + if (state == ShellIntegration::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 == ShellIntegration::STATE_NOT_DEFAULT && |
| + ShellIntegration::CanSetAsDefaultBrowser() != |
| + ShellIntegration::SET_DEFAULT_NOT_ALLOWED) { |
| + ShowPrompt(); |
| + } |
| +} |
| + |
| +bool CheckDefaultBrowserObserver::IsOwnedByWorker() { |
| + // Instruct the DefaultBrowserWorker to delete this instance when it is done. |
| + return true; |
| +} |
| + |
| +void CheckDefaultBrowserObserver::ResetCheckDefaultBrowserPref() { |
| + Profile* profile = |
| + g_browser_process->profile_manager()->GetProfileByPath(profile_path_); |
| + if (profile) |
| + profile->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true); |
| +} |
| + |
| +void CheckDefaultBrowserObserver::ShowPrompt() { |
| + Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type_); |
| if (!browser) |
| return; // Reached during ui tests. |
| @@ -195,43 +286,8 @@ void NotifyNotDefaultBrowserCallback(chrome::HostDesktopType desktop_type) { |
| DefaultBrowserInfoBarDelegate::Create( |
| InfoBarService::FromWebContents(web_contents), |
| - Profile::FromBrowserContext( |
| - web_contents->GetBrowserContext())->GetPrefs(), |
| - (ShellIntegration::CanSetAsDefaultBrowser() == |
| - ShellIntegration::SET_DEFAULT_INTERACTIVE)); |
| -} |
| - |
| -void ResetCheckDefaultBrowserPrefOnUIThread( |
| - const base::FilePath& profile_path) { |
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| - Profile* profile = |
| - g_browser_process->profile_manager()->GetProfileByPath(profile_path); |
| - if (profile) |
| - profile->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true); |
| -} |
| - |
| -void CheckDefaultBrowserOnFileThread(const base::FilePath& profile_path, |
| - bool show_prompt, |
| - chrome::HostDesktopType desktop_type) { |
| - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); |
| - ShellIntegration::DefaultWebClientState state = |
| - ShellIntegration::GetDefaultBrowser(); |
| - if (state == ShellIntegration::IS_DEFAULT) { |
| - // Notify the user in the future if Chrome ceases to be the user's chosen |
| - // default browser. |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::UI, FROM_HERE, |
| - base::Bind(&ResetCheckDefaultBrowserPrefOnUIThread, profile_path)); |
| - } else if (show_prompt && state == ShellIntegration::NOT_DEFAULT) { |
| - ShellIntegration::DefaultWebClientSetPermission default_change_mode = |
| - ShellIntegration::CanSetAsDefaultBrowser(); |
| - |
| - if (default_change_mode != ShellIntegration::SET_DEFAULT_NOT_ALLOWED) { |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::UI, FROM_HERE, |
| - base::Bind(&NotifyNotDefaultBrowserCallback, desktop_type)); |
| - } |
| - } |
| + Profile::FromBrowserContext(web_contents->GetBrowserContext()) |
| + ->GetPrefs()); |
| } |
| } // namespace |
| @@ -271,10 +327,11 @@ void ShowDefaultBrowserPrompt(Profile* profile, HostDesktopType desktop_type) { |
| } |
| } |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::FILE, FROM_HERE, |
| - base::Bind(&CheckDefaultBrowserOnFileThread, profile->GetPath(), |
| - show_prompt, desktop_type)); |
| + scoped_refptr<ShellIntegration::DefaultBrowserWorker>( |
| + new ShellIntegration::DefaultBrowserWorker( |
| + new CheckDefaultBrowserObserver(profile->GetPath(), show_prompt, |
| + desktop_type))) |
| + ->StartCheckIsDefault(); |
| } |
| #if !defined(OS_WIN) |