| 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..ce1585d507f7a7cfaeca528111b8e59d441d55c4 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;
 | 
| +
 | 
| + private:
 | 
| +  void SetDefaultWebClientUIState(
 | 
| +      ShellIntegration::DefaultWebClientUIState state) override;
 | 
| +  void OnSetAsDefaultConcluded(bool succeeded) override;
 | 
| +  bool IsOwnedByWorker() override;
 | 
| +  bool IsInteractiveSetDefaultPermitted() override;
 | 
| +
 | 
| +  // 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,73 @@ 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;
 | 
| +
 | 
| + private:
 | 
| +  void SetDefaultWebClientUIState(
 | 
| +      ShellIntegration::DefaultWebClientUIState state) override;
 | 
| +  bool IsOwnedByWorker() 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_;
 | 
| +  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 +287,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 +328,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)
 | 
| 
 |