sync_setup_wizard.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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/sync/sync_setup_wizard.h" 6 7#include "app/resource_bundle.h" 8#include "base/message_loop.h" 9#include "base/singleton.h" 10#include "chrome/browser/chrome_thread.h" 11#include "chrome/browser/dom_ui/chrome_url_data_manager.h" 12#include "chrome/browser/google/google_util.h" 13#include "chrome/browser/prefs/pref_service.h" 14#include "chrome/browser/profile.h" 15#include "chrome/browser/sync/profile_sync_service.h" 16#include "chrome/browser/sync/sync_setup_flow.h" 17#include "chrome/common/jstemplate_builder.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/common/url_constants.h" 20#include "googleurl/src/gurl.h" 21#include "grit/app_resources.h" 22#include "grit/browser_resources.h" 23#include "grit/chromium_strings.h" 24 25class SyncResourcesSource : public ChromeURLDataManager::DataSource { 26 public: 27 SyncResourcesSource() 28 : DataSource(chrome::kChromeUISyncResourcesHost, MessageLoop::current()) { 29 } 30 31 virtual void StartDataRequest(const std::string& path, 32 bool is_off_the_record, 33 int request_id); 34 35 virtual std::string GetMimeType(const std::string& path) const { 36 return "text/html"; 37 } 38 39 static const char* kInvalidPasswordHelpUrl; 40 static const char* kCanNotAccessAccountUrl; 41 static const char* kCreateNewAccountUrl; 42 43 private: 44 virtual ~SyncResourcesSource() {} 45 46 // Takes a string containing an URL and returns an URL containing a CGI 47 // parameter of the form "&hl=xy" where 'xy' is the language code of the 48 // current locale. 49 std::string GetLocalizedUrl(const std::string& url) const; 50 51 DISALLOW_COPY_AND_ASSIGN(SyncResourcesSource); 52}; 53 54const char* SyncResourcesSource::kInvalidPasswordHelpUrl = 55 "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444"; 56const char* SyncResourcesSource::kCanNotAccessAccountUrl = 57 "http://www.google.com/support/accounts/bin/answer.py?answer=48598"; 58const char* SyncResourcesSource::kCreateNewAccountUrl = 59 "https://www.google.com/accounts/NewAccount?service=chromiumsync"; 60 61void SyncResourcesSource::StartDataRequest(const std::string& path_raw, 62 bool is_off_the_record, int request_id) { 63 const char kSyncGaiaLoginPath[] = "gaialogin"; 64 const char kSyncChooseDataTypesPath[] = "choosedatatypes"; 65 const char kSyncSetupFlowPath[] = "setup"; 66 const char kSyncSetupDonePath[] = "setupdone"; 67 68 std::string response; 69 if (path_raw == kSyncGaiaLoginPath) { 70 DictionaryValue localized_strings; 71 72 // Start by setting the per-locale URLs we show on the setup wizard. 73 localized_strings.SetString("invalidpasswordhelpurl", 74 GetLocalizedUrl(kInvalidPasswordHelpUrl)); 75 localized_strings.SetString("cannotaccessaccounturl", 76 GetLocalizedUrl(kCanNotAccessAccountUrl)); 77 localized_strings.SetString("createnewaccounturl", 78 GetLocalizedUrl(kCreateNewAccountUrl)); 79 80 localized_strings.SetString("settingupsync", 81 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP_SYNC)); 82 localized_strings.SetString("introduction", 83 l10n_util::GetStringFUTF16(IDS_SYNC_LOGIN_INTRODUCTION, 84 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); 85 localized_strings.SetString("signinprefix", 86 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SIGNIN_PREFIX)); 87 localized_strings.SetString("signinsuffix", 88 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SIGNIN_SUFFIX)); 89 localized_strings.SetString("cannotbeblank", 90 l10n_util::GetStringUTF16(IDS_SYNC_CANNOT_BE_BLANK)); 91 localized_strings.SetString("emaillabel", 92 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_EMAIL)); 93 localized_strings.SetString("passwordlabel", 94 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_PASSWORD)); 95 localized_strings.SetString("invalidcredentials", 96 l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS)); 97 localized_strings.SetString("signin", 98 l10n_util::GetStringUTF16(IDS_SYNC_SIGNIN)); 99 localized_strings.SetString("couldnotconnect", 100 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_COULD_NOT_CONNECT)); 101 localized_strings.SetString("cannotaccessaccount", 102 l10n_util::GetStringUTF16(IDS_SYNC_CANNOT_ACCESS_ACCOUNT)); 103 localized_strings.SetString("createaccount", 104 l10n_util::GetStringUTF16(IDS_SYNC_CREATE_ACCOUNT)); 105 localized_strings.SetString("cancel", 106 l10n_util::GetStringUTF16(IDS_CANCEL)); 107 localized_strings.SetString("settingup", 108 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP)); 109 localized_strings.SetString("success", 110 l10n_util::GetStringUTF16(IDS_SYNC_SUCCESS)); 111 localized_strings.SetString("errorsigningin", 112 l10n_util::GetStringUTF16(IDS_SYNC_ERROR_SIGNING_IN)); 113 localized_strings.SetString("captchainstructions", 114 l10n_util::GetStringUTF16(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS)); 115 static const base::StringPiece html(ResourceBundle::GetSharedInstance() 116 .GetRawDataResource(IDR_GAIA_LOGIN_HTML)); 117 SetFontAndTextDirection(&localized_strings); 118 response = jstemplate_builder::GetI18nTemplateHtml( 119 html, &localized_strings); 120 } else if (path_raw == kSyncChooseDataTypesPath) { 121 DictionaryValue localized_strings; 122 localized_strings.SetString("choosedatatypesheader", 123 l10n_util::GetStringUTF16(IDS_SYNC_CHOOSE_DATATYPES_HEADER)); 124 localized_strings.SetString("choosedatatypesinstructions", 125 l10n_util::GetStringFUTF16(IDS_SYNC_CHOOSE_DATATYPES_INSTRUCTIONS, 126 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); 127 localized_strings.SetString("keepeverythingsynced", 128 l10n_util::GetStringUTF16(IDS_SYNC_EVERYTHING)); 129 localized_strings.SetString("choosedatatypes", 130 l10n_util::GetStringUTF16(IDS_SYNC_CHOOSE_DATATYPES)); 131 localized_strings.SetString("bookmarks", 132 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS)); 133 localized_strings.SetString("preferences", 134 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES)); 135 localized_strings.SetString("autofill", 136 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL)); 137 localized_strings.SetString("themes", 138 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES)); 139 localized_strings.SetString("passwords", 140 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS)); 141 localized_strings.SetString("extensions", 142 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS)); 143 localized_strings.SetString("typedurls", 144 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS)); 145 localized_strings.SetString("apps", 146 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS)); 147 localized_strings.SetString("synczerodatatypeserror", 148 l10n_util::GetStringUTF16(IDS_SYNC_ZERO_DATA_TYPES_ERROR)); 149 localized_strings.SetString("setupabortederror", 150 l10n_util::GetStringUTF16(IDS_SYNC_SETUP_ABORTED_BY_PENDING_CLEAR)); 151 localized_strings.SetString("ok", 152 l10n_util::GetStringUTF16(IDS_OK)); 153 localized_strings.SetString("cancel", 154 l10n_util::GetStringUTF16(IDS_CANCEL)); 155 localized_strings.SetString("settingup", 156 l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP)); 157 static const base::StringPiece html(ResourceBundle::GetSharedInstance() 158 .GetRawDataResource(IDR_SYNC_CHOOSE_DATATYPES_HTML)); 159 SetFontAndTextDirection(&localized_strings); 160 response = jstemplate_builder::GetI18nTemplateHtml( 161 html, &localized_strings); 162 } else if (path_raw == kSyncSetupDonePath) { 163 DictionaryValue localized_strings; 164 localized_strings.SetString("success", 165 l10n_util::GetStringUTF16(IDS_SYNC_SUCCESS)); 166 localized_strings.SetString("setupsummary", 167 l10n_util::GetStringFUTF16(IDS_SYNC_SETUP_ALL_DONE, 168 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); 169 localized_strings.SetString("firsttimesetupsummary", 170 l10n_util::GetStringUTF16(IDS_SYNC_SETUP_FIRST_TIME_ALL_DONE)); 171 localized_strings.SetString("okay", 172 l10n_util::GetStringUTF16(IDS_SYNC_SETUP_OK_BUTTON_LABEL)); 173 static const base::StringPiece html(ResourceBundle::GetSharedInstance() 174 .GetRawDataResource(IDR_SYNC_SETUP_DONE_HTML)); 175 SetFontAndTextDirection(&localized_strings); 176 response = jstemplate_builder::GetI18nTemplateHtml( 177 html, &localized_strings); 178 } else if (path_raw == kSyncSetupFlowPath) { 179 static const base::StringPiece html(ResourceBundle::GetSharedInstance() 180 .GetRawDataResource(IDR_SYNC_SETUP_FLOW_HTML)); 181 response = html.as_string(); 182 } 183 // Send the response. 184 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); 185 html_bytes->data.resize(response.size()); 186 std::copy(response.begin(), response.end(), html_bytes->data.begin()); 187 SendResponse(request_id, html_bytes); 188} 189 190std::string SyncResourcesSource::GetLocalizedUrl( 191 const std::string& url) const { 192 GURL original_url(url); 193 DCHECK(original_url.is_valid()); 194 GURL localized_url = google_util::AppendGoogleLocaleParam(original_url); 195 return localized_url.spec(); 196} 197 198SyncSetupWizard::SyncSetupWizard(ProfileSyncService* service) 199 : service_(service), 200 flow_container_(new SyncSetupFlowContainer()), 201 parent_window_(NULL) { 202 // Add our network layer data source for 'cloudy' URLs. 203 SyncResourcesSource* sync_source = new SyncResourcesSource(); 204 ChromeThread::PostTask( 205 ChromeThread::IO, FROM_HERE, 206 NewRunnableMethod(Singleton<ChromeURLDataManager>::get(), 207 &ChromeURLDataManager::AddDataSource, 208 make_scoped_refptr(sync_source))); 209} 210 211SyncSetupWizard::~SyncSetupWizard() { 212 delete flow_container_; 213} 214 215void SyncSetupWizard::Step(State advance_state) { 216 SyncSetupFlow* flow = flow_container_->get_flow(); 217 if (flow) { 218 // A setup flow is in progress and dialog is currently showing. 219 flow->Advance(advance_state); 220 } else if (!service_->profile()->GetPrefs()->GetBoolean( 221 prefs::kSyncHasSetupCompleted)) { 222 if (IsTerminalState(advance_state)) 223 return; 224 // No flow is in progress, and we have never escorted the user all the 225 // way through the wizard flow. 226 flow_container_->set_flow( 227 SyncSetupFlow::Run(service_, flow_container_, advance_state, DONE, 228 parent_window_)); 229 } else { 230 // No flow in in progress, but we've finished the wizard flow once before. 231 // This is just a discrete run. 232 if (IsTerminalState(advance_state)) 233 return; // Nothing to do. 234 flow_container_->set_flow(SyncSetupFlow::Run(service_, flow_container_, 235 advance_state, GetEndStateForDiscreteRun(advance_state), 236 parent_window_)); 237 } 238} 239 240// static 241bool SyncSetupWizard::IsTerminalState(State advance_state) { 242 return advance_state == GAIA_SUCCESS || 243 advance_state == DONE || 244 advance_state == DONE_FIRST_TIME || 245 advance_state == FATAL_ERROR || 246 advance_state == SETUP_ABORTED_BY_PENDING_CLEAR; 247} 248 249bool SyncSetupWizard::IsVisible() const { 250 return flow_container_->get_flow() != NULL; 251} 252 253void SyncSetupWizard::Focus() { 254 SyncSetupFlow* flow = flow_container_->get_flow(); 255 if (flow) { 256 flow->Focus(); 257 } 258} 259 260void SyncSetupWizard::SetParent(gfx::NativeWindow parent_window) { 261 parent_window_ = parent_window; 262} 263 264// static 265SyncSetupWizard::State SyncSetupWizard::GetEndStateForDiscreteRun( 266 State start_state) { 267 State result = FATAL_ERROR; 268 if (start_state == GAIA_LOGIN) { 269 result = GAIA_SUCCESS; 270 } else if (start_state == CHOOSE_DATA_TYPES) { 271 result = DONE; 272 } 273 DCHECK_NE(FATAL_ERROR, result) << 274 "Invalid start state for discrete run: " << start_state; 275 return result; 276} 277