OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/bind.h" | |
11 #include "base/command_line.h" | |
12 #include "base/path_service.h" | |
13 #include "base/stl_util.h" | |
14 #include "base/string_number_conversions.h" | |
15 #include "base/utf_string_conversions.h" | |
16 #include "base/value_conversions.h" | |
17 #include "base/values.h" | |
18 #include "build/build_config.h" | |
19 #include "chrome/browser/browser_process.h" | |
20 #include "chrome/browser/profiles/profile.h" | |
21 #include "chrome/browser/profiles/profile_info_cache.h" | |
22 #include "chrome/browser/profiles/profile_info_util.h" | |
23 #include "chrome/browser/profiles/profile_manager.h" | |
24 #include "chrome/browser/sync/profile_sync_service.h" | |
25 #include "chrome/browser/sync/profile_sync_service_factory.h" | |
26 #include "chrome/browser/sync/sync_setup_flow.h" | |
27 #include "chrome/browser/sync/sync_ui_util.h" | |
28 #include "chrome/browser/themes/theme_service.h" | |
29 #include "chrome/browser/themes/theme_service_factory.h" | |
30 #include "chrome/browser/ui/webui/web_ui_util.h" | |
31 #include "chrome/common/chrome_notification_types.h" | |
32 #include "chrome/common/chrome_paths.h" | |
33 #include "chrome/common/chrome_switches.h" | |
34 #include "chrome/common/net/gaia/google_service_auth_error.h" | |
35 #include "chrome/common/url_constants.h" | |
36 #include "content/public/browser/notification_service.h" | |
37 #include "content/public/browser/user_metrics.h" | |
38 #include "content/public/browser/web_contents.h" | |
39 #include "grit/chromium_strings.h" | |
40 #include "grit/generated_resources.h" | |
41 #include "grit/locale_settings.h" | |
42 #include "grit/theme_resources.h" | |
43 #include "ui/base/l10n/l10n_util.h" | |
44 | |
45 #if defined(OS_CHROMEOS) | |
46 #include "chrome/browser/chromeos/login/user_manager.h" | |
47 #include "chrome/browser/chromeos/options/take_photo_dialog.h" | |
48 #include "chrome/browser/ui/browser_window.h" | |
49 #include "chrome/browser/ui/views/window.h" | |
50 #include "third_party/skia/include/core/SkBitmap.h" | |
51 #endif // defined(OS_CHROMEOS) | |
52 #if defined(TOOLKIT_GTK) | |
53 #include "chrome/browser/ui/gtk/theme_service_gtk.h" | |
54 #endif // defined(TOOLKIT_GTK) | |
55 | |
56 using content::UserMetricsAction; | |
57 | |
58 PersonalOptionsHandler::PersonalOptionsHandler() { | |
59 multiprofile_ = ProfileManager::IsMultipleProfilesEnabled(); | |
60 #if defined(OS_CHROMEOS) | |
61 registrar_.Add(this, | |
62 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, | |
63 content::NotificationService::AllSources()); | |
64 #endif | |
65 } | |
66 | |
67 PersonalOptionsHandler::~PersonalOptionsHandler() { | |
68 ProfileSyncService* sync_service(ProfileSyncServiceFactory:: | |
69 GetInstance()->GetForProfile(Profile::FromWebUI(web_ui()))); | |
70 if (sync_service) | |
71 sync_service->RemoveObserver(this); | |
72 } | |
73 | |
74 void PersonalOptionsHandler::GetLocalizedValues( | |
75 DictionaryValue* localized_strings) { | |
76 DCHECK(localized_strings); | |
77 | |
78 RegisterTitle(localized_strings, "personalPage", | |
79 IDS_OPTIONS_CONTENT_TAB_LABEL); | |
80 | |
81 | |
82 localized_strings->SetString( | |
83 "syncOverview", | |
84 l10n_util::GetStringFUTF16(IDS_SYNC_OVERVIEW, | |
85 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | |
86 localized_strings->SetString("syncSection", | |
87 l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME)); | |
88 localized_strings->SetString("customizeSync", | |
89 l10n_util::GetStringUTF16(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL)); | |
90 localized_strings->SetString("syncLearnMoreURL", chrome::kSyncLearnMoreURL); | |
91 | |
92 localized_strings->SetString("profiles", | |
93 l10n_util::GetStringUTF16(IDS_PROFILES_OPTIONS_GROUP_NAME)); | |
94 localized_strings->SetString("profilesCreate", | |
95 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_BUTTON_LABEL)); | |
96 localized_strings->SetString("profilesManage", | |
97 l10n_util::GetStringUTF16(IDS_PROFILES_MANAGE_BUTTON_LABEL)); | |
98 localized_strings->SetString("profilesDelete", | |
99 l10n_util::GetStringUTF16(IDS_PROFILES_DELETE_BUTTON_LABEL)); | |
100 localized_strings->SetString("profilesDeleteSingle", | |
101 l10n_util::GetStringUTF16(IDS_PROFILES_DELETE_SINGLE_BUTTON_LABEL)); | |
102 localized_strings->SetString("profilesListItemCurrent", | |
103 l10n_util::GetStringUTF16(IDS_PROFILES_LIST_ITEM_CURRENT)); | |
104 localized_strings->SetString("profilesSingleUser", | |
105 l10n_util::GetStringFUTF16(IDS_PROFILES_SINGLE_USER_MESSAGE, | |
106 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | |
107 | |
108 localized_strings->SetString("passwords", | |
109 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_GROUP_NAME)); | |
110 localized_strings->SetString("passwordsAskToSave", | |
111 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_ASKTOSAVE)); | |
112 localized_strings->SetString("passwordsNeverSave", | |
113 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_NEVERSAVE)); | |
114 localized_strings->SetString("manage_passwords", | |
115 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS)); | |
116 #if defined(OS_MACOSX) | |
117 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
118 if (profile_manager->GetNumberOfProfiles() > 1) { | |
119 localized_strings->SetString("macPasswordsWarning", | |
120 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MAC_WARNING)); | |
121 } | |
122 #endif | |
123 localized_strings->SetString("autologinEnabled", | |
124 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_AUTOLOGIN)); | |
125 | |
126 localized_strings->SetString("autofill", | |
127 l10n_util::GetStringUTF16(IDS_AUTOFILL_SETTING_WINDOWS_GROUP_NAME)); | |
128 localized_strings->SetString("autofillEnabled", | |
129 l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOFILL_ENABLE)); | |
130 localized_strings->SetString("manageAutofillSettings", | |
131 l10n_util::GetStringUTF16(IDS_OPTIONS_MANAGE_AUTOFILL_SETTINGS)); | |
132 | |
133 localized_strings->SetString("browsingData", | |
134 l10n_util::GetStringUTF16(IDS_OPTIONS_BROWSING_DATA_GROUP_NAME)); | |
135 localized_strings->SetString("importData", | |
136 l10n_util::GetStringUTF16(IDS_OPTIONS_IMPORT_DATA_BUTTON)); | |
137 | |
138 localized_strings->SetString("themesGallery", | |
139 l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON)); | |
140 localized_strings->SetString("themesGalleryURL", | |
141 l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_URL)); | |
142 | |
143 #if defined(TOOLKIT_GTK) | |
144 localized_strings->SetString("appearance", | |
145 l10n_util::GetStringUTF16(IDS_APPEARANCE_GROUP_NAME)); | |
146 localized_strings->SetString("themesGTKButton", | |
147 l10n_util::GetStringUTF16(IDS_THEMES_GTK_BUTTON)); | |
148 localized_strings->SetString("themesSetClassic", | |
149 l10n_util::GetStringUTF16(IDS_THEMES_SET_CLASSIC)); | |
150 localized_strings->SetString("showWindowDecorations", | |
151 l10n_util::GetStringUTF16(IDS_SHOW_WINDOW_DECORATIONS)); | |
152 localized_strings->SetString("hideWindowDecorations", | |
153 l10n_util::GetStringUTF16(IDS_HIDE_WINDOW_DECORATIONS)); | |
154 #else | |
155 localized_strings->SetString("themes", | |
156 l10n_util::GetStringUTF16(IDS_THEMES_GROUP_NAME)); | |
157 localized_strings->SetString("themesReset", | |
158 l10n_util::GetStringUTF16(IDS_THEMES_RESET_BUTTON)); | |
159 #endif | |
160 | |
161 // Sync select control. | |
162 ListValue* sync_select_list = new ListValue; | |
163 ListValue* datatypes = new ListValue; | |
164 datatypes->Append(Value::CreateBooleanValue(false)); | |
165 datatypes->Append( | |
166 Value::CreateStringValue( | |
167 l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_DATATYPES))); | |
168 sync_select_list->Append(datatypes); | |
169 ListValue* everything = new ListValue; | |
170 everything->Append(Value::CreateBooleanValue(true)); | |
171 everything->Append( | |
172 Value::CreateStringValue( | |
173 l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_SELECT_EVERYTHING))); | |
174 sync_select_list->Append(everything); | |
175 localized_strings->Set("syncSelectList", sync_select_list); | |
176 | |
177 // Sync page. | |
178 localized_strings->SetString("syncPage", | |
179 l10n_util::GetStringUTF16(IDS_SYNC_NTP_SYNC_SECTION_TITLE)); | |
180 localized_strings->SetString("sync_title", | |
181 l10n_util::GetStringUTF16(IDS_CUSTOMIZE_SYNC_DESCRIPTION)); | |
182 localized_strings->SetString("syncsettings", | |
183 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES)); | |
184 localized_strings->SetString("syncbookmarks", | |
185 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS)); | |
186 localized_strings->SetString("synctypedurls", | |
187 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS)); | |
188 localized_strings->SetString("syncpasswords", | |
189 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS)); | |
190 localized_strings->SetString("syncextensions", | |
191 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS)); | |
192 localized_strings->SetString("syncautofill", | |
193 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL)); | |
194 localized_strings->SetString("syncthemes", | |
195 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES)); | |
196 localized_strings->SetString("syncapps", | |
197 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS)); | |
198 localized_strings->SetString("syncsessions", | |
199 l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TABS)); | |
200 | |
201 #if defined(OS_CHROMEOS) | |
202 localized_strings->SetString("account", | |
203 l10n_util::GetStringUTF16(IDS_OPTIONS_PERSONAL_ACCOUNT_GROUP_NAME)); | |
204 localized_strings->SetString("enableScreenlock", | |
205 l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SCREENLOCKER_CHECKBOX)); | |
206 localized_strings->SetString("changePicture", | |
207 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE)); | |
208 if (chromeos::UserManager::Get()->IsUserLoggedIn()) { | |
209 localized_strings->SetString("username", | |
210 chromeos::UserManager::Get()->GetLoggedInUser().email()); | |
211 } | |
212 #endif | |
213 } | |
214 | |
215 void PersonalOptionsHandler::RegisterMessages() { | |
216 web_ui()->RegisterMessageCallback( | |
217 "themesReset", | |
218 base::Bind(&PersonalOptionsHandler::ThemesReset, | |
219 base::Unretained(this))); | |
220 #if defined(TOOLKIT_GTK) | |
221 web_ui()->RegisterMessageCallback( | |
222 "themesSetGTK", | |
223 base::Bind(&PersonalOptionsHandler::ThemesSetGTK, | |
224 base::Unretained(this))); | |
225 #endif | |
226 web_ui()->RegisterMessageCallback( | |
227 "createProfile", | |
228 base::Bind(&PersonalOptionsHandler::CreateProfile, | |
229 base::Unretained(this))); | |
230 } | |
231 | |
232 void PersonalOptionsHandler::Observe( | |
233 int type, | |
234 const content::NotificationSource& source, | |
235 const content::NotificationDetails& details) { | |
236 if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) { | |
237 ObserveThemeChanged(); | |
238 } else if (multiprofile_ && | |
239 type == chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED) { | |
240 SendProfilesInfo(); | |
241 #if defined(OS_CHROMEOS) | |
242 } else if (type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) { | |
243 UpdateAccountPicture(); | |
244 #endif | |
245 } else { | |
246 OptionsPageUIHandler::Observe(type, source, details); | |
247 } | |
248 } | |
249 | |
250 void PersonalOptionsHandler::OnStateChanged() { | |
251 string16 status_label; | |
252 string16 link_label; | |
253 ProfileSyncService* service(ProfileSyncServiceFactory:: | |
254 GetInstance()->GetForProfile(Profile::FromWebUI(web_ui()))); | |
255 DCHECK(service); | |
256 bool managed = service->IsManaged(); | |
257 bool sync_setup_completed = service->HasSyncSetupCompleted(); | |
258 bool status_has_error = sync_ui_util::GetStatusLabels( | |
259 service, sync_ui_util::WITH_HTML, &status_label, &link_label) == | |
260 sync_ui_util::SYNC_ERROR; | |
261 | |
262 string16 start_stop_button_label; | |
263 bool is_start_stop_button_visible = false; | |
264 bool is_start_stop_button_enabled = false; | |
265 if (sync_setup_completed) { | |
266 start_stop_button_label = | |
267 l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_BUTTON_LABEL); | |
268 #if defined(OS_CHROMEOS) | |
269 is_start_stop_button_visible = false; | |
270 #else | |
271 is_start_stop_button_visible = true; | |
272 #endif // defined(OS_CHROMEOS) | |
273 is_start_stop_button_enabled = !managed; | |
274 } else if (service->SetupInProgress()) { | |
275 start_stop_button_label = | |
276 l10n_util::GetStringUTF16(IDS_SYNC_NTP_SETUP_IN_PROGRESS); | |
277 is_start_stop_button_visible = true; | |
278 is_start_stop_button_enabled = false; | |
279 } else { | |
280 start_stop_button_label = | |
281 l10n_util::GetStringFUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL, | |
282 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); | |
283 is_start_stop_button_visible = true; | |
284 is_start_stop_button_enabled = !managed; | |
285 } | |
286 | |
287 scoped_ptr<Value> completed(Value::CreateBooleanValue(sync_setup_completed)); | |
288 web_ui()->CallJavascriptFunction("PersonalOptions.setSyncSetupCompleted", | |
289 *completed); | |
290 | |
291 scoped_ptr<Value> label(Value::CreateStringValue(status_label)); | |
292 web_ui()->CallJavascriptFunction("PersonalOptions.setSyncStatus", *label); | |
293 | |
294 scoped_ptr<Value> enabled( | |
295 Value::CreateBooleanValue(is_start_stop_button_enabled)); | |
296 web_ui()->CallJavascriptFunction("PersonalOptions.setStartStopButtonEnabled", | |
297 *enabled); | |
298 | |
299 scoped_ptr<Value> visible( | |
300 Value::CreateBooleanValue(is_start_stop_button_visible)); | |
301 web_ui()->CallJavascriptFunction("PersonalOptions.setStartStopButtonVisible", | |
302 *visible); | |
303 | |
304 label.reset(Value::CreateStringValue(start_stop_button_label)); | |
305 web_ui()->CallJavascriptFunction("PersonalOptions.setStartStopButtonLabel", | |
306 *label); | |
307 | |
308 label.reset(Value::CreateStringValue(link_label)); | |
309 web_ui()->CallJavascriptFunction("PersonalOptions.setSyncActionLinkLabel", | |
310 *label); | |
311 | |
312 enabled.reset(Value::CreateBooleanValue(!managed)); | |
313 web_ui()->CallJavascriptFunction("PersonalOptions.setSyncActionLinkEnabled", | |
314 *enabled); | |
315 | |
316 visible.reset(Value::CreateBooleanValue(status_has_error)); | |
317 web_ui()->CallJavascriptFunction("PersonalOptions.setSyncStatusErrorVisible", | |
318 *visible); | |
319 | |
320 enabled.reset(Value::CreateBooleanValue( | |
321 !service->unrecoverable_error_detected())); | |
322 web_ui()->CallJavascriptFunction( | |
323 "PersonalOptions.setCustomizeSyncButtonEnabled", | |
324 *enabled); | |
325 | |
326 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin)) { | |
327 visible.reset(Value::CreateBooleanValue( | |
328 service->AreCredentialsAvailable())); | |
329 web_ui()->CallJavascriptFunction("PersonalOptions.setAutoLoginVisible", | |
330 *visible); | |
331 } | |
332 | |
333 // Set profile creation text and button if multi-profiles switch is on. | |
334 visible.reset(Value::CreateBooleanValue(multiprofile_)); | |
335 web_ui()->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible", | |
336 *visible); | |
337 if (multiprofile_) | |
338 SendProfilesInfo(); | |
339 } | |
340 | |
341 void PersonalOptionsHandler::ObserveThemeChanged() { | |
342 Profile* profile = Profile::FromWebUI(web_ui()); | |
343 #if defined(TOOLKIT_GTK) | |
344 ThemeServiceGtk* theme_service = ThemeServiceGtk::GetFrom(profile); | |
345 bool is_gtk_theme = theme_service->UsingNativeTheme(); | |
346 base::FundamentalValue gtk_enabled(!is_gtk_theme); | |
347 web_ui()->CallJavascriptFunction( | |
348 "options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled); | |
349 #else | |
350 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile); | |
351 bool is_gtk_theme = false; | |
352 #endif | |
353 | |
354 bool is_classic_theme = !is_gtk_theme && theme_service->UsingDefaultTheme(); | |
355 base::FundamentalValue enabled(!is_classic_theme); | |
356 web_ui()->CallJavascriptFunction( | |
357 "options.PersonalOptions.setThemesResetButtonEnabled", enabled); | |
358 } | |
359 | |
360 void PersonalOptionsHandler::InitializeHandler() { | |
361 Profile* profile = Profile::FromWebUI(web_ui()); | |
362 | |
363 // Listen for theme installation. | |
364 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | |
365 content::Source<ThemeService>( | |
366 ThemeServiceFactory::GetForProfile(profile))); | |
367 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, | |
368 content::NotificationService::AllSources()); | |
369 ObserveThemeChanged(); | |
370 | |
371 ProfileSyncService* sync_service(ProfileSyncServiceFactory:: | |
372 GetInstance()->GetForProfile(profile)); | |
373 if (sync_service) { | |
374 sync_service->AddObserver(this); | |
375 OnStateChanged(); | |
376 } else { | |
377 web_ui()->CallJavascriptFunction("options.PersonalOptions.hideSyncSection"); | |
378 } | |
379 } | |
380 | |
381 void PersonalOptionsHandler::ThemesReset(const ListValue* args) { | |
382 content::RecordAction(UserMetricsAction("Options_ThemesReset")); | |
383 Profile* profile = Profile::FromWebUI(web_ui()); | |
384 ThemeServiceFactory::GetForProfile(profile)->UseDefaultTheme(); | |
385 } | |
386 | |
387 #if defined(TOOLKIT_GTK) | |
388 void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) { | |
389 content::RecordAction(UserMetricsAction("Options_GtkThemeSet")); | |
390 Profile* profile = Profile::FromWebUI(web_ui()); | |
391 ThemeServiceFactory::GetForProfile(profile)->SetNativeTheme(); | |
392 } | |
393 #endif | |
394 | |
395 #if defined(OS_CHROMEOS) | |
396 void PersonalOptionsHandler::UpdateAccountPicture() { | |
397 std::string email = chromeos::UserManager::Get()->GetLoggedInUser().email(); | |
398 if (!email.empty()) { | |
399 web_ui()->CallJavascriptFunction("PersonalOptions.updateAccountPicture"); | |
400 base::StringValue email_value(email); | |
401 web_ui()->CallJavascriptFunction("AccountsOptions.updateAccountPicture", | |
402 email_value); | |
403 } | |
404 } | |
405 #endif | |
406 | |
407 void PersonalOptionsHandler::SendProfilesInfo() { | |
408 ProfileInfoCache& cache = | |
409 g_browser_process->profile_manager()->GetProfileInfoCache(); | |
410 ListValue profile_info_list; | |
411 FilePath current_profile_path = | |
412 web_ui()->GetWebContents()->GetBrowserContext()->GetPath(); | |
413 for (size_t i = 0, e = cache.GetNumberOfProfiles(); i < e; ++i) { | |
414 DictionaryValue* profile_value = new DictionaryValue(); | |
415 FilePath profile_path = cache.GetPathOfProfileAtIndex(i); | |
416 profile_value->SetString("name", cache.GetNameOfProfileAtIndex(i)); | |
417 profile_value->Set("filePath", base::CreateFilePathValue(profile_path)); | |
418 profile_value->SetBoolean("isCurrentProfile", | |
419 profile_path == current_profile_path); | |
420 | |
421 bool is_gaia_picture = | |
422 cache.IsUsingGAIAPictureOfProfileAtIndex(i) && | |
423 cache.GetGAIAPictureOfProfileAtIndex(i); | |
424 if (is_gaia_picture) { | |
425 gfx::Image icon = profiles::GetAvatarIconForWebUI( | |
426 cache.GetAvatarIconOfProfileAtIndex(i), true); | |
427 profile_value->SetString("iconURL", web_ui_util::GetImageDataUrl(icon)); | |
428 } else { | |
429 size_t icon_index = cache.GetAvatarIconIndexOfProfileAtIndex(i); | |
430 profile_value->SetString("iconURL", | |
431 cache.GetDefaultAvatarIconUrl(icon_index)); | |
432 } | |
433 | |
434 profile_info_list.Append(profile_value); | |
435 } | |
436 | |
437 web_ui()->CallJavascriptFunction("PersonalOptions.setProfilesInfo", | |
438 profile_info_list); | |
439 } | |
440 | |
441 void PersonalOptionsHandler::CreateProfile(const ListValue* args) { | |
442 ProfileManager::CreateMultiProfileAsync(); | |
443 } | |
OLD | NEW |