OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/webui/sync_setup_handler2.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/json/json_reader.h" | |
10 #include "base/json/json_writer.h" | |
11 #include "base/metrics/histogram.h" | |
12 #include "base/utf_string_conversions.h" | |
13 #include "base/values.h" | |
14 #include "chrome/browser/google/google_util.h" | |
15 #include "chrome/browser/prefs/pref_service.h" | |
16 #include "chrome/browser/profiles/profile.h" | |
17 #include "chrome/browser/profiles/profile_info_cache.h" | |
18 #include "chrome/browser/profiles/profile_manager.h" | |
19 #include "chrome/browser/profiles/profile_metrics.h" | |
20 #include "chrome/browser/sync/profile_sync_service.h" | |
21 #include "chrome/browser/sync/protocol/service_constants.h" | |
22 #include "chrome/browser/sync/signin_manager.h" | |
23 #include "chrome/browser/sync/syncable/model_type.h" | |
24 #include "chrome/browser/sync/sync_setup_flow.h" | |
25 #include "chrome/browser/sync/util/oauth.h" | |
26 #include "chrome/browser/ui/browser_list.h" | |
27 #include "chrome/browser/ui/webui/sync_promo_trial.h" | |
28 #include "chrome/browser/ui/webui/sync_promo_ui.h" | |
29 #include "chrome/browser/ui/webui/user_selectable_sync_type.h" | |
30 #include "chrome/common/net/gaia/gaia_constants.h" | |
31 #include "chrome/common/pref_names.h" | |
32 #include "chrome/common/url_constants.h" | |
33 #include "content/browser/tab_contents/tab_contents.h" | |
34 #include "grit/chromium_strings.h" | |
35 #include "grit/generated_resources.h" | |
36 #include "grit/locale_settings.h" | |
37 #include "ui/base/l10n/l10n_util.h" | |
38 | |
39 using l10n_util::GetStringFUTF16; | |
40 using l10n_util::GetStringUTF16; | |
41 | |
42 namespace { | |
43 | |
44 bool GetAuthData(const std::string& json, | |
45 std::string* username, | |
46 std::string* password, | |
47 std::string* captcha, | |
48 std::string* access_code) { | |
49 scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false)); | |
50 if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) | |
51 return false; | |
52 | |
53 DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get()); | |
54 if (!result->GetString("user", username) || | |
55 !result->GetString("pass", password) || | |
56 !result->GetString("captcha", captcha) || | |
57 !result->GetString("access_code", access_code)) { | |
58 return false; | |
59 } | |
60 return true; | |
61 } | |
62 | |
63 bool GetConfiguration(const std::string& json, SyncConfiguration* config) { | |
64 scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false)); | |
65 if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) | |
66 return false; | |
67 | |
68 DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get()); | |
69 if (!result->GetBoolean("syncAllDataTypes", &config->sync_everything)) | |
70 return false; | |
71 | |
72 // These values need to be kept in sync with where they are written in | |
73 // choose_datatypes.html. | |
74 bool sync_bookmarks; | |
75 if (!result->GetBoolean("syncBookmarks", &sync_bookmarks)) | |
76 return false; | |
77 if (sync_bookmarks) | |
78 config->data_types.Put(syncable::BOOKMARKS); | |
79 | |
80 bool sync_preferences; | |
81 if (!result->GetBoolean("syncPreferences", &sync_preferences)) | |
82 return false; | |
83 if (sync_preferences) | |
84 config->data_types.Put(syncable::PREFERENCES); | |
85 | |
86 bool sync_themes; | |
87 if (!result->GetBoolean("syncThemes", &sync_themes)) | |
88 return false; | |
89 if (sync_themes) | |
90 config->data_types.Put(syncable::THEMES); | |
91 | |
92 bool sync_passwords; | |
93 if (!result->GetBoolean("syncPasswords", &sync_passwords)) | |
94 return false; | |
95 if (sync_passwords) | |
96 config->data_types.Put(syncable::PASSWORDS); | |
97 | |
98 bool sync_autofill; | |
99 if (!result->GetBoolean("syncAutofill", &sync_autofill)) | |
100 return false; | |
101 if (sync_autofill) | |
102 config->data_types.Put(syncable::AUTOFILL); | |
103 | |
104 bool sync_extensions; | |
105 if (!result->GetBoolean("syncExtensions", &sync_extensions)) | |
106 return false; | |
107 if (sync_extensions) { | |
108 config->data_types.Put(syncable::EXTENSIONS); | |
109 config->data_types.Put(syncable::EXTENSION_SETTINGS); | |
110 } | |
111 | |
112 bool sync_typed_urls; | |
113 if (!result->GetBoolean("syncTypedUrls", &sync_typed_urls)) | |
114 return false; | |
115 if (sync_typed_urls) | |
116 config->data_types.Put(syncable::TYPED_URLS); | |
117 | |
118 bool sync_sessions; | |
119 if (!result->GetBoolean("syncSessions", &sync_sessions)) | |
120 return false; | |
121 if (sync_sessions) | |
122 config->data_types.Put(syncable::SESSIONS); | |
123 | |
124 bool sync_apps; | |
125 if (!result->GetBoolean("syncApps", &sync_apps)) | |
126 return false; | |
127 if (sync_apps) { | |
128 config->data_types.Put(syncable::APPS); | |
129 config->data_types.Put(syncable::APP_SETTINGS); | |
130 } | |
131 | |
132 // Encryption settings. | |
133 if (!result->GetBoolean("encryptAllData", &config->encrypt_all)) | |
134 return false; | |
135 | |
136 // Passphrase settings. | |
137 bool have_passphrase; | |
138 if (!result->GetBoolean("usePassphrase", &have_passphrase)) | |
139 return false; | |
140 | |
141 if (have_passphrase) { | |
142 bool is_gaia; | |
143 if (!result->GetBoolean("isGooglePassphrase", &is_gaia)) | |
144 return false; | |
145 std::string passphrase; | |
146 if (!result->GetString("passphrase", &passphrase)) | |
147 return false; | |
148 // The user provided a passphrase - pass it off to SyncSetupFlow as either | |
149 // the secondary or GAIA passphrase as appropriate. | |
150 if (is_gaia) { | |
151 config->set_gaia_passphrase = true; | |
152 config->gaia_passphrase = passphrase; | |
153 } else { | |
154 config->set_secondary_passphrase = true; | |
155 config->secondary_passphrase = passphrase; | |
156 } | |
157 } | |
158 return true; | |
159 } | |
160 | |
161 bool HasConfigurationChanged(const SyncConfiguration& config, | |
162 Profile* profile) { | |
163 CHECK(profile); | |
164 | |
165 // This function must be updated every time a new sync datatype is added to | |
166 // the sync preferences page. | |
167 COMPILE_ASSERT(17 == syncable::MODEL_TYPE_COUNT, | |
168 UpdateCustomConfigHistogram); | |
169 | |
170 // If service is null or if this is a first time configuration, return true. | |
171 ProfileSyncService* service = profile->GetProfileSyncService(); | |
172 if (!service || !service->HasSyncSetupCompleted()) | |
173 return true; | |
174 | |
175 if ((config.set_secondary_passphrase || config.set_gaia_passphrase) && | |
176 !service->IsUsingSecondaryPassphrase()) | |
177 return true; | |
178 | |
179 if (config.encrypt_all != service->EncryptEverythingEnabled()) | |
180 return true; | |
181 | |
182 PrefService* pref_service = profile->GetPrefs(); | |
183 CHECK(pref_service); | |
184 | |
185 if (config.sync_everything != | |
186 pref_service->GetBoolean(prefs::kSyncKeepEverythingSynced)) | |
187 return true; | |
188 | |
189 // Only check the data types that are explicitly listed on the sync | |
190 // preferences page. | |
191 const syncable::ModelTypeSet types = config.data_types; | |
192 if (((types.Has(syncable::BOOKMARKS)) != | |
193 pref_service->GetBoolean(prefs::kSyncBookmarks)) || | |
194 ((types.Has(syncable::PREFERENCES)) != | |
195 pref_service->GetBoolean(prefs::kSyncPreferences)) || | |
196 ((types.Has(syncable::THEMES)) != | |
197 pref_service->GetBoolean(prefs::kSyncThemes)) || | |
198 ((types.Has(syncable::PASSWORDS)) != | |
199 pref_service->GetBoolean(prefs::kSyncPasswords)) || | |
200 ((types.Has(syncable::AUTOFILL)) != | |
201 pref_service->GetBoolean(prefs::kSyncAutofill)) || | |
202 ((types.Has(syncable::EXTENSIONS)) != | |
203 pref_service->GetBoolean(prefs::kSyncExtensions)) || | |
204 ((types.Has(syncable::TYPED_URLS)) != | |
205 pref_service->GetBoolean(prefs::kSyncTypedUrls)) || | |
206 ((types.Has(syncable::SESSIONS)) != | |
207 pref_service->GetBoolean(prefs::kSyncSessions)) || | |
208 ((types.Has(syncable::APPS)) != | |
209 pref_service->GetBoolean(prefs::kSyncApps))) | |
210 return true; | |
211 | |
212 return false; | |
213 } | |
214 | |
215 bool GetPassphrase(const std::string& json, std::string* passphrase) { | |
216 scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false)); | |
217 if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) | |
218 return false; | |
219 | |
220 DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get()); | |
221 return result->GetString("passphrase", passphrase); | |
222 } | |
223 | |
224 string16 NormalizeUserName(const string16& user) { | |
225 if (user.find_first_of(ASCIIToUTF16("@")) != string16::npos) | |
226 return user; | |
227 return user + ASCIIToUTF16("@") + ASCIIToUTF16(DEFAULT_SIGNIN_DOMAIN); | |
228 } | |
229 | |
230 bool AreUserNamesEqual(const string16& user1, const string16& user2) { | |
231 return NormalizeUserName(user1) == NormalizeUserName(user2); | |
232 } | |
233 | |
234 } // namespace | |
235 | |
236 SyncSetupHandler2::SyncSetupHandler2(ProfileManager* profile_manager) | |
237 : flow_(NULL), | |
238 profile_manager_(profile_manager) { | |
239 } | |
240 | |
241 SyncSetupHandler2::~SyncSetupHandler2() { | |
242 // This case is hit when the user performs a back navigation. | |
243 if (flow_) | |
244 flow_->OnDialogClosed(""); | |
245 } | |
246 | |
247 void SyncSetupHandler2::GetLocalizedValues(DictionaryValue* localized_strings) { | |
248 GetStaticLocalizedValues(localized_strings, web_ui_); | |
249 } | |
250 | |
251 void SyncSetupHandler2::GetStaticLocalizedValues( | |
252 DictionaryValue* localized_strings, | |
253 WebUI* web_ui) { | |
254 DCHECK(localized_strings); | |
255 | |
256 localized_strings->SetString( | |
257 "invalidPasswordHelpURL", | |
258 google_util::StringAppendGoogleLocaleParam( | |
259 chrome::kInvalidPasswordHelpURL)); | |
260 localized_strings->SetString( | |
261 "cannotAccessAccountURL", | |
262 google_util::StringAppendGoogleLocaleParam( | |
263 chrome::kCanNotAccessAccountURL)); | |
264 localized_strings->SetString( | |
265 "introduction", | |
266 GetStringFUTF16(IDS_SYNC_LOGIN_INTRODUCTION, | |
267 GetStringUTF16(IDS_PRODUCT_NAME))); | |
268 localized_strings->SetString( | |
269 "chooseDataTypesInstructions", | |
270 GetStringFUTF16(IDS_SYNC_CHOOSE_DATATYPES_INSTRUCTIONS, | |
271 GetStringUTF16(IDS_PRODUCT_NAME))); | |
272 localized_strings->SetString( | |
273 "encryptionInstructions", | |
274 GetStringFUTF16(IDS_SYNC_ENCRYPTION_INSTRUCTIONS, | |
275 GetStringUTF16(IDS_PRODUCT_NAME))); | |
276 localized_strings->SetString( | |
277 "encryptionHelpURL", | |
278 google_util::StringAppendGoogleLocaleParam( | |
279 chrome::kSyncEncryptionHelpURL)); | |
280 localized_strings->SetString( | |
281 "passphraseEncryptionMessage", | |
282 GetStringFUTF16(IDS_SYNC_PASSPHRASE_ENCRYPTION_MESSAGE, | |
283 GetStringUTF16(IDS_PRODUCT_NAME))); | |
284 localized_strings->SetString( | |
285 "passphraseRecover", | |
286 GetStringFUTF16(IDS_SYNC_PASSPHRASE_RECOVER, | |
287 ASCIIToUTF16(google_util::StringAppendGoogleLocaleParam( | |
288 chrome::kSyncGoogleDashboardURL)))); | |
289 localized_strings->SetString( | |
290 "promoTitle", | |
291 GetStringFUTF16(IDS_SYNC_PROMO_TITLE, | |
292 GetStringUTF16(IDS_PRODUCT_NAME))); | |
293 localized_strings->SetString( | |
294 "promoMessageTitle", | |
295 GetStringFUTF16(IDS_SYNC_PROMO_MESSAGE_TITLE, | |
296 GetStringUTF16(IDS_SHORT_PRODUCT_NAME))); | |
297 localized_strings->SetString( | |
298 "syncEverythingHelpURL", | |
299 google_util::StringAppendGoogleLocaleParam( | |
300 chrome::kSyncEverythingLearnMoreURL)); | |
301 | |
302 // The experimental body string only appears if we are on the launch page | |
303 // version of the Sync Promo. | |
304 int message_body_resource_id = IDS_SYNC_PROMO_MESSAGE_BODY_A; | |
305 if (web_ui && SyncPromoUI::GetIsLaunchPageForSyncPromoURL( | |
306 web_ui->tab_contents()->GetURL())) { | |
307 message_body_resource_id = sync_promo_trial::GetMessageBodyResID(); | |
308 } | |
309 localized_strings->SetString( | |
310 "promoMessageBody", | |
311 GetStringUTF16(message_body_resource_id)); | |
312 | |
313 std::string create_account_url = google_util::StringAppendGoogleLocaleParam( | |
314 chrome::kSyncCreateNewAccountURL); | |
315 string16 create_account = GetStringUTF16(IDS_SYNC_CREATE_ACCOUNT); | |
316 create_account= UTF8ToUTF16("<a id='create-account-link' target='_blank' " | |
317 "class='account-link' href='" + create_account_url + "'>") + | |
318 create_account + UTF8ToUTF16("</a>"); | |
319 localized_strings->SetString("createAccountLinkHTML", | |
320 GetStringFUTF16(IDS_SYNC_CREATE_ACCOUNT_PREFIX, create_account)); | |
321 | |
322 static OptionsStringResource resources[] = { | |
323 { "syncSetupOverlayTitle", IDS_SYNC_SETUP_TITLE }, | |
324 { "syncSetupConfigureTitle", IDS_SYNC_SETUP_CONFIGURE_TITLE }, | |
325 { "cannotBeBlank", IDS_SYNC_CANNOT_BE_BLANK }, | |
326 { "emailLabel", IDS_SYNC_LOGIN_EMAIL_NEW_LINE }, | |
327 { "passwordLabel", IDS_SYNC_LOGIN_PASSWORD_NEW_LINE }, | |
328 { "invalidCredentials", IDS_SYNC_INVALID_USER_CREDENTIALS }, | |
329 { "signin", IDS_SYNC_SIGNIN }, | |
330 { "couldNotConnect", IDS_SYNC_LOGIN_COULD_NOT_CONNECT }, | |
331 { "unrecoverableError", IDS_SYNC_UNRECOVERABLE_ERROR }, | |
332 { "errorLearnMore", IDS_LEARN_MORE }, | |
333 { "unrecoverableErrorHelpURL", IDS_SYNC_UNRECOVERABLE_ERROR_HELP_URL }, | |
334 { "cannotAccessAccount", IDS_SYNC_CANNOT_ACCESS_ACCOUNT }, | |
335 { "cancel", IDS_CANCEL }, | |
336 { "settingUp", IDS_SYNC_LOGIN_SETTING_UP }, | |
337 { "errorSigningIn", IDS_SYNC_ERROR_SIGNING_IN }, | |
338 { "signinHeader", IDS_SYNC_PROMO_SIGNIN_HEADER}, | |
339 { "captchaInstructions", IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS }, | |
340 { "invalidAccessCode", IDS_SYNC_INVALID_ACCESS_CODE_LABEL }, | |
341 { "enterAccessCode", IDS_SYNC_ENTER_ACCESS_CODE_LABEL }, | |
342 { "getAccessCodeHelp", IDS_SYNC_ACCESS_CODE_HELP_LABEL }, | |
343 { "getAccessCodeURL", IDS_SYNC_GET_ACCESS_CODE_URL }, | |
344 { "syncAllDataTypes", IDS_SYNC_EVERYTHING }, | |
345 { "chooseDataTypes", IDS_SYNC_CHOOSE_DATATYPES }, | |
346 { "bookmarks", IDS_SYNC_DATATYPE_BOOKMARKS }, | |
347 { "preferences", IDS_SYNC_DATATYPE_PREFERENCES }, | |
348 { "autofill", IDS_SYNC_DATATYPE_AUTOFILL }, | |
349 { "themes", IDS_SYNC_DATATYPE_THEMES }, | |
350 { "passwords", IDS_SYNC_DATATYPE_PASSWORDS }, | |
351 { "extensions", IDS_SYNC_DATATYPE_EXTENSIONS }, | |
352 { "typedURLs", IDS_SYNC_DATATYPE_TYPED_URLS }, | |
353 { "apps", IDS_SYNC_DATATYPE_APPS }, | |
354 { "openTabs", IDS_SYNC_DATATYPE_TABS }, | |
355 { "syncZeroDataTypesError", IDS_SYNC_ZERO_DATA_TYPES_ERROR }, | |
356 { "serviceUnavailableError", IDS_SYNC_SETUP_ABORTED_BY_PENDING_CLEAR }, | |
357 { "encryptAllLabel", IDS_SYNC_ENCRYPT_ALL_LABEL }, | |
358 { "googleOption", IDS_SYNC_PASSPHRASE_OPT_GOOGLE }, | |
359 { "explicitOption", IDS_SYNC_PASSPHRASE_OPT_EXPLICIT }, | |
360 { "sectionGoogleMessage", IDS_SYNC_PASSPHRASE_MSG_GOOGLE }, | |
361 { "sectionExplicitMessage", IDS_SYNC_PASSPHRASE_MSG_EXPLICIT }, | |
362 { "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL }, | |
363 { "confirmLabel", IDS_SYNC_CONFIRM_PASSPHRASE_LABEL }, | |
364 { "emptyErrorMessage", IDS_SYNC_EMPTY_PASSPHRASE_ERROR }, | |
365 { "mismatchErrorMessage", IDS_SYNC_PASSPHRASE_MISMATCH_ERROR }, | |
366 { "passphraseWarning", IDS_SYNC_PASSPHRASE_WARNING }, | |
367 { "customizeLinkLabel", IDS_SYNC_CUSTOMIZE_LINK_LABEL }, | |
368 { "confirmSyncPreferences", IDS_SYNC_CONFIRM_SYNC_PREFERENCES }, | |
369 { "syncEverything", IDS_SYNC_SYNC_EVERYTHING }, | |
370 { "useDefaultSettings", IDS_SYNC_USE_DEFAULT_SETTINGS }, | |
371 { "passphraseSectionTitle", IDS_SYNC_PASSPHRASE_SECTION_TITLE }, | |
372 { "privacyDashboardLink", IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL }, | |
373 { "enterPassphraseTitle", IDS_SYNC_ENTER_PASSPHRASE_TITLE }, | |
374 { "enterPassphraseBody", IDS_SYNC_ENTER_PASSPHRASE_BODY }, | |
375 { "enterOtherPassphraseBody", IDS_SYNC_ENTER_OTHER_PASSPHRASE_BODY }, | |
376 { "enterGooglePassphraseBody", IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY }, | |
377 { "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL }, | |
378 { "incorrectPassphrase", IDS_SYNC_INCORRECT_PASSPHRASE }, | |
379 { "passphraseWarning", IDS_SYNC_PASSPHRASE_WARNING }, | |
380 { "cancelWarningHeader", IDS_SYNC_PASSPHRASE_CANCEL_WARNING_HEADER }, | |
381 { "cancelWarning", IDS_SYNC_PASSPHRASE_CANCEL_WARNING }, | |
382 { "yes", IDS_SYNC_PASSPHRASE_CANCEL_YES }, | |
383 { "no", IDS_SYNC_PASSPHRASE_CANCEL_NO }, | |
384 { "sectionExplicitMessagePrefix", IDS_SYNC_PASSPHRASE_MSG_EXPLICIT_PREFIX }, | |
385 { "sectionExplicitMessagePostfix", | |
386 IDS_SYNC_PASSPHRASE_MSG_EXPLICIT_POSTFIX }, | |
387 { "encryptedDataTypesTitle", IDS_SYNC_ENCRYPTION_DATA_TYPES_TITLE }, | |
388 { "encryptSensitiveOption", IDS_SYNC_ENCRYPT_SENSITIVE_DATA }, | |
389 { "encryptAllOption", IDS_SYNC_ENCRYPT_ALL_DATA }, | |
390 { "encryptAllOption", IDS_SYNC_ENCRYPT_ALL_DATA }, | |
391 { "aspWarningText", IDS_SYNC_ASP_PASSWORD_WARNING_TEXT }, | |
392 { "promoPageTitle", IDS_SYNC_PROMO_TAB_TITLE}, | |
393 { "promoSkipButton", IDS_SYNC_PROMO_SKIP_BUTTON}, | |
394 { "promoAdvanced", IDS_SYNC_PROMO_ADVANCED}, | |
395 { "promoLearnMoreShow", IDS_SYNC_PROMO_LEARN_MORE_SHOW}, | |
396 { "promoLearnMoreHide", IDS_SYNC_PROMO_LEARN_MORE_HIDE}, | |
397 { "promoInformation", IDS_SYNC_PROMO_INFORMATION}, | |
398 }; | |
399 | |
400 RegisterStrings(localized_strings, resources, arraysize(resources)); | |
401 } | |
402 | |
403 void SyncSetupHandler2::Initialize() { | |
404 } | |
405 | |
406 void SyncSetupHandler2::OnGetOAuthTokenSuccess(const std::string& oauth_token) { | |
407 flow_->OnUserSubmittedOAuth(oauth_token); | |
408 } | |
409 | |
410 void SyncSetupHandler2::OnGetOAuthTokenFailure( | |
411 const GoogleServiceAuthError& error) { | |
412 CloseSyncSetup(); | |
413 } | |
414 | |
415 void SyncSetupHandler2::RegisterMessages() { | |
416 web_ui_->RegisterMessageCallback("SyncSetupDidClosePage", | |
417 base::Bind(&SyncSetupHandler2::OnDidClosePage, | |
418 base::Unretained(this))); | |
419 web_ui_->RegisterMessageCallback("SyncSetupSubmitAuth", | |
420 base::Bind(&SyncSetupHandler2::HandleSubmitAuth, | |
421 base::Unretained(this))); | |
422 web_ui_->RegisterMessageCallback("SyncSetupConfigure", | |
423 base::Bind(&SyncSetupHandler2::HandleConfigure, | |
424 base::Unretained(this))); | |
425 web_ui_->RegisterMessageCallback("SyncSetupPassphrase", | |
426 base::Bind(&SyncSetupHandler2::HandlePassphraseEntry, | |
427 base::Unretained(this))); | |
428 web_ui_->RegisterMessageCallback("SyncSetupPassphraseCancel", | |
429 base::Bind(&SyncSetupHandler2::HandlePassphraseCancel, | |
430 base::Unretained(this))); | |
431 web_ui_->RegisterMessageCallback("SyncSetupAttachHandler", | |
432 base::Bind(&SyncSetupHandler2::HandleAttachHandler, | |
433 base::Unretained(this))); | |
434 web_ui_->RegisterMessageCallback("SyncSetupShowErrorUI", | |
435 base::Bind(&SyncSetupHandler2::HandleShowErrorUI, | |
436 base::Unretained(this))); | |
437 web_ui_->RegisterMessageCallback("SyncSetupShowSetupUI", | |
438 base::Bind(&SyncSetupHandler2::HandleShowSetupUI, | |
439 base::Unretained(this))); | |
440 } | |
441 | |
442 // Ideal(?) solution here would be to mimic the ClientLogin overlay. Since | |
443 // this UI must render an external URL, that overlay cannot be used directly. | |
444 // The current implementation is functional, but fails asthetically. | |
445 // TODO(rickcam): Bug 90711: Update UI for OAuth sign-in flow | |
446 void SyncSetupHandler2::ShowOAuthLogin() { | |
447 DCHECK(browser_sync::IsUsingOAuth()); | |
448 | |
449 Profile* profile = Profile::FromWebUI(web_ui_); | |
450 oauth_login_.reset(new GaiaOAuthFetcher(this, | |
451 profile->GetRequestContext(), | |
452 profile, | |
453 GaiaConstants::kSyncServiceOAuth)); | |
454 oauth_login_->SetAutoFetchLimit(GaiaOAuthFetcher::OAUTH1_REQUEST_TOKEN); | |
455 oauth_login_->StartGetOAuthToken(); | |
456 } | |
457 | |
458 void SyncSetupHandler2::ShowGaiaLogin(const DictionaryValue& args) { | |
459 DCHECK(!browser_sync::IsUsingOAuth()); | |
460 StringValue page("login"); | |
461 web_ui_->CallJavascriptFunction( | |
462 "SyncSetupOverlay.showSyncSetupPage", page, args); | |
463 } | |
464 | |
465 void SyncSetupHandler2::ShowGaiaSuccessAndClose() { | |
466 web_ui_->CallJavascriptFunction("SyncSetupOverlay.showSuccessAndClose"); | |
467 } | |
468 | |
469 void SyncSetupHandler2::ShowGaiaSuccessAndSettingUp() { | |
470 web_ui_->CallJavascriptFunction("SyncSetupOverlay.showSuccessAndSettingUp"); | |
471 } | |
472 | |
473 void SyncSetupHandler2::ShowConfigure(const DictionaryValue& args) { | |
474 StringValue page("configure"); | |
475 web_ui_->CallJavascriptFunction( | |
476 "SyncSetupOverlay.showSyncSetupPage", page, args); | |
477 } | |
478 | |
479 void SyncSetupHandler2::ShowPassphraseEntry(const DictionaryValue& args) { | |
480 StringValue page("passphrase"); | |
481 web_ui_->CallJavascriptFunction( | |
482 "SyncSetupOverlay.showSyncSetupPage", page, args); | |
483 } | |
484 | |
485 void SyncSetupHandler2::ShowSettingUp() { | |
486 StringValue page("settingUp"); | |
487 web_ui_->CallJavascriptFunction( | |
488 "SyncSetupOverlay.showSyncSetupPage", page); | |
489 } | |
490 | |
491 void SyncSetupHandler2::ShowSetupDone(const string16& user) { | |
492 StringValue page("done"); | |
493 web_ui_->CallJavascriptFunction( | |
494 "SyncSetupOverlay.showSyncSetupPage", page); | |
495 | |
496 // Suppress the sync promo once the user signs into sync. This way the user | |
497 // doesn't see the sync promo even if they sign out of sync later on. | |
498 SyncPromoUI::SetUserSkippedSyncPromo(Profile::FromWebUI(web_ui_)); | |
499 | |
500 Profile* profile = Profile::FromWebUI(web_ui_); | |
501 ProfileSyncService* service = profile->GetProfileSyncService(); | |
502 if (!service->HasSyncSetupCompleted()) { | |
503 FilePath profile_file_path = profile->GetPath(); | |
504 ProfileMetrics::LogProfileSyncSignIn(profile_file_path); | |
505 } | |
506 } | |
507 | |
508 void SyncSetupHandler2::SetFlow(SyncSetupFlow* flow) { | |
509 flow_ = flow; | |
510 } | |
511 | |
512 void SyncSetupHandler2::Focus() { | |
513 static_cast<RenderViewHostDelegate*>(web_ui_->tab_contents())->Activate(); | |
514 } | |
515 | |
516 void SyncSetupHandler2::OnDidClosePage(const ListValue* args) { | |
517 CloseSyncSetup(); | |
518 } | |
519 | |
520 void SyncSetupHandler2::HandleSubmitAuth(const ListValue* args) { | |
521 std::string json; | |
522 if (!args->GetString(0, &json)) { | |
523 NOTREACHED() << "Could not read JSON argument"; | |
524 return; | |
525 } | |
526 | |
527 if (json.empty()) | |
528 return; | |
529 | |
530 std::string username, password, captcha, access_code; | |
531 if (!GetAuthData(json, &username, &password, &captcha, &access_code)) { | |
532 // The page sent us something that we didn't understand. | |
533 // This probably indicates a programming error. | |
534 NOTREACHED(); | |
535 return; | |
536 } | |
537 | |
538 string16 error_message; | |
539 if (!IsLoginAuthDataValid(username, &error_message)) { | |
540 ShowLoginErrorMessage(error_message); | |
541 return; | |
542 } | |
543 | |
544 if (flow_) | |
545 flow_->OnUserSubmittedAuth(username, password, captcha, access_code); | |
546 } | |
547 | |
548 void SyncSetupHandler2::HandleConfigure(const ListValue* args) { | |
549 std::string json; | |
550 if (!args->GetString(0, &json)) { | |
551 NOTREACHED() << "Could not read JSON argument"; | |
552 return; | |
553 } | |
554 if (json.empty()) { | |
555 NOTREACHED(); | |
556 return; | |
557 } | |
558 | |
559 SyncConfiguration configuration; | |
560 if (!GetConfiguration(json, &configuration)) { | |
561 // The page sent us something that we didn't understand. | |
562 // This probably indicates a programming error. | |
563 NOTREACHED(); | |
564 return; | |
565 } | |
566 | |
567 // We do not do UMA logging during unit tests. | |
568 if (web_ui_) { | |
569 Profile* profile = Profile::FromWebUI(web_ui_); | |
570 if (HasConfigurationChanged(configuration, profile)) { | |
571 UMA_HISTOGRAM_BOOLEAN("Sync.SyncEverything", | |
572 configuration.sync_everything); | |
573 if (!configuration.sync_everything) { | |
574 // Only log the data types that are explicitly listed on the sync | |
575 // preferences page. | |
576 const syncable::ModelTypeSet types = configuration.data_types; | |
577 if (types.Has(syncable::BOOKMARKS)) | |
578 UMA_HISTOGRAM_ENUMERATION( | |
579 "Sync.CustomSync", BOOKMARKS, SELECTABLE_DATATYPE_COUNT + 1); | |
580 if (types.Has(syncable::PREFERENCES)) | |
581 UMA_HISTOGRAM_ENUMERATION( | |
582 "Sync.CustomSync", PREFERENCES, SELECTABLE_DATATYPE_COUNT + 1); | |
583 if (types.Has(syncable::PASSWORDS)) | |
584 UMA_HISTOGRAM_ENUMERATION( | |
585 "Sync.CustomSync", PASSWORDS, SELECTABLE_DATATYPE_COUNT + 1); | |
586 if (types.Has(syncable::AUTOFILL)) | |
587 UMA_HISTOGRAM_ENUMERATION( | |
588 "Sync.CustomSync", AUTOFILL, SELECTABLE_DATATYPE_COUNT + 1); | |
589 if (types.Has(syncable::THEMES)) | |
590 UMA_HISTOGRAM_ENUMERATION( | |
591 "Sync.CustomSync", THEMES, SELECTABLE_DATATYPE_COUNT + 1); | |
592 if (types.Has(syncable::TYPED_URLS)) | |
593 UMA_HISTOGRAM_ENUMERATION( | |
594 "Sync.CustomSync", TYPED_URLS, SELECTABLE_DATATYPE_COUNT + 1); | |
595 if (types.Has(syncable::EXTENSIONS)) | |
596 UMA_HISTOGRAM_ENUMERATION( | |
597 "Sync.CustomSync", EXTENSIONS, SELECTABLE_DATATYPE_COUNT + 1); | |
598 if (types.Has(syncable::SESSIONS)) | |
599 UMA_HISTOGRAM_ENUMERATION( | |
600 "Sync.CustomSync", SESSIONS, SELECTABLE_DATATYPE_COUNT + 1); | |
601 if (types.Has(syncable::APPS)) | |
602 UMA_HISTOGRAM_ENUMERATION( | |
603 "Sync.CustomSync", APPS, SELECTABLE_DATATYPE_COUNT + 1); | |
604 COMPILE_ASSERT(17 == syncable::MODEL_TYPE_COUNT, | |
605 UpdateCustomConfigHistogram); | |
606 COMPILE_ASSERT(9 == SELECTABLE_DATATYPE_COUNT, | |
607 UpdateCustomConfigHistogram); | |
608 } | |
609 UMA_HISTOGRAM_BOOLEAN("Sync.EncryptAllData", configuration.encrypt_all); | |
610 UMA_HISTOGRAM_BOOLEAN("Sync.CustomPassphrase", | |
611 configuration.set_gaia_passphrase || | |
612 configuration.set_secondary_passphrase); | |
613 } | |
614 } | |
615 | |
616 DCHECK(flow_); | |
617 flow_->OnUserConfigured(configuration); | |
618 | |
619 ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_CUSTOMIZE); | |
620 if (configuration.encrypt_all) { | |
621 ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_ENCRYPT); | |
622 } | |
623 if (configuration.set_secondary_passphrase) { | |
624 ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_PASSPHRASE); | |
625 } | |
626 if (!configuration.sync_everything) { | |
627 ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_CHOOSE); | |
628 } | |
629 } | |
630 | |
631 void SyncSetupHandler2::HandlePassphraseEntry(const ListValue* args) { | |
632 std::string json; | |
633 if (!args->GetString(0, &json)) { | |
634 NOTREACHED() << "Could not read JSON argument"; | |
635 return; | |
636 } | |
637 | |
638 if (json.empty()) | |
639 return; | |
640 | |
641 std::string passphrase; | |
642 if (!GetPassphrase(json, &passphrase)) { | |
643 // Couldn't understand what the page sent. Indicates a programming error. | |
644 NOTREACHED(); | |
645 return; | |
646 } | |
647 | |
648 DCHECK(flow_); | |
649 flow_->OnPassphraseEntry(passphrase); | |
650 } | |
651 | |
652 void SyncSetupHandler2::HandlePassphraseCancel(const ListValue* args) { | |
653 DCHECK(flow_); | |
654 flow_->OnPassphraseCancel(); | |
655 } | |
656 | |
657 void SyncSetupHandler2::HandleAttachHandler(const ListValue* args) { | |
658 OpenSyncSetup(); | |
659 } | |
660 | |
661 void SyncSetupHandler2::HandleShowErrorUI(const ListValue* args) { | |
662 DCHECK(!flow_); | |
663 | |
664 Profile* profile = Profile::FromWebUI(web_ui_); | |
665 ProfileSyncService* service = profile->GetProfileSyncService(); | |
666 DCHECK(service); | |
667 | |
668 service->ShowErrorUI(); | |
669 } | |
670 | |
671 void SyncSetupHandler2::HandleShowSetupUI(const ListValue* args) { | |
672 DCHECK(!flow_); | |
673 if (FocusExistingWizard()) { | |
674 CloseOverlay(); | |
675 return; | |
676 } | |
677 ShowSetupUI(); | |
678 } | |
679 | |
680 void SyncSetupHandler2::CloseSyncSetup() { | |
681 if (flow_) { | |
682 flow_->OnDialogClosed(std::string()); | |
683 flow_ = NULL; | |
684 } | |
685 } | |
686 | |
687 void SyncSetupHandler2::OpenSyncSetup() { | |
688 DCHECK(web_ui_); | |
689 DCHECK(!flow_); | |
690 | |
691 Profile* profile = Profile::FromWebUI(web_ui_); | |
692 ProfileSyncService* service = profile->GetProfileSyncService(); | |
693 if (!service) { | |
694 // If there's no sync service, the user tried to manually invoke a syncSetup | |
695 // URL, but sync features are disabled. We need to close the overlay for | |
696 // this (rare) case. | |
697 CloseOverlay(); | |
698 return; | |
699 } | |
700 | |
701 // If the wizard is already visible, it must be attached to another flow | |
702 // handler. | |
703 if (FocusExistingWizard()) { | |
704 CloseOverlay(); | |
705 return; | |
706 } | |
707 | |
708 // Attach this as the sync setup handler, before calling ShowSetupUI(). | |
709 if (!service->get_wizard().AttachSyncSetupHandler(this)) { | |
710 LOG(ERROR) << "SyncSetupHandler attach failed!"; | |
711 CloseOverlay(); | |
712 return; | |
713 } | |
714 | |
715 ShowSetupUI(); | |
716 } | |
717 | |
718 // Private member functions. | |
719 | |
720 bool SyncSetupHandler2::FocusExistingWizard() { | |
721 Profile* profile = Profile::FromWebUI(web_ui_); | |
722 ProfileSyncService* service = profile->GetProfileSyncService(); | |
723 if (!service) | |
724 return false; | |
725 | |
726 // If the wizard is already visible, focus it. | |
727 if (service->get_wizard().IsVisible()) { | |
728 service->get_wizard().Focus(); | |
729 return true; | |
730 } | |
731 return false; | |
732 } | |
733 | |
734 void SyncSetupHandler2::CloseOverlay() { | |
735 web_ui_->CallJavascriptFunction("OptionsPage.closeOverlay"); | |
736 } | |
737 | |
738 bool SyncSetupHandler2::IsLoginAuthDataValid(const std::string& username, | |
739 string16* error_message) { | |
740 // Happens during unit tests. | |
741 if (!web_ui_ || !profile_manager_) | |
742 return true; | |
743 | |
744 if (username.empty()) | |
745 return true; | |
746 | |
747 // Check if the username is already in use by another profile. | |
748 const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache(); | |
749 size_t current_profile_index = cache.GetIndexOfProfileWithPath( | |
750 Profile::FromWebUI(web_ui_)->GetPath()); | |
751 string16 username_utf16 = UTF8ToUTF16(username); | |
752 | |
753 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | |
754 if (i != current_profile_index && AreUserNamesEqual( | |
755 cache.GetUserNameOfProfileAtIndex(i), username_utf16)) { | |
756 *error_message = l10n_util::GetStringUTF16( | |
757 IDS_SYNC_USER_NAME_IN_USE_ERROR); | |
758 return false; | |
759 } | |
760 } | |
761 | |
762 return true; | |
763 } | |
764 | |
765 void SyncSetupHandler2::ShowLoginErrorMessage(const string16& error_message) { | |
766 DictionaryValue args; | |
767 Profile* profile = Profile::FromWebUI(web_ui_); | |
768 ProfileSyncService* service = profile->GetProfileSyncService(); | |
769 SyncSetupFlow::GetArgsForGaiaLogin(service, &args); | |
770 args.SetString("error_message", error_message); | |
771 ShowGaiaLogin(args); | |
772 } | |
OLD | NEW |