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/sync/one_click_signin_sync_starter.h"
6
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10
11 #if defined(ENABLE_CONFIGURATION_POLICY)
12 #include "chrome/browser/policy/cloud/user_policy_signin_service.h"
13 #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
14 #endif
15
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
18 #include "chrome/browser/profiles/profile_info_cache.h"
19 #include "chrome/browser/profiles/profile_io_data.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/profiles/profile_window.h"
22 #include "chrome/browser/signin/signin_manager_factory.h"
23 #include "chrome/browser/signin/signin_tracker_factory.h"
24 #include "chrome/browser/sync/profile_sync_service.h"
25 #include "chrome/browser/sync/profile_sync_service_factory.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_dialogs.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/browser_navigator.h"
31 #include "chrome/browser/ui/browser_tabstrip.h"
32 #include "chrome/browser/ui/browser_window.h"
33 #include "chrome/browser/ui/chrome_pages.h"
34 #include "chrome/browser/ui/sync/one_click_signin_sync_observer.h"
35 #include "chrome/browser/ui/tabs/tab_strip_model.h"
36 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
37 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
38 #include "chrome/browser/ui/webui/signin/profile_signin_confirmation_dialog.h"
39 #include "chrome/common/url_constants.h"
40 #include "components/signin/core/browser/signin_manager.h"
41 #include "components/signin/core/browser/signin_metrics.h"
42 #include "components/signin/core/common/profile_management_switches.h"
43 #include "components/sync_driver/sync_prefs.h"
44 #include "grit/chromium_strings.h"
45 #include "grit/generated_resources.h"
46 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/base/resource/resource_bundle.h"
48
OneClickSigninSyncStarter(Profile * profile,Browser * browser,const std::string & email,const std::string & password,const std::string & refresh_token,StartSyncMode start_mode,content::WebContents * web_contents,ConfirmationRequired confirmation_required,const GURL & continue_url,Callback sync_setup_completed_callback)49 OneClickSigninSyncStarter::OneClickSigninSyncStarter(
50 Profile* profile,
51 Browser* browser,
52 const std::string& email,
53 const std::string& password,
54 const std::string& refresh_token,
55 StartSyncMode start_mode,
56 content::WebContents* web_contents,
57 ConfirmationRequired confirmation_required,
58 const GURL& continue_url,
59 Callback sync_setup_completed_callback)
60 : content::WebContentsObserver(web_contents),
61 start_mode_(start_mode),
62 desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE),
63 confirmation_required_(confirmation_required),
64 continue_url_(continue_url),
65 sync_setup_completed_callback_(sync_setup_completed_callback),
66 weak_pointer_factory_(this) {
67 DCHECK(profile);
68 DCHECK(web_contents || continue_url.is_empty());
69 BrowserList::AddObserver(this);
70
71 Initialize(profile, browser);
72
73 // Policy is enabled, so pass in a callback to do extra policy-related UI
74 // before signin completes.
75 SigninManagerFactory::GetForProfile(profile_)->
76 StartSignInWithRefreshToken(
77 refresh_token, email, password,
78 base::Bind(&OneClickSigninSyncStarter::ConfirmSignin,
79 weak_pointer_factory_.GetWeakPtr()));
80 }
81
OnBrowserRemoved(Browser * browser)82 void OneClickSigninSyncStarter::OnBrowserRemoved(Browser* browser) {
83 if (browser == browser_)
84 browser_ = NULL;
85 }
86
~OneClickSigninSyncStarter()87 OneClickSigninSyncStarter::~OneClickSigninSyncStarter() {
88 BrowserList::RemoveObserver(this);
89 }
90
Initialize(Profile * profile,Browser * browser)91 void OneClickSigninSyncStarter::Initialize(Profile* profile, Browser* browser) {
92 DCHECK(profile);
93 profile_ = profile;
94 browser_ = browser;
95
96 // Cache the parent desktop for the browser, so we can reuse that same
97 // desktop for any UI we want to display.
98 if (browser) {
99 desktop_type_ = browser->host_desktop_type();
100 } else {
101 desktop_type_ = chrome::GetActiveDesktop();
102 }
103
104 signin_tracker_ = SigninTrackerFactory::CreateForProfile(profile_, this);
105
106 // Let the sync service know that setup is in progress so it doesn't start
107 // syncing until the user has finished any configuration.
108 ProfileSyncService* profile_sync_service = GetProfileSyncService();
109 if (profile_sync_service)
110 profile_sync_service->SetSetupInProgress(true);
111
112 // Make sure the syncing is not suppressed, otherwise the SigninManager
113 // will not be able to complete sucessfully.
114 sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
115 sync_prefs.SetStartSuppressed(false);
116 }
117
ConfirmSignin(const std::string & oauth_token)118 void OneClickSigninSyncStarter::ConfirmSignin(const std::string& oauth_token) {
119 DCHECK(!oauth_token.empty());
120 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
121 // If this is a new signin (no authenticated username yet) try loading
122 // policy for this user now, before any signed in services are initialized.
123 if (signin->GetAuthenticatedUsername().empty()) {
124 #if defined(ENABLE_CONFIGURATION_POLICY)
125 policy::UserPolicySigninService* policy_service =
126 policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
127 policy_service->RegisterForPolicy(
128 signin->GetUsernameForAuthInProgress(),
129 oauth_token,
130 base::Bind(&OneClickSigninSyncStarter::OnRegisteredForPolicy,
131 weak_pointer_factory_.GetWeakPtr()));
132 return;
133 #else
134 ConfirmAndSignin();
135 #endif
136 } else {
137 // The user is already signed in - just tell SigninManager to continue
138 // with its re-auth flow.
139 signin->CompletePendingSignin();
140 }
141 }
142
143 #if defined(ENABLE_CONFIGURATION_POLICY)
SigninDialogDelegate(base::WeakPtr<OneClickSigninSyncStarter> sync_starter)144 OneClickSigninSyncStarter::SigninDialogDelegate::SigninDialogDelegate(
145 base::WeakPtr<OneClickSigninSyncStarter> sync_starter)
146 : sync_starter_(sync_starter) {
147 }
148
~SigninDialogDelegate()149 OneClickSigninSyncStarter::SigninDialogDelegate::~SigninDialogDelegate() {
150 }
151
OnCancelSignin()152 void OneClickSigninSyncStarter::SigninDialogDelegate::OnCancelSignin() {
153 if (sync_starter_ != NULL)
154 sync_starter_->CancelSigninAndDelete();
155 }
156
OnContinueSignin()157 void OneClickSigninSyncStarter::SigninDialogDelegate::OnContinueSignin() {
158 if (sync_starter_ != NULL)
159 sync_starter_->LoadPolicyWithCachedCredentials();
160 }
161
OnSigninWithNewProfile()162 void OneClickSigninSyncStarter::SigninDialogDelegate::OnSigninWithNewProfile() {
163 if (sync_starter_ != NULL)
164 sync_starter_->CreateNewSignedInProfile();
165 }
166
OnRegisteredForPolicy(const std::string & dm_token,const std::string & client_id)167 void OneClickSigninSyncStarter::OnRegisteredForPolicy(
168 const std::string& dm_token, const std::string& client_id) {
169 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
170 // If there's no token for the user (policy registration did not succeed) just
171 // finish signing in.
172 if (dm_token.empty()) {
173 DVLOG(1) << "Policy registration failed";
174 ConfirmAndSignin();
175 return;
176 }
177
178 DVLOG(1) << "Policy registration succeeded: dm_token=" << dm_token;
179
180 // Stash away a copy of our CloudPolicyClient (should not already have one).
181 DCHECK(dm_token_.empty());
182 DCHECK(client_id_.empty());
183 dm_token_ = dm_token;
184 client_id_ = client_id;
185
186 // Allow user to create a new profile before continuing with sign-in.
187 browser_ = EnsureBrowser(browser_, profile_, desktop_type_);
188 content::WebContents* web_contents =
189 browser_->tab_strip_model()->GetActiveWebContents();
190 if (!web_contents) {
191 CancelSigninAndDelete();
192 return;
193 }
194 chrome::ShowProfileSigninConfirmationDialog(
195 browser_,
196 web_contents,
197 profile_,
198 signin->GetUsernameForAuthInProgress(),
199 new SigninDialogDelegate(weak_pointer_factory_.GetWeakPtr()));
200 }
201
LoadPolicyWithCachedCredentials()202 void OneClickSigninSyncStarter::LoadPolicyWithCachedCredentials() {
203 DCHECK(!dm_token_.empty());
204 DCHECK(!client_id_.empty());
205 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
206 policy::UserPolicySigninService* policy_service =
207 policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
208 policy_service->FetchPolicyForSignedInUser(
209 signin->GetUsernameForAuthInProgress(),
210 dm_token_,
211 client_id_,
212 profile_->GetRequestContext(),
213 base::Bind(&OneClickSigninSyncStarter::OnPolicyFetchComplete,
214 weak_pointer_factory_.GetWeakPtr()));
215 }
216
OnPolicyFetchComplete(bool success)217 void OneClickSigninSyncStarter::OnPolicyFetchComplete(bool success) {
218 // For now, we allow signin to complete even if the policy fetch fails. If
219 // we ever want to change this behavior, we could call
220 // SigninManager::SignOut() here instead.
221 DLOG_IF(ERROR, !success) << "Error fetching policy for user";
222 DVLOG_IF(1, success) << "Policy fetch successful - completing signin";
223 SigninManagerFactory::GetForProfile(profile_)->CompletePendingSignin();
224 }
225
CreateNewSignedInProfile()226 void OneClickSigninSyncStarter::CreateNewSignedInProfile() {
227 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
228 DCHECK(!signin->GetUsernameForAuthInProgress().empty());
229 DCHECK(!dm_token_.empty());
230 DCHECK(!client_id_.empty());
231 // Create a new profile and have it call back when done so we can inject our
232 // signin credentials.
233 size_t icon_index = g_browser_process->profile_manager()->
234 GetProfileInfoCache().ChooseAvatarIconIndexForNewProfile();
235 ProfileManager::CreateMultiProfileAsync(
236 base::UTF8ToUTF16(signin->GetUsernameForAuthInProgress()),
237 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(icon_index)),
238 base::Bind(&OneClickSigninSyncStarter::CompleteInitForNewProfile,
239 weak_pointer_factory_.GetWeakPtr(), desktop_type_),
240 std::string());
241 }
242
CompleteInitForNewProfile(chrome::HostDesktopType desktop_type,Profile * new_profile,Profile::CreateStatus status)243 void OneClickSigninSyncStarter::CompleteInitForNewProfile(
244 chrome::HostDesktopType desktop_type,
245 Profile* new_profile,
246 Profile::CreateStatus status) {
247 DCHECK_NE(profile_, new_profile);
248
249 // TODO(atwilson): On error, unregister the client to release the DMToken
250 // and surface a better error for the user.
251 switch (status) {
252 case Profile::CREATE_STATUS_LOCAL_FAIL: {
253 NOTREACHED() << "Error creating new profile";
254 CancelSigninAndDelete();
255 return;
256 }
257 case Profile::CREATE_STATUS_CREATED: {
258 break;
259 }
260 case Profile::CREATE_STATUS_INITIALIZED: {
261 // Wait until the profile is initialized before we transfer credentials.
262 SigninManager* old_signin_manager =
263 SigninManagerFactory::GetForProfile(profile_);
264 SigninManager* new_signin_manager =
265 SigninManagerFactory::GetForProfile(new_profile);
266 DCHECK(!old_signin_manager->GetUsernameForAuthInProgress().empty());
267 DCHECK(old_signin_manager->GetAuthenticatedUsername().empty());
268 DCHECK(new_signin_manager->GetAuthenticatedUsername().empty());
269 DCHECK(!dm_token_.empty());
270 DCHECK(!client_id_.empty());
271
272 // Copy credentials from the old profile to the just-created profile,
273 // and switch over to tracking that profile.
274 new_signin_manager->CopyCredentialsFrom(*old_signin_manager);
275 FinishProfileSyncServiceSetup();
276 Initialize(new_profile, NULL);
277 DCHECK_EQ(profile_, new_profile);
278
279 // We've transferred our credentials to the new profile - notify that
280 // the signin for the original profile was cancelled (must do this after
281 // we have called Initialize() with the new profile, as otherwise this
282 // object will get freed when the signin on the old profile is cancelled.
283 old_signin_manager->SignOut(signin_metrics::TRANSFER_CREDENTIALS);
284
285 // Load policy for the just-created profile - once policy has finished
286 // loading the signin process will complete.
287 LoadPolicyWithCachedCredentials();
288
289 // Open the profile's first window, after all initialization.
290 profiles::FindOrCreateNewWindowForProfile(
291 new_profile,
292 chrome::startup::IS_PROCESS_STARTUP,
293 chrome::startup::IS_FIRST_RUN,
294 desktop_type,
295 false);
296 break;
297 }
298 case Profile::CREATE_STATUS_REMOTE_FAIL:
299 case Profile::CREATE_STATUS_CANCELED:
300 case Profile::MAX_CREATE_STATUS: {
301 NOTREACHED() << "Invalid profile creation status";
302 CancelSigninAndDelete();
303 return;
304 }
305 }
306 }
307 #endif
308
CancelSigninAndDelete()309 void OneClickSigninSyncStarter::CancelSigninAndDelete() {
310 SigninManagerFactory::GetForProfile(profile_)->SignOut(
311 signin_metrics::ABORT_SIGNIN);
312 // The statement above results in a call to SigninFailed() which will free
313 // this object, so do not refer to the OneClickSigninSyncStarter object
314 // after this point.
315 }
316
ConfirmAndSignin()317 void OneClickSigninSyncStarter::ConfirmAndSignin() {
318 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
319 if (confirmation_required_ == CONFIRM_UNTRUSTED_SIGNIN) {
320 browser_ = EnsureBrowser(browser_, profile_, desktop_type_);
321 // Display a confirmation dialog to the user.
322 browser_->window()->ShowOneClickSigninBubble(
323 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_SAML_MODAL_DIALOG,
324 base::UTF8ToUTF16(signin->GetUsernameForAuthInProgress()),
325 base::string16(), // No error message to display.
326 base::Bind(&OneClickSigninSyncStarter::UntrustedSigninConfirmed,
327 weak_pointer_factory_.GetWeakPtr()));
328 } else {
329 // No confirmation required - just sign in the user.
330 signin->CompletePendingSignin();
331 }
332 }
333
UntrustedSigninConfirmed(StartSyncMode response)334 void OneClickSigninSyncStarter::UntrustedSigninConfirmed(
335 StartSyncMode response) {
336 if (response == UNDO_SYNC) {
337 CancelSigninAndDelete(); // This statement frees this object.
338 } else {
339 // If the user clicked the "Advanced" link in the confirmation dialog, then
340 // override the current start_mode_ to bring up the advanced sync settings.
341 if (response == CONFIGURE_SYNC_FIRST)
342 start_mode_ = response;
343 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
344 signin->CompletePendingSignin();
345 }
346 }
347
SigninFailed(const GoogleServiceAuthError & error)348 void OneClickSigninSyncStarter::SigninFailed(
349 const GoogleServiceAuthError& error) {
350 if (!sync_setup_completed_callback_.is_null())
351 sync_setup_completed_callback_.Run(SYNC_SETUP_FAILURE);
352
353 FinishProfileSyncServiceSetup();
354 if (confirmation_required_ == CONFIRM_AFTER_SIGNIN) {
355 switch (error.state()) {
356 case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
357 DisplayFinalConfirmationBubble(l10n_util::GetStringUTF16(
358 IDS_SYNC_UNRECOVERABLE_ERROR));
359 break;
360 case GoogleServiceAuthError::REQUEST_CANCELED:
361 // No error notification needed if the user manually cancelled signin.
362 break;
363 default:
364 DisplayFinalConfirmationBubble(l10n_util::GetStringUTF16(
365 IDS_SYNC_ERROR_SIGNING_IN));
366 break;
367 }
368 }
369 delete this;
370 }
371
SigninSuccess()372 void OneClickSigninSyncStarter::SigninSuccess() {
373 if (switches::IsEnableWebBasedSignin())
374 MergeSessionComplete(GoogleServiceAuthError(GoogleServiceAuthError::NONE));
375 }
376
MergeSessionComplete(const GoogleServiceAuthError & error)377 void OneClickSigninSyncStarter::MergeSessionComplete(
378 const GoogleServiceAuthError& error) {
379 // Regardless of whether the merge session completed sucessfully or not,
380 // continue with sync starting.
381
382 if (!sync_setup_completed_callback_.is_null())
383 sync_setup_completed_callback_.Run(SYNC_SETUP_SUCCESS);
384
385 switch (start_mode_) {
386 case SYNC_WITH_DEFAULT_SETTINGS: {
387 // Just kick off the sync machine, no need to configure it first.
388 ProfileSyncService* profile_sync_service = GetProfileSyncService();
389 if (profile_sync_service)
390 profile_sync_service->SetSyncSetupCompleted();
391 FinishProfileSyncServiceSetup();
392 if (confirmation_required_ == CONFIRM_AFTER_SIGNIN) {
393 base::string16 message;
394 if (!profile_sync_service) {
395 // Sync is disabled by policy.
396 message = l10n_util::GetStringUTF16(
397 IDS_ONE_CLICK_SIGNIN_BUBBLE_SYNC_DISABLED_MESSAGE);
398 }
399 DisplayFinalConfirmationBubble(message);
400 }
401 break;
402 }
403 case CONFIGURE_SYNC_FIRST:
404 ShowSettingsPage(true); // Show sync config UI.
405 break;
406 case SHOW_SETTINGS_WITHOUT_CONFIGURE:
407 ShowSettingsPage(false); // Don't show sync config UI.
408 break;
409 case UNDO_SYNC:
410 NOTREACHED();
411 }
412
413 // Navigate to the |continue_url_| if one is set, unless the user first needs
414 // to configure Sync.
415 if (web_contents() && !continue_url_.is_empty() &&
416 start_mode_ != CONFIGURE_SYNC_FIRST) {
417 LoadContinueUrl();
418 }
419
420 delete this;
421 }
422
DisplayFinalConfirmationBubble(const base::string16 & custom_message)423 void OneClickSigninSyncStarter::DisplayFinalConfirmationBubble(
424 const base::string16& custom_message) {
425 browser_ = EnsureBrowser(browser_, profile_, desktop_type_);
426 browser_->window()->ShowOneClickSigninBubble(
427 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE,
428 base::string16(), // No email required - this is not a SAML confirmation.
429 custom_message,
430 // Callback is ignored.
431 BrowserWindow::StartSyncCallback());
432 }
433
434 // static
EnsureBrowser(Browser * browser,Profile * profile,chrome::HostDesktopType desktop_type)435 Browser* OneClickSigninSyncStarter::EnsureBrowser(
436 Browser* browser,
437 Profile* profile,
438 chrome::HostDesktopType desktop_type) {
439 if (!browser) {
440 // The user just created a new profile or has closed the browser that
441 // we used previously. Grab the most recently active browser or else
442 // create a new one.
443 browser = chrome::FindLastActiveWithProfile(profile, desktop_type);
444 if (!browser) {
445 browser = new Browser(Browser::CreateParams(profile,
446 desktop_type));
447 chrome::AddTabAt(browser, GURL(), -1, true);
448 }
449 browser->window()->Show();
450 }
451 return browser;
452 }
453
ShowSettingsPage(bool configure_sync)454 void OneClickSigninSyncStarter::ShowSettingsPage(bool configure_sync) {
455 // Give the user a chance to configure things. We don't clear the
456 // ProfileSyncService::setup_in_progress flag because we don't want sync
457 // to start up until after the configure UI is displayed (the configure UI
458 // will clear the flag when the user is done setting up sync).
459 ProfileSyncService* profile_sync_service = GetProfileSyncService();
460 LoginUIService* login_ui = LoginUIServiceFactory::GetForProfile(profile_);
461 if (login_ui->current_login_ui()) {
462 login_ui->current_login_ui()->FocusUI();
463 } else {
464 browser_ = EnsureBrowser(browser_, profile_, desktop_type_);
465
466 // If the sign in tab is showing the native signin page or the blank page
467 // for web-based flow, and is not about to be closed, use it to show the
468 // settings UI.
469 bool use_same_tab = false;
470 if (web_contents()) {
471 GURL current_url = web_contents()->GetLastCommittedURL();
472 bool is_chrome_signin_url =
473 current_url.GetOrigin().spec() == chrome::kChromeUIChromeSigninURL;
474 bool is_same_profile =
475 Profile::FromBrowserContext(web_contents()->GetBrowserContext()) ==
476 profile_;
477 use_same_tab =
478 (is_chrome_signin_url ||
479 signin::IsContinueUrlForWebBasedSigninFlow(current_url)) &&
480 !signin::IsAutoCloseEnabledInURL(current_url) &&
481 is_same_profile;
482 }
483 if (profile_sync_service) {
484 // Need to navigate to the settings page and display the sync UI.
485 if (use_same_tab) {
486 ShowSettingsPageInWebContents(web_contents(),
487 chrome::kSyncSetupSubPage);
488 } else {
489 // If the user is setting up sync for the first time, let them configure
490 // advanced sync settings. However, in the case of re-authentication,
491 // return the user to the settings page without showing any config UI.
492 if (configure_sync) {
493 chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage);
494 } else {
495 FinishProfileSyncServiceSetup();
496 chrome::ShowSettings(browser_);
497 }
498 }
499 } else {
500 // Sync is disabled - just display the settings page or redirect to the
501 // |continue_url_|.
502 FinishProfileSyncServiceSetup();
503 if (!use_same_tab)
504 chrome::ShowSettings(browser_);
505 else if (!continue_url_.is_empty())
506 LoadContinueUrl();
507 else
508 ShowSettingsPageInWebContents(web_contents(), std::string());
509 }
510 }
511 }
512
GetProfileSyncService()513 ProfileSyncService* OneClickSigninSyncStarter::GetProfileSyncService() {
514 ProfileSyncService* service = NULL;
515 if (profile_->IsSyncAccessible())
516 service = ProfileSyncServiceFactory::GetForProfile(profile_);
517 return service;
518 }
519
FinishProfileSyncServiceSetup()520 void OneClickSigninSyncStarter::FinishProfileSyncServiceSetup() {
521 ProfileSyncService* service =
522 ProfileSyncServiceFactory::GetForProfile(profile_);
523 if (service)
524 service->SetSetupInProgress(false);
525 }
526
ShowSettingsPageInWebContents(content::WebContents * contents,const std::string & sub_page)527 void OneClickSigninSyncStarter::ShowSettingsPageInWebContents(
528 content::WebContents* contents,
529 const std::string& sub_page) {
530 if (!continue_url_.is_empty()) {
531 // The observer deletes itself once it's done.
532 DCHECK(!sub_page.empty());
533 new OneClickSigninSyncObserver(contents, continue_url_);
534 }
535
536 GURL url = chrome::GetSettingsUrl(sub_page);
537 content::OpenURLParams params(url,
538 content::Referrer(),
539 CURRENT_TAB,
540 content::PAGE_TRANSITION_AUTO_TOPLEVEL,
541 false);
542 contents->OpenURL(params);
543
544 // Activate the tab.
545 Browser* browser = chrome::FindBrowserWithWebContents(contents);
546 int content_index =
547 browser->tab_strip_model()->GetIndexOfWebContents(contents);
548 browser->tab_strip_model()->ActivateTabAt(content_index,
549 false /* user_gesture */);
550 }
551
LoadContinueUrl()552 void OneClickSigninSyncStarter::LoadContinueUrl() {
553 web_contents()->GetController().LoadURL(
554 continue_url_,
555 content::Referrer(),
556 content::PAGE_TRANSITION_AUTO_TOPLEVEL,
557 std::string());
558 }
559