Home | History | Annotate | Download | only in options
      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/options/sync_setup_handler.h"
      6 
      7 #include "base/json/json_reader.h"
      8 #include "base/json/json_writer.h"
      9 #include "base/values.h"
     10 #include "chrome/browser/google/google_util.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/browser/sync/profile_sync_service.h"
     13 #include "chrome/browser/sync/sync_setup_flow.h"
     14 #include "grit/chromium_strings.h"
     15 #include "grit/generated_resources.h"
     16 #include "grit/locale_settings.h"
     17 #include "ui/base/l10n/l10n_util.h"
     18 
     19 using l10n_util::GetStringFUTF16;
     20 using l10n_util::GetStringUTF16;
     21 
     22 namespace {
     23 
     24 // TODO(jhawkins): Move these to url_constants.h.
     25 const char* kInvalidPasswordHelpUrl =
     26     "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
     27 const char* kCanNotAccessAccountUrl =
     28     "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
     29 #if defined(OS_CHROMEOS)
     30 const char* kEncryptionHelpUrl =
     31     "http://www.google.com/support/chromeos/bin/answer.py?answer=1181035";
     32 #else
     33 const char* kEncryptionHelpUrl =
     34     "http://www.google.com/support/chrome/bin/answer.py?answer=1181035";
     35 #endif
     36 const char* kCreateNewAccountUrl =
     37     "https://www.google.com/accounts/NewAccount?service=chromiumsync";
     38 
     39 bool GetAuthData(const std::string& json,
     40                  std::string* username,
     41                  std::string* password,
     42                  std::string* captcha,
     43                  std::string* access_code) {
     44   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
     45   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
     46     return false;
     47 
     48   DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
     49   if (!result->GetString("user", username) ||
     50       !result->GetString("pass", password) ||
     51       !result->GetString("captcha", captcha) ||
     52       !result->GetString("access_code", access_code)) {
     53       return false;
     54   }
     55   return true;
     56 }
     57 
     58 bool GetConfiguration(const std::string& json, SyncConfiguration* config) {
     59   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
     60   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
     61     return false;
     62 
     63   DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
     64   if (!result->GetBoolean("keepEverythingSynced", &config->sync_everything))
     65     return false;
     66 
     67   // These values need to be kept in sync with where they are written in
     68   // choose_datatypes.html.
     69   bool sync_bookmarks;
     70   if (!result->GetBoolean("syncBookmarks", &sync_bookmarks))
     71     return false;
     72   if (sync_bookmarks)
     73     config->data_types.insert(syncable::BOOKMARKS);
     74 
     75   bool sync_preferences;
     76   if (!result->GetBoolean("syncPreferences", &sync_preferences))
     77     return false;
     78   if (sync_preferences)
     79     config->data_types.insert(syncable::PREFERENCES);
     80 
     81   bool sync_themes;
     82   if (!result->GetBoolean("syncThemes", &sync_themes))
     83     return false;
     84   if (sync_themes)
     85     config->data_types.insert(syncable::THEMES);
     86 
     87   bool sync_passwords;
     88   if (!result->GetBoolean("syncPasswords", &sync_passwords))
     89     return false;
     90   if (sync_passwords)
     91     config->data_types.insert(syncable::PASSWORDS);
     92 
     93   bool sync_autofill;
     94   if (!result->GetBoolean("syncAutofill", &sync_autofill))
     95     return false;
     96   if (sync_autofill)
     97     config->data_types.insert(syncable::AUTOFILL);
     98 
     99   bool sync_extensions;
    100   if (!result->GetBoolean("syncExtensions", &sync_extensions))
    101     return false;
    102   if (sync_extensions)
    103     config->data_types.insert(syncable::EXTENSIONS);
    104 
    105   bool sync_typed_urls;
    106   if (!result->GetBoolean("syncTypedUrls", &sync_typed_urls))
    107     return false;
    108   if (sync_typed_urls)
    109     config->data_types.insert(syncable::TYPED_URLS);
    110 
    111   bool sync_sessions;
    112   if (!result->GetBoolean("syncSessions", &sync_sessions))
    113     return false;
    114   if (sync_sessions)
    115     config->data_types.insert(syncable::SESSIONS);
    116 
    117   bool sync_apps;
    118   if (!result->GetBoolean("syncApps", &sync_apps))
    119     return false;
    120   if (sync_apps)
    121     config->data_types.insert(syncable::APPS);
    122 
    123   // Encryption settings.
    124   if (!result->GetBoolean("usePassphrase", &config->use_secondary_passphrase))
    125     return false;
    126   if (config->use_secondary_passphrase &&
    127       !result->GetString("passphrase", &config->secondary_passphrase))
    128     return false;
    129 
    130   return true;
    131 }
    132 
    133 bool GetPassphrase(const std::string& json, std::string* passphrase) {
    134   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
    135   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
    136     return false;
    137 
    138   DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
    139   return result->GetString("passphrase", passphrase);
    140 }
    141 
    142 bool GetFirstPassphrase(const std::string& json,
    143                         std::string* option,
    144                         std::string* passphrase) {
    145   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
    146   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
    147     return false;
    148 
    149   DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
    150   return result->GetString("option", option) &&
    151          result->GetString("passphrase", passphrase);
    152 }
    153 
    154 }  // namespace
    155 
    156 SyncSetupHandler::SyncSetupHandler() : flow_(NULL) {
    157 }
    158 
    159 SyncSetupHandler::~SyncSetupHandler() {
    160 }
    161 
    162 void SyncSetupHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
    163   DCHECK(localized_strings);
    164 
    165   localized_strings->SetString(
    166       "invalidpasswordhelpurl",
    167       google_util::StringAppendGoogleLocaleParam(kInvalidPasswordHelpUrl));
    168   localized_strings->SetString(
    169       "cannotaccessaccounturl",
    170       google_util::StringAppendGoogleLocaleParam(kCanNotAccessAccountUrl));
    171   localized_strings->SetString(
    172       "createnewaccounturl",
    173       google_util::StringAppendGoogleLocaleParam(kCreateNewAccountUrl));
    174   localized_strings->SetString(
    175       "introduction",
    176       GetStringFUTF16(IDS_SYNC_LOGIN_INTRODUCTION,
    177                       GetStringUTF16(IDS_PRODUCT_NAME)));
    178   localized_strings->SetString(
    179       "choosedatatypesinstructions",
    180       GetStringFUTF16(IDS_SYNC_CHOOSE_DATATYPES_INSTRUCTIONS,
    181                       GetStringUTF16(IDS_PRODUCT_NAME)));
    182   localized_strings->SetString(
    183       "encryptionInstructions",
    184       GetStringFUTF16(IDS_SYNC_ENCRYPTION_INSTRUCTIONS,
    185                       GetStringUTF16(IDS_PRODUCT_NAME)));
    186   localized_strings->SetString(
    187       "encryptionhelpurl",
    188       google_util::StringAppendGoogleLocaleParam(kEncryptionHelpUrl));
    189   localized_strings->SetString(
    190       "passphraseEncryptionMessage",
    191       GetStringFUTF16(IDS_SYNC_PASSPHRASE_ENCRYPTION_MESSAGE,
    192                       GetStringUTF16(IDS_PRODUCT_NAME)));
    193 
    194   static OptionsStringResource resources[] = {
    195     { "syncSetupOverlayTitle", IDS_SYNC_SETUP_TITLE },
    196     { "syncSetupConfigureTitle", IDS_SYNC_SETUP_CONFIGURE_TITLE },
    197     { "signinprefix", IDS_SYNC_LOGIN_SIGNIN_PREFIX },
    198     { "signinsuffix", IDS_SYNC_LOGIN_SIGNIN_SUFFIX },
    199     { "cannotbeblank", IDS_SYNC_CANNOT_BE_BLANK },
    200     { "emaillabel", IDS_SYNC_LOGIN_EMAIL },
    201     { "passwordlabel", IDS_SYNC_LOGIN_PASSWORD },
    202     { "invalidcredentials", IDS_SYNC_INVALID_USER_CREDENTIALS },
    203     { "signin", IDS_SYNC_SIGNIN },
    204     { "couldnotconnect", IDS_SYNC_LOGIN_COULD_NOT_CONNECT },
    205     { "cannotaccessaccount", IDS_SYNC_CANNOT_ACCESS_ACCOUNT },
    206     { "createaccount", IDS_SYNC_CREATE_ACCOUNT },
    207     { "cancel", IDS_CANCEL },
    208     { "settingup", IDS_SYNC_LOGIN_SETTING_UP },
    209     { "settingupsync", IDS_SYNC_LOGIN_SETTING_UP_SYNC },
    210     { "errorsigningin", IDS_SYNC_ERROR_SIGNING_IN },
    211     { "captchainstructions", IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS },
    212     { "invalidaccesscode", IDS_SYNC_INVALID_ACCESS_CODE_LABEL },
    213     { "enteraccesscode", IDS_SYNC_ENTER_ACCESS_CODE_LABEL },
    214     { "getaccesscodehelp", IDS_SYNC_ACCESS_CODE_HELP_LABEL },
    215     { "getaccesscodeurl", IDS_SYNC_GET_ACCESS_CODE_URL },
    216     { "dataTypes", IDS_SYNC_DATA_TYPES_TAB_NAME },
    217     { "encryption", IDS_SYNC_ENCRYPTION_TAB_NAME },
    218     { "choosedatatypesheader", IDS_SYNC_CHOOSE_DATATYPES_HEADER },
    219     { "keepeverythingsynced", IDS_SYNC_EVERYTHING },
    220     { "choosedatatypes", IDS_SYNC_CHOOSE_DATATYPES },
    221     { "bookmarks", IDS_SYNC_DATATYPE_BOOKMARKS },
    222     { "preferences", IDS_SYNC_DATATYPE_PREFERENCES },
    223     { "autofill", IDS_SYNC_DATATYPE_AUTOFILL },
    224     { "themes", IDS_SYNC_DATATYPE_THEMES },
    225     { "passwords", IDS_SYNC_DATATYPE_PASSWORDS },
    226     { "extensions", IDS_SYNC_DATATYPE_EXTENSIONS },
    227     { "typedurls", IDS_SYNC_DATATYPE_TYPED_URLS },
    228     { "apps", IDS_SYNC_DATATYPE_APPS },
    229     { "foreignsessions", IDS_SYNC_DATATYPE_SESSIONS },
    230     { "synczerodatatypeserror", IDS_SYNC_ZERO_DATA_TYPES_ERROR },
    231     { "abortederror", IDS_SYNC_SETUP_ABORTED_BY_PENDING_CLEAR },
    232     { "encryptAllLabel", IDS_SYNC_ENCRYPT_ALL_LABEL },
    233     { "googleOption", IDS_SYNC_PASSPHRASE_OPT_GOOGLE },
    234     { "explicitOption", IDS_SYNC_PASSPHRASE_OPT_EXPLICIT },
    235     { "sectionGoogleMessage", IDS_SYNC_PASSPHRASE_MSG_GOOGLE },
    236     { "sectionExplicitMessage", IDS_SYNC_PASSPHRASE_MSG_EXPLICIT },
    237     { "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL },
    238     { "confirmLabel", IDS_SYNC_CONFIRM_PASSPHRASE_LABEL },
    239     { "emptyErrorMessage", IDS_SYNC_EMPTY_PASSPHRASE_ERROR },
    240     { "mismatchErrorMessage", IDS_SYNC_PASSPHRASE_MISMATCH_ERROR },
    241     { "passphraseWarning", IDS_SYNC_PASSPHRASE_WARNING },
    242     { "cleardata", IDS_SYNC_CLEAR_DATA_FOR_PASSPHRASE },
    243     { "cleardatalink", IDS_SYNC_CLEAR_DATA_LINK },
    244     { "settingup", IDS_SYNC_LOGIN_SETTING_UP },
    245     { "success", IDS_SYNC_SUCCESS },
    246     { "firsttimesummary", IDS_SYNC_SETUP_FIRST_TIME_ALL_DONE },
    247     { "okay", IDS_SYNC_SETUP_OK_BUTTON_LABEL },
    248     { "enterPassphraseTitle", IDS_SYNC_ENTER_PASSPHRASE_TITLE },
    249     { "firstPassphraseTitle", IDS_SYNC_FIRST_PASSPHRASE_TITLE },
    250     { "customizeLinkLabel", IDS_SYNC_CUSTOMIZE_LINK_LABEL },
    251     { "confirmSyncPreferences", IDS_SYNC_CONFIRM_SYNC_PREFERENCES },
    252     { "syncEverything", IDS_SYNC_SYNC_EVERYTHING },
    253     { "useDefaultSettings", IDS_SYNC_USE_DEFAULT_SETTINGS },
    254     { "passphraseSectionTitle", IDS_SYNC_PASSPHRASE_SECTION_TITLE },
    255     { "privacyDashboardLink", IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL },
    256     { "enterPassphraseTitle", IDS_SYNC_ENTER_PASSPHRASE_TITLE },
    257     { "enterPassphraseBody", IDS_SYNC_ENTER_PASSPHRASE_BODY },
    258     { "enterOtherPassphraseBody", IDS_SYNC_ENTER_OTHER_PASSPHRASE_BODY },
    259     { "passphraseLabel", IDS_SYNC_PASSPHRASE_LABEL },
    260     { "incorrectPassphrase", IDS_SYNC_INCORRECT_PASSPHRASE },
    261     { "passphraseRecover", IDS_SYNC_PASSPHRASE_RECOVER },
    262     { "passphraseWarning", IDS_SYNC_PASSPHRASE_WARNING },
    263     { "cleardatalink", IDS_SYNC_CLEAR_DATA_LINK },
    264     { "cancelWarningHeader", IDS_SYNC_PASSPHRASE_CANCEL_WARNING_HEADER },
    265     { "cancelWarning", IDS_SYNC_PASSPHRASE_CANCEL_WARNING },
    266     { "yes", IDS_SYNC_PASSPHRASE_CANCEL_YES },
    267     { "no", IDS_SYNC_PASSPHRASE_CANCEL_NO },
    268     { "sectionExplicitMessagePrefix", IDS_SYNC_PASSPHRASE_MSG_EXPLICIT_PREFIX },
    269     { "sectionExplicitMessagePostfix",
    270         IDS_SYNC_PASSPHRASE_MSG_EXPLICIT_POSTFIX },
    271   };
    272 
    273   RegisterStrings(localized_strings, resources, arraysize(resources));
    274 }
    275 
    276 void SyncSetupHandler::Initialize() {
    277 }
    278 
    279 void SyncSetupHandler::RegisterMessages() {
    280   web_ui_->RegisterMessageCallback("didShowPage",
    281       NewCallback(this, &SyncSetupHandler::OnDidShowPage));
    282   web_ui_->RegisterMessageCallback("didClosePage",
    283       NewCallback(this, &SyncSetupHandler::OnDidClosePage));
    284   web_ui_->RegisterMessageCallback("SubmitAuth",
    285       NewCallback(this, &SyncSetupHandler::HandleSubmitAuth));
    286   web_ui_->RegisterMessageCallback("Configure",
    287       NewCallback(this, &SyncSetupHandler::HandleConfigure));
    288   web_ui_->RegisterMessageCallback("Passphrase",
    289       NewCallback(this, &SyncSetupHandler::HandlePassphraseEntry));
    290   web_ui_->RegisterMessageCallback("PassphraseCancel",
    291       NewCallback(this, &SyncSetupHandler::HandlePassphraseCancel));
    292   web_ui_->RegisterMessageCallback("FirstPassphrase",
    293       NewCallback(this, &SyncSetupHandler::HandleFirstPassphrase));
    294   web_ui_->RegisterMessageCallback("GoToDashboard",
    295       NewCallback(this, &SyncSetupHandler::HandleGoToDashboard));
    296 }
    297 
    298 // Called by SyncSetupFlow::Advance.
    299 void SyncSetupHandler::ShowGaiaLogin(const DictionaryValue& args) {
    300   StringValue page("login");
    301   web_ui_->CallJavascriptFunction(
    302       "SyncSetupOverlay.showSyncSetupPage", page, args);
    303 }
    304 
    305 void SyncSetupHandler::ShowGaiaSuccessAndClose() {
    306   web_ui_->CallJavascriptFunction("SyncSetupOverlay.showSuccessAndClose");
    307 }
    308 
    309 void SyncSetupHandler::ShowGaiaSuccessAndSettingUp() {
    310   web_ui_->CallJavascriptFunction("SyncSetupOverlay.showSuccessAndSettingUp");
    311 }
    312 
    313 // Called by SyncSetupFlow::Advance.
    314 void SyncSetupHandler::ShowConfigure(const DictionaryValue& args) {
    315   StringValue page("configure");
    316   web_ui_->CallJavascriptFunction(
    317       "SyncSetupOverlay.showSyncSetupPage", page, args);
    318 }
    319 
    320 void SyncSetupHandler::ShowPassphraseEntry(const DictionaryValue& args) {
    321   StringValue page("passphrase");
    322   web_ui_->CallJavascriptFunction(
    323       "SyncSetupOverlay.showSyncSetupPage", page, args);
    324 }
    325 
    326 void SyncSetupHandler::ShowFirstPassphrase(const DictionaryValue& args) {
    327   // TODO(jhawkins): Remove this logic in SyncSetupFlow. It will never be
    328   // reached.
    329   NOTREACHED();
    330 }
    331 
    332 void SyncSetupHandler::ShowSettingUp() {
    333   StringValue page("settingUp");
    334   web_ui_->CallJavascriptFunction(
    335       "SyncSetupOverlay.showSyncSetupPage", page);
    336 }
    337 
    338 void SyncSetupHandler::ShowSetupDone(const std::wstring& user) {
    339   StringValue page("done");
    340   web_ui_->CallJavascriptFunction(
    341       "SyncSetupOverlay.showSyncSetupPage", page);
    342 }
    343 
    344 void SyncSetupHandler::ShowFirstTimeDone(const std::wstring& user) {
    345   // TODO(jhawkins): Remove this from Sync since it's not called anymore.
    346   NOTREACHED();
    347 }
    348 
    349 void SyncSetupHandler::OnDidShowPage(const ListValue* args) {
    350   DCHECK(web_ui_);
    351 
    352   ProfileSyncService* sync_service =
    353       web_ui_->GetProfile()->GetProfileSyncService();
    354   if (!sync_service)
    355     return;
    356 
    357   flow_ = sync_service->get_wizard().AttachSyncSetupHandler(this);
    358 }
    359 
    360 void SyncSetupHandler::OnDidClosePage(const ListValue* args) {
    361   if (flow_) {
    362     flow_->OnDialogClosed(std::string());
    363     flow_ = NULL;
    364   }
    365 }
    366 
    367 void SyncSetupHandler::HandleSubmitAuth(const ListValue* args) {
    368   std::string json;
    369   if (!args->GetString(0, &json)) {
    370     NOTREACHED() << "Could not read JSON argument";
    371     return;
    372   }
    373 
    374   if (json.empty())
    375     return;
    376 
    377   std::string username, password, captcha, access_code;
    378   if (!GetAuthData(json, &username, &password, &captcha, &access_code)) {
    379     // The page sent us something that we didn't understand.
    380     // This probably indicates a programming error.
    381     NOTREACHED();
    382     return;
    383   }
    384 
    385   if (flow_)
    386     flow_->OnUserSubmittedAuth(username, password, captcha, access_code);
    387 }
    388 
    389 void SyncSetupHandler::HandleConfigure(const ListValue* args) {
    390   std::string json;
    391   if (!args->GetString(0, &json)) {
    392     NOTREACHED() << "Could not read JSON argument";
    393     return;
    394   }
    395   if (json.empty()) {
    396     NOTREACHED();
    397     return;
    398   }
    399 
    400   SyncConfiguration configuration;
    401   if (!GetConfiguration(json, &configuration)) {
    402     // The page sent us something that we didn't understand.
    403     // This probably indicates a programming error.
    404     NOTREACHED();
    405     return;
    406   }
    407 
    408   DCHECK(flow_);
    409   flow_->OnUserConfigured(configuration);
    410 }
    411 
    412 void SyncSetupHandler::HandlePassphraseEntry(const ListValue* args) {
    413   std::string json;
    414   if (!args->GetString(0, &json)) {
    415     NOTREACHED() << "Could not read JSON argument";
    416     return;
    417   }
    418 
    419   if (json.empty())
    420     return;
    421 
    422   std::string passphrase;
    423   if (!GetPassphrase(json, &passphrase)) {
    424     // Couldn't understand what the page sent.  Indicates a programming error.
    425     NOTREACHED();
    426     return;
    427   }
    428 
    429   DCHECK(flow_);
    430   flow_->OnPassphraseEntry(passphrase);
    431 }
    432 
    433 void SyncSetupHandler::HandlePassphraseCancel(const ListValue* args) {
    434   DCHECK(flow_);
    435   flow_->OnPassphraseCancel();
    436 }
    437 
    438 void SyncSetupHandler::HandleFirstPassphrase(const ListValue* args) {
    439   std::string json;
    440   if (!args->GetString(0, &json)) {
    441     NOTREACHED() << "Could not read JSON argument";
    442     return;
    443   }
    444   if (json.empty())
    445     return;
    446 
    447   std::string option;
    448   std::string passphrase;
    449   if (!GetFirstPassphrase(json, &option, &passphrase)) {
    450     // Page sent result which couldn't be parsed.  Programming error.
    451     NOTREACHED();
    452     return;
    453   }
    454 
    455   DCHECK(flow_);
    456   flow_->OnFirstPassphraseEntry(option, passphrase);
    457 }
    458 
    459 void SyncSetupHandler::HandleGoToDashboard(const ListValue* args) {
    460   DCHECK(flow_);
    461   flow_->OnGoToDashboard();
    462 }
    463