Home | History | Annotate | Download | only in sync
      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 
     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 
     82 void OneClickSigninSyncStarter::OnBrowserRemoved(Browser* browser) {
     83   if (browser == browser_)
     84     browser_ = NULL;
     85 }
     86 
     87 OneClickSigninSyncStarter::~OneClickSigninSyncStarter() {
     88   BrowserList::RemoveObserver(this);
     89 }
     90 
     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 
    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)
    144 OneClickSigninSyncStarter::SigninDialogDelegate::SigninDialogDelegate(
    145     base::WeakPtr<OneClickSigninSyncStarter> sync_starter)
    146   : sync_starter_(sync_starter) {
    147 }
    148 
    149 OneClickSigninSyncStarter::SigninDialogDelegate::~SigninDialogDelegate() {
    150 }
    151 
    152 void OneClickSigninSyncStarter::SigninDialogDelegate::OnCancelSignin() {
    153   if (sync_starter_ != NULL)
    154     sync_starter_->CancelSigninAndDelete();
    155 }
    156 
    157 void OneClickSigninSyncStarter::SigninDialogDelegate::OnContinueSignin() {
    158   if (sync_starter_ != NULL)
    159     sync_starter_->LoadPolicyWithCachedCredentials();
    160 }
    161 
    162 void OneClickSigninSyncStarter::SigninDialogDelegate::OnSigninWithNewProfile() {
    163   if (sync_starter_ != NULL)
    164     sync_starter_->CreateNewSignedInProfile();
    165 }
    166 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    372 void OneClickSigninSyncStarter::SigninSuccess() {
    373   if (switches::IsEnableWebBasedSignin())
    374     MergeSessionComplete(GoogleServiceAuthError(GoogleServiceAuthError::NONE));
    375 }
    376 
    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 
    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
    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 
    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 
    513 ProfileSyncService* OneClickSigninSyncStarter::GetProfileSyncService() {
    514   ProfileSyncService* service = NULL;
    515   if (profile_->IsSyncAccessible())
    516     service = ProfileSyncServiceFactory::GetForProfile(profile_);
    517   return service;
    518 }
    519 
    520 void OneClickSigninSyncStarter::FinishProfileSyncServiceSetup() {
    521   ProfileSyncService* service =
    522       ProfileSyncServiceFactory::GetForProfile(profile_);
    523   if (service)
    524     service->SetSetupInProgress(false);
    525 }
    526 
    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 
    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