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

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

Powered by Google App Engine
This is Rietveld 408576698