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