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
PersonalOptionsHandler()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
~PersonalOptionsHandler()63 PersonalOptionsHandler::~PersonalOptionsHandler() {
64 ProfileSyncService* sync_service =
65 web_ui_->GetProfile()->GetProfileSyncService();
66 if (sync_service)
67 sync_service->RemoveObserver(this);
68 }
69
GetLocalizedValues(DictionaryValue * localized_strings)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
RegisterMessages()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
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)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
OnStateChanged()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
OnLoginSuccess()323 void PersonalOptionsHandler::OnLoginSuccess() {
324 OnStateChanged();
325 }
326
OnLoginFailure(const GoogleServiceAuthError & error)327 void PersonalOptionsHandler::OnLoginFailure(
328 const GoogleServiceAuthError& error) {
329 OnStateChanged();
330 }
331
ObserveThemeChanged()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
Initialize()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
ShowSyncActionDialog(const ListValue * args)378 void PersonalOptionsHandler::ShowSyncActionDialog(const ListValue* args) {
379 ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
380 DCHECK(service);
381 service->ShowErrorUI(NULL);
382 }
383
ShowSyncLoginDialog(const ListValue * args)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
ShowCustomizeSyncDialog(const ListValue * args)391 void PersonalOptionsHandler::ShowCustomizeSyncDialog(const ListValue* args) {
392 ProfileSyncService* service = web_ui_->GetProfile()->GetProfileSyncService();
393 DCHECK(service);
394 service->ShowConfigure(NULL, false);
395 }
396
ThemesReset(const ListValue * args)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)
ThemesSetGTK(const ListValue * args)403 void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) {
404 UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet"));
405 ThemeServiceFactory::GetForProfile(web_ui_->GetProfile())->SetNativeTheme();
406 }
407 #endif
408
OnPreferredDataTypesUpdated(const ListValue * args)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)
LoadAccountPicture(const ListValue * args)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