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

Side by Side Diff: chrome/browser/shell_integration.cc

Issue 1349163008: Setting chrome as the default browser is now fixed on Windows 10 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing Created 5 years, 2 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
« no previous file with comments | « chrome/browser/shell_integration.h ('k') | chrome/browser/shell_integration_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/shell_integration.h" 5 #include "chrome/browser/shell_integration.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/metrics/histogram_macros.h"
10 #include "base/prefs/pref_service.h" 11 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
grt (UTC plus 2) 2015/10/02 23:13:56 unused?
Patrick Monette 2015/10/05 15:54:31 Done.
12 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/thread_restrictions.h" 15 #include "base/threading/thread_restrictions.h"
16 #include "base/timer/timer.h"
14 #include "chrome/browser/policy/policy_path_parser.h" 17 #include "chrome/browser/policy/policy_path_parser.h"
15 #include "chrome/common/chrome_paths.h" 18 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/chrome_switches.h" 19 #include "chrome/common/chrome_switches.h"
17 #include "components/version_info/version_info.h" 20 #include "components/version_info/version_info.h"
18 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
19 22
20 #if defined(OS_CHROMEOS) 23 #if defined(OS_CHROMEOS)
21 #include "chromeos/chromeos_switches.h" 24 #include "chromeos/chromeos_switches.h"
22 #endif 25 #endif
23 26
(...skipping 11 matching lines...) Expand all
35 38
36 } // namespace 39 } // namespace
37 40
38 #if !defined(OS_WIN) 41 #if !defined(OS_WIN)
39 // static 42 // static
40 bool ShellIntegration::SetAsDefaultBrowserInteractive() { 43 bool ShellIntegration::SetAsDefaultBrowserInteractive() {
41 return false; 44 return false;
42 } 45 }
43 46
44 // static 47 // static
48 bool ShellIntegration::IsSetAsDefaultAsynchronous() {
49 return false;
50 }
51
52 // static
45 bool ShellIntegration::SetAsDefaultProtocolClientInteractive( 53 bool ShellIntegration::SetAsDefaultProtocolClientInteractive(
46 const std::string& protocol) { 54 const std::string& protocol) {
47 return false; 55 return false;
48 } 56 }
49 #endif // !defined(OS_WIN) 57 #endif // !defined(OS_WIN)
50 58
51 // static 59 // static
52 ShellIntegration::DefaultWebClientSetPermission 60 ShellIntegration::DefaultWebClientSetPermission
53 ShellIntegration::CanSetAsDefaultProtocolClient() { 61 ShellIntegration::CanSetAsDefaultProtocolClient() {
54 // Allowed as long as the browser can become the operating system default 62 // Allowed as long as the browser can become the operating system default
55 // browser. 63 // browser.
56 return CanSetAsDefaultBrowser(); 64 DefaultWebClientSetPermission permission = CanSetAsDefaultBrowser();
65
66 // Set as default asynchronous is only supported for default web browser.
67 return (permission == SET_DEFAULT_ASYNCHRONOUS) ? SET_DEFAULT_INTERACTIVE
68 : permission;
57 } 69 }
58 70
59 #if !defined(OS_WIN) 71 #if !defined(OS_WIN)
60 // static 72 // static
61 bool ShellIntegration::IsElevationNeededForSettingDefaultProtocolClient() { 73 bool ShellIntegration::IsElevationNeededForSettingDefaultProtocolClient() {
62 return false; 74 return false;
63 } 75 }
64 #endif // !defined(OS_WIN) 76 #endif // !defined(OS_WIN)
65 77
66 // static 78 // static
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 IsInteractiveSetDefaultPermitted() { 167 IsInteractiveSetDefaultPermitted() {
156 return false; 168 return false;
157 } 169 }
158 170
159 /////////////////////////////////////////////////////////////////////////////// 171 ///////////////////////////////////////////////////////////////////////////////
160 // ShellIntegration::DefaultWebClientWorker 172 // ShellIntegration::DefaultWebClientWorker
161 // 173 //
162 174
163 ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker( 175 ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
164 DefaultWebClientObserver* observer) 176 DefaultWebClientObserver* observer)
165 : observer_(observer) { 177 : observer_(observer) {}
166 }
167 178
168 void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() { 179 void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
169 if (observer_) { 180 if (observer_) {
170 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 181 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
171 BrowserThread::PostTask( 182 BrowserThread::PostTask(
172 BrowserThread::FILE, FROM_HERE, 183 BrowserThread::FILE, FROM_HERE,
173 base::Bind( 184 base::Bind(&DefaultWebClientWorker::CheckIsDefault, this));
174 &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
175 } 185 }
176 } 186 }
177 187
178 void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() { 188 void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
189 // Cancel the already running process if another start is requested.
190 if (set_as_default_in_progress_) {
191 if (set_as_default_initialized_) {
192 FinalizeSetAsDefault();
193 set_as_default_initialized_ = false;
194 }
195
196 ReportAttemptResult(AttemptResult::RETRY);
197 }
198
199 set_as_default_in_progress_ = true;
179 bool interactive_permitted = false; 200 bool interactive_permitted = false;
180 if (observer_) { 201 if (observer_) {
181 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 202 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
182 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted(); 203 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
204
205 // The initialization is only useful when there is an observer.
206 set_as_default_initialized_ = InitializeSetAsDefault();
183 } 207 }
184 BrowserThread::PostTask( 208
185 BrowserThread::FILE, FROM_HERE, 209 // Remember the start time.
186 base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this, 210 start_time_ = base::TimeTicks::Now();
187 interactive_permitted)); 211
212 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
213 base::Bind(&DefaultWebClientWorker::SetAsDefault,
214 this, interactive_permitted));
188 } 215 }
189 216
190 void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() { 217 void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
191 // Our associated view has gone away, so we shouldn't call back to it if 218 // Our associated view has gone away, so we shouldn't call back to it if
192 // our worker thread returns after the view is dead. 219 // our worker thread returns after the view is dead.
193 DCHECK_CURRENTLY_ON(BrowserThread::UI); 220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
194 observer_ = NULL; 221 observer_ = nullptr;
222
223 if (set_as_default_initialized_) {
224 FinalizeSetAsDefault();
225 set_as_default_initialized_ = false;
226 }
227
228 if (set_as_default_in_progress_)
229 ReportAttemptResult(AttemptResult::ABANDONED);
195 } 230 }
196 231
197 /////////////////////////////////////////////////////////////////////////////// 232 ///////////////////////////////////////////////////////////////////////////////
198 // DefaultWebClientWorker, private: 233 // DefaultWebClientWorker, private:
199 234
200 void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() { 235 ShellIntegration::DefaultWebClientWorker::~DefaultWebClientWorker() {}
201 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
202 DefaultWebClientState state = CheckIsDefault();
203 BrowserThread::PostTask(
204 BrowserThread::UI, FROM_HERE,
205 base::Bind(
206 &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
207 }
208 236
209 void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault( 237 void ShellIntegration::DefaultWebClientWorker::OnCheckIsDefaultComplete(
210 DefaultWebClientState state) { 238 DefaultWebClientState state) {
211 DCHECK_CURRENTLY_ON(BrowserThread::UI); 239 DCHECK_CURRENTLY_ON(BrowserThread::UI);
212 UpdateUI(state); 240 UpdateUI(state);
213 // The worker has finished everything it needs to do, so free the observer 241 // The worker has finished everything it needs to do, so free the observer
214 // if we own it. 242 // if we own it.
215 if (observer_ && observer_->IsOwnedByWorker()) { 243 if (observer_ && observer_->IsOwnedByWorker()) {
216 delete observer_; 244 delete observer_;
217 observer_ = NULL; 245 observer_ = nullptr;
218 } 246 }
219 } 247 }
220 248
221 void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault( 249 void ShellIntegration::DefaultWebClientWorker::OnSetAsDefaultAttemptComplete(
222 bool interactive_permitted) { 250 AttemptResult result) {
223 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 251 DCHECK_CURRENTLY_ON(BrowserThread::UI);
252 // Hold on to a reference because if this was called via the default browser
253 // callback in StartupBrowserCreator, clearing the callback in
254 // FinalizeSetAsDefault would otherwise remove the last reference and delete
255 // us in the middle of this function.
256 scoped_refptr<DefaultWebClientWorker> scoped_ref(this);
224 257
225 bool result = SetAsDefault(interactive_permitted); 258 if (set_as_default_in_progress_) {
226 BrowserThread::PostTask( 259 set_as_default_in_progress_ = false;
227 BrowserThread::UI, FROM_HERE, 260
228 base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result)); 261 if (set_as_default_initialized_) {
262 FinalizeSetAsDefault();
263 set_as_default_initialized_ = false;
264 }
265 if (observer_) {
266 bool succeeded = result == AttemptResult::SUCCESS ||
267 result == AttemptResult::ALREADY_DEFAULT;
268 observer_->OnSetAsDefaultConcluded(succeeded);
269 }
270
271 ReportAttemptResult(result);
272
273 // Start the default browser check which will notify the observer as to
274 // whether Chrome is really the default browser. This is needed because
275 // detecting that the process was successful is not 100% sure.
276 // For example, on Windows 10+, the user might have unchecked the "Always
277 // use this app" checkbox which can't be detected.
278 StartCheckIsDefault();
279 }
229 } 280 }
230 281
231 void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault( 282 void ShellIntegration::DefaultWebClientWorker::ReportAttemptResult(
232 bool succeeded) { 283 AttemptResult result) {
233 DCHECK_CURRENTLY_ON(BrowserThread::UI); 284 if (!ShouldReportAttemptResults())
234 // First tell the observer what the SetAsDefault call has returned. 285 return;
235 if (observer_) 286
236 observer_->OnSetAsDefaultConcluded(succeeded); 287 UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.AsyncSetAsDefault.Result", result,
237 // Set as default completed, check again to make sure it stuck... 288 AttemptResult::NUM_ATTEMPT_RESULT_TYPES);
238 StartCheckIsDefault(); 289
290 switch (result) {
291 case SUCCESS:
292 UMA_HISTOGRAM_MEDIUM_TIMES(
293 "DefaultBrowser.AsyncSetAsDefault.Duration_Success",
294 base::TimeTicks::Now() - start_time_);
295 break;
296 case FAILURE:
297 UMA_HISTOGRAM_MEDIUM_TIMES(
298 "DefaultBrowser.AsyncSetAsDefault.Duration_Failure",
299 base::TimeTicks::Now() - start_time_);
300 break;
301 case ABANDONED:
302 UMA_HISTOGRAM_MEDIUM_TIMES(
303 "DefaultBrowser.AsyncSetAsDefault.Duration_Abandoned",
304 base::TimeTicks::Now() - start_time_);
305 break;
306 case RETRY:
307 UMA_HISTOGRAM_MEDIUM_TIMES(
308 "DefaultBrowser.AsyncSetAsDefault.Duration_Retry",
309 base::TimeTicks::Now() - start_time_);
310 break;
311 default:
312 break;
313 }
239 } 314 }
240 315
316 bool ShellIntegration::DefaultWebClientWorker::InitializeSetAsDefault() {
317 return true;
318 }
319
320 void ShellIntegration::DefaultWebClientWorker::FinalizeSetAsDefault() {}
321
322 #if !defined(OS_WIN)
323 // static
324 bool ShellIntegration::DefaultWebClientWorker::ShouldReportAttemptResults() {
325 return false;
326 }
327 #endif // !defined(OS_WIN)
328
241 void ShellIntegration::DefaultWebClientWorker::UpdateUI( 329 void ShellIntegration::DefaultWebClientWorker::UpdateUI(
242 DefaultWebClientState state) { 330 DefaultWebClientState state) {
243 if (observer_) { 331 if (observer_) {
244 switch (state) { 332 switch (state) {
245 case NOT_DEFAULT: 333 case NOT_DEFAULT:
246 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT); 334 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
247 break; 335 break;
248 case IS_DEFAULT: 336 case IS_DEFAULT:
249 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT); 337 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
250 break; 338 break;
251 case UNKNOWN_DEFAULT: 339 case UNKNOWN_DEFAULT:
252 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN); 340 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
253 break; 341 break;
254 default: 342 default:
255 break; 343 break;
256 } 344 }
257 } 345 }
258 } 346 }
259 347
260 /////////////////////////////////////////////////////////////////////////////// 348 ///////////////////////////////////////////////////////////////////////////////
261 // ShellIntegration::DefaultBrowserWorker 349 // ShellIntegration::DefaultBrowserWorker
262 // 350 //
263 351
264 ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker( 352 ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
265 DefaultWebClientObserver* observer) 353 DefaultWebClientObserver* observer)
266 : DefaultWebClientWorker(observer) { 354 : DefaultWebClientWorker(observer) {
267 } 355 }
268 356
357 ShellIntegration::DefaultBrowserWorker::~DefaultBrowserWorker() {}
358
269 /////////////////////////////////////////////////////////////////////////////// 359 ///////////////////////////////////////////////////////////////////////////////
270 // DefaultBrowserWorker, private: 360 // DefaultBrowserWorker, private:
271 361
272 ShellIntegration::DefaultWebClientState 362 void ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
273 ShellIntegration::DefaultBrowserWorker::CheckIsDefault() { 363 DefaultWebClientState state = GetDefaultBrowser();
274 return ShellIntegration::GetDefaultBrowser(); 364 BrowserThread::PostTask(
365 BrowserThread::UI, FROM_HERE,
366 base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state));
275 } 367 }
276 368
277 bool ShellIntegration::DefaultBrowserWorker::SetAsDefault( 369 void ShellIntegration::DefaultBrowserWorker::SetAsDefault(
278 bool interactive_permitted) { 370 bool interactive_permitted) {
279 bool result = false; 371 AttemptResult result = AttemptResult::FAILURE;
280 switch (ShellIntegration::CanSetAsDefaultBrowser()) { 372 switch (CanSetAsDefaultBrowser()) {
281 case ShellIntegration::SET_DEFAULT_UNATTENDED: 373 case SET_DEFAULT_NOT_ALLOWED:
282 result = ShellIntegration::SetAsDefaultBrowser(); 374 NOTREACHED();
283 break; 375 break;
284 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 376 case SET_DEFAULT_UNATTENDED:
285 if (interactive_permitted) 377 if (SetAsDefaultBrowser())
286 result = ShellIntegration::SetAsDefaultBrowserInteractive(); 378 result = AttemptResult::SUCCESS;
287 break; 379 break;
288 default: 380 case SET_DEFAULT_INTERACTIVE:
381 if (interactive_permitted && SetAsDefaultBrowserInteractive())
382 result = AttemptResult::SUCCESS;
383 break;
384 case SET_DEFAULT_ASYNCHRONOUS:
385 #if defined(OS_WIN)
386 if (!interactive_permitted)
387 break;
388 if (GetDefaultBrowser() == IS_DEFAULT) {
389 // Don't start the asynchronous operation since it could result in
390 // losing the default browser status.
391 result = AttemptResult::ALREADY_DEFAULT;
392 break;
393 }
394 // This function will cause OnSetAsDefaultAttemptComplete() to be called
395 // asynchronously via a filter established in InitializeSetAsDefault().
396 if (!SetAsDefaultBrowserAsynchronous()) {
397 result = AttemptResult::LAUNCH_FAILURE;
398 break;
399 }
400 return;
401 #else
289 NOTREACHED(); 402 NOTREACHED();
403 break;
404 #endif
290 } 405 }
291 406 BrowserThread::PostTask(
292 return result; 407 BrowserThread::UI, FROM_HERE,
408 base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this,
409 result));
293 } 410 }
294 411
295 /////////////////////////////////////////////////////////////////////////////// 412 ///////////////////////////////////////////////////////////////////////////////
296 // ShellIntegration::DefaultProtocolClientWorker 413 // ShellIntegration::DefaultProtocolClientWorker
297 // 414 //
298 415
299 ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker( 416 ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
300 DefaultWebClientObserver* observer, const std::string& protocol) 417 DefaultWebClientObserver* observer, const std::string& protocol)
301 : DefaultWebClientWorker(observer), 418 : DefaultWebClientWorker(observer),
302 protocol_(protocol) { 419 protocol_(protocol) {
303 } 420 }
304 421
305 /////////////////////////////////////////////////////////////////////////////// 422 ///////////////////////////////////////////////////////////////////////////////
306 // DefaultProtocolClientWorker, private: 423 // DefaultProtocolClientWorker, private:
307 424
308 ShellIntegration::DefaultWebClientState 425 ShellIntegration::DefaultProtocolClientWorker::~DefaultProtocolClientWorker() {}
309 ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() { 426
310 return ShellIntegration::IsDefaultProtocolClient(protocol_); 427 void ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
428 DefaultWebClientState state = IsDefaultProtocolClient(protocol_);
429 BrowserThread::PostTask(
430 BrowserThread::UI, FROM_HERE,
431 base::Bind(&DefaultProtocolClientWorker::OnCheckIsDefaultComplete, this,
432 state));
311 } 433 }
312 434
313 bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault( 435 void ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
314 bool interactive_permitted) { 436 bool interactive_permitted) {
315 bool result = false; 437 AttemptResult result = AttemptResult::FAILURE;
316 switch (ShellIntegration::CanSetAsDefaultProtocolClient()) { 438 switch (CanSetAsDefaultProtocolClient()) {
317 case ShellIntegration::SET_DEFAULT_NOT_ALLOWED: 439 case SET_DEFAULT_NOT_ALLOWED:
318 result = false; 440 // Not allowed, do nothing.
319 break; 441 break;
320 case ShellIntegration::SET_DEFAULT_UNATTENDED: 442 case SET_DEFAULT_UNATTENDED:
321 result = ShellIntegration::SetAsDefaultProtocolClient(protocol_); 443 if (SetAsDefaultProtocolClient(protocol_))
444 result = AttemptResult::SUCCESS;
322 break; 445 break;
323 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 446 case SET_DEFAULT_INTERACTIVE:
324 if (interactive_permitted) { 447 if (interactive_permitted &&
325 result = ShellIntegration::SetAsDefaultProtocolClientInteractive( 448 SetAsDefaultProtocolClientInteractive(protocol_)) {
326 protocol_); 449 result = AttemptResult::SUCCESS;
327 } 450 }
328 break; 451 break;
452 case SET_DEFAULT_ASYNCHRONOUS:
453 NOTREACHED();
454 break;
329 } 455 }
330 456 BrowserThread::PostTask(
331 return result; 457 BrowserThread::UI, FROM_HERE,
458 base::Bind(&DefaultProtocolClientWorker::OnSetAsDefaultAttemptComplete,
459 this, result));
332 } 460 }
OLDNEW
« no previous file with comments | « chrome/browser/shell_integration.h ('k') | chrome/browser/shell_integration_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698