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

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: Report early success when already default browser 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/prefs/pref_service.h" 10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "base/timer/timer.h"
14 #include "chrome/browser/policy/policy_path_parser.h" 15 #include "chrome/browser/policy/policy_path_parser.h"
15 #include "chrome/common/chrome_paths.h" 16 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/chrome_switches.h" 17 #include "chrome/common/chrome_switches.h"
17 #include "components/version_info/version_info.h" 18 #include "components/version_info/version_info.h"
18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
19 20
20 #if defined(OS_CHROMEOS) 21 #if defined(OS_CHROMEOS)
21 #include "chromeos/chromeos_switches.h" 22 #include "chromeos/chromeos_switches.h"
22 #endif 23 #endif
23 24
24 #if !defined(OS_WIN) 25 #if !defined(OS_WIN)
25 #include "chrome/common/channel_info.h" 26 #include "chrome/common/channel_info.h"
26 #include "chrome/grit/chromium_strings.h" 27 #include "chrome/grit/chromium_strings.h"
27 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
28 #endif 29 #endif
29 30
30 using content::BrowserThread; 31 using content::BrowserThread;
31 32
32 // static 33 // static
33 ShellIntegration::DefaultWebClientSetPermission 34 ShellIntegration::DefaultWebClientSetPermission
34 ShellIntegration::CanSetAsDefaultProtocolClient() { 35 ShellIntegration::CanSetAsDefaultProtocolClient() {
35 // Allowed as long as the browser can become the operating system default 36 // Allowed as long as the browser can become the operating system default
36 // browser. 37 // browser.
37 return CanSetAsDefaultBrowser(); 38 DefaultWebClientSetPermission permission = CanSetAsDefaultBrowser();
39
40 // Set as default asynchronous is only supported for default web browser.
41 return (permission == SET_DEFAULT_ASYNCHRONOUS) ? SET_DEFAULT_INTERACTIVE
42 : permission;
38 } 43 }
39 44
40 static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL; 45 static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL;
41 46
42 // static 47 // static
43 void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) { 48 void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) {
44 gAppModeInfo = info; 49 gAppModeInfo = info;
45 } 50 }
46 51
47 // static 52 // static
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 if (chrome::GetChannel() == version_info::Channel::CANARY) 122 if (chrome::GetChannel() == version_info::Channel::CANARY)
118 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY); 123 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY);
119 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME); 124 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME);
120 } 125 }
121 126
122 // static 127 // static
123 bool ShellIntegration::SetAsDefaultBrowserInteractive() { 128 bool ShellIntegration::SetAsDefaultBrowserInteractive() {
124 return false; 129 return false;
125 } 130 }
126 131
132 #if !defined(OS_WIN)
133 // static
134 bool ShellIntegration::IsSetAsDefaultAsynchronous() {
135 return false;
136 }
137 #endif // !defined(OS_WIN)
138
127 // static 139 // static
128 bool ShellIntegration::SetAsDefaultProtocolClientInteractive( 140 bool ShellIntegration::SetAsDefaultProtocolClientInteractive(
129 const std::string& protocol) { 141 const std::string& protocol) {
130 return false; 142 return false;
131 } 143 }
132 144
133 // static 145 // static
134 bool ShellIntegration::IsElevationNeededForSettingDefaultProtocolClient() { 146 bool ShellIntegration::IsElevationNeededForSettingDefaultProtocolClient() {
135 return false; 147 return false;
136 } 148 }
137 149
138 #endif // !defined(OS_WIN) 150 #endif // !defined(OS_WIN)
139 151
140 bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() { 152 bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() {
141 return false; 153 return false;
142 } 154 }
143 155
144 bool ShellIntegration::DefaultWebClientObserver:: 156 bool ShellIntegration::DefaultWebClientObserver::
145 IsInteractiveSetDefaultPermitted() { 157 IsInteractiveSetDefaultPermitted() {
146 return false; 158 return false;
147 } 159 }
148 160
149 /////////////////////////////////////////////////////////////////////////////// 161 ///////////////////////////////////////////////////////////////////////////////
150 // ShellIntegration::DefaultWebClientWorker 162 // ShellIntegration::DefaultWebClientWorker
151 // 163 //
152 164
153 ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker( 165 ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
154 DefaultWebClientObserver* observer) 166 DefaultWebClientObserver* observer)
155 : observer_(observer) { 167 : observer_(observer) {}
156 }
157 168
158 void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() { 169 void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
159 if (observer_) { 170 if (observer_) {
160 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 171 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
161 BrowserThread::PostTask( 172 BrowserThread::PostTask(
162 BrowserThread::FILE, FROM_HERE, 173 BrowserThread::FILE, FROM_HERE,
163 base::Bind( 174 base::Bind(&DefaultWebClientWorker::CheckIsDefault, this));
164 &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
165 } 175 }
166 } 176 }
167 177
168 void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() { 178 void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
179 // Cancel the already running process if another start is requested.
180 if (set_as_default_in_progress_)
grt (UTC plus 2) 2015/09/30 17:22:32 in looking at how set_as_default_in_progress_ is u
Patrick Monette 2015/10/01 21:12:50 Done.
181 OnSetAsDefaultAttemptComplete(false);
182
183 set_as_default_in_progress_ = true;
169 bool interactive_permitted = false; 184 bool interactive_permitted = false;
170 if (observer_) { 185 if (observer_) {
171 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 186 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
172 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted(); 187 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
188
189 InitializeSetAsDefault();
173 } 190 }
174 BrowserThread::PostTask( 191
175 BrowserThread::FILE, FROM_HERE, 192 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
176 base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this, 193 base::Bind(&DefaultWebClientWorker::SetAsDefault,
177 interactive_permitted)); 194 this, interactive_permitted));
178 } 195 }
179 196
180 void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() { 197 void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
181 // Our associated view has gone away, so we shouldn't call back to it if 198 // Our associated view has gone away, so we shouldn't call back to it if
182 // our worker thread returns after the view is dead. 199 // our worker thread returns after the view is dead.
183 DCHECK_CURRENTLY_ON(BrowserThread::UI); 200 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 observer_ = NULL; 201 observer_ = NULL;
202 // If an attempt to set the default browser is already in progress, its result
203 // won't be posted to any observers. Manually invoke
204 // OnSetAsDefaultAttemptComplete() to ensure we free the default browser
grt (UTC plus 2) 2015/09/30 17:22:32 nit: "free" -> "clear"?
Patrick Monette 2015/10/01 21:12:51 Done.
205 // callback and timer.
206 if (set_as_default_in_progress_)
207 OnSetAsDefaultAttemptComplete(false);
185 } 208 }
186 209
187 /////////////////////////////////////////////////////////////////////////////// 210 ///////////////////////////////////////////////////////////////////////////////
188 // DefaultWebClientWorker, private: 211 // DefaultWebClientWorker, private:
189 212
190 void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() { 213 ShellIntegration::DefaultWebClientWorker::~DefaultWebClientWorker() {}
191 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
192 DefaultWebClientState state = CheckIsDefault();
193 BrowserThread::PostTask(
194 BrowserThread::UI, FROM_HERE,
195 base::Bind(
196 &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
197 }
198 214
199 void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault( 215 void ShellIntegration::DefaultWebClientWorker::OnCheckIsDefaultComplete(
200 DefaultWebClientState state) { 216 DefaultWebClientState state) {
201 DCHECK_CURRENTLY_ON(BrowserThread::UI); 217 DCHECK_CURRENTLY_ON(BrowserThread::UI);
202 UpdateUI(state); 218 UpdateUI(state);
203 // The worker has finished everything it needs to do, so free the observer 219 // The worker has finished everything it needs to do, so free the observer
204 // if we own it. 220 // if we own it.
205 if (observer_ && observer_->IsOwnedByWorker()) { 221 if (observer_ && observer_->IsOwnedByWorker()) {
206 delete observer_; 222 delete observer_;
207 observer_ = NULL; 223 observer_ = NULL;
208 } 224 }
209 } 225 }
210 226
211 void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault( 227 void ShellIntegration::DefaultWebClientWorker::OnSetAsDefaultAttemptComplete(
212 bool interactive_permitted) { 228 bool succeeded) {
213 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 229 DCHECK_CURRENTLY_ON(BrowserThread::UI);
230 // Hold on to a reference because if this was called via the default browser
231 // callback in StartupBrowserCreator, clearing the callback in
232 // FinalizeSetAsDefault would otherwise remove the last reference and delete
233 // us in the middle of this function.
234 scoped_refptr<DefaultWebClientWorker> scoped_ref(this);
214 235
215 bool result = SetAsDefault(interactive_permitted); 236 if (set_as_default_in_progress_) {
216 BrowserThread::PostTask( 237 set_as_default_in_progress_ = false;
217 BrowserThread::UI, FROM_HERE, 238
218 base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result)); 239 FinalizeSetAsDefault(succeeded);
240 if (observer_)
241 observer_->OnSetAsDefaultConcluded(succeeded);
242
243 // Start the default browser check which will notify the observer as to
244 // whether Chrome is really the default browser. This is needed because
245 // detecting that the process was successful is not 100% sure.
246 // For example, on Windows 10+, the user might have unchecked the "Always
247 // use this app" checkbox which can't be detected.
248 StartCheckIsDefault();
249 }
219 } 250 }
220 251
221 void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault( 252 void ShellIntegration::DefaultWebClientWorker::InitializeSetAsDefault() {}
222 bool succeeded) { 253
223 DCHECK_CURRENTLY_ON(BrowserThread::UI); 254 void ShellIntegration::DefaultWebClientWorker::FinalizeSetAsDefault(
224 // First tell the observer what the SetAsDefault call has returned. 255 bool succeeded) {}
225 if (observer_)
226 observer_->OnSetAsDefaultConcluded(succeeded);
227 // Set as default completed, check again to make sure it stuck...
228 StartCheckIsDefault();
229 }
230 256
231 void ShellIntegration::DefaultWebClientWorker::UpdateUI( 257 void ShellIntegration::DefaultWebClientWorker::UpdateUI(
232 DefaultWebClientState state) { 258 DefaultWebClientState state) {
233 if (observer_) { 259 if (observer_) {
234 switch (state) { 260 switch (state) {
235 case NOT_DEFAULT: 261 case NOT_DEFAULT:
236 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT); 262 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
237 break; 263 break;
238 case IS_DEFAULT: 264 case IS_DEFAULT:
239 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT); 265 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
240 break; 266 break;
241 case UNKNOWN_DEFAULT: 267 case UNKNOWN_DEFAULT:
242 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN); 268 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
243 break; 269 break;
244 default: 270 default:
245 break; 271 break;
246 } 272 }
247 } 273 }
248 } 274 }
249 275
250 /////////////////////////////////////////////////////////////////////////////// 276 ///////////////////////////////////////////////////////////////////////////////
251 // ShellIntegration::DefaultBrowserWorker 277 // ShellIntegration::DefaultBrowserWorker
252 // 278 //
253 279
254 ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker( 280 ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
255 DefaultWebClientObserver* observer) 281 DefaultWebClientObserver* observer)
256 : DefaultWebClientWorker(observer) { 282 : DefaultWebClientWorker(observer) {
257 } 283 }
258 284
285 ShellIntegration::DefaultBrowserWorker::~DefaultBrowserWorker() {
286 if (set_as_default_in_progress_)
287 OnSetAsDefaultAttemptComplete(false);
grt (UTC plus 2) 2015/09/30 17:22:32 i don't think this could ever happen. the object c
Patrick Monette 2015/10/01 21:12:50 SGTM. Done.
288 }
289
259 /////////////////////////////////////////////////////////////////////////////// 290 ///////////////////////////////////////////////////////////////////////////////
260 // DefaultBrowserWorker, private: 291 // DefaultBrowserWorker, private:
261 292
262 ShellIntegration::DefaultWebClientState 293 void ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
263 ShellIntegration::DefaultBrowserWorker::CheckIsDefault() { 294 DefaultWebClientState state = GetDefaultBrowser();
264 return ShellIntegration::GetDefaultBrowser(); 295 BrowserThread::PostTask(
296 BrowserThread::UI, FROM_HERE,
297 base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state));
265 } 298 }
266 299
267 bool ShellIntegration::DefaultBrowserWorker::SetAsDefault( 300 void ShellIntegration::DefaultBrowserWorker::SetAsDefault(
268 bool interactive_permitted) { 301 bool interactive_permitted) {
269 bool result = false; 302 bool result = false;
270 switch (ShellIntegration::CanSetAsDefaultBrowser()) { 303 switch (CanSetAsDefaultBrowser()) {
271 case ShellIntegration::SET_DEFAULT_UNATTENDED: 304 case SET_DEFAULT_NOT_ALLOWED:
272 result = ShellIntegration::SetAsDefaultBrowser(); 305 NOTREACHED();
273 break; 306 break;
274 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 307 case SET_DEFAULT_UNATTENDED:
308 result = SetAsDefaultBrowser();
309 break;
310 case SET_DEFAULT_INTERACTIVE:
275 if (interactive_permitted) 311 if (interactive_permitted)
276 result = ShellIntegration::SetAsDefaultBrowserInteractive(); 312 result = SetAsDefaultBrowserInteractive();
277 break; 313 break;
278 default: 314 case SET_DEFAULT_ASYNCHRONOUS:
315 #if defined(OS_WIN)
316 if (!interactive_permitted)
317 break;
318 if (GetDefaultBrowser() == IS_DEFAULT) {
319 // Don't start the asynchronous operation since it could result in
320 // losing the default browser status.
321 result = true;
322 break;
323 }
324 // This function will cause OnSetAsDefaultAttemptComplete() to be called
325 // asynchronously via a filter established in InitializeSetAsDefault().
326 SetAsDefaultBrowserAsynchronous();
327 return;
328 #else
279 NOTREACHED(); 329 NOTREACHED();
330 break;
331 #endif
280 } 332 }
281 333 BrowserThread::PostTask(
282 return result; 334 BrowserThread::UI, FROM_HERE,
335 base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this,
336 result));
283 } 337 }
284 338
285 /////////////////////////////////////////////////////////////////////////////// 339 ///////////////////////////////////////////////////////////////////////////////
286 // ShellIntegration::DefaultProtocolClientWorker 340 // ShellIntegration::DefaultProtocolClientWorker
287 // 341 //
288 342
289 ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker( 343 ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
290 DefaultWebClientObserver* observer, const std::string& protocol) 344 DefaultWebClientObserver* observer, const std::string& protocol)
291 : DefaultWebClientWorker(observer), 345 : DefaultWebClientWorker(observer),
292 protocol_(protocol) { 346 protocol_(protocol) {
293 } 347 }
294 348
295 /////////////////////////////////////////////////////////////////////////////// 349 ///////////////////////////////////////////////////////////////////////////////
296 // DefaultProtocolClientWorker, private: 350 // DefaultProtocolClientWorker, private:
297 351
298 ShellIntegration::DefaultWebClientState 352 ShellIntegration::DefaultProtocolClientWorker::~DefaultProtocolClientWorker() {}
299 ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() { 353
300 return ShellIntegration::IsDefaultProtocolClient(protocol_); 354 void ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
355 DefaultWebClientState state = IsDefaultProtocolClient(protocol_);
356 BrowserThread::PostTask(
357 BrowserThread::UI, FROM_HERE,
358 base::Bind(&DefaultProtocolClientWorker::OnCheckIsDefaultComplete, this,
359 state));
301 } 360 }
302 361
303 bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault( 362 void ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
304 bool interactive_permitted) { 363 bool interactive_permitted) {
305 bool result = false; 364 bool result = false;
306 switch (ShellIntegration::CanSetAsDefaultProtocolClient()) { 365 switch (CanSetAsDefaultProtocolClient()) {
307 case ShellIntegration::SET_DEFAULT_NOT_ALLOWED: 366 case SET_DEFAULT_NOT_ALLOWED:
308 result = false; 367 // Not allowed, do nothing.
309 break; 368 break;
310 case ShellIntegration::SET_DEFAULT_UNATTENDED: 369 case SET_DEFAULT_UNATTENDED:
311 result = ShellIntegration::SetAsDefaultProtocolClient(protocol_); 370 result = SetAsDefaultProtocolClient(protocol_);
312 break; 371 break;
313 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 372 case SET_DEFAULT_INTERACTIVE:
314 if (interactive_permitted) { 373 if (interactive_permitted) {
315 result = ShellIntegration::SetAsDefaultProtocolClientInteractive( 374 result = SetAsDefaultProtocolClientInteractive(protocol_);
316 protocol_);
317 } 375 }
318 break; 376 break;
377 case SET_DEFAULT_ASYNCHRONOUS:
378 NOTREACHED();
379 break;
319 } 380 }
320 381 BrowserThread::PostTask(
321 return result; 382 BrowserThread::UI, FROM_HERE,
383 base::Bind(&DefaultProtocolClientWorker::OnSetAsDefaultAttemptComplete,
384 this, result));
322 } 385 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698