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