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/personal_options_handler.h"
      6 
      7 #include <string>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/callback.h"
     11 #include "base/command_line.h"
     12 #include "base/path_service.h"
     13 #include "base/stl_util-inl.h"
     14 #include "base/stringprintf.h"
     15 #include "base/time.h"
     16 #include "base/utf_string_conversions.h"
     17 #include "base/values.h"
     18 #include "build/build_config.h"
     19 #include "chrome/browser/profiles/profile.h"
     20 #include "chrome/browser/profiles/profile_manager.h"
     21 #include "chrome/browser/sync/profile_sync_service.h"
     22 #include "chrome/browser/sync/sync_setup_flow.h"
     23 #include "chrome/browser/sync/sync_ui_util.h"
     24 #include "chrome/browser/themes/theme_service.h"
     25 #include "chrome/browser/themes/theme_service_factory.h"
     26 #include "chrome/browser/ui/browser_list.h"
     27 #include "chrome/browser/ui/options/options_page_base.h"
     28 #include "chrome/browser/ui/options/options_window.h"
     29 #include "chrome/browser/ui/webui/options/options_managed_banner_handler.h"
     30 #include "chrome/common/chrome_paths.h"
     31 #include "chrome/common/chrome_switches.h"
     32 #include "chrome/common/net/gaia/google_service_auth_error.h"
     33 #include "chrome/common/url_constants.h"
     34 #include "content/common/notification_service.h"
     35 #include "grit/chromium_strings.h"
     36 #include "grit/generated_resources.h"
     37 #include "grit/locale_settings.h"
     38 #include "grit/theme_resources.h"
     39 #include "ui/base/l10n/l10n_util.h"
     40 
     41 #if defined(OS_CHROMEOS)
     42 #include "chrome/browser/chromeos/login/user_manager.h"
     43 #include "chrome/browser/chromeos/options/take_photo_dialog.h"
     44 #include "chrome/browser/ui/browser_window.h"
     45 #include "chrome/browser/ui/views/window.h"
     46 #include "third_party/skia/include/core/SkBitmap.h"
     47 #include "views/window/window.h"
     48 #endif  // defined(OS_CHROMEOS)
     49 #if defined(TOOLKIT_GTK)
     50 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
     51 #endif  // defined(TOOLKIT_GTK)
     52 
     53 PersonalOptionsHandler::PersonalOptionsHandler() {
     54   const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
     55   multiprofile_ = browser_command_line.HasSwitch(switches::kMultiProfiles);
     56 #if defined(OS_CHROMEOS)
     57   registrar_.Add(this,
     58                  NotificationType::LOGIN_USER_IMAGE_CHANGED,
     59                  NotificationService::AllSources());
     60 #endif
     61 }
     62 
     63 PersonalOptionsHandler::~PersonalOptionsHandler() {
     64   ProfileSyncService* sync_service =
     65       web_ui_->GetProfile()->GetProfileSyncService();
     66   if (sync_service)
     67     sync_service->RemoveObserver(this);
     68 }
     69 
     70 void PersonalOptionsHandler::GetLocalizedValues(
     71     DictionaryValue* localized_strings) {
     72   DCHECK(localized_strings);
     73 
     74   RegisterTitle(localized_strings, "personalPage",
     75                 IDS_OPTIONS_CONTENT_TAB_LABEL);
     76 
     77 
     78   localized_strings->SetString(
     79       "syncOverview",
     80       l10n_util::GetStringFUTF16(IDS_SYNC_OVERVIEW,
     81                                  l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
     82   localized_strings->SetString(
     83       "syncFurtherOverview",
     84       l10n_util::GetStringUTF16(IDS_SYNC_FURTHER_OVERVIEW));
     85   localized_strings->SetString("syncSection",
     86       multiprofile_ ?
     87           l10n_util::GetStringUTF16(IDS_PROFILES_OPTIONS_GROUP_NAME) :
     88           l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME));
     89   localized_strings->SetString("customizeSync",
     90       multiprofile_ ?
     91           l10n_util::GetStringUTF16(IDS_PROFILES_SYNC_CUSTOMIZE_BUTTON_LABEL) :
     92           l10n_util::GetStringUTF16(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL));
     93   if (multiprofile_) {
     94     localized_strings->SetString("createNewProfile",
     95         l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_INFO));
     96     localized_strings->SetString("createProfileButton",
     97         l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_BUTTON_LABEL));
     98   }
     99 
    100   localized_strings->SetString("passwords",
    101       l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_GROUP_NAME));
    102   localized_strings->SetString("passwordsAskToSave",
    103       l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_ASKTOSAVE));
    104   localized_strings->SetString("passwordsNeverSave",
    105       l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_NEVERSAVE));
    106   localized_strings->SetString("manage_passwords",
    107       l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS));
    108 
    109   localized_strings->SetString("autofill",
    110       l10n_util::GetStringUTF16(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME));
    111   localized_strings->SetString("autofillEnabled",
    112       l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOFILL_ENABLE));
    113   localized_strings->SetString("manageAutofillSettings",
    114       l10n_util::GetStringUTF16(IDS_OPTIONS_MANAGE_AUTOFILL_SETTINGS));
    115 
    116   localized_strings->SetString("browsingData",
    117       l10n_util::GetStringUTF16(IDS_OPTIONS_BROWSING_DATA_GROUP_NAME));
    118   localized_strings->SetString("importData",
    119       l10n_util::GetStringUTF16(IDS_OPTIONS_IMPORT_DATA_BUTTON));
    120 
    121   localized_strings->SetString("themesGallery",
    122       l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON));
    123   localized_strings->SetString("themesGalleryURL",
    124       l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_URL));
    125 
    126 #if defined(TOOLKIT_GTK)
    127   localized_strings->SetString("appearance",
    128       l10n_util::GetStringUTF16(IDS_APPEARANCE_GROUP_NAME));
    129   localized_strings->SetString("themesGTKButton",
    130       l10n_util::GetStringUTF16(IDS_THEMES_GTK_BUTTON));
    131   localized_strings->SetString("themesSetClassic",
    132       l10n_util::GetStringUTF16(IDS_THEMES_SET_CLASSIC));
    133   localized_strings->SetString("showWindowDecorations",
    134       l10n_util::GetStringUTF16(IDS_SHOW_WINDOW_DECORATIONS_RADIO));
    135   localized_strings->SetString("hideWindowDecorations",
    136       l10n_util::GetStringUTF16(IDS_HIDE_WINDOW_DECORATIONS_RADIO));
    137 #else
    138   localized_strings->SetString("themes",
    139       l10n_util::GetStringUTF16(IDS_THEMES_GROUP_NAME));
    140   localized_strings->SetString("themesReset",
    141       l10n_util::GetStringUTF16(IDS_THEMES_RESET_BUTTON));
    142 #endif
    143 
    144   // Sync select control.
    145   ListValue* sync_select_list = new ListValue;
    146   ListValue* datatypes = new ListValue;
    147   datatypes->Append(Value::CreateBooleanValue(false));
    148   datatypes->Append(
    149       Value::CreateStringValue(
    150           l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_DATATYPES)));
    151   sync_select_list->Append(datatypes);
    152   ListValue* everything = new ListValue;
    153   everything->Append(Value::CreateBooleanValue(true));
    154   everything->Append(
    155       Value::CreateStringValue(
    156           l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_EVERYTHING)));
    157   sync_select_list->Append(everything);
    158   localized_strings->Set("syncSelectList", sync_select_list);
    159 
    160   // Sync page.
    161   localized_strings->SetString("syncPage",
    162       l10n_util::GetStringUTF16(IDS_SYNC_NTP_SYNC_SECTION_TITLE));
    163   localized_strings->SetString("sync_title",
    164       l10n_util::GetStringUTF16(IDS_CUSTOMIZE_SYNC_DESCRIPTION));
    165   localized_strings->SetString("syncsettings",
    166       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES));
    167   localized_strings->SetString("syncbookmarks",
    168       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS));
    169   localized_strings->SetString("synctypedurls",
    170       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS));
    171   localized_strings->SetString("syncpasswords",
    172       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS));
    173   localized_strings->SetString("syncextensions",
    174       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS));
    175   localized_strings->SetString("syncautofill",
    176       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL));
    177   localized_strings->SetString("syncthemes",
    178       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES));
    179   localized_strings->SetString("syncapps",
    180       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS));
    181   localized_strings->SetString("syncsessions",
    182       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_SESSIONS));
    183 
    184 #if defined(OS_CHROMEOS)
    185   localized_strings->SetString("account",
    186       l10n_util::GetStringUTF16(IDS_OPTIONS_PERSONAL_ACCOUNT_GROUP_NAME));
    187   localized_strings->SetString("enableScreenlock",
    188       l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SCREENLOCKER_CHECKBOX));
    189   localized_strings->SetString("changePicture",
    190       l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE));
    191 #endif
    192 }
    193 
    194 void PersonalOptionsHandler::RegisterMessages() {
    195   DCHECK(web_ui_);
    196   web_ui_->RegisterMessageCallback(
    197       "showSyncActionDialog",
    198       NewCallback(this, &PersonalOptionsHandler::ShowSyncActionDialog));
    199   web_ui_->RegisterMessageCallback(
    200       "showSyncLoginDialog",
    201       NewCallback(this, &PersonalOptionsHandler::ShowSyncLoginDialog));
    202   web_ui_->RegisterMessageCallback(
    203       "showCustomizeSyncDialog",
    204       NewCallback(this, &PersonalOptionsHandler::ShowCustomizeSyncDialog));
    205   web_ui_->RegisterMessageCallback(
    206       "themesReset",
    207       NewCallback(this, &PersonalOptionsHandler::ThemesReset));
    208 #if defined(TOOLKIT_GTK)
    209   web_ui_->RegisterMessageCallback(
    210       "themesSetGTK",
    211       NewCallback(this, &PersonalOptionsHandler::ThemesSetGTK));
    212 #endif
    213   web_ui_->RegisterMessageCallback("updatePreferredDataTypes",
    214       NewCallback(this, &PersonalOptionsHandler::OnPreferredDataTypesUpdated));
    215 #if defined(OS_CHROMEOS)
    216   web_ui_->RegisterMessageCallback(
    217       "loadAccountPicture",
    218       NewCallback(this, &PersonalOptionsHandler::LoadAccountPicture));
    219 #endif
    220 }
    221 
    222 void PersonalOptionsHandler::Observe(NotificationType type,
    223                                      const NotificationSource& source,
    224                                      const NotificationDetails& details) {
    225   if (type == NotificationType::BROWSER_THEME_CHANGED) {
    226     ObserveThemeChanged();
    227 #if defined(OS_CHROMEOS)
    228   } else if (type == NotificationType::LOGIN_USER_IMAGE_CHANGED) {
    229     LoadAccountPicture(NULL);
    230 #endif
    231   } else {
    232     OptionsPageUIHandler::Observe(type, source, details);
    233   }
    234 }
    235 
    236 void PersonalOptionsHandler::OnStateChanged() {
    237   string16 status_label;
    238   string16 link_label;
    239   ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
    240   DCHECK(service);
    241   bool managed = service->IsManaged();
    242   bool sync_setup_completed = service->HasSyncSetupCompleted();
    243   bool status_has_error = sync_ui_util::GetStatusLabels(service,
    244       &status_label, &link_label) == sync_ui_util::SYNC_ERROR;
    245 
    246   string16 start_stop_button_label;
    247   bool is_start_stop_button_visible = false;
    248   bool is_start_stop_button_enabled = false;
    249   if (sync_setup_completed) {
    250     start_stop_button_label = multiprofile_ ?
    251         l10n_util::GetStringUTF16(IDS_PROFILES_DISCONNECT_BUTTON_LABEL) :
    252         l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL);
    253 #if defined(OS_CHROMEOS)
    254     is_start_stop_button_visible = false;
    255 #else
    256     is_start_stop_button_visible = true;
    257 #endif  // defined(OS_CHROMEOS)
    258     is_start_stop_button_enabled = !managed;
    259   } else if (service->SetupInProgress()) {
    260     start_stop_button_label =
    261         l10n_util::GetStringUTF16(IDS_SYNC_NTP_SETUP_IN_PROGRESS);
    262     is_start_stop_button_visible = true;
    263     is_start_stop_button_enabled = false;
    264   } else {
    265     start_stop_button_label =
    266         multiprofile_ ?
    267             l10n_util::GetStringUTF16(IDS_PROFILES_CONNECT_BUTTON_LABEL) :
    268             l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL);
    269     is_start_stop_button_visible = true;
    270     is_start_stop_button_enabled = !managed;
    271   }
    272 
    273   scoped_ptr<Value> completed(Value::CreateBooleanValue(sync_setup_completed));
    274   web_ui_->CallJavascriptFunction("PersonalOptions.setSyncSetupCompleted",
    275                                   *completed);
    276 
    277   scoped_ptr<Value> label(Value::CreateStringValue(status_label));
    278   web_ui_->CallJavascriptFunction("PersonalOptions.setSyncStatus", *label);
    279 
    280   scoped_ptr<Value> enabled(
    281       Value::CreateBooleanValue(is_start_stop_button_enabled));
    282   web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonEnabled",
    283                                   *enabled);
    284 
    285   scoped_ptr<Value> visible(
    286       Value::CreateBooleanValue(is_start_stop_button_visible));
    287   web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonVisible",
    288                                   *visible);
    289 
    290   label.reset(Value::CreateStringValue(start_stop_button_label));
    291   web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonLabel",
    292                                   *label);
    293 
    294   label.reset(Value::CreateStringValue(link_label));
    295   web_ui_->CallJavascriptFunction("PersonalOptions.setSyncActionLinkLabel",
    296                                   *label);
    297 
    298   enabled.reset(Value::CreateBooleanValue(!managed));
    299   web_ui_->CallJavascriptFunction("PersonalOptions.setSyncActionLinkEnabled",
    300                                   *enabled);
    301 
    302   visible.reset(Value::CreateBooleanValue(status_has_error));
    303   web_ui_->CallJavascriptFunction("PersonalOptions.setSyncStatusErrorVisible",
    304                                   *visible);
    305 
    306   // Set profile creation text and button if multi-profiles switch is on.
    307   if (multiprofile_) {
    308     visible.reset(Value::CreateBooleanValue(true));
    309     web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible",
    310                                     *visible);
    311 
    312     // TODO(mirandac): enable when back end is ready.
    313     enabled.reset(Value::CreateBooleanValue(false));
    314     web_ui_->CallJavascriptFunction(
    315         "PersonalOptions.setNewProfileButtonEnabled", *enabled);
    316   } else {
    317     visible.reset(Value::CreateBooleanValue(false));
    318     web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible",
    319                                     *visible);
    320   }
    321 }
    322 
    323 void PersonalOptionsHandler::OnLoginSuccess() {
    324   OnStateChanged();
    325 }
    326 
    327 void PersonalOptionsHandler::OnLoginFailure(
    328     const GoogleServiceAuthError& error) {
    329   OnStateChanged();
    330 }
    331 
    332 void PersonalOptionsHandler::ObserveThemeChanged() {
    333   Profile* profile = web_ui_->GetProfile();
    334 #if defined(TOOLKIT_GTK)
    335   GtkThemeService* provider = GtkThemeService::GetFrom(profile);
    336   bool is_gtk_theme = provider->UseGtkTheme();
    337   FundamentalValue gtk_enabled(!is_gtk_theme);
    338   web_ui_->CallJavascriptFunction(
    339       "options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled);
    340 #else
    341   ThemeService* provider = ThemeServiceFactory::GetForProfile(profile);
    342   bool is_gtk_theme = false;
    343 #endif
    344 
    345   bool is_classic_theme = !is_gtk_theme && provider->UsingDefaultTheme();
    346   FundamentalValue enabled(!is_classic_theme);
    347   web_ui_->CallJavascriptFunction(
    348       "options.PersonalOptions.setThemesResetButtonEnabled", enabled);
    349 }
    350 
    351 void PersonalOptionsHandler::Initialize() {
    352   banner_handler_.reset(
    353       new OptionsManagedBannerHandler(web_ui_,
    354                                       ASCIIToUTF16("PersonalOptions"),
    355                                       OPTIONS_PAGE_CONTENT));
    356 
    357   // Listen for theme installation.
    358   registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
    359                  NotificationService::AllSources());
    360   ObserveThemeChanged();
    361 
    362   ProfileSyncService* sync_service =
    363       web_ui_->GetProfile()->GetProfileSyncService();
    364   if (sync_service) {
    365     sync_service->AddObserver(this);
    366     OnStateChanged();
    367 
    368     DictionaryValue args;
    369     SyncSetupFlow::GetArgsForConfigure(sync_service, &args);
    370 
    371     web_ui_->CallJavascriptFunction("PersonalOptions.setRegisteredDataTypes",
    372                                     args);
    373   } else {
    374     web_ui_->CallJavascriptFunction("options.PersonalOptions.hideSyncSection");
    375   }
    376 }
    377 
    378 void PersonalOptionsHandler::ShowSyncActionDialog(const ListValue* args) {
    379   ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
    380   DCHECK(service);
    381   service->ShowErrorUI(NULL);
    382 }
    383 
    384 void PersonalOptionsHandler::ShowSyncLoginDialog(const ListValue* args) {
    385   ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
    386   DCHECK(service);
    387   service->ShowLoginDialog(NULL);
    388   ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
    389 }
    390 
    391 void PersonalOptionsHandler::ShowCustomizeSyncDialog(const ListValue* args) {
    392   ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
    393   DCHECK(service);
    394   service->ShowConfigure(NULL, false);
    395 }
    396 
    397 void PersonalOptionsHandler::ThemesReset(const ListValue* args) {
    398   UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset"));
    399   ThemeServiceFactory::GetForProfile(web_ui_->GetProfile())->UseDefaultTheme();
    400 }
    401 
    402 #if defined(TOOLKIT_GTK)
    403 void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) {
    404   UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"));
    405   ThemeServiceFactory::GetForProfile(web_ui_->GetProfile())->SetNativeTheme();
    406 }
    407 #endif
    408 
    409 void PersonalOptionsHandler::OnPreferredDataTypesUpdated(
    410     const ListValue* args) {
    411   NotificationService::current()->Notify(
    412       NotificationType::SYNC_DATA_TYPES_UPDATED,
    413       Source<Profile>(web_ui_->GetProfile()),
    414       NotificationService::NoDetails());
    415 }
    416 
    417 #if defined(OS_CHROMEOS)
    418 void PersonalOptionsHandler::LoadAccountPicture(const ListValue* args) {
    419   const chromeos::UserManager::User& user =
    420       chromeos::UserManager::Get()->logged_in_user();
    421   std::string email = user.email();
    422   if (!email.empty()) {
    423     // int64 is either long or long long, but we need a certain format
    424     // specifier.
    425     long long timestamp = base::TimeTicks::Now().ToInternalValue();
    426     StringValue image_url(
    427         StringPrintf("%s%s?id=%lld",
    428                      chrome::kChromeUIUserImageURL,
    429                      email.c_str(),
    430                      timestamp));
    431     web_ui_->CallJavascriptFunction("PersonalOptions.setAccountPicture",
    432                                     image_url);
    433   }
    434 }
    435 
    436 #endif
    437