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

Side by Side Diff: chrome/browser/ui/webui/set_as_default_browser_ui.cc

Issue 2090773002: Improves first run dialog performance on Win8 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cr Created 4 years, 4 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 unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "chrome/browser/ui/webui/set_as_default_browser_ui.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/metrics/histogram.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/shell_integration.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_dialogs.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/browser/ui/browser_list_observer.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/browser/ui/chrome_pages.h"
24 #include "chrome/browser/ui/singleton_tabs.h"
25 #include "chrome/browser/ui/startup/default_browser_prompt.h"
26 #include "chrome/browser/ui/sync/sync_promo_ui.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/grit/chromium_strings.h"
31 #include "chrome/grit/generated_resources.h"
32 #include "chrome/grit/locale_settings.h"
33 #include "chrome/installer/util/install_util.h"
34 #include "components/prefs/pref_service.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_delegate.h"
38 #include "content/public/browser/web_ui.h"
39 #include "content/public/browser/web_ui_data_source.h"
40 #include "content/public/browser/web_ui_message_handler.h"
41 #include "grit/browser_resources.h"
42 #include "ui/base/l10n/l10n_font_util.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/gfx/font.h"
45 #include "ui/views/widget/widget.h"
46 #include "ui/web_dialogs/web_dialog_delegate.h"
47
48 using content::BrowserThread;
49 using content::WebContents;
50 using content::WebUIMessageHandler;
51
52 namespace {
53
54 const char kSetAsDefaultBrowserHistogram[] = "DefaultBrowser.InteractionResult";
55
56 // The enum permits registering in UMA the three possible outcomes (do not
57 // reorder these).
58 // ACCEPTED: user pressed Next and made Chrome default.
59 // DECLINED: user simply closed the dialog without making Chrome default.
60 // REGRETTED: user pressed Next but then elected a different default browser.
61 enum MakeChromeDefaultResult {
62 MAKE_CHROME_DEFAULT_ACCEPTED = 0,
63 MAKE_CHROME_DEFAULT_DECLINED = 1,
64 MAKE_CHROME_DEFAULT_REGRETTED = 2,
65 // MAKE_CHROME_DEFAULT_ACCEPTED_IMMERSE = 3, // Deprecated.
66 MAKE_CHROME_DEFAULT_MAX
67 };
68
69 content::WebUIDataSource* CreateSetAsDefaultBrowserUIHTMLSource() {
70 content::WebUIDataSource* data_source = content::WebUIDataSource::Create(
71 chrome::kChromeUIMetroFlowHost);
72 data_source->AddLocalizedString("page-title", IDS_METRO_FLOW_TAB_TITLE);
73 data_source->AddLocalizedString("flowTitle", IDS_METRO_FLOW_TITLE_SHORT);
74 data_source->AddLocalizedString("flowDescription",
75 IDS_METRO_FLOW_DESCRIPTION);
76 data_source->AddLocalizedString("flowNext",
77 IDS_METRO_FLOW_SET_DEFAULT);
78 data_source->AddLocalizedString("chromeLogoString",
79 IDS_METRO_FLOW_LOGO_STRING_ALT);
80 data_source->SetJsonPath("strings.js");
81 data_source->AddResourcePath("set_as_default_browser.js",
82 IDR_SET_AS_DEFAULT_BROWSER_JS);
83 data_source->SetDefaultResource(IDR_SET_AS_DEFAULT_BROWSER_HTML);
84 return data_source;
85 }
86
87 // A simple class serving as a delegate for passing down the result of the
88 // interaction.
89 class ResponseDelegate {
90 public:
91 virtual void SetDialogInteractionResult(MakeChromeDefaultResult result) = 0;
92
93 protected:
94 virtual ~ResponseDelegate() { }
95 };
96
97 // Event handler for SetAsDefaultBrowserUI. Capable of setting Chrome as the
98 // default browser on button click, closing itself and triggering Chrome
99 // restart.
100 class SetAsDefaultBrowserHandler : public WebUIMessageHandler {
101 public:
102 explicit SetAsDefaultBrowserHandler(
103 const base::WeakPtr<ResponseDelegate>& response_delegate);
104
105 // WebUIMessageHandler implementation.
106 void RegisterMessages() override;
107
108 private:
109 // Handler for the 'Next' (or 'make Chrome the Metro browser') button.
110 void HandleLaunchSetDefaultBrowserFlow(const base::ListValue* args);
111
112 // Close this web ui.
113 void ConcludeInteraction(MakeChromeDefaultResult interaction_result);
114
115 void OnDefaultBrowserWorkerFinished(
116 shell_integration::DefaultWebClientState state);
117
118 // The worker pointer is reference counted. While it is running, the
119 // message loops of the FILE and UI thread will hold references to it
120 // and it will be automatically freed once all its tasks have finished.
121 scoped_refptr<shell_integration::DefaultBrowserWorker>
122 default_browser_worker_;
123 base::WeakPtr<ResponseDelegate> response_delegate_;
124
125 // Used to invalidate the DefaultBrowserWorker callback.
126 base::WeakPtrFactory<SetAsDefaultBrowserHandler> weak_ptr_factory_;
127
128 DISALLOW_COPY_AND_ASSIGN(SetAsDefaultBrowserHandler);
129 };
130
131 SetAsDefaultBrowserHandler::SetAsDefaultBrowserHandler(
132 const base::WeakPtr<ResponseDelegate>& response_delegate)
133 : response_delegate_(response_delegate), weak_ptr_factory_(this) {
134 default_browser_worker_ = new shell_integration::DefaultBrowserWorker(
135 base::Bind(&SetAsDefaultBrowserHandler::OnDefaultBrowserWorkerFinished,
136 weak_ptr_factory_.GetWeakPtr()));
137 }
138
139 void SetAsDefaultBrowserHandler::RegisterMessages() {
140 web_ui()->RegisterMessageCallback(
141 "SetAsDefaultBrowser:LaunchSetDefaultBrowserFlow",
142 base::Bind(&SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow,
143 base::Unretained(this)));
144 }
145
146 void SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow(
147 const base::ListValue* args) {
148 default_browser_worker_->StartSetAsDefault();
149 }
150
151 void SetAsDefaultBrowserHandler::ConcludeInteraction(
152 MakeChromeDefaultResult interaction_result) {
153 DCHECK_CURRENTLY_ON(BrowserThread::UI);
154
155 if (response_delegate_)
156 response_delegate_->SetDialogInteractionResult(interaction_result);
157
158 WebContents* contents = web_ui()->GetWebContents();
159
160 if (contents) {
161 content::WebContentsDelegate* delegate = contents->GetDelegate();
162 if (delegate)
163 delegate->CloseContents(contents);
164 }
165 }
166
167 void SetAsDefaultBrowserHandler::OnDefaultBrowserWorkerFinished(
168 shell_integration::DefaultWebClientState state) {
169 // The callback is expected to be invoked once the procedure has completed.
170 DCHECK_CURRENTLY_ON(BrowserThread::UI);
171 if (state == shell_integration::NOT_DEFAULT) {
172 // The operation concluded, but Chrome is still not the default. This
173 // suggests the user has decided not to make Chrome the default.
174 ConcludeInteraction(MAKE_CHROME_DEFAULT_REGRETTED);
175 } else if (state == shell_integration::IS_DEFAULT) {
176 ConcludeInteraction(MAKE_CHROME_DEFAULT_ACCEPTED);
177 }
178
179 // Otherwise, keep the dialog open since the user probably didn't make a
180 // choice.
181 }
182
183 // A web dialog delegate implementation for when 'Make Chrome Metro' UI
184 // is displayed on a dialog.
185 class SetAsDefaultBrowserDialogImpl : public ui::WebDialogDelegate,
186 public ResponseDelegate,
187 public chrome::BrowserListObserver {
188 public:
189 SetAsDefaultBrowserDialogImpl(Profile* profile, Browser* browser);
190 ~SetAsDefaultBrowserDialogImpl() override;
191 // Show a modal web dialog with kChromeUIMetroFlowURL page.
192 void ShowDialog();
193
194 protected:
195 // Overridden from WebDialogDelegate:
196 ui::ModalType GetDialogModalType() const override;
197 base::string16 GetDialogTitle() const override;
198 GURL GetDialogContentURL() const override;
199 void GetWebUIMessageHandlers(
200 std::vector<WebUIMessageHandler*>* handlers) const override;
201 void GetDialogSize(gfx::Size* size) const override;
202 std::string GetDialogArgs() const override;
203 void OnDialogClosed(const std::string& json_retval) override;
204 void OnCloseContents(WebContents* source, bool* out_close_dialog) override;
205 bool ShouldShowDialogTitle() const override;
206 bool HandleContextMenu(const content::ContextMenuParams& params) override;
207
208 // Overridden from ResponseDelegate:
209 void SetDialogInteractionResult(MakeChromeDefaultResult result) override;
210
211 // Overridden from BrowserListObserver:
212 void OnBrowserRemoved(Browser* browser) override;
213
214 private:
215 Profile* profile_;
216 Browser* browser_;
217 mutable bool owns_handler_;
218 base::WeakPtrFactory<ResponseDelegate> response_delegate_ptr_factory_;
219 SetAsDefaultBrowserHandler* handler_;
220 MakeChromeDefaultResult dialog_interaction_result_;
221
222 DISALLOW_COPY_AND_ASSIGN(SetAsDefaultBrowserDialogImpl);
223 };
224
225 SetAsDefaultBrowserDialogImpl::SetAsDefaultBrowserDialogImpl(Profile* profile,
226 Browser* browser)
227 : profile_(profile),
228 browser_(browser),
229 owns_handler_(true),
230 response_delegate_ptr_factory_(this),
231 handler_(new SetAsDefaultBrowserHandler(
232 response_delegate_ptr_factory_.GetWeakPtr())),
233 dialog_interaction_result_(MAKE_CHROME_DEFAULT_DECLINED) {
234 BrowserList::AddObserver(this);
235 }
236
237 SetAsDefaultBrowserDialogImpl::~SetAsDefaultBrowserDialogImpl() {
238 if (browser_)
239 BrowserList::RemoveObserver(this);
240 if (owns_handler_)
241 delete handler_;
242 }
243
244 void SetAsDefaultBrowserDialogImpl::ShowDialog() {
245 // Use a NULL parent window to make sure that the dialog will have an item
246 // in the Windows task bar. The code below will make it highlight if the
247 // dialog is not in the foreground.
248 gfx::NativeWindow native_window = chrome::ShowWebDialog(NULL, profile_, this);
249 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(
250 native_window);
251 widget->FlashFrame(true);
252 }
253
254 ui::ModalType SetAsDefaultBrowserDialogImpl::GetDialogModalType() const {
255 return ui::MODAL_TYPE_SYSTEM;
256 }
257
258 base::string16 SetAsDefaultBrowserDialogImpl::GetDialogTitle() const {
259 return l10n_util::GetStringUTF16(IDS_METRO_FLOW_TAB_TITLE);
260 }
261
262 GURL SetAsDefaultBrowserDialogImpl::GetDialogContentURL() const {
263 std::string url_string(chrome::kChromeUIMetroFlowURL);
264 return GURL(url_string);
265 }
266
267 void SetAsDefaultBrowserDialogImpl::GetWebUIMessageHandlers(
268 std::vector<WebUIMessageHandler*>* handlers) const {
269 handlers->push_back(handler_);
270 owns_handler_ = false;
271 }
272
273 void SetAsDefaultBrowserDialogImpl::GetDialogSize(gfx::Size* size) const {
274 PrefService* prefs = profile_->GetPrefs();
275 gfx::Font approximate_web_font(
276 prefs->GetString(prefs::kWebKitSansSerifFontFamily),
277 prefs->GetInteger(prefs::kWebKitDefaultFontSize));
278
279 *size = ui::GetLocalizedContentsSizeForFont(
280 IDS_METRO_FLOW_WIDTH_CHARS, IDS_METRO_FLOW_HEIGHT_LINES,
281 approximate_web_font);
282 }
283
284 std::string SetAsDefaultBrowserDialogImpl::GetDialogArgs() const {
285 return "[]";
286 }
287
288 void SetAsDefaultBrowserDialogImpl::OnDialogClosed(
289 const std::string& json_retval) {
290 // Register the user's response in UMA.
291 UMA_HISTOGRAM_ENUMERATION(kSetAsDefaultBrowserHistogram,
292 dialog_interaction_result_,
293 MAKE_CHROME_DEFAULT_MAX);
294
295 // Suppress showing the default browser infobar if the user explicitly elected
296 // *not to* make Chrome default.
297 if (dialog_interaction_result_ == MAKE_CHROME_DEFAULT_REGRETTED)
298 chrome::DefaultBrowserPromptDeclined(profile_);
299
300 // Carry on with a normal chrome session. For the purpose of surfacing this
301 // dialog the actual browser window had to remain hidden. Now it's time to
302 // show it.
303 if (browser_) {
304 BrowserWindow* window = browser_->window();
305 WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents();
306 window->Show();
307 if (contents)
308 contents->SetInitialFocus();
309 }
310
311 delete this;
312 }
313
314 void SetAsDefaultBrowserDialogImpl::OnCloseContents(WebContents* source,
315 bool* out_close_dialog) {
316 *out_close_dialog = true;
317 }
318
319 bool SetAsDefaultBrowserDialogImpl::ShouldShowDialogTitle() const {
320 return true;
321 }
322
323 bool SetAsDefaultBrowserDialogImpl::HandleContextMenu(
324 const content::ContextMenuParams& params) {
325 return true;
326 }
327
328 void SetAsDefaultBrowserDialogImpl::SetDialogInteractionResult(
329 MakeChromeDefaultResult result) {
330 dialog_interaction_result_ = result;
331 }
332
333 void SetAsDefaultBrowserDialogImpl::OnBrowserRemoved(Browser* browser) {
334 if (browser_ == browser) {
335 browser_ = NULL;
336 BrowserList::RemoveObserver(this);
337 }
338 }
339
340 } // namespace
341
342 SetAsDefaultBrowserUI::SetAsDefaultBrowserUI(content::WebUI* web_ui)
343 : ui::WebDialogUI(web_ui) {
344 content::WebUIDataSource::Add(
345 Profile::FromWebUI(web_ui), CreateSetAsDefaultBrowserUIHTMLSource());
346 }
347
348 // static
349 void SetAsDefaultBrowserUI::Show(Profile* profile, Browser* browser) {
350 DCHECK_CURRENTLY_ON(BrowserThread::UI);
351 SetAsDefaultBrowserDialogImpl* dialog =
352 new SetAsDefaultBrowserDialogImpl(profile, browser);
353 dialog->ShowDialog();
354 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698