[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | bc4303d3 | 2012-05-10 14:58:55 | [diff] [blame] | 5 | #include "chrome/browser/ui/startup/default_browser_prompt.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 6 | |
| 7 | #include "base/memory/weak_ptr.h" |
| 8 | #include "base/message_loop.h" |
| 9 | #include "base/metrics/histogram.h" |
[email protected] | 77a91c7 | 2012-08-13 16:19:34 | [diff] [blame] | 10 | #include "chrome/browser/api/infobars/confirm_infobar_delegate.h" |
[email protected] | 4f822f02 | 2012-12-20 19:11:42 | [diff] [blame] | 11 | #include "chrome/browser/api/infobars/infobar_service.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 12 | #include "chrome/browser/browser_process.h" |
| 13 | #include "chrome/browser/first_run/first_run.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 14 | #include "chrome/browser/prefs/pref_service.h" |
| 15 | #include "chrome/browser/profiles/profile.h" |
| 16 | #include "chrome/browser/shell_integration.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 17 | #include "chrome/browser/ui/browser.h" |
[email protected] | 8381068 | 2012-10-12 21:10:14 | [diff] [blame] | 18 | #include "chrome/browser/ui/browser_finder.h" |
[email protected] | 617ee96 | 2013-01-29 20:49:12 | [diff] [blame^] | 19 | #include "chrome/browser/ui/tabs/tab_strip_model.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 20 | #include "chrome/common/pref_names.h" |
| 21 | #include "content/public/browser/browser_thread.h" |
| 22 | #include "content/public/browser/navigation_details.h" |
[email protected] | 4f822f02 | 2012-12-20 19:11:42 | [diff] [blame] | 23 | #include "content/public/browser/web_contents.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 24 | #include "grit/chromium_strings.h" |
| 25 | #include "grit/generated_resources.h" |
| 26 | #include "grit/theme_resources.h" |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 27 | #include "ui/base/l10n/l10n_util.h" |
| 28 | #include "ui/base/resource/resource_bundle.h" |
| 29 | |
| 30 | using content::BrowserThread; |
| 31 | |
| 32 | namespace { |
| 33 | |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 34 | // Calls the appropriate function for setting Chrome as the default browser. |
| 35 | // This requires IO access (registry) and may result in interaction with a |
| 36 | // modal system UI. |
[email protected] | 693baa5d | 2012-06-22 22:23:38 | [diff] [blame] | 37 | void SetChromeAsDefaultBrowser(bool interactive_flow, PrefService* prefs) { |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 38 | if (interactive_flow) { |
| 39 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefaultUI", 1); |
[email protected] | 693baa5d | 2012-06-22 22:23:38 | [diff] [blame] | 40 | if (!ShellIntegration::SetAsDefaultBrowserInteractive()) { |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 41 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefaultUIFailed", 1); |
[email protected] | 8988665 | 2012-12-11 18:09:07 | [diff] [blame] | 42 | } else if (ShellIntegration::GetDefaultBrowser() == |
| 43 | ShellIntegration::NOT_DEFAULT) { |
[email protected] | 693baa5d | 2012-06-22 22:23:38 | [diff] [blame] | 44 | // If the interaction succeeded but we are still not the default browser |
| 45 | // it likely means the user simply selected another browser from the |
| 46 | // panel. We will respect this choice and write it down as 'no, thanks'. |
| 47 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.DontSetAsDefault", 1); |
[email protected] | 693baa5d | 2012-06-22 22:23:38 | [diff] [blame] | 48 | } |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 49 | } else { |
| 50 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefault", 1); |
| 51 | ShellIntegration::SetAsDefaultBrowser(); |
| 52 | } |
| 53 | } |
| 54 | |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 55 | // The delegate for the infobar shown when Chrome is not the default browser. |
| 56 | class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate { |
| 57 | public: |
[email protected] | 0be0993 | 2013-01-08 02:03:50 | [diff] [blame] | 58 | // Creates a default browser delegate and adds it to |infobar_service|. |
| 59 | static void Create(InfoBarService* infobar_service, |
| 60 | PrefService* prefs, |
| 61 | bool interactive_flow_required); |
| 62 | |
| 63 | private: |
[email protected] | 4f822f02 | 2012-12-20 19:11:42 | [diff] [blame] | 64 | DefaultBrowserInfoBarDelegate(InfoBarService* infobar_service, |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 65 | PrefService* prefs, |
| 66 | bool interactive_flow_required); |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 67 | virtual ~DefaultBrowserInfoBarDelegate(); |
| 68 | |
| 69 | void AllowExpiry() { should_expire_ = true; } |
| 70 | |
| 71 | // ConfirmInfoBarDelegate: |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 72 | virtual gfx::Image* GetIcon() const OVERRIDE; |
| 73 | virtual string16 GetMessageText() const OVERRIDE; |
| 74 | virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; |
| 75 | virtual bool NeedElevation(InfoBarButton button) const OVERRIDE; |
| 76 | virtual bool Accept() OVERRIDE; |
| 77 | virtual bool Cancel() OVERRIDE; |
[email protected] | ff51c40 | 2012-06-22 04:18:47 | [diff] [blame] | 78 | virtual bool ShouldExpireInternal( |
| 79 | const content::LoadCommittedDetails& details) const OVERRIDE; |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 80 | |
| 81 | // The prefs to use. |
| 82 | PrefService* prefs_; |
| 83 | |
| 84 | // Whether the user clicked one of the buttons. |
| 85 | bool action_taken_; |
| 86 | |
| 87 | // Whether the info-bar should be dismissed on the next navigation. |
| 88 | bool should_expire_; |
| 89 | |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 90 | // Whether changing the default application will require entering the |
| 91 | // modal-UI flow. |
| 92 | const bool interactive_flow_required_; |
| 93 | |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 94 | // Used to delay the expiration of the info-bar. |
| 95 | base::WeakPtrFactory<DefaultBrowserInfoBarDelegate> weak_factory_; |
| 96 | |
| 97 | DISALLOW_COPY_AND_ASSIGN(DefaultBrowserInfoBarDelegate); |
| 98 | }; |
| 99 | |
[email protected] | 0be0993 | 2013-01-08 02:03:50 | [diff] [blame] | 100 | // static |
| 101 | void DefaultBrowserInfoBarDelegate::Create(InfoBarService* infobar_service, |
| 102 | PrefService* prefs, |
| 103 | bool interactive_flow_required) { |
| 104 | infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( |
| 105 | new DefaultBrowserInfoBarDelegate(infobar_service, prefs, |
| 106 | interactive_flow_required))); |
| 107 | } |
| 108 | |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 109 | DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate( |
[email protected] | 4f822f02 | 2012-12-20 19:11:42 | [diff] [blame] | 110 | InfoBarService* infobar_service, |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 111 | PrefService* prefs, |
| 112 | bool interactive_flow_required) |
[email protected] | 4f822f02 | 2012-12-20 19:11:42 | [diff] [blame] | 113 | : ConfirmInfoBarDelegate(infobar_service), |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 114 | prefs_(prefs), |
| 115 | action_taken_(false), |
| 116 | should_expire_(false), |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 117 | interactive_flow_required_(interactive_flow_required), |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 118 | ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 119 | // We want the info-bar to stick-around for few seconds and then be hidden |
| 120 | // on the next navigation after that. |
| 121 | MessageLoop::current()->PostDelayedTask( |
| 122 | FROM_HERE, base::Bind(&DefaultBrowserInfoBarDelegate::AllowExpiry, |
| 123 | weak_factory_.GetWeakPtr()), |
| 124 | base::TimeDelta::FromSeconds(8)); |
| 125 | } |
| 126 | |
| 127 | DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() { |
| 128 | if (!action_taken_) |
| 129 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.Ignored", 1); |
| 130 | } |
| 131 | |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 132 | gfx::Image* DefaultBrowserInfoBarDelegate::GetIcon() const { |
| 133 | return &ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 134 | IDR_PRODUCT_LOGO_32); |
| 135 | } |
| 136 | |
| 137 | string16 DefaultBrowserInfoBarDelegate::GetMessageText() const { |
| 138 | return l10n_util::GetStringUTF16(IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT); |
| 139 | } |
| 140 | |
| 141 | string16 DefaultBrowserInfoBarDelegate::GetButtonLabel( |
| 142 | InfoBarButton button) const { |
| 143 | return l10n_util::GetStringUTF16((button == BUTTON_OK) ? |
| 144 | IDS_SET_AS_DEFAULT_INFOBAR_BUTTON_LABEL : |
| 145 | IDS_DONT_ASK_AGAIN_INFOBAR_BUTTON_LABEL); |
| 146 | } |
| 147 | |
| 148 | bool DefaultBrowserInfoBarDelegate::NeedElevation(InfoBarButton button) const { |
| 149 | return button == BUTTON_OK; |
| 150 | } |
| 151 | |
| 152 | bool DefaultBrowserInfoBarDelegate::Accept() { |
| 153 | action_taken_ = true; |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 154 | BrowserThread::PostTask( |
| 155 | BrowserThread::FILE, |
| 156 | FROM_HERE, |
[email protected] | 693baa5d | 2012-06-22 22:23:38 | [diff] [blame] | 157 | base::Bind(&SetChromeAsDefaultBrowser, interactive_flow_required_, |
| 158 | prefs_)); |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 159 | |
[email protected] | 268942a | 2012-05-08 22:40:35 | [diff] [blame] | 160 | return true; |
| 161 | } |
| 162 | |
| 163 | bool DefaultBrowserInfoBarDelegate::Cancel() { |
| 164 | action_taken_ = true; |
| 165 | UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.DontSetAsDefault", 1); |
| 166 | // User clicked "Don't ask me again", remember that. |
| 167 | prefs_->SetBoolean(prefs::kCheckDefaultBrowser, false); |
| 168 | return true; |
| 169 | } |
| 170 | |
[email protected] | ff51c40 | 2012-06-22 04:18:47 | [diff] [blame] | 171 | bool DefaultBrowserInfoBarDelegate::ShouldExpireInternal( |
| 172 | const content::LoadCommittedDetails& details) const { |
| 173 | return should_expire_; |
| 174 | } |
| 175 | |
[email protected] | 8381068 | 2012-10-12 21:10:14 | [diff] [blame] | 176 | void NotifyNotDefaultBrowserCallback(chrome::HostDesktopType desktop_type) { |
[email protected] | 53a6733 | 2012-11-11 00:29:09 | [diff] [blame] | 177 | Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type); |
[email protected] | 3a798230 | 2012-05-25 15:53:04 | [diff] [blame] | 178 | if (!browser) |
| 179 | return; // Reached during ui tests. |
| 180 | |
| 181 | // In ChromeBot tests, there might be a race. This line appears to get |
| 182 | // called during shutdown and |tab| can be NULL. |
[email protected] | 617ee96 | 2013-01-29 20:49:12 | [diff] [blame^] | 183 | content::WebContents* web_contents = |
| 184 | browser->tab_strip_model()->GetActiveWebContents(); |
[email protected] | 591a59f | 2012-10-11 01:16:23 | [diff] [blame] | 185 | if (!web_contents) |
[email protected] | 3a798230 | 2012-05-25 15:53:04 | [diff] [blame] | 186 | return; |
| 187 | |
[email protected] | bd046bd4 | 2012-06-08 05:07:32 | [diff] [blame] | 188 | bool interactive_flow = ShellIntegration::CanSetAsDefaultBrowser() == |
| 189 | ShellIntegration::SET_DEFAULT_INTERACTIVE; |
[email protected] | 591a59f | 2012-10-11 01:16:23 | [diff] [blame] | 190 | Profile* profile = |
| 191 | Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
[email protected] | 0be0993 | 2013-01-08 02:03:50 | [diff] [blame] | 192 | DefaultBrowserInfoBarDelegate::Create( |
| 193 | InfoBarService::FromWebContents(web_contents), profile->GetPrefs(), |
| 194 | interactive_flow); |
[email protected] | 3a798230 | 2012-05-25 15:53:04 | [diff] [blame] | 195 | } |
| 196 | |
[email protected] | 8381068 | 2012-10-12 21:10:14 | [diff] [blame] | 197 | void CheckDefaultBrowserCallback(chrome::HostDesktopType desktop_type) { |
[email protected] | 8988665 | 2012-12-11 18:09:07 | [diff] [blame] | 198 | if (ShellIntegration::GetDefaultBrowser() == ShellIntegration::NOT_DEFAULT) { |
[email protected] | 8381068 | 2012-10-12 21:10:14 | [diff] [blame] | 199 | ShellIntegration::DefaultWebClientSetPermission default_change_mode = |
| 200 | ShellIntegration::CanSetAsDefaultBrowser(); |
| 201 | |
| 202 | if (default_change_mode != ShellIntegration::SET_DEFAULT_NOT_ALLOWED) { |
| 203 | BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 204 | base::Bind(&NotifyNotDefaultBrowserCallback, desktop_type)); |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | } // namespace |
| 210 | |
| 211 | namespace chrome { |
| 212 | |
| 213 | void ShowDefaultBrowserPrompt(Profile* profile, HostDesktopType desktop_type) { |
| 214 | // We do not check if we are the default browser if: |
| 215 | // - the user said "don't ask me again" on the infobar earlier. |
| 216 | // - There is a policy in control of this setting. |
| 217 | if (!profile->GetPrefs()->GetBoolean(prefs::kCheckDefaultBrowser)) |
| 218 | return; |
| 219 | |
| 220 | if (g_browser_process->local_state()->IsManagedPreference( |
| 221 | prefs::kDefaultBrowserSettingEnabled)) { |
| 222 | if (g_browser_process->local_state()->GetBoolean( |
| 223 | prefs::kDefaultBrowserSettingEnabled)) { |
| 224 | BrowserThread::PostTask( |
| 225 | BrowserThread::FILE, FROM_HERE, |
| 226 | base::Bind( |
| 227 | base::IgnoreResult(&ShellIntegration::SetAsDefaultBrowser))); |
| 228 | } else { |
| 229 | // TODO(pastarmovj): We can't really do anything meaningful here yet but |
| 230 | // just prevent showing the infobar. |
| 231 | } |
| 232 | return; |
| 233 | } |
| 234 | BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 235 | base::Bind(&CheckDefaultBrowserCallback, |
| 236 | desktop_type)); |
| 237 | |
| 238 | } |
| 239 | |
| 240 | #if !defined(OS_WIN) |
| 241 | bool ShowFirstRunDefaultBrowserPrompt(Profile* profile) { |
| 242 | return false; |
| 243 | } |
| 244 | #endif |
| 245 | |
[email protected] | 4feb37d9 | 2012-07-01 20:22:13 | [diff] [blame] | 246 | } // namespace chrome |