blob: 8f0f5e091fd918d8d0bc8c0508b62c4bb0fd8976 [file] [log] [blame]
[email protected]268942a2012-05-08 22:40:351// 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]bc4303d32012-05-10 14:58:555#include "chrome/browser/ui/startup/default_browser_prompt.h"
[email protected]268942a2012-05-08 22:40:356
7#include "base/memory/weak_ptr.h"
8#include "base/message_loop.h"
9#include "base/metrics/histogram.h"
[email protected]77a91c72012-08-13 16:19:3410#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
[email protected]4f822f022012-12-20 19:11:4211#include "chrome/browser/api/infobars/infobar_service.h"
[email protected]268942a2012-05-08 22:40:3512#include "chrome/browser/browser_process.h"
13#include "chrome/browser/first_run/first_run.h"
[email protected]268942a2012-05-08 22:40:3514#include "chrome/browser/prefs/pref_service.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/shell_integration.h"
[email protected]268942a2012-05-08 22:40:3517#include "chrome/browser/ui/browser.h"
[email protected]83810682012-10-12 21:10:1418#include "chrome/browser/ui/browser_finder.h"
[email protected]617ee962013-01-29 20:49:1219#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]268942a2012-05-08 22:40:3520#include "chrome/common/pref_names.h"
21#include "content/public/browser/browser_thread.h"
22#include "content/public/browser/navigation_details.h"
[email protected]4f822f022012-12-20 19:11:4223#include "content/public/browser/web_contents.h"
[email protected]268942a2012-05-08 22:40:3524#include "grit/chromium_strings.h"
25#include "grit/generated_resources.h"
26#include "grit/theme_resources.h"
[email protected]268942a2012-05-08 22:40:3527#include "ui/base/l10n/l10n_util.h"
28#include "ui/base/resource/resource_bundle.h"
29
30using content::BrowserThread;
31
32namespace {
33
[email protected]bd046bd42012-06-08 05:07:3234// 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]693baa5d2012-06-22 22:23:3837void SetChromeAsDefaultBrowser(bool interactive_flow, PrefService* prefs) {
[email protected]bd046bd42012-06-08 05:07:3238 if (interactive_flow) {
39 UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefaultUI", 1);
[email protected]693baa5d2012-06-22 22:23:3840 if (!ShellIntegration::SetAsDefaultBrowserInteractive()) {
[email protected]bd046bd42012-06-08 05:07:3241 UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefaultUIFailed", 1);
[email protected]89886652012-12-11 18:09:0742 } else if (ShellIntegration::GetDefaultBrowser() ==
43 ShellIntegration::NOT_DEFAULT) {
[email protected]693baa5d2012-06-22 22:23:3844 // 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]693baa5d2012-06-22 22:23:3848 }
[email protected]bd046bd42012-06-08 05:07:3249 } else {
50 UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefault", 1);
51 ShellIntegration::SetAsDefaultBrowser();
52 }
53}
54
[email protected]268942a2012-05-08 22:40:3555// The delegate for the infobar shown when Chrome is not the default browser.
56class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate {
57 public:
[email protected]0be09932013-01-08 02:03:5058 // 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]4f822f022012-12-20 19:11:4264 DefaultBrowserInfoBarDelegate(InfoBarService* infobar_service,
[email protected]bd046bd42012-06-08 05:07:3265 PrefService* prefs,
66 bool interactive_flow_required);
[email protected]268942a2012-05-08 22:40:3567 virtual ~DefaultBrowserInfoBarDelegate();
68
69 void AllowExpiry() { should_expire_ = true; }
70
71 // ConfirmInfoBarDelegate:
[email protected]268942a2012-05-08 22:40:3572 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]ff51c402012-06-22 04:18:4778 virtual bool ShouldExpireInternal(
79 const content::LoadCommittedDetails& details) const OVERRIDE;
[email protected]268942a2012-05-08 22:40:3580
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]bd046bd42012-06-08 05:07:3290 // Whether changing the default application will require entering the
91 // modal-UI flow.
92 const bool interactive_flow_required_;
93
[email protected]268942a2012-05-08 22:40:3594 // 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]0be09932013-01-08 02:03:50100// static
101void 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]268942a2012-05-08 22:40:35109DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate(
[email protected]4f822f022012-12-20 19:11:42110 InfoBarService* infobar_service,
[email protected]bd046bd42012-06-08 05:07:32111 PrefService* prefs,
112 bool interactive_flow_required)
[email protected]4f822f022012-12-20 19:11:42113 : ConfirmInfoBarDelegate(infobar_service),
[email protected]268942a2012-05-08 22:40:35114 prefs_(prefs),
115 action_taken_(false),
116 should_expire_(false),
[email protected]bd046bd42012-06-08 05:07:32117 interactive_flow_required_(interactive_flow_required),
[email protected]268942a2012-05-08 22:40:35118 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
127DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() {
128 if (!action_taken_)
129 UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.Ignored", 1);
130}
131
[email protected]268942a2012-05-08 22:40:35132gfx::Image* DefaultBrowserInfoBarDelegate::GetIcon() const {
133 return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
134 IDR_PRODUCT_LOGO_32);
135}
136
137string16 DefaultBrowserInfoBarDelegate::GetMessageText() const {
138 return l10n_util::GetStringUTF16(IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT);
139}
140
141string16 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
148bool DefaultBrowserInfoBarDelegate::NeedElevation(InfoBarButton button) const {
149 return button == BUTTON_OK;
150}
151
152bool DefaultBrowserInfoBarDelegate::Accept() {
153 action_taken_ = true;
[email protected]268942a2012-05-08 22:40:35154 BrowserThread::PostTask(
155 BrowserThread::FILE,
156 FROM_HERE,
[email protected]693baa5d2012-06-22 22:23:38157 base::Bind(&SetChromeAsDefaultBrowser, interactive_flow_required_,
158 prefs_));
[email protected]bd046bd42012-06-08 05:07:32159
[email protected]268942a2012-05-08 22:40:35160 return true;
161}
162
163bool 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]ff51c402012-06-22 04:18:47171bool DefaultBrowserInfoBarDelegate::ShouldExpireInternal(
172 const content::LoadCommittedDetails& details) const {
173 return should_expire_;
174}
175
[email protected]83810682012-10-12 21:10:14176void NotifyNotDefaultBrowserCallback(chrome::HostDesktopType desktop_type) {
[email protected]53a67332012-11-11 00:29:09177 Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type);
[email protected]3a7982302012-05-25 15:53:04178 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]617ee962013-01-29 20:49:12183 content::WebContents* web_contents =
184 browser->tab_strip_model()->GetActiveWebContents();
[email protected]591a59f2012-10-11 01:16:23185 if (!web_contents)
[email protected]3a7982302012-05-25 15:53:04186 return;
187
[email protected]bd046bd42012-06-08 05:07:32188 bool interactive_flow = ShellIntegration::CanSetAsDefaultBrowser() ==
189 ShellIntegration::SET_DEFAULT_INTERACTIVE;
[email protected]591a59f2012-10-11 01:16:23190 Profile* profile =
191 Profile::FromBrowserContext(web_contents->GetBrowserContext());
[email protected]0be09932013-01-08 02:03:50192 DefaultBrowserInfoBarDelegate::Create(
193 InfoBarService::FromWebContents(web_contents), profile->GetPrefs(),
194 interactive_flow);
[email protected]3a7982302012-05-25 15:53:04195}
196
[email protected]83810682012-10-12 21:10:14197void CheckDefaultBrowserCallback(chrome::HostDesktopType desktop_type) {
[email protected]89886652012-12-11 18:09:07198 if (ShellIntegration::GetDefaultBrowser() == ShellIntegration::NOT_DEFAULT) {
[email protected]83810682012-10-12 21:10:14199 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
211namespace chrome {
212
213void 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)
241bool ShowFirstRunDefaultBrowserPrompt(Profile* profile) {
242 return false;
243}
244#endif
245
[email protected]4feb37d92012-07-01 20:22:13246} // namespace chrome