// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/webui/options/personal_options_handler.h" #include <string> #include "base/basictypes.h" #include "base/callback.h" #include "base/command_line.h" #include "base/path_service.h" #include "base/stl_util-inl.h" #include "base/stringprintf.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_setup_flow.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/options/options_page_base.h" #include "chrome/browser/ui/options/options_window.h" #include "chrome/browser/ui/webui/options/options_managed_banner_handler.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/url_constants.h" #include "content/common/notification_service.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/options/take_photo_dialog.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/views/window.h" #include "third_party/skia/include/core/SkBitmap.h" #include "views/window/window.h" #endif // defined(OS_CHROMEOS) #if defined(TOOLKIT_GTK) #include "chrome/browser/ui/gtk/gtk_theme_service.h" #endif // defined(TOOLKIT_GTK) PersonalOptionsHandler::PersonalOptionsHandler() { const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); multiprofile_ = browser_command_line.HasSwitch(switches::kMultiProfiles); #if defined(OS_CHROMEOS) registrar_.Add(this, NotificationType::LOGIN_USER_IMAGE_CHANGED, NotificationService::AllSources()); #endif } PersonalOptionsHandler::~PersonalOptionsHandler() { ProfileSyncService* sync_service = web_ui_->GetProfile()->GetProfileSyncService(); if (sync_service) sync_service->RemoveObserver(this); } void PersonalOptionsHandler::GetLocalizedValues( DictionaryValue* localized_strings) { DCHECK(localized_strings); RegisterTitle(localized_strings, "personalPage", IDS_OPTIONS_CONTENT_TAB_LABEL); localized_strings->SetString( "syncOverview", l10n_util::GetStringFUTF16(IDS_SYNC_OVERVIEW, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); localized_strings->SetString( "syncFurtherOverview", l10n_util::GetStringUTF16(IDS_SYNC_FURTHER_OVERVIEW)); localized_strings->SetString("syncSection", multiprofile_ ? l10n_util::GetStringUTF16(IDS_PROFILES_OPTIONS_GROUP_NAME) : l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME)); localized_strings->SetString("customizeSync", multiprofile_ ? l10n_util::GetStringUTF16(IDS_PROFILES_SYNC_CUSTOMIZE_BUTTON_LABEL) : l10n_util::GetStringUTF16(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL)); if (multiprofile_) { localized_strings->SetString("createNewProfile", l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_INFO)); localized_strings->SetString("createProfileButton", l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_BUTTON_LABEL)); } localized_strings->SetString("passwords", l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_GROUP_NAME)); localized_strings->SetString("passwordsAskToSave", l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_ASKTOSAVE)); localized_strings->SetString("passwordsNeverSave", l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_NEVERSAVE)); localized_strings->SetString("manage_passwords", l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS)); localized_strings->SetString("autofill", l10n_util::GetStringUTF16(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME)); localized_strings->SetString("autofillEnabled", l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOFILL_ENABLE)); localized_strings->SetString("manageAutofillSettings", l10n_util::GetStringUTF16(IDS_OPTIONS_MANAGE_AUTOFILL_SETTINGS)); localized_strings->SetString("browsingData", l10n_util::GetStringUTF16(IDS_OPTIONS_BROWSING_DATA_GROUP_NAME)); localized_strings->SetString("importData", l10n_util::GetStringUTF16(IDS_OPTIONS_IMPORT_DATA_BUTTON)); localized_strings->SetString("themesGallery", l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON)); localized_strings->SetString("themesGalleryURL", l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_URL)); #if defined(TOOLKIT_GTK) localized_strings->SetString("appearance", l10n_util::GetStringUTF16(IDS_APPEARANCE_GROUP_NAME)); localized_strings->SetString("themesGTKButton", l10n_util::GetStringUTF16(IDS_THEMES_GTK_BUTTON)); localized_strings->SetString("themesSetClassic", l10n_util::GetStringUTF16(IDS_THEMES_SET_CLASSIC)); localized_strings->SetString("showWindowDecorations", l10n_util::GetStringUTF16(IDS_SHOW_WINDOW_DECORATIONS_RADIO)); localized_strings->SetString("hideWindowDecorations", l10n_util::GetStringUTF16(IDS_HIDE_WINDOW_DECORATIONS_RADIO)); #else localized_strings->SetString("themes", l10n_util::GetStringUTF16(IDS_THEMES_GROUP_NAME)); localized_strings->SetString("themesReset", l10n_util::GetStringUTF16(IDS_THEMES_RESET_BUTTON)); #endif // Sync select control. ListValue* sync_select_list = new ListValue; ListValue* datatypes = new ListValue; datatypes->Append(Value::CreateBooleanValue(false)); datatypes->Append( Value::CreateStringValue( l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_DATATYPES))); sync_select_list->Append(datatypes); ListValue* everything = new ListValue; everything->Append(Value::CreateBooleanValue(true)); everything->Append( Value::CreateStringValue( l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_EVERYTHING))); sync_select_list->Append(everything); localized_strings->Set("syncSelectList", sync_select_list); // Sync page. localized_strings->SetString("syncPage", l10n_util::GetStringUTF16(IDS_SYNC_NTP_SYNC_SECTION_TITLE)); localized_strings->SetString("sync_title", l10n_util::GetStringUTF16(IDS_CUSTOMIZE_SYNC_DESCRIPTION)); localized_strings->SetString("syncsettings", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES)); localized_strings->SetString("syncbookmarks", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS)); localized_strings->SetString("synctypedurls", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS)); localized_strings->SetString("syncpasswords", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS)); localized_strings->SetString("syncextensions", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS)); localized_strings->SetString("syncautofill", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL)); localized_strings->SetString("syncthemes", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES)); localized_strings->SetString("syncapps", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS)); localized_strings->SetString("syncsessions", l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_SESSIONS)); #if defined(OS_CHROMEOS) localized_strings->SetString("account", l10n_util::GetStringUTF16(IDS_OPTIONS_PERSONAL_ACCOUNT_GROUP_NAME)); localized_strings->SetString("enableScreenlock", l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SCREENLOCKER_CHECKBOX)); localized_strings->SetString("changePicture", l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE)); #endif } void PersonalOptionsHandler::RegisterMessages() { DCHECK(web_ui_); web_ui_->RegisterMessageCallback( "showSyncActionDialog", NewCallback(this, &PersonalOptionsHandler::ShowSyncActionDialog)); web_ui_->RegisterMessageCallback( "showSyncLoginDialog", NewCallback(this, &PersonalOptionsHandler::ShowSyncLoginDialog)); web_ui_->RegisterMessageCallback( "showCustomizeSyncDialog", NewCallback(this, &PersonalOptionsHandler::ShowCustomizeSyncDialog)); web_ui_->RegisterMessageCallback( "themesReset", NewCallback(this, &PersonalOptionsHandler::ThemesReset)); #if defined(TOOLKIT_GTK) web_ui_->RegisterMessageCallback( "themesSetGTK", NewCallback(this, &PersonalOptionsHandler::ThemesSetGTK)); #endif web_ui_->RegisterMessageCallback("updatePreferredDataTypes", NewCallback(this, &PersonalOptionsHandler::OnPreferredDataTypesUpdated)); #if defined(OS_CHROMEOS) web_ui_->RegisterMessageCallback( "loadAccountPicture", NewCallback(this, &PersonalOptionsHandler::LoadAccountPicture)); #endif } void PersonalOptionsHandler::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { if (type == NotificationType::BROWSER_THEME_CHANGED) { ObserveThemeChanged(); #if defined(OS_CHROMEOS) } else if (type == NotificationType::LOGIN_USER_IMAGE_CHANGED) { LoadAccountPicture(NULL); #endif } else { OptionsPageUIHandler::Observe(type, source, details); } } void PersonalOptionsHandler::OnStateChanged() { string16 status_label; string16 link_label; ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService(); DCHECK(service); bool managed = service->IsManaged(); bool sync_setup_completed = service->HasSyncSetupCompleted(); bool status_has_error = sync_ui_util::GetStatusLabels(service, &status_label, &link_label) == sync_ui_util::SYNC_ERROR; string16 start_stop_button_label; bool is_start_stop_button_visible = false; bool is_start_stop_button_enabled = false; if (sync_setup_completed) { start_stop_button_label = multiprofile_ ? l10n_util::GetStringUTF16(IDS_PROFILES_DISCONNECT_BUTTON_LABEL) : l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL); #if defined(OS_CHROMEOS) is_start_stop_button_visible = false; #else is_start_stop_button_visible = true; #endif // defined(OS_CHROMEOS) is_start_stop_button_enabled = !managed; } else if (service->SetupInProgress()) { start_stop_button_label = l10n_util::GetStringUTF16(IDS_SYNC_NTP_SETUP_IN_PROGRESS); is_start_stop_button_visible = true; is_start_stop_button_enabled = false; } else { start_stop_button_label = multiprofile_ ? l10n_util::GetStringUTF16(IDS_PROFILES_CONNECT_BUTTON_LABEL) : l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL); is_start_stop_button_visible = true; is_start_stop_button_enabled = !managed; } scoped_ptr<Value> completed(Value::CreateBooleanValue(sync_setup_completed)); web_ui_->CallJavascriptFunction("PersonalOptions.setSyncSetupCompleted", *completed); scoped_ptr<Value> label(Value::CreateStringValue(status_label)); web_ui_->CallJavascriptFunction("PersonalOptions.setSyncStatus", *label); scoped_ptr<Value> enabled( Value::CreateBooleanValue(is_start_stop_button_enabled)); web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonEnabled", *enabled); scoped_ptr<Value> visible( Value::CreateBooleanValue(is_start_stop_button_visible)); web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonVisible", *visible); label.reset(Value::CreateStringValue(start_stop_button_label)); web_ui_->CallJavascriptFunction("PersonalOptions.setStartStopButtonLabel", *label); label.reset(Value::CreateStringValue(link_label)); web_ui_->CallJavascriptFunction("PersonalOptions.setSyncActionLinkLabel", *label); enabled.reset(Value::CreateBooleanValue(!managed)); web_ui_->CallJavascriptFunction("PersonalOptions.setSyncActionLinkEnabled", *enabled); visible.reset(Value::CreateBooleanValue(status_has_error)); web_ui_->CallJavascriptFunction("PersonalOptions.setSyncStatusErrorVisible", *visible); // Set profile creation text and button if multi-profiles switch is on. if (multiprofile_) { visible.reset(Value::CreateBooleanValue(true)); web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible", *visible); // TODO(mirandac): enable when back end is ready. enabled.reset(Value::CreateBooleanValue(false)); web_ui_->CallJavascriptFunction( "PersonalOptions.setNewProfileButtonEnabled", *enabled); } else { visible.reset(Value::CreateBooleanValue(false)); web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible", *visible); } } void PersonalOptionsHandler::OnLoginSuccess() { OnStateChanged(); } void PersonalOptionsHandler::OnLoginFailure( const GoogleServiceAuthError& error) { OnStateChanged(); } void PersonalOptionsHandler::ObserveThemeChanged() { Profile* profile = web_ui_->GetProfile(); #if defined(TOOLKIT_GTK) GtkThemeService* provider = GtkThemeService::GetFrom(profile); bool is_gtk_theme = provider->UseGtkTheme(); FundamentalValue gtk_enabled(!is_gtk_theme); web_ui_->CallJavascriptFunction( "options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled); #else ThemeService* provider = ThemeServiceFactory::GetForProfile(profile); bool is_gtk_theme = false; #endif bool is_classic_theme = !is_gtk_theme && provider->UsingDefaultTheme(); FundamentalValue enabled(!is_classic_theme); web_ui_->CallJavascriptFunction( "options.PersonalOptions.setThemesResetButtonEnabled", enabled); } void PersonalOptionsHandler::Initialize() { banner_handler_.reset( new OptionsManagedBannerHandler(web_ui_, ASCIIToUTF16("PersonalOptions"), OPTIONS_PAGE_CONTENT)); // Listen for theme installation. registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, NotificationService::AllSources()); ObserveThemeChanged(); ProfileSyncService* sync_service = web_ui_->GetProfile()->GetProfileSyncService(); if (sync_service) { sync_service->AddObserver(this); OnStateChanged(); DictionaryValue args; SyncSetupFlow::GetArgsForConfigure(sync_service, &args); web_ui_->CallJavascriptFunction("PersonalOptions.setRegisteredDataTypes", args); } else { web_ui_->CallJavascriptFunction("options.PersonalOptions.hideSyncSection"); } } void PersonalOptionsHandler::ShowSyncActionDialog(const ListValue* args) { ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService(); DCHECK(service); service->ShowErrorUI(NULL); } void PersonalOptionsHandler::ShowSyncLoginDialog(const ListValue* args) { ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService(); DCHECK(service); service->ShowLoginDialog(NULL); ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS); } void PersonalOptionsHandler::ShowCustomizeSyncDialog(const ListValue* args) { ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService(); DCHECK(service); service->ShowConfigure(NULL, false); } void PersonalOptionsHandler::ThemesReset(const ListValue* args) { UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset")); ThemeServiceFactory::GetForProfile(web_ui_->GetProfile())->UseDefaultTheme(); } #if defined(TOOLKIT_GTK) void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) { UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet")); ThemeServiceFactory::GetForProfile(web_ui_->GetProfile())->SetNativeTheme(); } #endif void PersonalOptionsHandler::OnPreferredDataTypesUpdated( const ListValue* args) { NotificationService::current()->Notify( NotificationType::SYNC_DATA_TYPES_UPDATED, Source<Profile>(web_ui_->GetProfile()), NotificationService::NoDetails()); } #if defined(OS_CHROMEOS) void PersonalOptionsHandler::LoadAccountPicture(const ListValue* args) { const chromeos::UserManager::User& user = chromeos::UserManager::Get()->logged_in_user(); std::string email = user.email(); if (!email.empty()) { // int64 is either long or long long, but we need a certain format // specifier. long long timestamp = base::TimeTicks::Now().ToInternalValue(); StringValue image_url( StringPrintf("%s%s?id=%lld", chrome::kChromeUIUserImageURL, email.c_str(), timestamp)); web_ui_->CallJavascriptFunction("PersonalOptions.setAccountPicture", image_url); } } #endif