summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/webui/options2
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/webui/options2')
-rw-r--r--chrome/browser/ui/webui/options2/OWNERS4
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_browsertest.js63
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_handler.cc641
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_handler.h182
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_utils.h25
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_utils_mac.mm41
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_utils_win.cc68
-rw-r--r--chrome/browser/ui/webui/options2/advanced_options_utils_x11.cc140
-rw-r--r--chrome/browser/ui/webui/options2/autofill_options_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/autofill_options_handler.cc614
-rw-r--r--chrome/browser/ui/webui/options2/autofill_options_handler.h89
-rw-r--r--chrome/browser/ui/webui/options2/browser_options_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/browser_options_handler.cc494
-rw-r--r--chrome/browser/ui/webui/options2/browser_options_handler.h136
-rw-r--r--chrome/browser/ui/webui/options2/certificate_manager_browsertest.js33
-rw-r--r--chrome/browser/ui/webui/options2/certificate_manager_handler.cc1046
-rw-r--r--chrome/browser/ui/webui/options2/certificate_manager_handler.h171
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/about_page_handler.cc419
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/about_page_handler.h74
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.cc132
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h40
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.cc411
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.h138
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.cc344
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.h113
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.cc268
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.h53
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.cc242
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h73
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/guest_mode_options_ui_uitest.cc43
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/internet_options_handler.cc1372
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/internet_options_handler.h148
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.cc103
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.h35
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.cc79
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.h30
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.cc47
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.h38
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.cc70
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.h34
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_options_util.cc18
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_options_util.h83
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.cc67
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.h34
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/proxy_handler.cc86
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/proxy_handler.h33
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/stats_options_handler.cc45
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/stats_options_handler.h38
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/system_options_handler.cc170
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/system_options_handler.h50
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/system_settings_provider.cc331
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h76
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/user_image_source.cc53
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/user_image_source.h44
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.cc237
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.h78
-rw-r--r--chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler_unittest.cc550
-rw-r--r--chrome/browser/ui/webui/options2/clear_browser_data_handler.cc143
-rw-r--r--chrome/browser/ui/webui/options2/clear_browser_data_handler.h45
-rw-r--r--chrome/browser/ui/webui/options2/content_options_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/content_settings_exception_area_browsertest.js26
-rw-r--r--chrome/browser/ui/webui/options2/content_settings_handler.cc877
-rw-r--r--chrome/browser/ui/webui/options2/content_settings_handler.h113
-rw-r--r--chrome/browser/ui/webui/options2/cookies_view_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/cookies_view_handler.cc222
-rw-r--r--chrome/browser/ui/webui/options2/cookies_view_handler.h69
-rw-r--r--chrome/browser/ui/webui/options2/core_options_handler.cc464
-rw-r--r--chrome/browser/ui/webui/options2/core_options_handler.h151
-rw-r--r--chrome/browser/ui/webui/options2/extension_settings_handler.cc785
-rw-r--r--chrome/browser/ui/webui/options2/extension_settings_handler.h200
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_handler.cc211
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_handler.h55
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_utils.h22
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_utils_mac.mm38
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_utils_win.cc11
-rw-r--r--chrome/browser/ui/webui/options2/font_settings_utils_x11.cc10
-rw-r--r--chrome/browser/ui/webui/options2/handler_options_handler.cc207
-rw-r--r--chrome/browser/ui/webui/options2/handler_options_handler.h76
-rw-r--r--chrome/browser/ui/webui/options2/import_data_handler.cc177
-rw-r--r--chrome/browser/ui/webui/options2/import_data_handler.h59
-rw-r--r--chrome/browser/ui/webui/options2/language_options_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/language_options_handler.cc116
-rw-r--r--chrome/browser/ui/webui/options2/language_options_handler.h44
-rw-r--r--chrome/browser/ui/webui/options2/language_options_handler_common.cc163
-rw-r--r--chrome/browser/ui/webui/options2/language_options_handler_common.h69
-rw-r--r--chrome/browser/ui/webui/options2/language_options_handler_unittest.cc198
-rw-r--r--chrome/browser/ui/webui/options2/manage_profile_handler.cc300
-rw-r--r--chrome/browser/ui/webui/options2/manage_profile_handler.h82
-rw-r--r--chrome/browser/ui/webui/options2/options_browsertest.js93
-rw-r--r--chrome/browser/ui/webui/options2/options_sync_setup_handler.cc37
-rw-r--r--chrome/browser/ui/webui/options2/options_sync_setup_handler.h21
-rw-r--r--chrome/browser/ui/webui/options2/options_ui.cc369
-rw-r--r--chrome/browser/ui/webui/options2/options_ui.h111
-rw-r--r--chrome/browser/ui/webui/options2/options_ui_uitest.cc65
-rw-r--r--chrome/browser/ui/webui/options2/options_ui_uitest.h38
-rw-r--r--chrome/browser/ui/webui/options2/pack_extension_handler.cc101
-rw-r--r--chrome/browser/ui/webui/options2/pack_extension_handler.h49
-rw-r--r--chrome/browser/ui/webui/options2/password_manager_browsertest.js25
-rw-r--r--chrome/browser/ui/webui/options2/password_manager_handler.cc291
-rw-r--r--chrome/browser/ui/webui/options2/password_manager_handler.h129
-rw-r--r--chrome/browser/ui/webui/options2/personal_options_browsertest.js24
-rw-r--r--chrome/browser/ui/webui/options2/personal_options_handler.cc442
-rw-r--r--chrome/browser/ui/webui/options2/personal_options_handler.h70
-rw-r--r--chrome/browser/ui/webui/options2/search_engine_manager_browsertest.js33
-rw-r--r--chrome/browser/ui/webui/options2/search_engine_manager_handler.cc313
-rw-r--r--chrome/browser/ui/webui/options2/search_engine_manager_handler.h79
-rw-r--r--chrome/browser/ui/webui/options2/stop_syncing_handler.cc54
-rw-r--r--chrome/browser/ui/webui/options2/stop_syncing_handler.h29
-rw-r--r--chrome/browser/ui/webui/options2/web_intents_settings_handler.cc160
-rw-r--r--chrome/browser/ui/webui/options2/web_intents_settings_handler.h77
111 files changed, 17733 insertions, 0 deletions
diff --git a/chrome/browser/ui/webui/options2/OWNERS b/chrome/browser/ui/webui/options2/OWNERS
new file mode 100644
index 0000000..67257e6
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/OWNERS
@@ -0,0 +1,4 @@
+csilv@chromium.org
+estade@chromium.org
+jhawkins@chromium.org
+stuartmorgan@chromium.org
diff --git a/chrome/browser/ui/webui/options2/advanced_options_browsertest.js b/chrome/browser/ui/webui/options2/advanced_options_browsertest.js
new file mode 100644
index 0000000..a929bbb
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_browsertest.js
@@ -0,0 +1,63 @@
+// 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.
+
+/**
+ * TestFixture for advanced options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function AdvancedOptionsWebUITest() {}
+
+AdvancedOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to advanced options.
+ **/
+ browsePreload: 'chrome://settings/advanced',
+
+ /**
+ * Register a mock handler.
+ * @type {Function}
+ * @override
+ */
+ preLoad: function() {
+ this.makeAndRegisterMockHandler(['defaultZoomFactorAction']);
+ },
+};
+
+/**
+ * The expected minimum length of the |defaultZoomFactor| element.
+ * @type {number}
+ * @const
+ */
+var defaultZoomFactorMinimumLength = 10;
+
+/**
+ * Test opening the advanced options has correct location.
+ */
+TEST_F('AdvancedOptionsWebUITest', 'testOpenAdvancedOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
+
+/**
+ * Test the default zoom factor select element.
+ */
+TEST_F('AdvancedOptionsWebUITest', 'testDefaultZoomFactor', function() {
+ // Verify that the zoom factor element exists.
+ var defaultZoomFactor = $('defaultZoomFactor');
+ assertNotEquals(defaultZoomFactor, null);
+
+ // Verify that the zoom factor element has a reasonable number of choices.
+ expectGE(defaultZoomFactor.options.length, defaultZoomFactorMinimumLength);
+
+ // Simulate a change event, selecting the highest zoom value. Verify that
+ // the javascript handler was invoked once.
+ this.mockHandler.expects(once()).defaultZoomFactorAction(NOT_NULL).
+ will(callFunction(function() { }));
+ defaultZoomFactor.selectedIndex = defaultZoomFactor.options.length - 1;
+ var event = { target: defaultZoomFactor };
+ if (defaultZoomFactor.onchange) defaultZoomFactor.onchange(event);
+});
+
diff --git a/chrome/browser/ui/webui/options2/advanced_options_handler.cc b/chrome/browser/ui/webui/options2/advanced_options_handler.cc
new file mode 100644
index 0000000..8bb8ee0
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_handler.cc
@@ -0,0 +1,641 @@
+// 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/options2/advanced_options_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_page_zoom.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_url.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/service/service_process_control.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/download/download_manager.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/common/page_zoom.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(OS_CHROMEOS)
+#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
+#include "chrome/browser/ui/webui/options2/advanced_options_utils.h"
+#endif
+
+AdvancedOptionsHandler::AdvancedOptionsHandler() {
+
+#if(!defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
+ // On Windows, we need the PDF plugin which is only guaranteed to exist on
+ // Google Chrome builds. Use a command-line switch for Windows non-Google
+ // Chrome builds.
+ cloud_print_proxy_ui_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCloudPrintProxy);
+#elif(!defined(OS_CHROMEOS))
+ // Always enabled for Mac, Linux and Google Chrome Windows builds.
+ // Never enabled for Chrome OS, we don't even need to indicate it.
+ cloud_print_proxy_ui_enabled_ = true;
+#endif
+}
+
+AdvancedOptionsHandler::~AdvancedOptionsHandler() {
+ // There may be pending file dialogs, we need to tell them that we've gone
+ // away so they don't try and call back to us.
+ if (select_folder_dialog_.get())
+ select_folder_dialog_->ListenerDestroyed();
+}
+
+void AdvancedOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "downloadLocationGroupName",
+ IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME },
+ { "downloadLocationChangeButton",
+ IDS_OPTIONS_DOWNLOADLOCATION_CHANGE_BUTTON },
+ { "downloadLocationBrowseTitle",
+ IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE },
+ { "downloadLocationBrowseWindowTitle",
+ IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_WINDOW_TITLE },
+ { "downloadLocationAskForSaveLocation",
+ IDS_OPTIONS_DOWNLOADLOCATION_ASKFORSAVELOCATION },
+ { "autoOpenFileTypesInfo",
+ IDS_OPTIONS_OPEN_FILE_TYPES_AUTOMATICALLY },
+ { "autoOpenFileTypesResetToDefault",
+ IDS_OPTIONS_AUTOOPENFILETYPES_RESETTODEFAULT },
+ { "translateEnableTranslate",
+ IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE },
+ { "certificatesManageButton",
+ IDS_OPTIONS_CERTIFICATES_MANAGE_BUTTON },
+ { "proxiesLabel",
+ IDS_OPTIONS_PROXIES_LABEL },
+#if !defined(OS_CHROMEOS)
+ { "proxiesConfigureButton",
+ IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON },
+#endif
+ { "safeBrowsingEnableProtection",
+ IDS_OPTIONS_SAFEBROWSING_ENABLEPROTECTION },
+ { "sslGroupDescription",
+ IDS_OPTIONS_SSL_GROUP_DESCRIPTION },
+ { "sslCheckRevocation",
+ IDS_OPTIONS_SSL_CHECKREVOCATION },
+ { "networkPredictionEnabledDescription",
+ IDS_NETWORK_PREDICTION_ENABLED_DESCRIPTION },
+ { "privacyContentSettingsButton",
+ IDS_OPTIONS_PRIVACY_CONTENT_SETTINGS_BUTTON },
+ { "privacyClearDataButton",
+ IDS_OPTIONS_PRIVACY_CLEAR_DATA_BUTTON },
+ { "linkDoctorPref",
+ IDS_OPTIONS_LINKDOCTOR_PREF },
+ { "suggestPref",
+ IDS_OPTIONS_SUGGEST_PREF },
+ { "tabsToLinksPref",
+ IDS_OPTIONS_TABS_TO_LINKS_PREF },
+ { "fontSettingsInfo",
+ IDS_OPTIONS_FONTSETTINGS_INFO },
+ { "defaultZoomFactorLabel",
+ IDS_OPTIONS_DEFAULT_ZOOM_LEVEL_LABEL },
+ { "defaultFontSizeLabel",
+ IDS_OPTIONS_DEFAULT_FONT_SIZE_LABEL },
+ { "fontSizeLabelVerySmall",
+ IDS_OPTIONS_FONT_SIZE_LABEL_VERY_SMALL },
+ { "fontSizeLabelSmall",
+ IDS_OPTIONS_FONT_SIZE_LABEL_SMALL },
+ { "fontSizeLabelMedium",
+ IDS_OPTIONS_FONT_SIZE_LABEL_MEDIUM },
+ { "fontSizeLabelLarge",
+ IDS_OPTIONS_FONT_SIZE_LABEL_LARGE },
+ { "fontSizeLabelVeryLarge",
+ IDS_OPTIONS_FONT_SIZE_LABEL_VERY_LARGE },
+ { "fontSizeLabelCustom",
+ IDS_OPTIONS_FONT_SIZE_LABEL_CUSTOM },
+ { "fontSettingsCustomizeFontsButton",
+ IDS_OPTIONS_FONTSETTINGS_CUSTOMIZE_FONTS_BUTTON },
+ { "languageAndSpellCheckSettingsButton",
+ IDS_OPTIONS_LANGUAGE_AND_SPELLCHECK_BUTTON },
+ { "advancedSectionTitlePrivacy",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY },
+ { "advancedSectionTitleContent",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_CONTENT },
+ { "advancedSectionTitleSecurity",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_SECURITY },
+ { "advancedSectionTitleNetwork",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_NETWORK },
+ { "advancedSectionTitleTranslate",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_TRANSLATE },
+ { "translateEnableTranslate",
+ IDS_OPTIONS_TRANSLATE_ENABLE_TRANSLATE },
+ { "enableLogging",
+ IDS_OPTIONS_ENABLE_LOGGING },
+ { "improveBrowsingExperience",
+ IDS_OPTIONS_IMPROVE_BROWSING_EXPERIENCE },
+ { "disableWebServices",
+ IDS_OPTIONS_DISABLE_WEB_SERVICES },
+#if defined(OS_CHROMEOS)
+ { "cloudPrintChromeosOptionLabel",
+ IDS_CLOUD_PRINT_CHROMEOS_OPTION_LABEL },
+ { "cloudPrintChromeosOptionButton",
+ IDS_CLOUD_PRINT_CHROMEOS_OPTION_BUTTON },
+#endif
+ { "cloudPrintOptionsStaticLabel",
+ IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE },
+ { "cloudPrintProxyEnabledManageButton",
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_MANAGE_BUTTON },
+ { "advancedSectionTitleCloudPrint",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_CLOUD_PRINT },
+#if !defined(OS_CHROMEOS)
+ { "cloudPrintProxyDisabledLabel",
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_LABEL },
+ { "cloudPrintProxyDisabledButton",
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_BUTTON },
+ { "cloudPrintProxyEnabledButton",
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_BUTTON },
+ { "cloudPrintProxyEnablingButton",
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLING_BUTTON },
+#endif
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ { "advancedSectionTitleBackground",
+ IDS_OPTIONS_ADVANCED_SECTION_TITLE_BACKGROUND },
+ { "backgroundModeCheckbox",
+ IDS_OPTIONS_BACKGROUND_ENABLE_BACKGROUND_MODE },
+#endif
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "advancedPage",
+ IDS_OPTIONS_ADVANCED_TAB_LABEL);
+
+ localized_strings->SetString("privacyLearnMoreURL",
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kPrivacyLearnMoreURL)).spec());
+
+#if defined(OS_CHROMEOS)
+ localized_strings->SetString("cloudPrintLearnMoreURL",
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kCloudPrintLearnMoreURL)).spec());
+#endif
+}
+
+void AdvancedOptionsHandler::Initialize() {
+ DCHECK(web_ui_);
+ SetupMetricsReportingCheckbox();
+ SetupMetricsReportingSettingVisibility();
+ SetupFontSizeSelector();
+ SetupPageZoomSelector();
+ SetupAutoOpenFileTypesDisabledAttribute();
+ SetupProxySettingsSection();
+ SetupSSLConfigSettings();
+#if !defined(OS_CHROMEOS)
+ if (cloud_print_proxy_ui_enabled_) {
+ SetupCloudPrintProxySection();
+ RefreshCloudPrintStatusFromService();
+ } else {
+ RemoveCloudPrintProxySection();
+ }
+#endif
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ SetupBackgroundModeSettings();
+#endif
+
+}
+
+WebUIMessageHandler* AdvancedOptionsHandler::Attach(WebUI* web_ui) {
+ // Call through to superclass.
+ WebUIMessageHandler* handler = OptionsPage2UIHandler::Attach(web_ui);
+
+ // Register for preferences that we need to observe manually. These have
+ // special behaviors that aren't handled by the standard prefs UI.
+ DCHECK(web_ui_);
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+#if !defined(OS_CHROMEOS)
+ enable_metrics_recording_.Init(prefs::kMetricsReportingEnabled,
+ g_browser_process->local_state(), this);
+ cloud_print_proxy_email_.Init(prefs::kCloudPrintEmail, prefs, this);
+ cloud_print_proxy_enabled_.Init(prefs::kCloudPrintProxyEnabled, prefs, this);
+#endif
+
+ rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled,
+ g_browser_process->local_state(), this);
+
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ background_mode_enabled_.Init(prefs::kBackgroundModeEnabled,
+ g_browser_process->local_state(),
+ this);
+#endif
+
+ auto_open_files_.Init(prefs::kDownloadExtensionsToOpen, prefs, this);
+ default_font_size_.Init(prefs::kWebKitDefaultFontSize, prefs, this);
+ default_zoom_level_.Init(prefs::kDefaultZoomLevel, prefs, this);
+#if !defined(OS_CHROMEOS)
+ proxy_prefs_.reset(
+ PrefSetObserver::CreateProxyPrefSetObserver(prefs, this));
+#endif // !defined(OS_CHROMEOS)
+
+ // Return result from the superclass.
+ return handler;
+}
+
+void AdvancedOptionsHandler::RegisterMessages() {
+ // Setup handlers specific to this panel.
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("selectDownloadLocation",
+ base::Bind(&AdvancedOptionsHandler::HandleSelectDownloadLocation,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("autoOpenFileTypesAction",
+ base::Bind(&AdvancedOptionsHandler::HandleAutoOpenButton,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("defaultFontSizeAction",
+ base::Bind(&AdvancedOptionsHandler::HandleDefaultFontSize,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("defaultZoomFactorAction",
+ base::Bind(&AdvancedOptionsHandler::HandleDefaultZoomFactor,
+ base::Unretained(this)));
+#if !defined(OS_CHROMEOS)
+ web_ui_->RegisterMessageCallback("metricsReportingCheckboxAction",
+ base::Bind(&AdvancedOptionsHandler::HandleMetricsReportingCheckbox,
+ base::Unretained(this)));
+#endif
+#if !defined(USE_NSS) && !defined(USE_OPENSSL)
+ web_ui_->RegisterMessageCallback("showManageSSLCertificates",
+ base::Bind(&AdvancedOptionsHandler::ShowManageSSLCertificates,
+ base::Unretained(this)));
+#endif
+ web_ui_->RegisterMessageCallback("showCloudPrintManagePage",
+ base::Bind(&AdvancedOptionsHandler::ShowCloudPrintManagePage,
+ base::Unretained(this)));
+#if !defined(OS_CHROMEOS)
+ if (cloud_print_proxy_ui_enabled_) {
+ web_ui_->RegisterMessageCallback("showCloudPrintSetupDialog",
+ base::Bind(&AdvancedOptionsHandler::ShowCloudPrintSetupDialog,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("disableCloudPrintProxy",
+ base::Bind(&AdvancedOptionsHandler::HandleDisableCloudPrintProxy,
+ base::Unretained(this)));
+ }
+ web_ui_->RegisterMessageCallback("showNetworkProxySettings",
+ base::Bind(&AdvancedOptionsHandler::ShowNetworkProxySettings,
+ base::Unretained(this)));
+#endif
+ web_ui_->RegisterMessageCallback("checkRevocationCheckboxAction",
+ base::Bind(&AdvancedOptionsHandler::HandleCheckRevocationCheckbox,
+ base::Unretained(this)));
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ web_ui_->RegisterMessageCallback("backgroundModeAction",
+ base::Bind(&AdvancedOptionsHandler::HandleBackgroundModeCheckbox,
+ base::Unretained(this)));
+#endif
+}
+
+void AdvancedOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ std::string* pref_name = content::Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kDownloadExtensionsToOpen) {
+ SetupAutoOpenFileTypesDisabledAttribute();
+#if !defined(OS_CHROMEOS)
+ } else if (proxy_prefs_->IsObserved(*pref_name)) {
+ SetupProxySettingsSection();
+#endif // !defined(OS_CHROMEOS)
+ } else if ((*pref_name == prefs::kCloudPrintEmail) ||
+ (*pref_name == prefs::kCloudPrintProxyEnabled)) {
+#if !defined(OS_CHROMEOS)
+ if (cloud_print_proxy_ui_enabled_)
+ SetupCloudPrintProxySection();
+#endif
+ } else if (*pref_name == prefs::kWebKitDefaultFontSize) {
+ SetupFontSizeSelector();
+ } else if (*pref_name == prefs::kDefaultZoomLevel) {
+ SetupPageZoomSelector();
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ } else if (*pref_name == prefs::kBackgroundModeEnabled) {
+ SetupBackgroundModeSettings();
+#endif
+ }
+ }
+}
+
+void AdvancedOptionsHandler::HandleSelectDownloadLocation(
+ const ListValue* args) {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ select_folder_dialog_ = SelectFileDialog::Create(this);
+ select_folder_dialog_->SelectFile(
+ SelectFileDialog::SELECT_FOLDER,
+ l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE),
+ pref_service->GetFilePath(prefs::kDownloadDefaultDirectory),
+ NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
+ web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+}
+
+void AdvancedOptionsHandler::FileSelected(const FilePath& path, int index,
+ void* params) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_SetDownloadDirectory"));
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ pref_service->SetFilePath(prefs::kDownloadDefaultDirectory, path);
+}
+
+void AdvancedOptionsHandler::OnCloudPrintSetupClosed() {
+#if !defined(OS_CHROMEOS)
+ if (cloud_print_proxy_ui_enabled_)
+ SetupCloudPrintProxySection();
+#endif
+}
+
+void AdvancedOptionsHandler::HandleAutoOpenButton(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_ResetAutoOpenFiles"));
+ DownloadManager* manager =
+ web_ui_->tab_contents()->browser_context()->GetDownloadManager();
+ if (manager)
+ DownloadPrefs::FromDownloadManager(manager)->ResetAutoOpen();
+}
+
+void AdvancedOptionsHandler::HandleMetricsReportingCheckbox(
+ const ListValue* args) {
+#if defined(GOOGLE_CHROME_BUILD) && !defined(OS_CHROMEOS)
+ std::string checked_str = UTF16ToUTF8(ExtractStringValue(args));
+ bool enabled = checked_str == "true";
+ UserMetrics::RecordAction(
+ enabled ?
+ UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
+ UserMetricsAction("Options_MetricsReportingCheckbox_Disable"));
+ bool is_enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled);
+ enable_metrics_recording_.SetValue(is_enabled);
+ SetupMetricsReportingCheckbox();
+#endif
+}
+
+void AdvancedOptionsHandler::HandleDefaultFontSize(const ListValue* args) {
+ int font_size;
+ if (ExtractIntegerValue(args, &font_size)) {
+ if (font_size > 0) {
+ default_font_size_.SetValue(font_size);
+ SetupFontSizeSelector();
+ }
+ }
+}
+
+void AdvancedOptionsHandler::HandleDefaultZoomFactor(const ListValue* args) {
+ double zoom_factor;
+ if (ExtractDoubleValue(args, &zoom_factor)) {
+ default_zoom_level_.SetValue(
+ WebKit::WebView::zoomFactorToZoomLevel(zoom_factor));
+ }
+}
+
+void AdvancedOptionsHandler::HandleCheckRevocationCheckbox(
+ const ListValue* args) {
+ std::string checked_str = UTF16ToUTF8(ExtractStringValue(args));
+ bool enabled = checked_str == "true";
+ UserMetrics::RecordAction(
+ enabled ?
+ UserMetricsAction("Options_CheckCertRevocation_Enable") :
+ UserMetricsAction("Options_CheckCertRevocation_Disable"));
+ rev_checking_enabled_.SetValue(enabled);
+}
+
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+void AdvancedOptionsHandler::HandleBackgroundModeCheckbox(
+ const ListValue* args) {
+ std::string checked_str = UTF16ToUTF8(ExtractStringValue(args));
+ bool enabled = checked_str == "true";
+ UserMetrics::RecordAction(enabled ?
+ UserMetricsAction("Options_BackgroundMode_Enable") :
+ UserMetricsAction("Options_BackgroundMode_Disable"));
+ background_mode_enabled_.SetValue(enabled);
+}
+
+void AdvancedOptionsHandler::SetupBackgroundModeSettings() {
+ base::FundamentalValue checked(background_mode_enabled_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetBackgroundModeCheckboxState", checked);
+}
+#endif
+
+#if !defined(OS_CHROMEOS)
+void AdvancedOptionsHandler::ShowNetworkProxySettings(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_ShowProxySettings"));
+ AdvancedOptionsUtilities::ShowNetworkProxySettings(web_ui_->tab_contents());
+}
+#endif
+
+#if !defined(USE_NSS) && !defined(USE_OPENSSL)
+void AdvancedOptionsHandler::ShowManageSSLCertificates(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_ManageSSLCertificates"));
+ AdvancedOptionsUtilities::ShowManageSSLCertificates(web_ui_->tab_contents());
+}
+#endif
+
+void AdvancedOptionsHandler::ShowCloudPrintManagePage(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_ManageCloudPrinters"));
+ // Open a new tab in the current window for the management page.
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ web_ui_->tab_contents()->OpenURL(
+ CloudPrintURL(profile).GetCloudPrintServiceManageURL(),
+ GURL(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK);
+}
+
+#if !defined(OS_CHROMEOS)
+void AdvancedOptionsHandler::ShowCloudPrintSetupDialog(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_EnableCloudPrintProxy"));
+ // Open the connector enable page in the current tab.
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ web_ui_->tab_contents()->OpenURL(
+ CloudPrintURL(profile).GetCloudPrintServiceEnableURL(
+ CloudPrintProxyServiceFactory::GetForProfile(profile)->proxy_id()),
+ GURL(), CURRENT_TAB, content::PAGE_TRANSITION_LINK);
+}
+
+void AdvancedOptionsHandler::HandleDisableCloudPrintProxy(
+ const ListValue* args) {
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DisableCloudPrintProxy"));
+ CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui_))->
+ DisableForUser();
+}
+
+void AdvancedOptionsHandler::RefreshCloudPrintStatusFromService() {
+ if (cloud_print_proxy_ui_enabled_)
+ CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui_))->
+ RefreshStatusFromService();
+}
+
+void AdvancedOptionsHandler::SetupCloudPrintProxySection() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ if (!CloudPrintProxyServiceFactory::GetForProfile(profile)) {
+ cloud_print_proxy_ui_enabled_ = false;
+ RemoveCloudPrintProxySection();
+ return;
+ }
+
+ bool cloud_print_proxy_allowed =
+ !cloud_print_proxy_enabled_.IsManaged() ||
+ cloud_print_proxy_enabled_.GetValue();
+ base::FundamentalValue allowed(cloud_print_proxy_allowed);
+
+ std::string email;
+ if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
+ cloud_print_proxy_allowed) {
+ email = profile->GetPrefs()->GetString(prefs::kCloudPrintEmail);
+ }
+ base::FundamentalValue disabled(email.empty());
+
+ string16 label_str;
+ if (email.empty()) {
+ label_str = l10n_util::GetStringUTF16(
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_DISABLED_LABEL);
+ } else {
+ label_str = l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_CLOUD_PRINT_PROXY_ENABLED_LABEL, UTF8ToUTF16(email));
+ }
+ StringValue label(label_str);
+
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetupCloudPrintProxySection",
+ disabled, label, allowed);
+}
+
+void AdvancedOptionsHandler::RemoveCloudPrintProxySection() {
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.RemoveCloudPrintProxySection");
+}
+
+#endif
+
+void AdvancedOptionsHandler::SetupMetricsReportingCheckbox() {
+#if defined(GOOGLE_CHROME_BUILD) && !defined(OS_CHROMEOS)
+ base::FundamentalValue checked(enable_metrics_recording_.GetValue());
+ base::FundamentalValue disabled(enable_metrics_recording_.IsManaged());
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetMetricsReportingCheckboxState", checked,
+ disabled);
+#endif
+}
+
+void AdvancedOptionsHandler::SetupMetricsReportingSettingVisibility() {
+#if defined(GOOGLE_CHROME_BUILD) && defined(OS_CHROMEOS)
+ // Don't show the reporting setting if we are in the guest mode.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) {
+ base::FundamentalValue visible(false);
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetMetricsReportingSettingVisibility",
+ visible);
+ }
+#endif
+}
+
+void AdvancedOptionsHandler::SetupFontSizeSelector() {
+ // We're only interested in integer values, so convert to int.
+ base::FundamentalValue font_size(default_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetFontSize", font_size);
+}
+
+void AdvancedOptionsHandler::SetupPageZoomSelector() {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ double default_zoom_level = pref_service->GetDouble(prefs::kDefaultZoomLevel);
+ double default_zoom_factor =
+ WebKit::WebView::zoomLevelToZoomFactor(default_zoom_level);
+
+ // Generate a vector of zoom factors from an array of known presets along with
+ // the default factor added if necessary.
+ std::vector<double> zoom_factors =
+ chrome_page_zoom::PresetZoomFactors(default_zoom_factor);
+
+ // Iterate through the zoom factors and and build the contents of the
+ // selector that will be sent to the javascript handler.
+ // Each item in the list has the following parameters:
+ // 1. Title (string).
+ // 2. Value (double).
+ // 3. Is selected? (bool).
+ ListValue zoom_factors_value;
+ for (std::vector<double>::const_iterator i = zoom_factors.begin();
+ i != zoom_factors.end(); ++i) {
+ ListValue* option = new ListValue();
+ double factor = *i;
+ int percent = static_cast<int>(factor * 100 + 0.5);
+ option->Append(Value::CreateStringValue(
+ l10n_util::GetStringFUTF16Int(IDS_ZOOM_PERCENT, percent)));
+ option->Append(Value::CreateDoubleValue(factor));
+ bool selected = content::ZoomValuesEqual(factor, default_zoom_factor);
+ option->Append(Value::CreateBooleanValue(selected));
+ zoom_factors_value.Append(option);
+ }
+
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetupPageZoomSelector", zoom_factors_value);
+}
+
+void AdvancedOptionsHandler::SetupAutoOpenFileTypesDisabledAttribute() {
+ // Set the enabled state for the AutoOpenFileTypesResetToDefault button.
+ // We enable the button if the user has any auto-open file types registered.
+ DownloadManager* manager =
+ web_ui_->tab_contents()->browser_context()->GetDownloadManager();
+ bool disabled = !(manager &&
+ DownloadPrefs::FromDownloadManager(manager)->IsAutoOpenUsed());
+ base::FundamentalValue value(disabled);
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetAutoOpenFileTypesDisabledAttribute", value);
+}
+
+void AdvancedOptionsHandler::SetupProxySettingsSection() {
+#if !defined(OS_CHROMEOS)
+ // Disable the button if proxy settings are managed by a sysadmin or
+ // overridden by an extension.
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ const PrefService::Preference* proxy_config =
+ pref_service->FindPreference(prefs::kProxy);
+ bool is_extension_controlled = (proxy_config &&
+ proxy_config->IsExtensionControlled());
+
+ base::FundamentalValue disabled(proxy_prefs_->IsManaged() ||
+ is_extension_controlled);
+
+ // Get the appropriate info string to describe the button.
+ string16 label_str;
+ if (is_extension_controlled) {
+ label_str = l10n_util::GetStringUTF16(IDS_OPTIONS_EXTENSION_PROXIES_LABEL);
+ } else {
+ label_str = l10n_util::GetStringFUTF16(IDS_OPTIONS_SYSTEM_PROXIES_LABEL,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+ }
+ StringValue label(label_str);
+
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetupProxySettingsSection", disabled, label);
+#endif // !defined(OS_CHROMEOS)
+}
+
+void AdvancedOptionsHandler::SetupSSLConfigSettings() {
+ {
+ base::FundamentalValue checked(rev_checking_enabled_.GetValue());
+ base::FundamentalValue disabled(rev_checking_enabled_.IsManaged());
+ web_ui_->CallJavascriptFunction(
+ "options.AdvancedOptions.SetCheckRevocationCheckboxState", checked,
+ disabled);
+ }
+}
diff --git a/chrome/browser/ui/webui/options2/advanced_options_handler.h b/chrome/browser/ui/webui/options2/advanced_options_handler.h
new file mode 100644
index 0000000..ed3a49b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_handler.h
@@ -0,0 +1,182 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_setup_handler.h"
+#include "chrome/browser/ui/select_file_dialog.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+#if !defined(OS_CHROMEOS)
+#include "chrome/browser/prefs/pref_set_observer.h"
+#endif // !defined(OS_CHROMEOS)
+
+class CloudPrintSetupHandler;
+
+// Chrome advanced options page UI handler.
+class AdvancedOptionsHandler
+ : public OptionsPage2UIHandler,
+ public SelectFileDialog::Listener,
+ public CloudPrintSetupHandlerDelegate {
+ public:
+ AdvancedOptionsHandler();
+ virtual ~AdvancedOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // SelectFileDialog::Listener implementation
+ virtual void FileSelected(const FilePath& path,
+ int index,
+ void* params) OVERRIDE;
+
+ // CloudPrintSetupHandler::Delegate implementation.
+ virtual void OnCloudPrintSetupClosed() OVERRIDE;
+
+ private:
+ // Callback for the "selectDownloadLocation" message. This will prompt the
+ // user for a destination folder using platform-specific APIs.
+ void HandleSelectDownloadLocation(const ListValue* args);
+
+ // Callback for the "autoOpenFileTypesResetToDefault" message. This will
+ // remove all auto-open file-type settings.
+ void HandleAutoOpenButton(const ListValue* args);
+
+ // Callback for the "metricsReportingCheckboxAction" message. This is called
+ // if the user toggles the metrics reporting checkbox.
+ void HandleMetricsReportingCheckbox(const ListValue* args);
+
+ // Callback for the "defaultFontSizeAction" message. This is called if the
+ // user changes the default font size. |args| is an array that contains
+ // one item, the font size as a numeric value.
+ void HandleDefaultFontSize(const ListValue* args);
+
+ // Callback for the "defaultZoomFactorAction" message. This is called if the
+ // user changes the default zoom factor. |args| is an array that contains
+ // one item, the zoom factor as a numeric value.
+ void HandleDefaultZoomFactor(const ListValue* args);
+
+ // Callback for the "Check for server certificate revocation" checkbox. This
+ // is called if the user toggles the "Check for server certificate revocation"
+ // checkbox.
+ void HandleCheckRevocationCheckbox(const ListValue* args);
+
+ // Callback for the "Use SSL 3.0" checkbox. This is called if the user toggles
+ // the "Use SSL 3.0" checkbox.
+ void HandleUseSSL3Checkbox(const ListValue* args);
+
+ // Callback for the "Use TLS 1.0" checkbox. This is called if the user toggles
+ // the "Use TLS 1.0" checkbox.
+ void HandleUseTLS1Checkbox(const ListValue* args);
+
+#if !defined(OS_CHROMEOS)
+ // Callback for the "showNetworkProxySettings" message. This will invoke
+ // an appropriate dialog for configuring proxy settings.
+ void ShowNetworkProxySettings(const ListValue* args);
+#endif
+
+#if !defined(USE_NSS)
+ // Callback for the "showManageSSLCertificates" message. This will invoke
+ // an appropriate certificate management action based on the platform.
+ void ShowManageSSLCertificates(const ListValue* args);
+#endif
+
+ // Callback for the Cloud Print manage button. This will open a new
+ // tab pointed at the management URL.
+ void ShowCloudPrintManagePage(const ListValue* args);
+
+#if !defined(OS_CHROMEOS)
+ // Callback for the Sign in to Cloud Print button. This will start
+ // the authentication process.
+ void ShowCloudPrintSetupDialog(const ListValue* args);
+
+ // Callback for the Disable Cloud Print button. This will sign out
+ // of cloud print.
+ void HandleDisableCloudPrintProxy(const ListValue* args);
+
+ // Pings the service to send us it's current notion of the enabled state.
+ void RefreshCloudPrintStatusFromService();
+
+ // Setup the enabled or disabled state of the cloud print proxy
+ // management UI.
+ void SetupCloudPrintProxySection();
+
+ // Remove cloud print proxy section if cloud print proxy management UI is
+ // disabled.
+ void RemoveCloudPrintProxySection();
+
+#endif
+
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ // Sets up the checked state for the "Continue running background apps..."
+ // checkbox.
+ void SetupBackgroundModeSettings();
+
+ // Callback for the "Continue running background apps..." checkbox.
+ void HandleBackgroundModeCheckbox(const ListValue* args);
+#endif
+
+ // Setup the checked state for the metrics reporting checkbox.
+ void SetupMetricsReportingCheckbox();
+
+ // Setup the visibility for the metrics reporting setting.
+ void SetupMetricsReportingSettingVisibility();
+
+ // Setup the font size selector control.
+ void SetupFontSizeSelector();
+
+ // Setup the page zoom selector control.
+ void SetupPageZoomSelector();
+
+ // Setup the enabled state of the reset button.
+ void SetupAutoOpenFileTypesDisabledAttribute();
+
+ // Setup the proxy settings section UI.
+ void SetupProxySettingsSection();
+
+ // Setup the checked state for SSL related checkboxes.
+ void SetupSSLConfigSettings();
+
+ scoped_refptr<SelectFileDialog> select_folder_dialog_;
+
+#if !defined(OS_CHROMEOS)
+ BooleanPrefMember enable_metrics_recording_;
+ StringPrefMember cloud_print_proxy_email_;
+ BooleanPrefMember cloud_print_proxy_enabled_;
+ bool cloud_print_proxy_ui_enabled_;
+ scoped_ptr<CloudPrintSetupHandler> cloud_print_setup_handler_;
+#endif
+
+ // SSLConfigService prefs.
+ BooleanPrefMember rev_checking_enabled_;
+
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
+ BooleanPrefMember background_mode_enabled_;
+#endif
+
+ StringPrefMember auto_open_files_;
+ IntegerPrefMember default_font_size_;
+ DoublePrefMember default_zoom_level_;
+
+#if !defined(OS_CHROMEOS)
+ scoped_ptr<PrefSetObserver> proxy_prefs_;
+#endif // !defined(OS_CHROMEOS)
+
+ DISALLOW_COPY_AND_ASSIGN(AdvancedOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/advanced_options_utils.h b/chrome/browser/ui/webui/options2/advanced_options_utils.h
new file mode 100644
index 0000000..edaacf5
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_utils.h
@@ -0,0 +1,25 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_UTILS_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_UTILS_H_
+
+#include "base/basictypes.h"
+
+class TabContents;
+
+// Chrome advanced options utility methods.
+class AdvancedOptionsUtilities {
+ public:
+ // Invoke UI for network proxy settings.
+ static void ShowNetworkProxySettings(TabContents*);
+
+ // Invoke UI for SSL certificates.
+ static void ShowManageSSLCertificates(TabContents*);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AdvancedOptionsUtilities);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_ADVANCED_OPTIONS_UTILS_H_
diff --git a/chrome/browser/ui/webui/options2/advanced_options_utils_mac.mm b/chrome/browser/ui/webui/options2/advanced_options_utils_mac.mm
new file mode 100644
index 0000000..c1e5b52
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_utils_mac.mm
@@ -0,0 +1,41 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/ui/webui/options2/advanced_options_utils.h"
+
+#include "base/logging.h"
+#include "base/mac/scoped_aedesc.h"
+
+void AdvancedOptionsUtilities::ShowNetworkProxySettings(
+ TabContents* tab_contents) {
+ NSArray* itemsToOpen = [NSArray arrayWithObject:[NSURL fileURLWithPath:
+ @"/System/Library/PreferencePanes/Network.prefPane"]];
+
+ const char* proxyPrefCommand = "Proxies";
+ base::mac::ScopedAEDesc<> openParams;
+ OSStatus status = AECreateDesc('ptru',
+ proxyPrefCommand,
+ strlen(proxyPrefCommand),
+ openParams.OutPointer());
+ LOG_IF(ERROR, status != noErr) << "Failed to create open params: " << status;
+
+ LSLaunchURLSpec launchSpec = { 0 };
+ launchSpec.itemURLs = (CFArrayRef)itemsToOpen;
+ launchSpec.passThruParams = openParams;
+ launchSpec.launchFlags = kLSLaunchAsync | kLSLaunchDontAddToRecents;
+ LSOpenFromURLSpec(&launchSpec, NULL);
+}
+
+void AdvancedOptionsUtilities::ShowManageSSLCertificates(
+ TabContents* tab_contents) {
+ NSString* const kKeychainBundleId = @"com.apple.keychainaccess";
+ [[NSWorkspace sharedWorkspace]
+ launchAppWithBundleIdentifier:kKeychainBundleId
+ options:0L
+ additionalEventParamDescriptor:nil
+ launchIdentifier:nil];
+}
+
diff --git a/chrome/browser/ui/webui/options2/advanced_options_utils_win.cc b/chrome/browser/ui/webui/options2/advanced_options_utils_win.cc
new file mode 100644
index 0000000..5942ff9
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_utils_win.cc
@@ -0,0 +1,68 @@
+// 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/options2/advanced_options_utils.h"
+
+#include <windows.h>
+#include <cryptuiapi.h>
+#pragma comment(lib, "cryptui.lib")
+#include <shellapi.h>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/threading/thread.h"
+#include "chrome/browser/browser_process.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+// Callback that opens the Internet Options control panel dialog with the
+// Connections tab selected.
+void OpenConnectionDialogCallback() {
+ // Using rundll32 seems better than LaunchConnectionDialog which causes a
+ // new dialog to be made for each call. rundll32 uses the same global
+ // dialog and it seems to share with the shortcut in control panel.
+ FilePath rundll32;
+ PathService::Get(base::DIR_SYSTEM, &rundll32);
+ rundll32 = rundll32.AppendASCII("rundll32.exe");
+
+ FilePath shell32dll;
+ PathService::Get(base::DIR_SYSTEM, &shell32dll);
+ shell32dll = shell32dll.AppendASCII("shell32.dll");
+
+ FilePath inetcpl;
+ PathService::Get(base::DIR_SYSTEM, &inetcpl);
+ inetcpl = inetcpl.AppendASCII("inetcpl.cpl,,4");
+
+ std::wstring args(shell32dll.value());
+ args.append(L",Control_RunDLL ");
+ args.append(inetcpl.value());
+
+ ShellExecute(NULL, L"open", rundll32.value().c_str(), args.c_str(), NULL,
+ SW_SHOWNORMAL);
+}
+
+void AdvancedOptionsUtilities::ShowNetworkProxySettings(
+ TabContents* tab_contents) {
+ DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::FILE));
+ BrowserThread::PostTask(BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&OpenConnectionDialogCallback));
+}
+
+void AdvancedOptionsUtilities::ShowManageSSLCertificates(
+ TabContents* tab_contents) {
+ CRYPTUI_CERT_MGR_STRUCT cert_mgr = { 0 };
+ cert_mgr.dwSize = sizeof(CRYPTUI_CERT_MGR_STRUCT);
+ cert_mgr.hwndParent =
+#if defined(USE_AURA)
+ NULL;
+#else
+ tab_contents->view()->GetTopLevelNativeWindow();
+#endif
+ ::CryptUIDlgCertMgr(&cert_mgr);
+}
diff --git a/chrome/browser/ui/webui/options2/advanced_options_utils_x11.cc b/chrome/browser/ui/webui/options2/advanced_options_utils_x11.cc
new file mode 100644
index 0000000..20579b3
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/advanced_options_utils_x11.cc
@@ -0,0 +1,140 @@
+// 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.
+
+#if !defined(OS_CHROMEOS)
+
+#include "chrome/browser/ui/webui/options2/advanced_options_utils.h"
+
+#include "base/bind.h"
+#include "base/environment.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/nix/xdg_util.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+// Command used to configure GNOME 2 proxy settings.
+const char* kGNOME2ProxyConfigCommand[] = {"gnome-network-properties", NULL};
+// In GNOME 3, we might need to run gnome-control-center instead. We try this
+// only after gnome-network-properties is not found, because older GNOME also
+// has this but it doesn't do the same thing. See below where we use it.
+const char* kGNOME3ProxyConfigCommand[] = {"gnome-control-center", "network",
+ NULL};
+// KDE3 and KDE4 are only slightly different, but incompatible. Go figure.
+const char* kKDE3ProxyConfigCommand[] = {"kcmshell", "proxy", NULL};
+const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};
+
+// The URL for Linux proxy configuration help when not running under a
+// supported desktop environment.
+const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";
+
+namespace {
+
+// Show the proxy config URL in the given tab.
+void ShowLinuxProxyConfigUrl(TabContents* tab_contents) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ const char* name = base::nix::GetDesktopEnvironmentName(env.get());
+ if (name)
+ LOG(ERROR) << "Could not find " << name << " network settings in $PATH";
+ tab_contents->OpenURL(GURL(kLinuxProxyConfigUrl), GURL(),
+ NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK);
+}
+
+// Start the given proxy configuration utility.
+bool StartProxyConfigUtil(TabContents* tab_contents, const char* command[]) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ // base::LaunchProcess() returns true ("success") if the fork()
+ // succeeds, but not necessarily the exec(). We'd like to be able to
+ // use StartProxyConfigUtil() to search possible options and stop on
+ // success, so we search $PATH first to predict whether the exec is
+ // expected to succeed.
+ // TODO(mdm): this is a useful check, and is very similar to some
+ // code in proxy_config_service_linux.cc. It should probably be in
+ // base:: somewhere.
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ std::string path;
+ if (!env->GetVar("PATH", &path)) {
+ LOG(ERROR) << "No $PATH variable. Assuming no " << command[0] << ".";
+ return false;
+ }
+ std::vector<std::string> paths;
+ Tokenize(path, ":", &paths);
+ bool found = false;
+ for (size_t i = 0; i < paths.size(); ++i) {
+ FilePath file(paths[i]);
+ if (file_util::PathExists(file.Append(command[0]))) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ std::vector<std::string> argv;
+ for (size_t i = 0; command[i]; ++i)
+ argv.push_back(command[i]);
+ base::ProcessHandle handle;
+ if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
+ LOG(ERROR) << "StartProxyConfigUtil failed to start " << command[0];
+ return false;
+ }
+ base::EnsureProcessGetsReaped(handle);
+ return true;
+}
+
+// Detect, and if possible, start the appropriate proxy config utility. On
+// failure to do so, show the Linux proxy config URL in a new tab instead.
+void DetectAndStartProxyConfigUtil(TabContents* tab_contents) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+
+ bool launched = false;
+ switch (base::nix::GetDesktopEnvironment(env.get())) {
+ case base::nix::DESKTOP_ENVIRONMENT_GNOME: {
+ launched = StartProxyConfigUtil(tab_contents, kGNOME2ProxyConfigCommand);
+ if (!launched) {
+ // We try this second, even though it's the newer way, because this
+ // command existed in older versions of GNOME, but it didn't do the
+ // same thing. The older command is gone though, so this should do
+ // the right thing. (Also some distributions have blurred the lines
+ // between GNOME 2 and 3, so we can't necessarily detect what the
+ // right thing is based on indications of which version we have.)
+ launched = StartProxyConfigUtil(tab_contents,
+ kGNOME3ProxyConfigCommand);
+ }
+ break;
+ }
+
+ case base::nix::DESKTOP_ENVIRONMENT_KDE3:
+ launched = StartProxyConfigUtil(tab_contents, kKDE3ProxyConfigCommand);
+ break;
+
+ case base::nix::DESKTOP_ENVIRONMENT_KDE4:
+ launched = StartProxyConfigUtil(tab_contents, kKDE4ProxyConfigCommand);
+ break;
+
+ case base::nix::DESKTOP_ENVIRONMENT_XFCE:
+ case base::nix::DESKTOP_ENVIRONMENT_OTHER:
+ break;
+ }
+
+ if (launched)
+ return;
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&ShowLinuxProxyConfigUrl, tab_contents));
+}
+
+} // anonymous namespace
+
+void AdvancedOptionsUtilities::ShowNetworkProxySettings(
+ TabContents* tab_contents) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DetectAndStartProxyConfigUtil, tab_contents));
+}
+
+#endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/options2/autofill_options_browsertest.js b/chrome/browser/ui/webui/options2/autofill_options_browsertest.js
new file mode 100644
index 0000000..d9a5c9b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/autofill_options_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for autofill options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function AutofillOptionsWebUITest() {}
+
+AutofillOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to autofill options.
+ **/
+ browsePreload: 'chrome://settings/autofill',
+};
+
+// Test opening the autofill options has correct location.
+TEST_F('AutofillOptionsWebUITest', 'testOpenAutofillOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/autofill_options_handler.cc b/chrome/browser/ui/webui/options2/autofill_options_handler.cc
new file mode 100644
index 0000000..f751e635
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/autofill_options_handler.cc
@@ -0,0 +1,614 @@
+// 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/options2/autofill_options_handler.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/autofill/autofill_country.h"
+#include "chrome/browser/autofill/autofill_profile.h"
+#include "chrome/browser/autofill/credit_card.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
+#include "chrome/browser/autofill/phone_number_i18n.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/web_ui_util.h"
+#include "chrome/common/guid.h"
+#include "grit/generated_resources.h"
+#include "grit/webkit_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// Converts a credit card type to the appropriate resource ID of the CC icon.
+int CreditCardTypeToResourceID(const std::string& type) {
+ if (type == kAmericanExpressCard)
+ return IDR_AUTOFILL_CC_AMEX;
+ else if (type == kDinersCard)
+ return IDR_AUTOFILL_CC_DINERS;
+ else if (type == kDiscoverCard)
+ return IDR_AUTOFILL_CC_DISCOVER;
+ else if (type == kGenericCard)
+ return IDR_AUTOFILL_CC_GENERIC;
+ else if (type == kJCBCard)
+ return IDR_AUTOFILL_CC_JCB;
+ else if (type == kMasterCard)
+ return IDR_AUTOFILL_CC_MASTERCARD;
+ else if (type == kSoloCard)
+ return IDR_AUTOFILL_CC_SOLO;
+ else if (type == kVisaCard)
+ return IDR_AUTOFILL_CC_VISA;
+
+ NOTREACHED();
+ return 0;
+}
+
+// Converts a credit card type to the appropriate localized card type.
+string16 LocalizedCreditCardType(const std::string& type) {
+ if (type == kAmericanExpressCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
+ else if (type == kDinersCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
+ else if (type == kDiscoverCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
+ else if (type == kGenericCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
+ else if (type == kJCBCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
+ else if (type == kMasterCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
+ else if (type == kSoloCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_SOLO);
+ else if (type == kVisaCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
+
+ NOTREACHED();
+ return string16();
+}
+
+// Returns a dictionary that maps country codes to data for the country.
+DictionaryValue* GetCountryData() {
+ std::string app_locale = AutofillCountry::ApplicationLocale();
+ std::vector<std::string> country_codes;
+ AutofillCountry::GetAvailableCountries(&country_codes);
+
+ DictionaryValue* country_data = new DictionaryValue();
+ for (size_t i = 0; i < country_codes.size(); ++i) {
+ const AutofillCountry country(country_codes[i], app_locale);
+
+ DictionaryValue* details = new DictionaryValue();
+ details->SetString("name", country.name());
+ details->SetString("postalCodeLabel", country.postal_code_label());
+ details->SetString("stateLabel", country.state_label());
+
+ country_data->Set(country.country_code(), details);
+ }
+
+ return country_data;
+}
+
+// Get the multi-valued element for |type| and return it in |ListValue| form.
+void GetValueList(const AutofillProfile& profile,
+ AutofillFieldType type,
+ scoped_ptr<ListValue>* list) {
+ list->reset(new ListValue);
+
+ std::vector<string16> values;
+ profile.GetMultiInfo(type, &values);
+
+ // |GetMultiInfo()| always returns at least one, potentially empty, item.
+ if (values.size() == 1 && values.front().empty())
+ return;
+
+ for (size_t i = 0; i < values.size(); ++i) {
+ (*list)->Set(i, Value::CreateStringValue(values[i]));
+ }
+}
+
+// Set the multi-valued element for |type| from input |list| values.
+void SetValueList(const ListValue* list,
+ AutofillFieldType type,
+ AutofillProfile* profile) {
+ std::vector<string16> values(list->GetSize());
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ string16 value;
+ if (list->GetString(i, &value))
+ values[i] = value;
+ }
+ profile->SetMultiInfo(type, values);
+}
+
+// Get the multi-valued element for |type| and return it in |ListValue| form.
+void GetNameList(const AutofillProfile& profile,
+ scoped_ptr<ListValue>* names) {
+ names->reset(new ListValue);
+
+ std::vector<string16> first_names;
+ std::vector<string16> middle_names;
+ std::vector<string16> last_names;
+ profile.GetMultiInfo(NAME_FIRST, &first_names);
+ profile.GetMultiInfo(NAME_MIDDLE, &middle_names);
+ profile.GetMultiInfo(NAME_LAST, &last_names);
+ DCHECK_EQ(first_names.size(), middle_names.size());
+ DCHECK_EQ(first_names.size(), last_names.size());
+
+ // |GetMultiInfo()| always returns at least one, potentially empty, item.
+ if (first_names.size() == 1 && first_names.front().empty() &&
+ middle_names.front().empty() && last_names.front().empty()) {
+ return;
+ }
+
+ for (size_t i = 0; i < first_names.size(); ++i) {
+ ListValue* name = new ListValue; // owned by |list|
+ name->Set(0, Value::CreateStringValue(first_names[i]));
+ name->Set(1, Value::CreateStringValue(middle_names[i]));
+ name->Set(2, Value::CreateStringValue(last_names[i]));
+ (*names)->Set(i, name);
+ }
+}
+
+// Set the multi-valued element for |type| from input |list| values.
+void SetNameList(const ListValue* names,
+ AutofillProfile* profile) {
+ const size_t size = names->GetSize();
+ std::vector<string16> first_names(size);
+ std::vector<string16> middle_names(size);
+ std::vector<string16> last_names(size);
+
+ for (size_t i = 0; i < size; ++i) {
+ ListValue* name;
+ bool success = names->GetList(i, &name);
+ DCHECK(success);
+
+ string16 first_name;
+ success = name->GetString(0, &first_name);
+ DCHECK(success);
+ first_names[i] = first_name;
+
+ string16 middle_name;
+ success = name->GetString(1, &middle_name);
+ DCHECK(success);
+ middle_names[i] = middle_name;
+
+ string16 last_name;
+ success = name->GetString(2, &last_name);
+ DCHECK(success);
+ last_names[i] = last_name;
+ }
+
+ profile->SetMultiInfo(NAME_FIRST, first_names);
+ profile->SetMultiInfo(NAME_MIDDLE, middle_names);
+ profile->SetMultiInfo(NAME_LAST, last_names);
+}
+
+// Pulls the phone number |index|, |phone_number_list|, and |country_code| from
+// the |args| input.
+void ExtractPhoneNumberInformation(const ListValue* args,
+ size_t* index,
+ ListValue** phone_number_list,
+ std::string* country_code) {
+ // Retrieve index as a |double|, as that is how it comes across from
+ // JavaScript.
+ double number = 0.0;
+ if (!args->GetDouble(0, &number)) {
+ NOTREACHED();
+ return;
+ }
+ *index = number;
+
+ if (!args->GetList(1, phone_number_list)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (!args->GetString(2, country_code)) {
+ NOTREACHED();
+ return;
+ }
+}
+
+// Searches the |list| for the value at |index|. If this value is present
+// in any of the rest of the list, then the item (at |index|) is removed.
+// The comparison of phone number values is done on normalized versions of the
+// phone number values.
+void RemoveDuplicatePhoneNumberAtIndex(size_t index,
+ const std::string& country_code,
+ ListValue* list) {
+ string16 new_value;
+ if (!list->GetString(index, &new_value)) {
+ NOTREACHED() << "List should have a value at index " << index;
+ return;
+ }
+
+ bool is_duplicate = false;
+ for (size_t i = 0; i < list->GetSize() && !is_duplicate; ++i) {
+ if (i == index)
+ continue;
+
+ string16 existing_value;
+ if (!list->GetString(i, &existing_value)) {
+ NOTREACHED() << "List should have a value at index " << i;
+ continue;
+ }
+ is_duplicate = autofill_i18n::PhoneNumbersMatch(new_value,
+ existing_value,
+ country_code);
+ }
+
+ if (is_duplicate)
+ list->Remove(index, NULL);
+}
+
+void ValidatePhoneArguments(const ListValue* args, ListValue** list) {
+ size_t index = 0;
+ std::string country_code;
+ ExtractPhoneNumberInformation(args, &index, list, &country_code);
+
+ RemoveDuplicatePhoneNumberAtIndex(index, country_code, *list);
+}
+
+} // namespace
+
+AutofillOptionsHandler::AutofillOptionsHandler()
+ : personal_data_(NULL) {
+}
+
+AutofillOptionsHandler::~AutofillOptionsHandler() {
+ if (personal_data_)
+ personal_data_->RemoveObserver(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// OptionsPageUIHandler implementation:
+void AutofillOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME },
+ { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME },
+ { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON },
+ { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON },
+ { "autofillEditProfileButton", IDS_AUTOFILL_EDIT_PROFILE_BUTTON },
+ { "helpButton", IDS_AUTOFILL_HELP_LABEL },
+ { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION },
+ { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION },
+ { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION },
+ { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION },
+#if defined(OS_MACOSX)
+ { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK },
+#endif // defined(OS_MACOSX)
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "autofillOptionsPage",
+ IDS_AUTOFILL_OPTIONS_TITLE);
+
+ SetAddressOverlayStrings(localized_strings);
+ SetCreditCardOverlayStrings(localized_strings);
+}
+
+void AutofillOptionsHandler::Initialize() {
+ personal_data_ = PersonalDataManagerFactory::GetForProfile(
+ Profile::FromWebUI(web_ui_));
+ // personal_data_ is NULL in guest mode on Chrome OS.
+ if (personal_data_) {
+ personal_data_->SetObserver(this);
+ LoadAutofillData();
+ }
+}
+
+void AutofillOptionsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback(
+ "removeAddress",
+ base::Bind(&AutofillOptionsHandler::RemoveAddress,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "removeCreditCard",
+ base::Bind(&AutofillOptionsHandler::RemoveCreditCard,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "loadAddressEditor",
+ base::Bind(&AutofillOptionsHandler::LoadAddressEditor,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "loadCreditCardEditor",
+ base::Bind(&AutofillOptionsHandler::LoadCreditCardEditor,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "setAddress",
+ base::Bind(&AutofillOptionsHandler::SetAddress, base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "setCreditCard",
+ base::Bind(&AutofillOptionsHandler::SetCreditCard,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "validatePhoneNumbers",
+ base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers,
+ base::Unretained(this)));
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// PersonalDataManagerObserver implementation:
+void AutofillOptionsHandler::OnPersonalDataChanged() {
+ LoadAutofillData();
+}
+
+void AutofillOptionsHandler::SetAddressOverlayStrings(
+ DictionaryValue* localized_strings) {
+ localized_strings->SetString("autofillEditAddressTitle",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION));
+ localized_strings->SetString("autofillFirstNameLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_FIRST_NAME));
+ localized_strings->SetString("autofillMiddleNameLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_MIDDLE_NAME));
+ localized_strings->SetString("autofillLastNameLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_LAST_NAME));
+ localized_strings->SetString("autofillCompanyNameLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COMPANY_NAME));
+ localized_strings->SetString("autofillAddrLine1Label",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1));
+ localized_strings->SetString("autofillAddrLine2Label",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2));
+ localized_strings->SetString("autofillCityLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CITY));
+ localized_strings->SetString("autofillCountryLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COUNTRY));
+ localized_strings->SetString("autofillPhoneLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PHONE));
+ localized_strings->SetString("autofillEmailLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EMAIL));
+ localized_strings->SetString("autofillAddFirstNamePlaceholder",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_FIRST_NAME));
+ localized_strings->SetString("autofillAddMiddleNamePlaceholder",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_MIDDLE_NAME));
+ localized_strings->SetString("autofillAddLastNamePlaceholder",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_LAST_NAME));
+ localized_strings->SetString("autofillAddPhonePlaceholder",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_PHONE));
+ localized_strings->SetString("autofillAddEmailPlaceholder",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_EMAIL));
+
+ std::string app_locale = AutofillCountry::ApplicationLocale();
+ std::string default_country_code =
+ AutofillCountry::CountryCodeForLocale(app_locale);
+ localized_strings->SetString("defaultCountryCode", default_country_code);
+ localized_strings->Set("autofillCountryData", GetCountryData());
+}
+
+void AutofillOptionsHandler::SetCreditCardOverlayStrings(
+ DictionaryValue* localized_strings) {
+ localized_strings->SetString("autofillEditCreditCardTitle",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
+ localized_strings->SetString("nameOnCardLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NAME_ON_CARD));
+ localized_strings->SetString("creditCardNumberLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER));
+ localized_strings->SetString("creditCardExpirationDateLabel",
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE));
+}
+
+void AutofillOptionsHandler::LoadAutofillData() {
+ if (!personal_data_->IsDataLoaded())
+ return;
+
+ ListValue addresses;
+ for (std::vector<AutofillProfile*>::const_iterator i =
+ personal_data_->web_profiles().begin();
+ i != personal_data_->web_profiles().end(); ++i) {
+ ListValue* entry = new ListValue();
+ entry->Append(new StringValue((*i)->guid()));
+ entry->Append(new StringValue((*i)->Label()));
+ addresses.Append(entry);
+ }
+
+ web_ui_->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
+
+ ListValue credit_cards;
+ for (std::vector<CreditCard*>::const_iterator i =
+ personal_data_->credit_cards().begin();
+ i != personal_data_->credit_cards().end(); ++i) {
+ ListValue* entry = new ListValue();
+ entry->Append(new StringValue((*i)->guid()));
+ entry->Append(new StringValue((*i)->Label()));
+ int res = CreditCardTypeToResourceID((*i)->type());
+ entry->Append(
+ new StringValue(web_ui_util::GetImageDataUrlFromResource(res)));
+ entry->Append(new StringValue(LocalizedCreditCardType((*i)->type())));
+ credit_cards.Append(entry);
+ }
+
+ web_ui_->CallJavascriptFunction("AutofillOptions.setCreditCardList",
+ credit_cards);
+}
+
+void AutofillOptionsHandler::RemoveAddress(const ListValue* args) {
+ DCHECK(personal_data_->IsDataLoaded());
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ personal_data_->RemoveProfile(guid);
+}
+
+void AutofillOptionsHandler::RemoveCreditCard(const ListValue* args) {
+ DCHECK(personal_data_->IsDataLoaded());
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ personal_data_->RemoveCreditCard(guid);
+}
+
+void AutofillOptionsHandler::LoadAddressEditor(const ListValue* args) {
+ DCHECK(personal_data_->IsDataLoaded());
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
+ if (!profile) {
+ // There is a race where a user can click once on the close button and
+ // quickly click again on the list item before the item is removed (since
+ // the list is not updated until the model tells the list an item has been
+ // removed). This will activate the editor for a profile that has been
+ // removed. Do nothing in that case.
+ return;
+ }
+
+ DictionaryValue address;
+ address.SetString("guid", profile->guid());
+ scoped_ptr<ListValue> list;
+ GetNameList(*profile, &list);
+ address.Set("fullName", list.release());
+ address.SetString("companyName", profile->GetInfo(COMPANY_NAME));
+ address.SetString("addrLine1", profile->GetInfo(ADDRESS_HOME_LINE1));
+ address.SetString("addrLine2", profile->GetInfo(ADDRESS_HOME_LINE2));
+ address.SetString("city", profile->GetInfo(ADDRESS_HOME_CITY));
+ address.SetString("state", profile->GetInfo(ADDRESS_HOME_STATE));
+ address.SetString("postalCode", profile->GetInfo(ADDRESS_HOME_ZIP));
+ address.SetString("country", profile->CountryCode());
+ GetValueList(*profile, PHONE_HOME_WHOLE_NUMBER, &list);
+ address.Set("phone", list.release());
+ GetValueList(*profile, EMAIL_ADDRESS, &list);
+ address.Set("email", list.release());
+
+ web_ui_->CallJavascriptFunction("AutofillOptions.editAddress", address);
+}
+
+void AutofillOptionsHandler::LoadCreditCardEditor(const ListValue* args) {
+ DCHECK(personal_data_->IsDataLoaded());
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
+ if (!credit_card) {
+ // There is a race where a user can click once on the close button and
+ // quickly click again on the list item before the item is removed (since
+ // the list is not updated until the model tells the list an item has been
+ // removed). This will activate the editor for a profile that has been
+ // removed. Do nothing in that case.
+ return;
+ }
+
+ DictionaryValue credit_card_data;
+ credit_card_data.SetString("guid", credit_card->guid());
+ credit_card_data.SetString("nameOnCard",
+ credit_card->GetInfo(CREDIT_CARD_NAME));
+ credit_card_data.SetString("creditCardNumber",
+ credit_card->GetInfo(CREDIT_CARD_NUMBER));
+ credit_card_data.SetString("expirationMonth",
+ credit_card->GetInfo(CREDIT_CARD_EXP_MONTH));
+ credit_card_data.SetString(
+ "expirationYear",
+ credit_card->GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+
+ web_ui_->CallJavascriptFunction("AutofillOptions.editCreditCard",
+ credit_card_data);
+}
+
+void AutofillOptionsHandler::SetAddress(const ListValue* args) {
+ if (!personal_data_->IsDataLoaded())
+ return;
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ AutofillProfile profile(guid);
+
+ std::string country_code;
+ string16 value;
+ ListValue* list_value;
+ if (args->GetList(1, &list_value))
+ SetNameList(list_value, &profile);
+ if (args->GetString(2, &value))
+ profile.SetInfo(COMPANY_NAME, value);
+ if (args->GetString(3, &value))
+ profile.SetInfo(ADDRESS_HOME_LINE1, value);
+ if (args->GetString(4, &value))
+ profile.SetInfo(ADDRESS_HOME_LINE2, value);
+ if (args->GetString(5, &value))
+ profile.SetInfo(ADDRESS_HOME_CITY, value);
+ if (args->GetString(6, &value))
+ profile.SetInfo(ADDRESS_HOME_STATE, value);
+ if (args->GetString(7, &value))
+ profile.SetInfo(ADDRESS_HOME_ZIP, value);
+ if (args->GetString(8, &country_code))
+ profile.SetCountryCode(country_code);
+ if (args->GetList(9, &list_value))
+ SetValueList(list_value, PHONE_HOME_WHOLE_NUMBER, &profile);
+ if (args->GetList(10, &list_value))
+ SetValueList(list_value, EMAIL_ADDRESS, &profile);
+
+ if (!guid::IsValidGUID(profile.guid())) {
+ profile.set_guid(guid::GenerateGUID());
+ personal_data_->AddProfile(profile);
+ } else {
+ personal_data_->UpdateProfile(profile);
+ }
+}
+
+void AutofillOptionsHandler::SetCreditCard(const ListValue* args) {
+ if (!personal_data_->IsDataLoaded())
+ return;
+
+ std::string guid;
+ if (!args->GetString(0, &guid)) {
+ NOTREACHED();
+ return;
+ }
+
+ CreditCard credit_card(guid);
+
+ string16 value;
+ if (args->GetString(1, &value))
+ credit_card.SetInfo(CREDIT_CARD_NAME, value);
+ if (args->GetString(2, &value))
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, value);
+ if (args->GetString(3, &value))
+ credit_card.SetInfo(CREDIT_CARD_EXP_MONTH, value);
+ if (args->GetString(4, &value))
+ credit_card.SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
+
+ if (!guid::IsValidGUID(credit_card.guid())) {
+ credit_card.set_guid(guid::GenerateGUID());
+ personal_data_->AddCreditCard(credit_card);
+ } else {
+ personal_data_->UpdateCreditCard(credit_card);
+ }
+}
+
+void AutofillOptionsHandler::ValidatePhoneNumbers(const ListValue* args) {
+ if (!personal_data_->IsDataLoaded())
+ return;
+
+ ListValue* list_value = NULL;
+ ValidatePhoneArguments(args, &list_value);
+
+ web_ui_->CallJavascriptFunction(
+ "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value);
+}
diff --git a/chrome/browser/ui/webui/options2/autofill_options_handler.h b/chrome/browser/ui/webui/options2/autofill_options_handler.h
new file mode 100644
index 0000000..9c25074
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/autofill_options_handler.h
@@ -0,0 +1,89 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_AUTOFILL_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_AUTOFILL_OPTIONS_HANDLER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/autofill/personal_data_manager_observer.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+class PersonalDataManager;
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+class AutofillOptionsHandler : public OptionsPage2UIHandler,
+ public PersonalDataManagerObserver {
+ public:
+ AutofillOptionsHandler();
+ virtual ~AutofillOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // PersonalDataManagerObserver implementation.
+ virtual void OnPersonalDataChanged() OVERRIDE;
+
+ private:
+ // Loads the strings for the address and credit card overlays.
+ void SetAddressOverlayStrings(base::DictionaryValue* localized_strings);
+ void SetCreditCardOverlayStrings(base::DictionaryValue* localized_strings);
+
+ // Loads Autofill addresses and credit cards using the PersonalDataManager.
+ void LoadAutofillData();
+
+ // Removes an address from the PersonalDataManager.
+ // |args| - A string, the GUID of the address to remove.
+ void RemoveAddress(const base::ListValue* args);
+
+ // Removes a credit card from the PersonalDataManager.
+ // |args| - A string, the GUID of the credit card to remove.
+ void RemoveCreditCard(const base::ListValue* args);
+
+ // Requests profile data for a specific address. Calls into WebUI with the
+ // loaded profile data to open the address editor.
+ // |args| - A string, the GUID of the address to load.
+ void LoadAddressEditor(const base::ListValue* args);
+
+ // Requests profile data for a specific credit card. Calls into WebUI with the
+ // loaded profile data to open the credit card editor.
+ // |args| - A string, the GUID of the credit card to load.
+ void LoadCreditCardEditor(const base::ListValue* args);
+
+ // Adds or updates an address, depending on the GUID of the profile. If the
+ // GUID is empty, a new address is added to the WebDatabase; otherwise, the
+ // address with the matching GUID is updated. Called from WebUI.
+ // |args| - an array containing the GUID of the address followed by the
+ // address data.
+ void SetAddress(const base::ListValue* args);
+
+ // Adds or updates a credit card, depending on the GUID of the profile. If the
+ // GUID is empty, a new credit card is added to the WebDatabase; otherwise,
+ // the credit card with the matching GUID is updated. Called from WebUI.
+ // |args| - an array containing the GUID of the credit card followed by the
+ // credit card data.
+ void SetCreditCard(const base::ListValue* args);
+
+ // Validates a list of phone numbers. The resulting validated list of
+ // numbers is then sent back to the WebUI.
+ // |args| - an array containing the index of the modified or added number, the
+ // array of numbers, and the country code string set on the profile.
+ void ValidatePhoneNumbers(const base::ListValue* args);
+
+ // The personal data manager, used to load Autofill profiles and credit cards.
+ // Unowned pointer, may not be NULL.
+ PersonalDataManager* personal_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_AUTOFILL_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/browser_options_browsertest.js b/chrome/browser/ui/webui/options2/browser_options_browsertest.js
new file mode 100644
index 0000000..e983b27
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/browser_options_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for browser options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function BrowserOptionsWebUITest() {}
+
+BrowserOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to browser options.
+ **/
+ browsePreload: 'chrome://settings/browser',
+};
+
+// Test opening the browser options has correct location.
+TEST_F('BrowserOptionsWebUITest', 'testOpenBrowserOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/browser_options_handler.cc b/chrome/browser/ui/webui/options2/browser_options_handler.cc
new file mode 100644
index 0000000..23b1d46
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/browser_options_handler.cc
@@ -0,0 +1,494 @@
+// 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/options2/browser_options_handler.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/singleton.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_match.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/custom_home_pages_table_model.h"
+#include "chrome/browser/instant/instant_confirm_dialog.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/instant/instant_field_trial.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/webui/favicon_source.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+BrowserOptionsHandler::BrowserOptionsHandler()
+ : template_url_service_(NULL), startup_custom_pages_table_model_(NULL) {
+#if !defined(OS_MACOSX)
+ default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
+#endif
+}
+
+BrowserOptionsHandler::~BrowserOptionsHandler() {
+ if (default_browser_worker_.get())
+ default_browser_worker_->ObserverDestroyed();
+ if (template_url_service_)
+ template_url_service_->RemoveObserver(this);
+}
+
+void BrowserOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "startupGroupName", IDS_OPTIONS_STARTUP_GROUP_NAME },
+ { "startupShowDefaultAndNewTab",
+ IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB},
+ { "startupShowLastSession", IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION },
+ { "startupShowPages", IDS_OPTIONS_STARTUP_SHOW_PAGES },
+ { "startupAddLabel", IDS_OPTIONS_STARTUP_ADD_LABEL },
+ { "startupUseCurrent", IDS_OPTIONS_STARTUP_USE_CURRENT },
+ { "homepageGroupName", IDS_OPTIONS_HOMEPAGE_GROUP_NAME },
+ { "homepageUseNewTab", IDS_OPTIONS_HOMEPAGE_USE_NEWTAB },
+ { "homepageUseURL", IDS_OPTIONS_HOMEPAGE_USE_URL },
+ { "toolbarGroupName", IDS_OPTIONS_TOOLBAR_GROUP_NAME },
+ { "toolbarShowHomeButton", IDS_OPTIONS_TOOLBAR_SHOW_HOME_BUTTON },
+ { "toolbarShowBookmarksBar", IDS_OPTIONS_TOOLBAR_SHOW_BOOKMARKS_BAR },
+ { "defaultSearchGroupName", IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME },
+ { "defaultSearchManageEngines", IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES },
+ { "instantName", IDS_INSTANT_PREF },
+ { "instantWarningText", IDS_INSTANT_PREF_WARNING },
+ { "instantConfirmTitle", IDS_INSTANT_OPT_IN_TITLE },
+ { "instantConfirmMessage", IDS_INSTANT_OPT_IN_MESSAGE },
+ { "defaultBrowserGroupName", IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "browserPage",
+ IDS_OPTIONS_GENERAL_TAB_LABEL);
+
+ localized_strings->SetString("instantLearnMoreLink",
+ ASCIIToUTF16(browser::InstantLearnMoreURL().spec()));
+ localized_strings->SetString("defaultBrowserUnknown",
+ l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+ localized_strings->SetString("defaultBrowserUseAsDefault",
+ l10n_util::GetStringFUTF16(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+}
+
+void BrowserOptionsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("becomeDefaultBrowser",
+ base::Bind(&BrowserOptionsHandler::BecomeDefaultBrowser,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setDefaultSearchEngine",
+ base::Bind(&BrowserOptionsHandler::SetDefaultSearchEngine,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeStartupPages",
+ base::Bind(&BrowserOptionsHandler::RemoveStartupPages,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("addStartupPage",
+ base::Bind(&BrowserOptionsHandler::AddStartupPage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("editStartupPage",
+ base::Bind(&BrowserOptionsHandler::EditStartupPage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setStartupPagesToCurrentPages",
+ base::Bind(&BrowserOptionsHandler::SetStartupPagesToCurrentPages,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("dragDropStartupPage",
+ base::Bind(&BrowserOptionsHandler::DragDropStartupPage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("requestAutocompleteSuggestions",
+ base::Bind(&BrowserOptionsHandler::RequestAutocompleteSuggestions,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("enableInstant",
+ base::Bind(&BrowserOptionsHandler::EnableInstant,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("disableInstant",
+ base::Bind(&BrowserOptionsHandler::DisableInstant,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("getInstantFieldTrialStatus",
+ base::Bind(&BrowserOptionsHandler::GetInstantFieldTrialStatus,
+ base::Unretained(this)));
+}
+
+void BrowserOptionsHandler::Initialize() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+
+ // Create our favicon data source.
+ profile->GetChromeURLDataManager()->AddDataSource(
+ new FaviconSource(profile, FaviconSource::FAVICON));
+
+ homepage_.Init(prefs::kHomePage, profile->GetPrefs(), NULL);
+ default_browser_policy_.Init(prefs::kDefaultBrowserSettingEnabled,
+ g_browser_process->local_state(),
+ this);
+ UpdateDefaultBrowserState();
+
+ startup_custom_pages_table_model_.reset(
+ new CustomHomePagesTableModel(profile));
+ startup_custom_pages_table_model_->SetObserver(this);
+ UpdateStartupPages();
+
+ pref_change_registrar_.Init(profile->GetPrefs());
+ pref_change_registrar_.Add(prefs::kURLsToRestoreOnStartup, this);
+
+ UpdateSearchEngines();
+
+ autocomplete_controller_.reset(new AutocompleteController(profile, this));
+}
+
+void BrowserOptionsHandler::UpdateDefaultBrowserState() {
+ // Check for side-by-side first.
+ if (!ShellIntegration::CanSetAsDefaultBrowser()) {
+ SetDefaultBrowserUIString(IDS_OPTIONS_DEFAULTBROWSER_SXS);
+ return;
+ }
+
+#if defined(OS_MACOSX)
+ ShellIntegration::DefaultWebClientState state =
+ ShellIntegration::IsDefaultBrowser();
+ int status_string_id;
+ if (state == ShellIntegration::IS_DEFAULT_WEB_CLIENT)
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
+ else if (state == ShellIntegration::NOT_DEFAULT_WEB_CLIENT)
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
+ else
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
+
+ SetDefaultBrowserUIString(status_string_id);
+#else
+ default_browser_worker_->StartCheckIsDefault();
+#endif
+}
+
+void BrowserOptionsHandler::BecomeDefaultBrowser(const ListValue* args) {
+ // If the default browser setting is managed then we should not be able to
+ // call this function.
+ if (default_browser_policy_.IsManaged())
+ return;
+
+ UserMetrics::RecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"));
+#if defined(OS_MACOSX)
+ if (ShellIntegration::SetAsDefaultBrowser())
+ UpdateDefaultBrowserState();
+#else
+ default_browser_worker_->StartSetAsDefault();
+ // Callback takes care of updating UI.
+#endif
+
+ // If the user attempted to make Chrome the default browser, then he/she
+ // arguably wants to be notified when that changes.
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+ prefs->SetBoolean(prefs::kCheckDefaultBrowser, true);
+}
+
+int BrowserOptionsHandler::StatusStringIdForState(
+ ShellIntegration::DefaultWebClientState state) {
+ if (state == ShellIntegration::IS_DEFAULT_WEB_CLIENT)
+ return IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
+ if (state == ShellIntegration::NOT_DEFAULT_WEB_CLIENT)
+ return IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
+ return IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
+}
+
+void BrowserOptionsHandler::SetDefaultWebClientUIState(
+ ShellIntegration::DefaultWebClientUIState state) {
+ int status_string_id;
+ if (state == ShellIntegration::STATE_IS_DEFAULT)
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_DEFAULT;
+ else if (state == ShellIntegration::STATE_NOT_DEFAULT)
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT;
+ else if (state == ShellIntegration::STATE_UNKNOWN)
+ status_string_id = IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN;
+ else
+ return; // Still processing.
+
+ SetDefaultBrowserUIString(status_string_id);
+}
+
+void BrowserOptionsHandler::SetDefaultBrowserUIString(int status_string_id) {
+ scoped_ptr<Value> status_string(Value::CreateStringValue(
+ l10n_util::GetStringFUTF16(status_string_id,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));
+
+ scoped_ptr<Value> is_default(Value::CreateBooleanValue(
+ status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT));
+
+ scoped_ptr<Value> can_be_default(Value::CreateBooleanValue(
+ !default_browser_policy_.IsManaged() &&
+ (status_string_id == IDS_OPTIONS_DEFAULTBROWSER_DEFAULT ||
+ status_string_id == IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT)));
+
+ web_ui_->CallJavascriptFunction("BrowserOptions.updateDefaultBrowserState",
+ *status_string, *is_default, *can_be_default);
+}
+
+void BrowserOptionsHandler::OnTemplateURLServiceChanged() {
+ if (!template_url_service_ || !template_url_service_->loaded())
+ return;
+
+ const TemplateURL* default_url =
+ template_url_service_->GetDefaultSearchProvider();
+
+ int default_index = 0;
+ ListValue search_engines;
+ std::vector<const TemplateURL*> model_urls =
+ template_url_service_->GetTemplateURLs();
+ for (size_t i = 0; i < model_urls.size(); ++i) {
+ if (!model_urls[i]->ShowInDefaultList())
+ continue;
+
+ DictionaryValue* entry = new DictionaryValue();
+ entry->SetString("name", model_urls[i]->short_name());
+ entry->SetInteger("index", i);
+ search_engines.Append(entry);
+ if (model_urls[i] == default_url)
+ default_index = i;
+ }
+
+ scoped_ptr<Value> default_value(Value::CreateIntegerValue(default_index));
+ scoped_ptr<Value> default_managed(Value::CreateBooleanValue(
+ template_url_service_->is_default_search_managed()));
+
+ web_ui_->CallJavascriptFunction("BrowserOptions.updateSearchEngines",
+ search_engines, *default_value,
+ *default_managed);
+}
+
+void BrowserOptionsHandler::SetDefaultSearchEngine(const ListValue* args) {
+ int selected_index = -1;
+ if (!ExtractIntegerValue(args, &selected_index)) {
+ NOTREACHED();
+ return;
+ }
+
+ std::vector<const TemplateURL*> model_urls =
+ template_url_service_->GetTemplateURLs();
+ if (selected_index >= 0 &&
+ selected_index < static_cast<int>(model_urls.size()))
+ template_url_service_->SetDefaultSearchProvider(model_urls[selected_index]);
+
+ UserMetrics::RecordAction(UserMetricsAction("Options_SearchEngineChanged"));
+}
+
+void BrowserOptionsHandler::UpdateSearchEngines() {
+ template_url_service_ =
+ TemplateURLServiceFactory::GetForProfile(Profile::FromWebUI(web_ui_));
+ if (template_url_service_) {
+ template_url_service_->Load();
+ template_url_service_->AddObserver(this);
+ OnTemplateURLServiceChanged();
+ }
+}
+
+void BrowserOptionsHandler::UpdateStartupPages() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ const SessionStartupPref startup_pref =
+ SessionStartupPref::GetStartupPref(profile->GetPrefs());
+ startup_custom_pages_table_model_->SetURLs(startup_pref.urls);
+}
+
+void BrowserOptionsHandler::OnModelChanged() {
+ ListValue startup_pages;
+ int page_count = startup_custom_pages_table_model_->RowCount();
+ std::vector<GURL> urls = startup_custom_pages_table_model_->GetURLs();
+ for (int i = 0; i < page_count; ++i) {
+ DictionaryValue* entry = new DictionaryValue();
+ entry->SetString("title", startup_custom_pages_table_model_->GetText(i, 0));
+ entry->SetString("url", urls[i].spec());
+ entry->SetString("tooltip",
+ startup_custom_pages_table_model_->GetTooltip(i));
+ entry->SetString("modelIndex", base::IntToString(i));
+ startup_pages.Append(entry);
+ }
+
+ web_ui_->CallJavascriptFunction("BrowserOptions.updateStartupPages",
+ startup_pages);
+}
+
+void BrowserOptionsHandler::OnItemsChanged(int start, int length) {
+ OnModelChanged();
+}
+
+void BrowserOptionsHandler::OnItemsAdded(int start, int length) {
+ OnModelChanged();
+}
+
+void BrowserOptionsHandler::OnItemsRemoved(int start, int length) {
+ OnModelChanged();
+}
+
+void BrowserOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ std::string* pref = content::Details<std::string>(details).ptr();
+ if (*pref == prefs::kDefaultBrowserSettingEnabled) {
+ UpdateDefaultBrowserState();
+ } else if (*pref == prefs::kURLsToRestoreOnStartup) {
+ UpdateStartupPages();
+ } else {
+ NOTREACHED();
+ }
+ } else {
+ NOTREACHED();
+ }
+}
+
+void BrowserOptionsHandler::SetStartupPagesToCurrentPages(
+ const ListValue* args) {
+ startup_custom_pages_table_model_->SetToCurrentlyOpenPages();
+ SaveStartupPagesPref();
+}
+
+void BrowserOptionsHandler::RemoveStartupPages(const ListValue* args) {
+ for (int i = args->GetSize() - 1; i >= 0; --i) {
+ std::string string_value;
+ CHECK(args->GetString(i, &string_value));
+
+ int selected_index;
+ base::StringToInt(string_value, &selected_index);
+ if (selected_index < 0 ||
+ selected_index >= startup_custom_pages_table_model_->RowCount()) {
+ NOTREACHED();
+ return;
+ }
+ startup_custom_pages_table_model_->Remove(selected_index);
+ }
+
+ SaveStartupPagesPref();
+}
+
+void BrowserOptionsHandler::AddStartupPage(const ListValue* args) {
+ std::string url_string;
+ CHECK_EQ(args->GetSize(), 1U);
+ CHECK(args->GetString(0, &url_string));
+
+ GURL url = URLFixerUpper::FixupURL(url_string, std::string());
+ if (!url.is_valid())
+ return;
+ int index = startup_custom_pages_table_model_->RowCount();
+ startup_custom_pages_table_model_->Add(index, url);
+ SaveStartupPagesPref();
+}
+
+void BrowserOptionsHandler::EditStartupPage(const ListValue* args) {
+ std::string url_string;
+ std::string index_string;
+ int index;
+ CHECK_EQ(args->GetSize(), 2U);
+ CHECK(args->GetString(0, &index_string));
+ CHECK(base::StringToInt(index_string, &index));
+ CHECK(args->GetString(1, &url_string));
+
+ if (index < 0 || index > startup_custom_pages_table_model_->RowCount()) {
+ NOTREACHED();
+ return;
+ }
+
+ std::vector<GURL> urls = startup_custom_pages_table_model_->GetURLs();
+ urls[index] = URLFixerUpper::FixupURL(url_string, std::string());
+ startup_custom_pages_table_model_->SetURLs(urls);
+ SaveStartupPagesPref();
+}
+
+void BrowserOptionsHandler::DragDropStartupPage(const ListValue* args) {
+ CHECK_EQ(args->GetSize(), 2U);
+
+ std::string value;
+ int to_index;
+
+ CHECK(args->GetString(0, &value));
+ base::StringToInt(value, &to_index);
+
+ ListValue* selected;
+ CHECK(args->GetList(1, &selected));
+
+ std::vector<int> index_list;
+ for (size_t i = 0; i < selected->GetSize(); ++i) {
+ int index;
+ CHECK(selected->GetString(i, &value));
+ base::StringToInt(value, &index);
+ index_list.push_back(index);
+ }
+
+ startup_custom_pages_table_model_->MoveURLs(to_index, index_list);
+ SaveStartupPagesPref();
+}
+
+void BrowserOptionsHandler::SaveStartupPagesPref() {
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+
+ SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
+ pref.urls = startup_custom_pages_table_model_->GetURLs();
+
+ SessionStartupPref::SetStartupPref(prefs, pref);
+}
+
+void BrowserOptionsHandler::RequestAutocompleteSuggestions(
+ const ListValue* args) {
+ string16 input;
+ CHECK_EQ(args->GetSize(), 1U);
+ CHECK(args->GetString(0, &input));
+
+ autocomplete_controller_->Start(input, string16(), true, false, false,
+ AutocompleteInput::ALL_MATCHES);
+}
+
+void BrowserOptionsHandler::EnableInstant(const ListValue* args) {
+ InstantController::Enable(Profile::FromWebUI(web_ui_));
+}
+
+void BrowserOptionsHandler::DisableInstant(const ListValue* args) {
+ InstantController::Disable(Profile::FromWebUI(web_ui_));
+}
+
+void BrowserOptionsHandler::GetInstantFieldTrialStatus(const ListValue* args) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ base::FundamentalValue enabled(
+ InstantFieldTrial::IsInstantExperiment(profile) &&
+ !InstantFieldTrial::IsHiddenExperiment(profile));
+ web_ui_->CallJavascriptFunction("BrowserOptions.setInstantFieldTrialStatus",
+ enabled);
+}
+
+void BrowserOptionsHandler::OnResultChanged(bool default_match_changed) {
+ const AutocompleteResult& result = autocomplete_controller_->result();
+ ListValue suggestions;
+ for (size_t i = 0; i < result.size(); ++i) {
+ const AutocompleteMatch& match = result.match_at(i);
+ AutocompleteMatch::Type type = match.type;
+ if (type != AutocompleteMatch::HISTORY_URL &&
+ type != AutocompleteMatch::HISTORY_TITLE &&
+ type != AutocompleteMatch::HISTORY_BODY &&
+ type != AutocompleteMatch::HISTORY_KEYWORD &&
+ type != AutocompleteMatch::NAVSUGGEST)
+ continue;
+ DictionaryValue* entry = new DictionaryValue();
+ entry->SetString("title", match.description);
+ entry->SetString("displayURL", match.contents);
+ entry->SetString("url", match.destination_url.spec());
+ suggestions.Append(entry);
+ }
+
+ web_ui_->CallJavascriptFunction(
+ "BrowserOptions.updateAutocompleteSuggestions", suggestions);
+}
diff --git a/chrome/browser/ui/webui/options2/browser_options_handler.h b/chrome/browser/ui/webui/options2/browser_options_handler.h
new file mode 100644
index 0000000..dcd8a86
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/browser_options_handler.h
@@ -0,0 +1,136 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_BROWSER_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_BROWSER_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/autocomplete/autocomplete_controller_delegate.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/search_engines/template_url_service_observer.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "ui/base/models/table_model_observer.h"
+
+class AutocompleteController;
+class CustomHomePagesTableModel;
+class TemplateURLService;
+
+// Chrome browser options page UI handler.
+class BrowserOptionsHandler : public OptionsPage2UIHandler,
+ public AutocompleteControllerDelegate,
+ public ShellIntegration::DefaultWebClientObserver,
+ public TemplateURLServiceObserver,
+ public ui::TableModelObserver {
+ public:
+ BrowserOptionsHandler();
+ virtual ~BrowserOptionsHandler();
+
+ virtual void Initialize() OVERRIDE;
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // AutocompleteControllerDelegate implementation.
+ virtual void OnResultChanged(bool default_match_changed) OVERRIDE;
+
+ // ShellIntegration::DefaultWebClientObserver implementation.
+ virtual void SetDefaultWebClientUIState(
+ ShellIntegration::DefaultWebClientUIState state) OVERRIDE;
+
+ // TemplateURLServiceObserver implementation.
+ virtual void OnTemplateURLServiceChanged() OVERRIDE;
+
+ // ui::TableModelObserver implementation.
+ virtual void OnModelChanged() OVERRIDE;
+ virtual void OnItemsChanged(int start, int length) OVERRIDE;
+ virtual void OnItemsAdded(int start, int length) OVERRIDE;
+ virtual void OnItemsRemoved(int start, int length) OVERRIDE;
+
+ private:
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // Makes this the default browser. Called from WebUI.
+ void BecomeDefaultBrowser(const ListValue* args);
+
+ // Sets the search engine at the given index to be default. Called from WebUI.
+ void SetDefaultSearchEngine(const ListValue* args);
+
+ // Removes the startup page at the given indexes. Called from WebUI.
+ void RemoveStartupPages(const ListValue* args);
+
+ // Adds a startup page with the given URL after the given index.
+ // Called from WebUI.
+ void AddStartupPage(const ListValue* args);
+
+ // Changes the startup page at the given index to the given URL.
+ // Called from WebUI.
+ void EditStartupPage(const ListValue* args);
+
+ // Sets the startup page set to the current pages. Called from WebUI.
+ void SetStartupPagesToCurrentPages(const ListValue* args);
+
+ // Writes the current set of startup pages to prefs. Called from WebUI.
+ void DragDropStartupPage(const ListValue* args);
+
+ // Gets autocomplete suggestions asychronously for the given string.
+ // Called from WebUI.
+ void RequestAutocompleteSuggestions(const ListValue* args);
+
+ // Enables/disables Instant.
+ void EnableInstant(const ListValue* args);
+ void DisableInstant(const ListValue* args);
+
+ // Called to request information about the Instant field trial.
+ void GetInstantFieldTrialStatus(const ListValue* args);
+
+ // Returns the string ID for the given default browser state.
+ int StatusStringIdForState(ShellIntegration::DefaultWebClientState state);
+
+ // Gets the current default browser state, and asynchronously reports it to
+ // the WebUI page.
+ void UpdateDefaultBrowserState();
+
+ // Updates the UI with the given state for the default browser.
+ void SetDefaultBrowserUIString(int status_string_id);
+
+ // Loads the current set of custom startup pages and reports it to the WebUI.
+ void UpdateStartupPages();
+
+ // Loads the possible default search engine list and reports it to the WebUI.
+ void UpdateSearchEngines();
+
+ // Writes the current set of startup pages to prefs.
+ void SaveStartupPagesPref();
+
+ scoped_refptr<ShellIntegration::DefaultBrowserWorker>
+ default_browser_worker_;
+
+ StringPrefMember homepage_;
+ BooleanPrefMember default_browser_policy_;
+
+ // Used to observe updates to the preference of the list of URLs to load
+ // on startup, which can be updated via sync.
+ PrefChangeRegistrar pref_change_registrar_;
+
+ TemplateURLService* template_url_service_; // Weak.
+
+ // TODO(stuartmorgan): Once there are no other clients of
+ // CustomHomePagesTableModel, consider changing it to something more like
+ // TemplateURLService.
+ scoped_ptr<CustomHomePagesTableModel> startup_custom_pages_table_model_;
+
+ scoped_ptr<AutocompleteController> autocomplete_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_BROWSER_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/certificate_manager_browsertest.js b/chrome/browser/ui/webui/options2/certificate_manager_browsertest.js
new file mode 100644
index 0000000..fdd2373
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/certificate_manager_browsertest.js
@@ -0,0 +1,33 @@
+// 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.
+
+/**
+ * TestFixture for certificate manager WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function CertificateManagerWebUITest() {}
+
+CertificateManagerWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the certificate manager.
+ **/
+ browsePreload: 'chrome://settings/certificates',
+};
+
+// Mac and Windows go to native certificate manager.
+GEN('#if defined(OS_MACOSX) || defined(OS_WIN)');
+GEN('#define MAYBE_testOpenCertificateManager ' +
+ 'DISABLED_testOpenCertificateManager');
+GEN('#else');
+GEN('#define MAYBE_testOpenCertificateManager ' +
+ 'testOpenCertificateManager');
+GEN('#endif // defined(OS_MACOSX) || defined(OS_WIN)');
+// Test opening the certificate manager has correct location.
+TEST_F('CertificateManagerWebUITest',
+ 'MAYBE_testOpenCertificateManager', function() {
+ assertEquals(this.browsePreload, document.location.href);
+ });
diff --git a/chrome/browser/ui/webui/options2/certificate_manager_handler.cc b/chrome/browser/ui/webui/options2/certificate_manager_handler.cc
new file mode 100644
index 0000000..00d52f6
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/certificate_manager_handler.cc
@@ -0,0 +1,1046 @@
+// 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/options2/certificate_manager_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h" // for FileAccessProvider
+#include "base/memory/scoped_vector.h"
+#include "base/safe_strerror_posix.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/ui/certificate_dialogs.h"
+#include "chrome/browser/ui/crypto_module_password_dialog.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/public/browser/browser_thread.h" // for FileAccessProvider
+#include "grit/generated_resources.h"
+#include "net/base/crypto_module.h"
+#include "net/base/x509_certificate.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#endif
+
+using content::BrowserThread;
+
+namespace {
+
+static const char kKeyId[] = "id";
+static const char kSubNodesId[] = "subnodes";
+static const char kNameId[] = "name";
+static const char kReadOnlyId[] = "readonly";
+static const char kUntrustedId[] = "untrusted";
+static const char kSecurityDeviceId[] = "device";
+static const char kErrorId[] = "error";
+
+// Enumeration of different callers of SelectFile. (Start counting at 1 so
+// if SelectFile is accidentally called with params=NULL it won't match any.)
+enum {
+ EXPORT_PERSONAL_FILE_SELECTED = 1,
+ IMPORT_PERSONAL_FILE_SELECTED,
+ IMPORT_SERVER_FILE_SELECTED,
+ IMPORT_CA_FILE_SELECTED,
+};
+
+// TODO(mattm): These are duplicated from cookies_view_handler.cc
+// Encodes a pointer value into a hex string.
+std::string PointerToHexString(const void* pointer) {
+ return base::HexEncode(&pointer, sizeof(pointer));
+}
+
+// Decodes a pointer from a hex string.
+void* HexStringToPointer(const std::string& str) {
+ std::vector<uint8> buffer;
+ if (!base::HexStringToBytes(str, &buffer) ||
+ buffer.size() != sizeof(void*)) {
+ return NULL;
+ }
+
+ return *reinterpret_cast<void**>(&buffer[0]);
+}
+
+std::string OrgNameToId(const std::string& org) {
+ return "org-" + org;
+}
+
+std::string CertToId(const net::X509Certificate& cert) {
+ return "cert-" + PointerToHexString(&cert);
+}
+
+net::X509Certificate* IdToCert(const std::string& id) {
+ if (!StartsWithASCII(id, "cert-", true))
+ return NULL;
+ return reinterpret_cast<net::X509Certificate*>(
+ HexStringToPointer(id.substr(5)));
+}
+
+net::X509Certificate* CallbackArgsToCert(const ListValue* args) {
+ std::string node_id;
+ if (!args->GetString(0, &node_id)){
+ return NULL;
+ }
+ net::X509Certificate* cert = IdToCert(node_id);
+ if (!cert) {
+ NOTREACHED();
+ return NULL;
+ }
+ return cert;
+}
+
+bool CallbackArgsToBool(const ListValue* args, int index, bool* result) {
+ std::string string_value;
+ if (!args->GetString(index, &string_value))
+ return false;
+
+ *result = string_value[0] == 't';
+ return true;
+}
+
+struct DictionaryIdComparator {
+ explicit DictionaryIdComparator(icu::Collator* collator)
+ : collator_(collator) {
+ }
+
+ bool operator()(const Value* a,
+ const Value* b) const {
+ DCHECK(a->GetType() == Value::TYPE_DICTIONARY);
+ DCHECK(b->GetType() == Value::TYPE_DICTIONARY);
+ const DictionaryValue* a_dict = reinterpret_cast<const DictionaryValue*>(a);
+ const DictionaryValue* b_dict = reinterpret_cast<const DictionaryValue*>(b);
+ string16 a_str;
+ string16 b_str;
+ a_dict->GetString(kNameId, &a_str);
+ b_dict->GetString(kNameId, &b_str);
+ if (collator_ == NULL)
+ return a_str < b_str;
+ return l10n_util::CompareString16WithCollator(
+ collator_, a_str, b_str) == UCOL_LESS;
+ }
+
+ icu::Collator* collator_;
+};
+
+std::string NetErrorToString(int net_error) {
+ switch (net_error) {
+ // TODO(mattm): handle more cases.
+ case net::ERR_IMPORT_CA_CERT_NOT_CA:
+ return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_ERROR_NOT_CA);
+ default:
+ return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR);
+ }
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// FileAccessProvider
+
+// TODO(mattm): Move to some shared location?
+class FileAccessProvider
+ : public base::RefCountedThreadSafe<FileAccessProvider>,
+ public CancelableRequestProvider {
+ public:
+ // Reports 0 on success or errno on failure, and the data of the file upon
+ // success.
+ // TODO(mattm): don't pass std::string by value.. could use RefCountedBytes
+ // but it's a vector. Maybe do the derive from CancelableRequest thing
+ // described in cancelable_request.h?
+ typedef Callback2<int, std::string>::Type ReadCallback;
+
+ // Reports 0 on success or errno on failure, and the number of bytes written,
+ // on success.
+ typedef Callback2<int, int>::Type WriteCallback;
+
+ Handle StartRead(const FilePath& path,
+ CancelableRequestConsumerBase* consumer,
+ ReadCallback* callback);
+ Handle StartWrite(const FilePath& path,
+ const std::string& data,
+ CancelableRequestConsumerBase* consumer,
+ WriteCallback* callback);
+
+ private:
+ void DoRead(scoped_refptr<CancelableRequest<ReadCallback> > request,
+ FilePath path);
+ void DoWrite(scoped_refptr<CancelableRequest<WriteCallback> > request,
+ FilePath path,
+ std::string data);
+};
+
+CancelableRequestProvider::Handle FileAccessProvider::StartRead(
+ const FilePath& path,
+ CancelableRequestConsumerBase* consumer,
+ FileAccessProvider::ReadCallback* callback) {
+ scoped_refptr<CancelableRequest<ReadCallback> > request(
+ new CancelableRequest<ReadCallback>(callback));
+ AddRequest(request, consumer);
+
+ // Send the parameters and the request to the file thread.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&FileAccessProvider::DoRead, this, request, path));
+
+ // The handle will have been set by AddRequest.
+ return request->handle();
+}
+
+CancelableRequestProvider::Handle FileAccessProvider::StartWrite(
+ const FilePath& path,
+ const std::string& data,
+ CancelableRequestConsumerBase* consumer,
+ WriteCallback* callback) {
+ scoped_refptr<CancelableRequest<WriteCallback> > request(
+ new CancelableRequest<WriteCallback>(callback));
+ AddRequest(request, consumer);
+
+ // Send the parameters and the request to the file thWrite.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&FileAccessProvider::DoWrite, this, request, path, data));
+
+ // The handle will have been set by AddRequest.
+ return request->handle();
+}
+
+void FileAccessProvider::DoRead(
+ scoped_refptr<CancelableRequest<ReadCallback> > request,
+ FilePath path) {
+ if (request->canceled())
+ return;
+
+ std::string data;
+ VLOG(1) << "DoRead starting read";
+ bool success = file_util::ReadFileToString(path, &data);
+ int saved_errno = success ? 0 : errno;
+ VLOG(1) << "DoRead done read: " << success << " " << data.size();
+ request->ForwardResult(ReadCallback::TupleType(saved_errno, data));
+}
+
+void FileAccessProvider::DoWrite(
+ scoped_refptr<CancelableRequest<WriteCallback> > request,
+ FilePath path,
+ std::string data) {
+ VLOG(1) << "DoWrite starting write";
+ int bytes_written = file_util::WriteFile(path, data.data(), data.size());
+ int saved_errno = bytes_written >= 0 ? 0 : errno;
+ VLOG(1) << "DoWrite done write " << bytes_written;
+
+ if (request->canceled())
+ return;
+
+ request->ForwardResult(WriteCallback::TupleType(saved_errno, bytes_written));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CertificateManagerHandler
+
+CertificateManagerHandler::CertificateManagerHandler()
+ : file_access_provider_(new FileAccessProvider) {
+ certificate_manager_model_.reset(new CertificateManagerModel(this));
+}
+
+CertificateManagerHandler::~CertificateManagerHandler() {
+}
+
+void CertificateManagerHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "certificateManagerPage",
+ IDS_CERTIFICATE_MANAGER_TITLE);
+
+ // Tabs.
+ localized_strings->SetString("personalCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL));
+ localized_strings->SetString("serverCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL));
+ localized_strings->SetString("caCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL));
+ localized_strings->SetString("unknownCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TAB_LABEL));
+
+ // Tab descriptions.
+ localized_strings->SetString("personalCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_USER_TREE_DESCRIPTION));
+ localized_strings->SetString("serverCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION));
+ localized_strings->SetString("caCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION));
+ localized_strings->SetString("unknownCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TREE_DESCRIPTION));
+
+ // Tree columns.
+ localized_strings->SetString("certNameColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_NAME_COLUMN_LABEL));
+ localized_strings->SetString("certDeviceColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL));
+ localized_strings->SetString("certSerialColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL));
+ localized_strings->SetString("certExpiresColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPIRES_COLUMN_LABEL));
+
+ // Buttons.
+ localized_strings->SetString("view_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
+ localized_strings->SetString("import_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_BUTTON));
+ localized_strings->SetString("export_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_BUTTON));
+ localized_strings->SetString("export_all_certificates",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_ALL_BUTTON));
+ localized_strings->SetString("edit_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_BUTTON));
+ localized_strings->SetString("delete_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_BUTTON));
+
+ // Certificate Delete overlay strings.
+ localized_strings->SetString("personalCertsTabDeleteConfirm",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_FORMAT));
+ localized_strings->SetString("personalCertsTabDeleteImpact",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_DESCRIPTION));
+ localized_strings->SetString("serverCertsTabDeleteConfirm",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_FORMAT));
+ localized_strings->SetString("serverCertsTabDeleteImpact",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_DESCRIPTION));
+ localized_strings->SetString("caCertsTabDeleteConfirm",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_FORMAT));
+ localized_strings->SetString("caCertsTabDeleteImpact",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_DESCRIPTION));
+ localized_strings->SetString("unknownCertsTabDeleteConfirm",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_UNKNOWN_FORMAT));
+ localized_strings->SetString("unknownCertsTabDeleteImpact", "");
+
+ // Certificate Restore overlay strings.
+ localized_strings->SetString("certificateRestorePasswordDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_RESTORE_PASSWORD_DESC));
+ localized_strings->SetString("certificatePasswordLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PASSWORD_LABEL));
+
+ // Personal Certificate Export overlay strings.
+ localized_strings->SetString("certificateExportPasswordDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_DESC));
+ localized_strings->SetString("certificateExportPasswordHelp",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_HELP));
+ localized_strings->SetString("certificateConfirmPasswordLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CONFIRM_PASSWORD_LABEL));
+
+ // Edit CA Trust & Import CA overlay strings.
+ localized_strings->SetString("certificateEditTrustLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_TRUST_LABEL));
+ localized_strings->SetString("certificateEditCaTrustDescriptionFormat",
+ l10n_util::GetStringUTF16(
+ IDS_CERT_MANAGER_EDIT_CA_TRUST_DESCRIPTION_FORMAT));
+ localized_strings->SetString("certificateImportCaDescriptionFormat",
+ l10n_util::GetStringUTF16(
+ IDS_CERT_MANAGER_IMPORT_CA_DESCRIPTION_FORMAT));
+ localized_strings->SetString("certificateCaTrustSSLLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_SSL_LABEL));
+ localized_strings->SetString("certificateCaTrustEmailLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_EMAIL_LABEL));
+ localized_strings->SetString("certificateCaTrustObjSignLabel",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_OBJSIGN_LABEL));
+ localized_strings->SetString("certificateImportErrorFormat",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_ERROR_FORMAT));
+
+ // Badges next to certificates
+ localized_strings->SetString("badgeCertUntrusted",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNTRUSTED));
+
+#if defined(OS_CHROMEOS)
+ localized_strings->SetString("importAndBindCertificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_AND_BIND_BUTTON));
+ localized_strings->SetString("hardwareBackedKeyFormat",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT));
+ localized_strings->SetString("chromeOSDeviceName",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
+#endif // defined(OS_CHROMEOS)
+}
+
+void CertificateManagerHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback(
+ "viewCertificate",
+ base::Bind(&CertificateManagerHandler::View, base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "getCaCertificateTrust",
+ base::Bind(&CertificateManagerHandler::GetCATrust,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "editCaCertificateTrust",
+ base::Bind(&CertificateManagerHandler::EditCATrust,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "editServerCertificate",
+ base::Bind(&CertificateManagerHandler::EditServer,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "cancelImportExportCertificate",
+ base::Bind(&CertificateManagerHandler::CancelImportExportProcess,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "exportPersonalCertificate",
+ base::Bind(&CertificateManagerHandler::ExportPersonal,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "exportAllPersonalCertificates",
+ base::Bind(&CertificateManagerHandler::ExportAllPersonal,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "exportPersonalCertificatePasswordSelected",
+ base::Bind(&CertificateManagerHandler::ExportPersonalPasswordSelected,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "importPersonalCertificate",
+ base::Bind(&CertificateManagerHandler::StartImportPersonal,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "importPersonalCertificatePasswordSelected",
+ base::Bind(&CertificateManagerHandler::ImportPersonalPasswordSelected,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "importCaCertificate",
+ base::Bind(&CertificateManagerHandler::ImportCA,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "importCaCertificateTrustSelected",
+ base::Bind(&CertificateManagerHandler::ImportCATrustSelected,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "importServerCertificate",
+ base::Bind(&CertificateManagerHandler::ImportServer,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "exportCertificate",
+ base::Bind(&CertificateManagerHandler::Export,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "deleteCertificate",
+ base::Bind(&CertificateManagerHandler::Delete,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback(
+ "populateCertificateManager",
+ base::Bind(&CertificateManagerHandler::Populate,
+ base::Unretained(this)));
+
+#if defined(OS_CHROMEOS)
+ web_ui_->RegisterMessageCallback(
+ "checkTpmTokenReady",
+ base::Bind(&CertificateManagerHandler::CheckTpmTokenReady,
+ base::Unretained(this)));
+#endif
+}
+
+void CertificateManagerHandler::CertificatesRefreshed() {
+ PopulateTree("personalCertsTab", net::USER_CERT);
+ PopulateTree("serverCertsTab", net::SERVER_CERT);
+ PopulateTree("caCertsTab", net::CA_CERT);
+ PopulateTree("otherCertsTab", net::UNKNOWN_CERT);
+ VLOG(1) << "populating finished";
+}
+
+void CertificateManagerHandler::FileSelected(const FilePath& path, int index,
+ void* params) {
+ switch (reinterpret_cast<intptr_t>(params)) {
+ case EXPORT_PERSONAL_FILE_SELECTED:
+ ExportPersonalFileSelected(path);
+ break;
+ case IMPORT_PERSONAL_FILE_SELECTED:
+ ImportPersonalFileSelected(path);
+ break;
+ case IMPORT_SERVER_FILE_SELECTED:
+ ImportServerFileSelected(path);
+ break;
+ case IMPORT_CA_FILE_SELECTED:
+ ImportCAFileSelected(path);
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void CertificateManagerHandler::FileSelectionCanceled(void* params) {
+ switch (reinterpret_cast<intptr_t>(params)) {
+ case EXPORT_PERSONAL_FILE_SELECTED:
+ case IMPORT_PERSONAL_FILE_SELECTED:
+ case IMPORT_SERVER_FILE_SELECTED:
+ case IMPORT_CA_FILE_SELECTED:
+ ImportExportCleanup();
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void CertificateManagerHandler::View(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ if (!cert)
+ return;
+ ShowCertificateViewer(GetParentWindow(), cert);
+}
+
+void CertificateManagerHandler::GetCATrust(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ if (!cert) {
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
+ return;
+ }
+
+ net::CertDatabase::TrustBits trust_bits =
+ certificate_manager_model_->cert_db().GetCertTrust(cert, net::CA_CERT);
+ base::FundamentalValue ssl_value(
+ static_cast<bool>(trust_bits & net::CertDatabase::TRUSTED_SSL));
+ base::FundamentalValue email_value(
+ static_cast<bool>(trust_bits & net::CertDatabase::TRUSTED_EMAIL));
+ base::FundamentalValue obj_sign_value(
+ static_cast<bool>(trust_bits & net::CertDatabase::TRUSTED_OBJ_SIGN));
+ web_ui_->CallJavascriptFunction(
+ "CertificateEditCaTrustOverlay.populateTrust",
+ ssl_value, email_value, obj_sign_value);
+}
+
+void CertificateManagerHandler::EditCATrust(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ bool fail = !cert;
+ bool trust_ssl = false;
+ bool trust_email = false;
+ bool trust_obj_sign = false;
+ fail |= !CallbackArgsToBool(args, 1, &trust_ssl);
+ fail |= !CallbackArgsToBool(args, 2, &trust_email);
+ fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
+ if (fail) {
+ LOG(ERROR) << "EditCATrust args fail";
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
+ return;
+ }
+
+ bool result = certificate_manager_model_->SetCertTrust(
+ cert,
+ net::CA_CERT,
+ trust_ssl * net::CertDatabase::TRUSTED_SSL +
+ trust_email * net::CertDatabase::TRUSTED_EMAIL +
+ trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN);
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
+ if (!result) {
+ // TODO(mattm): better error messages?
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SET_TRUST_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
+ }
+}
+
+void CertificateManagerHandler::EditServer(const ListValue* args) {
+ NOTIMPLEMENTED();
+}
+
+void CertificateManagerHandler::ExportPersonal(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ if (!cert)
+ return;
+
+ selected_cert_list_.push_back(cert);
+
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.resize(1);
+ file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
+ file_type_info.extension_description_overrides.push_back(
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
+ file_type_info.include_all_files = true;
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ select_file_dialog_->SelectFile(
+ SelectFileDialog::SELECT_SAVEAS_FILE, string16(),
+ FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
+ web_ui_->tab_contents(), GetParentWindow(),
+ reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED));
+}
+
+void CertificateManagerHandler::ExportAllPersonal(const ListValue* args) {
+ NOTIMPLEMENTED();
+}
+
+void CertificateManagerHandler::ExportPersonalFileSelected(
+ const FilePath& path) {
+ file_path_ = path;
+ web_ui_->CallJavascriptFunction(
+ "CertificateManager.exportPersonalAskPassword");
+}
+
+void CertificateManagerHandler::ExportPersonalPasswordSelected(
+ const ListValue* args) {
+ if (!args->GetString(0, &password_)){
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ImportExportCleanup();
+ return;
+ }
+
+ // Currently, we don't support exporting more than one at a time. If we do,
+ // this would need to either change this to use UnlockSlotsIfNecessary or
+ // change UnlockCertSlotIfNecessary to take a CertificateList.
+ DCHECK_EQ(selected_cert_list_.size(), 1U);
+
+ // TODO(mattm): do something smarter about non-extractable keys
+ browser::UnlockCertSlotIfNecessary(
+ selected_cert_list_[0].get(),
+ browser::kCryptoModulePasswordCertExport,
+ "", // unused.
+ base::Bind(&CertificateManagerHandler::ExportPersonalSlotsUnlocked,
+ base::Unretained(this)));
+}
+
+void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
+ std::string output;
+ int num_exported = certificate_manager_model_->cert_db().ExportToPKCS12(
+ selected_cert_list_,
+ password_,
+ &output);
+ if (!num_exported) {
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
+ ImportExportCleanup();
+ return;
+ }
+ file_access_provider_->StartWrite(
+ file_path_,
+ output,
+ &consumer_,
+ NewCallback(this, &CertificateManagerHandler::ExportPersonalFileWritten));
+}
+
+void CertificateManagerHandler::ExportPersonalFileWritten(int write_errno,
+ int bytes_written) {
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ImportExportCleanup();
+ if (write_errno) {
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
+ l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_WRITE_ERROR_FORMAT,
+ UTF8ToUTF16(safe_strerror(write_errno))));
+ }
+}
+
+void CertificateManagerHandler::StartImportPersonal(const ListValue* args) {
+ SelectFileDialog::FileTypeInfo file_type_info;
+ if (!args->GetBoolean(0, &use_hardware_backed_)){
+ // Unable to retrieve the hardware backed attribute from the args,
+ // so bail.
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ImportExportCleanup();
+ return;
+ }
+ file_type_info.extensions.resize(1);
+ file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
+ file_type_info.extension_description_overrides.push_back(
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
+ file_type_info.include_all_files = true;
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ select_file_dialog_->SelectFile(
+ SelectFileDialog::SELECT_OPEN_FILE, string16(),
+ FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
+ web_ui_->tab_contents(), GetParentWindow(),
+ reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED));
+}
+
+void CertificateManagerHandler::ImportPersonalFileSelected(
+ const FilePath& path) {
+ file_path_ = path;
+ web_ui_->CallJavascriptFunction(
+ "CertificateManager.importPersonalAskPassword");
+}
+
+void CertificateManagerHandler::ImportPersonalPasswordSelected(
+ const ListValue* args) {
+ if (!args->GetString(0, &password_)){
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ImportExportCleanup();
+ return;
+ }
+ file_access_provider_->StartRead(
+ file_path_,
+ &consumer_,
+ NewCallback(this, &CertificateManagerHandler::ImportPersonalFileRead));
+}
+
+void CertificateManagerHandler::ImportPersonalFileRead(
+ int read_errno, std::string data) {
+ if (read_errno) {
+ ImportExportCleanup();
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
+ UTF8ToUTF16(safe_strerror(read_errno))));
+ return;
+ }
+
+ file_data_ = data;
+
+ if (use_hardware_backed_) {
+ module_ = certificate_manager_model_->cert_db().GetPrivateModule();
+ } else {
+ module_ = certificate_manager_model_->cert_db().GetPublicModule();
+ }
+
+ net::CryptoModuleList modules;
+ modules.push_back(module_);
+ browser::UnlockSlotsIfNecessary(
+ modules,
+ browser::kCryptoModulePasswordCertImport,
+ "", // unused.
+ base::Bind(&CertificateManagerHandler::ImportPersonalSlotUnlocked,
+ base::Unretained(this)));
+}
+
+void CertificateManagerHandler::ImportPersonalSlotUnlocked() {
+ // Determine if the private key should be unextractable after the import.
+ // We do this by checking the value of |use_hardware_backed_| which is set
+ // to true if importing into a hardware module. Currently, this only happens
+ // for Chrome OS when the "Import and Bind" option is chosen.
+ bool is_extractable = !use_hardware_backed_;
+ int result = certificate_manager_model_->ImportFromPKCS12(
+ module_, file_data_, password_, is_extractable);
+ ImportExportCleanup();
+ web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
+ int string_id;
+ switch (result) {
+ case net::OK:
+ return;
+ case net::ERR_PKCS12_IMPORT_BAD_PASSWORD:
+ // TODO(mattm): if the error was a bad password, we should reshow the
+ // password dialog after the user dismisses the error dialog.
+ string_id = IDS_CERT_MANAGER_BAD_PASSWORD;
+ break;
+ case net::ERR_PKCS12_IMPORT_INVALID_MAC:
+ string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_INVALID_MAC;
+ break;
+ case net::ERR_PKCS12_IMPORT_INVALID_FILE:
+ string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_INVALID_FILE;
+ break;
+ case net::ERR_PKCS12_IMPORT_UNSUPPORTED:
+ string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_UNSUPPORTED;
+ break;
+ default:
+ string_id = IDS_CERT_MANAGER_UNKNOWN_ERROR;
+ break;
+ }
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(string_id));
+}
+
+void CertificateManagerHandler::CancelImportExportProcess(
+ const ListValue* args) {
+ ImportExportCleanup();
+}
+
+void CertificateManagerHandler::ImportExportCleanup() {
+ file_path_.clear();
+ password_.clear();
+ file_data_.clear();
+ use_hardware_backed_ = false;
+ selected_cert_list_.clear();
+ module_ = NULL;
+
+ // There may be pending file dialogs, we need to tell them that we've gone
+ // away so they don't try and call back to us.
+ if (select_file_dialog_.get())
+ select_file_dialog_->ListenerDestroyed();
+ select_file_dialog_ = NULL;
+}
+
+void CertificateManagerHandler::ImportServer(const ListValue* args) {
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ ShowCertSelectFileDialog(
+ select_file_dialog_.get(),
+ SelectFileDialog::SELECT_OPEN_FILE,
+ FilePath(),
+ web_ui_->tab_contents(),
+ GetParentWindow(),
+ reinterpret_cast<void*>(IMPORT_SERVER_FILE_SELECTED));
+}
+
+void CertificateManagerHandler::ImportServerFileSelected(const FilePath& path) {
+ file_path_ = path;
+ file_access_provider_->StartRead(
+ file_path_,
+ &consumer_,
+ NewCallback(this, &CertificateManagerHandler::ImportServerFileRead));
+}
+
+void CertificateManagerHandler::ImportServerFileRead(int read_errno,
+ std::string data) {
+ if (read_errno) {
+ ImportExportCleanup();
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
+ UTF8ToUTF16(safe_strerror(read_errno))));
+ return;
+ }
+
+ selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
+ data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
+ if (selected_cert_list_.empty()) {
+ ImportExportCleanup();
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
+ return;
+ }
+
+ net::CertDatabase::ImportCertFailureList not_imported;
+ bool result = certificate_manager_model_->ImportServerCert(
+ selected_cert_list_,
+ &not_imported);
+ if (!result) {
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
+ } else if (!not_imported.empty()) {
+ ShowImportErrors(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
+ not_imported);
+ }
+ ImportExportCleanup();
+}
+
+void CertificateManagerHandler::ImportCA(const ListValue* args) {
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ ShowCertSelectFileDialog(select_file_dialog_.get(),
+ SelectFileDialog::SELECT_OPEN_FILE,
+ FilePath(),
+ web_ui_->tab_contents(),
+ GetParentWindow(),
+ reinterpret_cast<void*>(IMPORT_CA_FILE_SELECTED));
+}
+
+void CertificateManagerHandler::ImportCAFileSelected(const FilePath& path) {
+ file_path_ = path;
+ file_access_provider_->StartRead(
+ file_path_,
+ &consumer_,
+ NewCallback(this, &CertificateManagerHandler::ImportCAFileRead));
+}
+
+void CertificateManagerHandler::ImportCAFileRead(int read_errno,
+ std::string data) {
+ if (read_errno) {
+ ImportExportCleanup();
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
+ UTF8ToUTF16(safe_strerror(read_errno))));
+ return;
+ }
+
+ selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
+ data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
+ if (selected_cert_list_.empty()) {
+ ImportExportCleanup();
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
+ return;
+ }
+
+ scoped_refptr<net::X509Certificate> root_cert =
+ certificate_manager_model_->cert_db().FindRootInList(selected_cert_list_);
+
+ // TODO(mattm): check here if root_cert is not a CA cert and show error.
+
+ StringValue cert_name(root_cert->subject().GetDisplayName());
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.showImport",
+ cert_name);
+}
+
+void CertificateManagerHandler::ImportCATrustSelected(const ListValue* args) {
+ bool fail = false;
+ bool trust_ssl = false;
+ bool trust_email = false;
+ bool trust_obj_sign = false;
+ fail |= !CallbackArgsToBool(args, 0, &trust_ssl);
+ fail |= !CallbackArgsToBool(args, 1, &trust_email);
+ fail |= !CallbackArgsToBool(args, 2, &trust_obj_sign);
+ if (fail) {
+ LOG(ERROR) << "ImportCATrustSelected args fail";
+ ImportExportCleanup();
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
+ return;
+ }
+
+ net::CertDatabase::ImportCertFailureList not_imported;
+ bool result = certificate_manager_model_->ImportCACerts(
+ selected_cert_list_,
+ trust_ssl * net::CertDatabase::TRUSTED_SSL +
+ trust_email * net::CertDatabase::TRUSTED_EMAIL +
+ trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN,
+ &not_imported);
+ web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
+ if (!result) {
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
+ } else if (!not_imported.empty()) {
+ ShowImportErrors(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
+ not_imported);
+ }
+ ImportExportCleanup();
+}
+
+void CertificateManagerHandler::Export(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ if (!cert)
+ return;
+ ShowCertExportDialog(web_ui_->tab_contents(), GetParentWindow(),
+ cert->os_cert_handle());
+}
+
+void CertificateManagerHandler::Delete(const ListValue* args) {
+ net::X509Certificate* cert = CallbackArgsToCert(args);
+ if (!cert)
+ return;
+ bool result = certificate_manager_model_->Delete(cert);
+ if (!result) {
+ // TODO(mattm): better error messages?
+ ShowError(
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_DELETE_CERT_ERROR_TITLE),
+ l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
+ }
+}
+
+void CertificateManagerHandler::Populate(const ListValue* args) {
+ certificate_manager_model_->Refresh();
+}
+
+void CertificateManagerHandler::PopulateTree(const std::string& tab_name,
+ net::CertType type) {
+ const std::string tree_name = tab_name + "-tree";
+
+ scoped_ptr<icu::Collator> collator;
+ UErrorCode error = U_ZERO_ERROR;
+ collator.reset(
+ icu::Collator::createInstance(
+ icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
+ error));
+ if (U_FAILURE(error))
+ collator.reset(NULL);
+ DictionaryIdComparator comparator(collator.get());
+ CertificateManagerModel::OrgGroupingMap map;
+
+ certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
+
+ {
+ ListValue* nodes = new ListValue;
+ for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
+ i != map.end(); ++i) {
+ // Populate first level (org name).
+ DictionaryValue* dict = new DictionaryValue;
+ dict->SetString(kKeyId, OrgNameToId(i->first));
+ dict->SetString(kNameId, i->first);
+
+ // Populate second level (certs).
+ ListValue* subnodes = new ListValue;
+ for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
+ org_cert_it != i->second.end(); ++org_cert_it) {
+ DictionaryValue* cert_dict = new DictionaryValue;
+ net::X509Certificate* cert = org_cert_it->get();
+ cert_dict->SetString(kKeyId, CertToId(*cert));
+ cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
+ *cert, CertificateManagerModel::COL_SUBJECT_NAME));
+ cert_dict->SetBoolean(
+ kReadOnlyId,
+ certificate_manager_model_->cert_db().IsReadOnly(cert));
+ cert_dict->SetBoolean(
+ kUntrustedId,
+ certificate_manager_model_->cert_db().IsUntrusted(cert));
+ // TODO(mattm): Other columns.
+ subnodes->Append(cert_dict);
+ }
+ std::sort(subnodes->begin(), subnodes->end(), comparator);
+
+ dict->Set(kSubNodesId, subnodes);
+ nodes->Append(dict);
+ }
+ std::sort(nodes->begin(), nodes->end(), comparator);
+
+ ListValue args;
+ args.Append(Value::CreateStringValue(tree_name));
+ args.Append(nodes);
+ web_ui_->CallJavascriptFunction("CertificateManager.onPopulateTree", args);
+ }
+}
+
+void CertificateManagerHandler::ShowError(const std::string& title,
+ const std::string& error) const {
+ ScopedVector<const Value> args;
+ args.push_back(Value::CreateStringValue(title));
+ args.push_back(Value::CreateStringValue(error));
+ args.push_back(Value::CreateStringValue(l10n_util::GetStringUTF8(IDS_OK)));
+ args.push_back(Value::CreateNullValue()); // cancelTitle
+ args.push_back(Value::CreateNullValue()); // okCallback
+ args.push_back(Value::CreateNullValue()); // cancelCallback
+ web_ui_->CallJavascriptFunction("AlertOverlay.show", args.get());
+}
+
+void CertificateManagerHandler::ShowImportErrors(
+ const std::string& title,
+ const net::CertDatabase::ImportCertFailureList& not_imported) const {
+ std::string error;
+ if (selected_cert_list_.size() == 1)
+ error = l10n_util::GetStringUTF8(
+ IDS_CERT_MANAGER_IMPORT_SINGLE_NOT_IMPORTED);
+ else if (not_imported.size() == selected_cert_list_.size())
+ error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_ALL_NOT_IMPORTED);
+ else
+ error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_SOME_NOT_IMPORTED);
+
+ ListValue cert_error_list;
+ for (size_t i = 0; i < not_imported.size(); ++i) {
+ const net::CertDatabase::ImportCertFailure& failure = not_imported[i];
+ DictionaryValue* dict = new DictionaryValue;
+ dict->SetString(kNameId, failure.certificate->subject().GetDisplayName());
+ dict->SetString(kErrorId, NetErrorToString(failure.net_error));
+ cert_error_list.Append(dict);
+ }
+
+ StringValue title_value(title);
+ StringValue error_value(error);
+ web_ui_->CallJavascriptFunction("CertificateImportErrorOverlay.show",
+ title_value,
+ error_value,
+ cert_error_list);
+}
+
+#if defined(OS_CHROMEOS)
+void CertificateManagerHandler::CheckTpmTokenReady(const ListValue* args) {
+ chromeos::CryptohomeLibrary* cryptohome =
+ chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
+
+ // TODO(xiyuan): Use async way when underlying supports it.
+ base::FundamentalValue ready(cryptohome->Pkcs11IsTpmTokenReady());
+ web_ui_->CallJavascriptFunction("CertificateManager.onCheckTpmTokenReady",
+ ready);
+}
+#endif
+
+gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
+ return web_ui_->tab_contents()->view()->GetTopLevelNativeWindow();
+}
diff --git a/chrome/browser/ui/webui/options2/certificate_manager_handler.h b/chrome/browser/ui/webui/options2/certificate_manager_handler.h
new file mode 100644
index 0000000..0e26a17
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/certificate_manager_handler.h
@@ -0,0 +1,171 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CERTIFICATE_MANAGER_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CERTIFICATE_MANAGER_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/certificate_manager_model.h"
+#include "chrome/browser/ui/select_file_dialog.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "content/browser/cancelable_request.h"
+#include "net/base/cert_database.h"
+#include "ui/gfx/native_widget_types.h"
+
+class FileAccessProvider;
+
+class CertificateManagerHandler : public OptionsPage2UIHandler,
+ public CertificateManagerModel::Observer,
+ public SelectFileDialog::Listener {
+ public:
+ CertificateManagerHandler();
+ virtual ~CertificateManagerHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // CertificateManagerModel::Observer implementation.
+ virtual void CertificatesRefreshed() OVERRIDE;
+
+ // SelectFileDialog::Listener implementation.
+ virtual void FileSelected(const FilePath& path,
+ int index,
+ void* params) OVERRIDE;
+ virtual void FileSelectionCanceled(void* params) OVERRIDE;
+
+ private:
+ // View certificate.
+ void View(const base::ListValue* args);
+
+ // Edit server certificate trust values.
+ void EditServer(const base::ListValue* args);
+
+ // Edit certificate authority trust values. The sequence goes like:
+ // 1. user clicks edit button -> CertificateEditCaTrustOverlay.show ->
+ // GetCATrust -> CertificateEditCaTrustOverlay.populateTrust
+ // 2. user clicks ok -> EditCATrust -> CertificateEditCaTrustOverlay.dismiss
+ void GetCATrust(const base::ListValue* args);
+ void EditCATrust(const base::ListValue* args);
+
+ // Cleanup state stored during import or export process.
+ void CancelImportExportProcess(const base::ListValue* args);
+ void ImportExportCleanup();
+
+ // Export to PKCS #12 file. The sequence goes like:
+ // 1a. user click on export button -> ExportPersonal -> launches file
+ // selector
+ // 1b. user click on export all button -> ExportAllPersonal -> launches file
+ // selector
+ // 2. user selects file -> ExportPersonalFileSelected -> launches password
+ // dialog
+ // 3. user enters password -> ExportPersonalPasswordSelected -> unlock slots
+ // 4. slots unlocked -> ExportPersonalSlotsUnlocked -> exports to memory
+ // buffer -> starts async write operation
+ // 5. write finishes (or fails) -> ExportPersonalFileWritten
+ void ExportPersonal(const base::ListValue* args);
+ void ExportAllPersonal(const base::ListValue* args);
+ void ExportPersonalFileSelected(const FilePath& path);
+ void ExportPersonalPasswordSelected(const base::ListValue* args);
+ void ExportPersonalSlotsUnlocked();
+ void ExportPersonalFileWritten(int write_errno, int bytes_written);
+
+ // Import from PKCS #12 file. The sequence goes like:
+ // 1. user click on import button -> StartImportPersonal -> launches file
+ // selector
+ // 2. user selects file -> ImportPersonalFileSelected -> launches password
+ // dialog
+ // 3. user enters password -> ImportPersonalPasswordSelected -> starts async
+ // read operation
+ // 4. read operation completes -> ImportPersonalFileRead -> unlock slot
+ // 5. slot unlocked -> ImportPersonalSlotUnlocked attempts to
+ // import with previously entered password
+ // 6a. if import succeeds -> ImportExportCleanup
+ // 6b. if import fails -> show error, ImportExportCleanup
+ // TODO(mattm): allow retrying with different password
+ void StartImportPersonal(const base::ListValue* args);
+ void ImportPersonalFileSelected(const FilePath& path);
+ void ImportPersonalPasswordSelected(const base::ListValue* args);
+ void ImportPersonalFileRead(int read_errno, std::string data);
+ void ImportPersonalSlotUnlocked();
+
+ // Import Server certificates from file. Sequence goes like:
+ // 1. user clicks on import button -> ImportServer -> launches file selector
+ // 2. user selects file -> ImportServerFileSelected -> starts async read
+ // 3. read completes -> ImportServerFileRead -> parse certs -> attempt import
+ // 4a. if import succeeds -> ImportExportCleanup
+ // 4b. if import fails -> show error, ImportExportCleanup
+ void ImportServer(const base::ListValue* args);
+ void ImportServerFileSelected(const FilePath& path);
+ void ImportServerFileRead(int read_errno, std::string data);
+
+ // Import Certificate Authorities from file. Sequence goes like:
+ // 1. user clicks on import button -> ImportCA -> launches file selector
+ // 2. user selects file -> ImportCAFileSelected -> starts async read
+ // 3. read completes -> ImportCAFileRead -> parse certs ->
+ // CertificateEditCaTrustOverlay.showImport
+ // 4. user clicks ok -> ImportCATrustSelected -> attempt import
+ // 5a. if import succeeds -> ImportExportCleanup
+ // 5b. if import fails -> show error, ImportExportCleanup
+ void ImportCA(const base::ListValue* args);
+ void ImportCAFileSelected(const FilePath& path);
+ void ImportCAFileRead(int read_errno, std::string data);
+ void ImportCATrustSelected(const base::ListValue* args);
+
+ // Export a certificate.
+ void Export(const base::ListValue* args);
+
+ // Delete certificate and private key (if any).
+ void Delete(const base::ListValue* args);
+
+ // Populate the trees in all the tabs.
+ void Populate(const base::ListValue* args);
+
+ // Populate the given tab's tree.
+ void PopulateTree(const std::string& tab_name, net::CertType type);
+
+ // Display a WebUI error message box.
+ void ShowError(const std::string& title, const std::string& error) const;
+
+ // Display a WebUI error message box for import failures.
+ // Depends on |selected_cert_list_| being set to the imports that we
+ // attempted to import.
+ void ShowImportErrors(
+ const std::string& title,
+ const net::CertDatabase::ImportCertFailureList& not_imported) const;
+
+#if defined(OS_CHROMEOS)
+ // Check whether Tpm token is ready and notifiy JS side.
+ void CheckTpmTokenReady(const base::ListValue* args);
+#endif
+
+ gfx::NativeWindow GetParentWindow() const;
+
+ // The Certificates Manager model
+ scoped_ptr<CertificateManagerModel> certificate_manager_model_;
+
+ // For multi-step import or export processes, we need to store the path,
+ // password, etc the user chose while we wait for them to enter a password,
+ // wait for file to be read, etc.
+ FilePath file_path_;
+ string16 password_;
+ bool use_hardware_backed_;
+ std::string file_data_;
+ net::CertificateList selected_cert_list_;
+ scoped_refptr<SelectFileDialog> select_file_dialog_;
+ scoped_refptr<net::CryptoModule> module_;
+
+ // Used in reading and writing certificate files.
+ CancelableRequestConsumer consumer_;
+ scoped_refptr<FileAccessProvider> file_access_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(CertificateManagerHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CERTIFICATE_MANAGER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/about_page_handler.cc b/chrome/browser/ui/webui/options2/chromeos/about_page_handler.cc
new file mode 100644
index 0000000..31d960e
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/about_page_handler.cc
@@ -0,0 +1,419 @@
+// 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/options2/chromeos/about_page_handler.h"
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/i18n/time_formatting.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
+#include "chrome/browser/chromeos/dbus/power_manager_client.h"
+#include "chrome/browser/chromeos/dbus/update_engine_client.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/common/content_client.h"
+#include "googleurl/src/gurl.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"
+#include "ui/base/resource/resource_bundle.h"
+#include "v8/include/v8.h"
+#include "webkit/glue/user_agent.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/glue/user_agent.h"
+
+namespace {
+
+// These are used as placeholder text around the links in the text in the
+// license.
+const char kBeginLink[] = "BEGIN_LINK";
+const char kEndLink[] = "END_LINK";
+const char kBeginLinkChr[] = "BEGIN_LINK_CHR";
+const char kBeginLinkOss[] = "BEGIN_LINK_OSS";
+const char kEndLinkChr[] = "END_LINK_CHR";
+const char kEndLinkOss[] = "END_LINK_OSS";
+const char kBeginLinkCrosOss[] = "BEGIN_LINK_CROS_OSS";
+const char kEndLinkCrosOss[] = "END_LINK_CROS_OSS";
+
+// Returns a substring [start, end) from |text|.
+std::string StringSubRange(const std::string& text, size_t start,
+ size_t end) {
+ DCHECK(end > start);
+ return text.substr(start, end - start);
+}
+
+} // namespace
+
+namespace chromeos {
+
+class AboutPageHandler::UpdateObserver
+ : public UpdateEngineClient::Observer {
+ public:
+ explicit UpdateObserver(AboutPageHandler* handler) : page_handler_(handler) {}
+ virtual ~UpdateObserver() {}
+
+ AboutPageHandler* page_handler() const { return page_handler_; }
+
+ private:
+ virtual void UpdateStatusChanged(
+ const UpdateEngineClient::Status& status) OVERRIDE {
+ page_handler_->UpdateStatus(status);
+ }
+
+ AboutPageHandler* page_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateObserver);
+};
+
+AboutPageHandler::AboutPageHandler()
+ : progress_(-1),
+ sticky_(false),
+ started_(false)
+{}
+
+AboutPageHandler::~AboutPageHandler() {
+ if (update_observer_.get()) {
+ DBusThreadManager::Get()->GetUpdateEngineClient()->
+ RemoveObserver(update_observer_.get());
+ }
+}
+
+void AboutPageHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "firmware", IDS_ABOUT_PAGE_FIRMWARE },
+ { "product", IDS_PRODUCT_OS_NAME },
+ { "os", IDS_PRODUCT_OS_NAME },
+ { "platform", IDS_PLATFORM_LABEL },
+ { "loading", IDS_ABOUT_PAGE_LOADING },
+ { "check_now", IDS_ABOUT_PAGE_CHECK_NOW },
+ { "update_status", IDS_UPGRADE_CHECK_STARTED },
+ { "restart_now", IDS_RELAUNCH_AND_UPDATE },
+ { "browser", IDS_PRODUCT_NAME },
+ { "more_info", IDS_ABOUT_PAGE_MORE_INFO },
+ { "copyright", IDS_ABOUT_VERSION_COPYRIGHT },
+ { "channel", IDS_ABOUT_PAGE_CHANNEL },
+ { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE },
+ { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA },
+ { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT },
+ { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY },
+ { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER },
+ { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT },
+ { "user_agent", IDS_ABOUT_VERSION_USER_AGENT },
+ { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "aboutPage", IDS_ABOUT_TAB_TITLE);
+
+ // browser version
+
+ chrome::VersionInfo version_info;
+ DCHECK(version_info.is_valid());
+
+ std::string browser_version = version_info.Version();
+ std::string version_modifier =
+ chrome::VersionInfo::GetVersionStringModifier();
+ if (!version_modifier.empty())
+ browser_version += " " + version_modifier;
+
+#if !defined(GOOGLE_CHROME_BUILD)
+ browser_version += " (";
+ browser_version += version_info.LastChange();
+ browser_version += ")";
+#endif
+
+ localized_strings->SetString("browser_version", browser_version);
+
+ // license
+
+ std::string text = l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_LICENSE);
+
+ bool chromium_url_appears_first =
+ text.find(kBeginLinkChr) < text.find(kBeginLinkOss);
+
+ size_t link1 = text.find(kBeginLink);
+ DCHECK(link1 != std::string::npos);
+ size_t link1_end = text.find(kEndLink, link1);
+ DCHECK(link1_end != std::string::npos);
+ size_t link2 = text.find(kBeginLink, link1_end);
+ DCHECK(link2 != std::string::npos);
+ size_t link2_end = text.find(kEndLink, link2);
+ DCHECK(link2_end != std::string::npos);
+
+ localized_strings->SetString("license_content_0", text.substr(0, link1));
+ localized_strings->SetString("license_content_1",
+ StringSubRange(text, link1_end + strlen(kEndLinkOss), link2));
+ localized_strings->SetString("license_content_2",
+ text.substr(link2_end + strlen(kEndLinkOss)));
+
+ // The Chromium link within the main text of the dialog.
+ localized_strings->SetString(chromium_url_appears_first ?
+ "license_link_content_0" : "license_link_content_1",
+ StringSubRange(text,
+ text.find(kBeginLinkChr) + strlen(kBeginLinkChr),
+ text.find(kEndLinkChr)));
+ GURL url = google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kChromiumProjectURL));
+ localized_strings->SetString(chromium_url_appears_first ?
+ "license_link_0" : "license_link_1", url.spec());
+
+ // The Open Source link within the main text of the dialog.
+ localized_strings->SetString(chromium_url_appears_first ?
+ "license_link_content_1" : "license_link_content_0",
+ StringSubRange(text,
+ text.find(kBeginLinkOss) + strlen(kBeginLinkOss),
+ text.find(kEndLinkOss)));
+ localized_strings->SetString(chromium_url_appears_first ?
+ "license_link_1" : "license_link_0", chrome::kChromeUICreditsURL);
+
+ std::string cros_text =
+ l10n_util::GetStringUTF8(IDS_ABOUT_CROS_VERSION_LICENSE);
+
+ size_t cros_link = cros_text.find(kBeginLinkCrosOss);
+ DCHECK(cros_link != std::string::npos);
+ size_t cros_link_end = cros_text.find(kEndLinkCrosOss, cros_link);
+ DCHECK(cros_link_end != std::string::npos);
+
+ localized_strings->SetString("cros_license_content_0",
+ cros_text.substr(0, cros_link));
+ localized_strings->SetString("cros_license_content_1",
+ cros_text.substr(cros_link_end + strlen(kEndLinkCrosOss)));
+ localized_strings->SetString("cros_license_link_content_0",
+ StringSubRange(cros_text, cros_link + strlen(kBeginLinkCrosOss),
+ cros_link_end));
+ localized_strings->SetString("cros_license_link_0",
+ chrome::kChromeUIOSCreditsURL);
+
+ // webkit
+
+ localized_strings->SetString("webkit_version",
+ webkit_glue::GetWebKitVersion());
+
+ // javascript
+
+ localized_strings->SetString("js_engine", "V8");
+ localized_strings->SetString("js_engine_version", v8::V8::GetVersion());
+
+ // user agent
+
+ localized_strings->SetString("user_agent_info",
+ content::GetUserAgent(GURL()));
+
+ // command line
+
+#if defined(OS_WIN)
+ localized_strings->SetString("command_line_info",
+ WideToUTF16(CommandLine::ForCurrentProcess()->GetCommandLineString()));
+#elif defined(OS_POSIX)
+ // TODO(viettrungluu): something horrible might happen if there are non-UTF-8
+ // arguments (since |SetString()| requires Unicode).
+ std::string command_line = "";
+ typedef std::vector<std::string> ArgvList;
+ const ArgvList& argv = CommandLine::ForCurrentProcess()->argv();
+ for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++)
+ command_line += " " + *iter;
+ localized_strings->SetString("command_line_info", command_line);
+#endif
+}
+
+void AboutPageHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("PageReady",
+ base::Bind(&AboutPageHandler::PageReady, base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("SetReleaseTrack",
+ base::Bind(&AboutPageHandler::SetReleaseTrack, base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback("CheckNow",
+ base::Bind(&AboutPageHandler::CheckNow, base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("RestartNow",
+ base::Bind(&AboutPageHandler::RestartNow, base::Unretained(this)));
+}
+
+void AboutPageHandler::PageReady(const ListValue* args) {
+ // Version information is loaded from a callback
+ loader_.GetVersion(&consumer_,
+ base::Bind(&AboutPageHandler::OnOSVersion,
+ base::Unretained(this)),
+ VersionLoader::VERSION_FULL);
+ loader_.GetFirmware(&consumer_,
+ base::Bind(&AboutPageHandler::OnOSFirmware,
+ base::Unretained(this)));
+
+ UpdateEngineClient* update_engine_client =
+ DBusThreadManager::Get()->GetUpdateEngineClient();
+
+ update_observer_.reset(new UpdateObserver(this));
+ update_engine_client->AddObserver(update_observer_.get());
+
+ // Update the WebUI page with the current status. See comments below.
+ UpdateStatus(update_engine_client->GetLastStatus());
+
+ // Initiate update check. UpdateStatus() below will be called when we
+ // get update status via update_observer_. If the update has been
+ // already complete, update_observer_ won't receive a notification.
+ // This is why we manually update the WebUI page above.
+ CheckNow(NULL);
+
+ // Request the channel information. Use the observer to track the about
+ // page handler and ensure it does not get deleted before the callback.
+ update_engine_client->GetReleaseTrack(
+ base::Bind(UpdateSelectedChannel, update_observer_.get()));
+}
+
+void AboutPageHandler::SetReleaseTrack(const ListValue* args) {
+ if (!UserManager::Get()->current_user_is_owner()) {
+ LOG(WARNING) << "Non-owner tried to change release track.";
+ return;
+ }
+ const std::string channel = UTF16ToUTF8(ExtractStringValue(args));
+ DBusThreadManager::Get()->GetUpdateEngineClient()->SetReleaseTrack(channel);
+}
+
+void AboutPageHandler::CheckNow(const ListValue* args) {
+ // Make sure that libcros is loaded and OOBE is complete.
+ if (!WizardController::default_controller() ||
+ WizardController::IsDeviceRegistered()) {
+ DBusThreadManager::Get()->GetUpdateEngineClient()->
+ RequestUpdateCheck(UpdateEngineClient::EmptyUpdateCheckCallback());
+ }
+}
+
+void AboutPageHandler::RestartNow(const ListValue* args) {
+ DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
+}
+
+void AboutPageHandler::UpdateStatus(
+ const UpdateEngineClient::Status& status) {
+ string16 message;
+ std::string image = "up-to-date";
+ bool enabled = false;
+
+ switch (status.status) {
+ case UpdateEngineClient::UPDATE_STATUS_IDLE:
+ if (!sticky_) {
+ message = l10n_util::GetStringFUTF16(IDS_UPGRADE_ALREADY_UP_TO_DATE,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME));
+ enabled = true;
+ }
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
+ message = l10n_util::GetStringUTF16(IDS_UPGRADE_CHECK_STARTED);
+ sticky_ = false;
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
+ message = l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE);
+ started_ = true;
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
+ {
+ int progress = static_cast<int>(status.download_progress * 100.0);
+ if (progress != progress_) {
+ progress_ = progress;
+ message = l10n_util::GetStringFUTF16Int(IDS_UPDATE_DOWNLOADING,
+ progress_);
+ }
+ started_ = true;
+ }
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_VERIFYING:
+ message = l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING);
+ started_ = true;
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_FINALIZING:
+ message = l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING);
+ started_ = true;
+ break;
+ case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
+ message = l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED);
+ image = "available";
+ sticky_ = true;
+ break;
+ default:
+ // case UpdateEngineClient::UPDATE_STATUS_ERROR:
+ // case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
+
+ // The error is only displayed if we were able to determine an
+ // update was available.
+ if (started_) {
+ message = l10n_util::GetStringUTF16(IDS_UPDATE_ERROR);
+ image = "fail";
+ enabled = true;
+ sticky_ = true;
+ started_ = false;
+ }
+ break;
+ }
+ if (message.size()) {
+ scoped_ptr<Value> update_message(Value::CreateStringValue(message));
+ // "Checking for update..." needs to be shown for a while, so users
+ // can read it, hence insert delay for this.
+ scoped_ptr<Value> insert_delay(Value::CreateBooleanValue(
+ status.status ==
+ UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE));
+ web_ui_->CallJavascriptFunction("AboutPage.updateStatusCallback",
+ *update_message, *insert_delay);
+
+ scoped_ptr<Value> enabled_value(Value::CreateBooleanValue(enabled));
+ web_ui_->CallJavascriptFunction("AboutPage.updateEnableCallback",
+ *enabled_value);
+
+ scoped_ptr<Value> image_string(Value::CreateStringValue(image));
+ web_ui_->CallJavascriptFunction("AboutPage.setUpdateImage",
+ *image_string);
+ }
+ // We'll change the "Check For Update" button to "Restart" button.
+ if (status.status == UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+ web_ui_->CallJavascriptFunction("AboutPage.changeToRestartButton");
+ }
+}
+
+void AboutPageHandler::OnOSVersion(VersionLoader::Handle handle,
+ std::string version) {
+ if (version.size()) {
+ scoped_ptr<Value> version_string(Value::CreateStringValue(version));
+ web_ui_->CallJavascriptFunction("AboutPage.updateOSVersionCallback",
+ *version_string);
+ }
+}
+
+void AboutPageHandler::OnOSFirmware(VersionLoader::Handle handle,
+ std::string firmware) {
+ if (firmware.size()) {
+ scoped_ptr<Value> firmware_string(Value::CreateStringValue(firmware));
+ web_ui_->CallJavascriptFunction("AboutPage.updateOSFirmwareCallback",
+ *firmware_string);
+ }
+}
+
+// Callback from UpdateEngine with channel information.
+// static
+void AboutPageHandler::UpdateSelectedChannel(UpdateObserver* observer,
+ const std::string& channel) {
+ if (DBusThreadManager::Get()->GetUpdateEngineClient()
+ ->HasObserver(observer)) {
+ // If UpdateEngineClient still has the observer, then the page handler
+ // is valid.
+ AboutPageHandler* handler = observer->page_handler();
+ scoped_ptr<Value> channel_string(Value::CreateStringValue(channel));
+ handler->web_ui_->CallJavascriptFunction(
+ "AboutPage.updateSelectedOptionCallback", *channel_string);
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/about_page_handler.h b/chrome/browser/ui/webui/options2/chromeos/about_page_handler.h
new file mode 100644
index 0000000..69b6895
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/about_page_handler.h
@@ -0,0 +1,74 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ABOUT_PAGE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ABOUT_PAGE_HANDLER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "chrome/browser/chromeos/dbus/update_engine_client.h"
+#include "chrome/browser/chromeos/version_loader.h"
+
+namespace chromeos {
+
+// ChromeOS about page UI handler.
+class AboutPageHandler : public OptionsPage2UIHandler {
+
+ public:
+ AboutPageHandler();
+ virtual ~AboutPageHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ class UpdateObserver;
+
+ // The function is called from JavaScript when the about page is ready.
+ void PageReady(const base::ListValue* args);
+
+ // The function is called from JavaScript to set the release track like
+ // "beta-channel" and "dev-channel".
+ void SetReleaseTrack(const base::ListValue* args);
+
+ // Initiates update check.
+ void CheckNow(const base::ListValue* args);
+
+ // Restarts the system.
+ void RestartNow(const base::ListValue* args);
+
+ // Callback from VersionLoader giving the version.
+ void OnOSVersion(VersionLoader::Handle handle,
+ std::string version);
+ void OnOSFirmware(VersionLoader::Handle handle,
+ std::string firmware);
+ void UpdateStatus(const UpdateEngineClient::Status& status);
+
+ // UpdateEngine Callback handler.
+ static void UpdateSelectedChannel(UpdateObserver* observer,
+ const std::string& channel);
+
+ // Handles asynchronously loading the version.
+ VersionLoader loader_;
+
+ // Used to request the version.
+ CancelableRequestConsumer consumer_;
+
+ // Update Observer
+ scoped_ptr<UpdateObserver> update_observer_;
+
+ int progress_;
+ bool sticky_;
+ bool started_;
+
+ DISALLOW_COPY_AND_ASSIGN(AboutPageHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ABOUT_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.cc
new file mode 100644
index 0000000..396dcec
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.cc
@@ -0,0 +1,132 @@
+// 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/options2/chromeos/accounts_options_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
+#include "chrome/browser/chromeos/login/authenticator.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+
+namespace {
+
+// Adds specified user to the whitelist. Returns false if that user is already
+// in the whitelist.
+bool WhitelistUser(const std::string& username) {
+ CrosSettings* cros_settings = CrosSettings::Get();
+ if (cros_settings->FindEmailInList(kAccountsPrefUsers, username))
+ return false;
+ base::StringValue username_value(username);
+ cros_settings->AppendToList(kAccountsPrefUsers, &username_value);
+ return true;
+}
+
+} // namespace
+
+AccountsOptionsHandler::AccountsOptionsHandler() {
+}
+
+AccountsOptionsHandler::~AccountsOptionsHandler() {
+}
+
+void AccountsOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("whitelistUser",
+ base::Bind(&AccountsOptionsHandler::HandleWhitelistUser,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("unwhitelistUser",
+ base::Bind(&AccountsOptionsHandler::HandleUnwhitelistUser,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("whitelistExistingUsers",
+ base::Bind(&AccountsOptionsHandler::HandleWhitelistExistingUsers,
+ base::Unretained(this)));
+}
+
+void AccountsOptionsHandler::GetLocalizedValues(
+ base::DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "accountsPage",
+ IDS_OPTIONS_ACCOUNTS_TAB_LABEL);
+
+ localized_strings->SetString("allow_BWSI", l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_ALLOW_BWSI_DESCRIPTION));
+ localized_strings->SetString("use_whitelist",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_USE_WHITELIST_DESCRIPTION));
+ localized_strings->SetString("show_user_on_signin",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_SHOW_USER_NAMES_ON_SINGIN_DESCRIPTION));
+ localized_strings->SetString("username_edit_hint",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_USERNAME_EDIT_HINT));
+ localized_strings->SetString("username_format",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_USERNAME_FORMAT));
+ localized_strings->SetString("add_users",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_ADD_USERS));
+ localized_strings->SetString("owner_only", l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_OWNER_ONLY));
+
+ std::string owner_email;
+ CrosSettings::Get()->GetString(kDeviceOwner, &owner_email);
+ // Translate owner's email to the display email.
+ std::string display_email =
+ UserManager::Get()->GetUserDisplayEmail(owner_email);
+ localized_strings->SetString("owner_user_id", UTF8ToUTF16(display_email));
+
+ localized_strings->SetString("current_user_is_owner",
+ UserManager::Get()->current_user_is_owner() ?
+ ASCIIToUTF16("true") : ASCIIToUTF16("false"));
+ localized_strings->SetString("logged_in_as_guest",
+ UserManager::Get()->IsLoggedInAsGuest() ?
+ ASCIIToUTF16("true") : ASCIIToUTF16("false"));
+ localized_strings->SetString("whitelist_is_managed",
+ g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ?
+ ASCIIToUTF16("true") : ASCIIToUTF16("false"));
+}
+
+void AccountsOptionsHandler::HandleWhitelistUser(const base::ListValue* args) {
+ std::string typed_email;
+ std::string name;
+ if (!args->GetString(0, &typed_email) ||
+ !args->GetString(1, &name)) {
+ return;
+ }
+
+ WhitelistUser(Authenticator::Canonicalize(typed_email));
+}
+
+void AccountsOptionsHandler::HandleUnwhitelistUser(
+ const base::ListValue* args) {
+ std::string email;
+ if (!args->GetString(0, &email)) {
+ return;
+ }
+
+ base::StringValue canonical_email(Authenticator::Canonicalize(email));
+ CrosSettings::Get()->RemoveFromList(kAccountsPrefUsers, &canonical_email);
+ UserManager::Get()->RemoveUser(email, NULL);
+}
+
+void AccountsOptionsHandler::HandleWhitelistExistingUsers(
+ const base::ListValue* args) {
+ DCHECK(args && args->empty());
+
+ const UserList& users = UserManager::Get()->GetUsers();
+ for (UserList::const_iterator it = users.begin(); it < users.end(); ++it) {
+ WhitelistUser((*it)->email());
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h
new file mode 100644
index 0000000..61c2487
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ACCOUNTS_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ACCOUNTS_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace chromeos {
+
+// ChromeOS accounts options page handler.
+class AccountsOptionsHandler : public OptionsPage2UIHandler {
+ public:
+ AccountsOptionsHandler();
+ virtual ~AccountsOptionsHandler();
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ // Javascript callbacks to whitelist/unwhitelist user.
+ void HandleWhitelistUser(const base::ListValue* args);
+ void HandleUnwhitelistUser(const base::ListValue* args);
+
+ // Javascript callback to auto add existing users to white list.
+ void HandleWhitelistExistingUsers(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(AccountsOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_ACCOUNTS_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.cc
new file mode 100644
index 0000000..f8f6a28
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.cc
@@ -0,0 +1,411 @@
+// 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/options2/chromeos/bluetooth_options_handler.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/bluetooth/bluetooth_device.h"
+#include "chrome/browser/chromeos/system/runtime_environment.h"
+#include "chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h"
+#include "chrome/common/chrome_switches.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// |UpdateDeviceCallback| takes a variable length list as an argument. The
+// value stored in each list element is indicated by the following constants.
+const int kUpdateDeviceAddressIndex = 0;
+const int kUpdateDeviceCommandIndex = 1;
+const int kUpdateDevicePasskeyIndex = 2;
+
+} // namespace
+
+namespace chromeos {
+
+BluetoothOptionsHandler::BluetoothOptionsHandler() {
+}
+
+BluetoothOptionsHandler::~BluetoothOptionsHandler() {
+ if (!CommandLine::ForCurrentProcess()
+ ->HasSwitch(switches::kEnableBluetooth)) {
+ return;
+ }
+
+ chromeos::BluetoothManager* bluetooth_manager =
+ chromeos::BluetoothManager::GetInstance();
+ DCHECK(bluetooth_manager);
+
+ chromeos::BluetoothAdapter* default_adapter =
+ bluetooth_manager->DefaultAdapter();
+
+ if (default_adapter != NULL) {
+ default_adapter->RemoveObserver(this);
+ }
+
+ bluetooth_manager->RemoveObserver(this);
+}
+
+void BluetoothOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ localized_strings->SetString("bluetooth",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH));
+ localized_strings->SetString("disableBluetooth",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_DISABLE));
+ localized_strings->SetString("enableBluetooth",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_ENABLE));
+ localized_strings->SetString("noBluetoothDevicesFound",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_NO_BLUETOOTH_DEVICES_FOUND));
+ localized_strings->SetString("findBluetoothDevices",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_FIND_BLUETOOTH_DEVICES));
+ localized_strings->SetString("bluetoothScanning",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING));
+ localized_strings->SetString("bluetoothDeviceConnected",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTED));
+ localized_strings->SetString("bluetoothDeviceConnecting",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTING));
+ localized_strings->SetString("bluetoothDeviceNotPaired",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_NOT_PAIRED));
+ localized_strings->SetString("bluetoothDevicePaired",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_PAIRED));
+ localized_strings->SetString("bluetoothDeviceFailedPairing",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_FAILED_PAIRING));
+ localized_strings->SetString("bluetoothConnectDevice",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT));
+ localized_strings->SetString("bluetoothDisconnectDevice",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT));
+ localized_strings->SetString("bluetoothForgetDevice",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET));
+ localized_strings->SetString("bluetoothCancel",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BLUETOOTH_CANCEL));
+ localized_strings->SetString("bluetoothAcceptPasskey",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY));
+ localized_strings->SetString("bluetoothRejectPasskey",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY));
+ localized_strings->SetString("bluetoothConfirmPasskey",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY_REQUEST));
+ localized_strings->SetString("bluetoothEnterPasskey",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PASSKEY_REQUEST));
+ localized_strings->SetString("bluetoothRemotePasskey",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PASSKEY_REQUEST));
+ localized_strings->SetString("bluetoothFailedPairingInstructions",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BLUETOOTH_FAILED_PAIRING_INSTRUCTIONS));
+}
+
+void BluetoothOptionsHandler::Initialize() {
+ DCHECK(web_ui_);
+ // Bluetooth support is a work in progress. Supress the feature unless
+ // explicitly enabled via a command line flag.
+ if (!CommandLine::ForCurrentProcess()
+ ->HasSwitch(switches::kEnableBluetooth)) {
+ return;
+ }
+
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.showBluetoothSettings");
+
+ // TODO(kevers): Determine whether bluetooth adapter is powered.
+ bool bluetooth_on = false;
+ base::FundamentalValue checked(bluetooth_on);
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.setBluetoothState", checked);
+
+ chromeos::BluetoothManager* bluetooth_manager =
+ chromeos::BluetoothManager::GetInstance();
+ DCHECK(bluetooth_manager);
+ bluetooth_manager->AddObserver(this);
+
+ chromeos::BluetoothAdapter* default_adapter =
+ bluetooth_manager->DefaultAdapter();
+ DefaultAdapterChanged(default_adapter);
+}
+
+void BluetoothOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("bluetoothEnableChange",
+ base::Bind(&BluetoothOptionsHandler::EnableChangeCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("findBluetoothDevices",
+ base::Bind(&BluetoothOptionsHandler::FindDevicesCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("updateBluetoothDevice",
+ base::Bind(&BluetoothOptionsHandler::UpdateDeviceCallback,
+ base::Unretained(this)));
+}
+
+void BluetoothOptionsHandler::EnableChangeCallback(
+ const ListValue* args) {
+ bool bluetooth_enabled;
+ args->GetBoolean(0, &bluetooth_enabled);
+ // TODO(kevers): Call Bluetooth API to enable or disable.
+ base::FundamentalValue checked(bluetooth_enabled);
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.setBluetoothState", checked);
+}
+
+void BluetoothOptionsHandler::FindDevicesCallback(
+ const ListValue* args) {
+ // We only initiate a scan if we're running on Chrome OS. Otherwise, we
+ // generate a fake device list.
+ if (!chromeos::system::runtime_environment::IsRunningOnChromeOS()) {
+ GenerateFakeDeviceList();
+ return;
+ }
+
+ chromeos::BluetoothManager* bluetooth_manager =
+ chromeos::BluetoothManager::GetInstance();
+ DCHECK(bluetooth_manager);
+
+ chromeos::BluetoothAdapter* default_adapter =
+ bluetooth_manager->DefaultAdapter();
+
+ ValidateDefaultAdapter(default_adapter);
+
+ if (default_adapter == NULL) {
+ VLOG(1) << "FindDevicesCallback: no default adapter";
+ return;
+ }
+
+ default_adapter->StartDiscovery();
+}
+
+void BluetoothOptionsHandler::UpdateDeviceCallback(
+ const ListValue* args) {
+ // TODO(kevers): Trigger connect/disconnect.
+ int size = args->GetSize();
+ std::string address;
+ std::string command;
+ args->GetString(kUpdateDeviceAddressIndex, &address);
+ args->GetString(kUpdateDeviceCommandIndex, &command);
+ if (size > kUpdateDevicePasskeyIndex) {
+ // Passkey confirmation as part of the pairing process.
+ std::string passkey;
+ args->GetString(kUpdateDevicePasskeyIndex, &passkey);
+ DVLOG(1) << "UpdateDeviceCallback: " << address << ": " << command
+ << " [" << passkey << "]";
+ } else {
+ // Initiating a device connection or disconnecting
+ DVLOG(1) << "UpdateDeviceCallback: " << address << ": " << command;
+ }
+}
+
+void BluetoothOptionsHandler::SendDeviceNotification(
+ chromeos::BluetoothDevice* device,
+ base::DictionaryValue* params) {
+ // Retrieve properties of the bluetooth device. The properties names are
+ // in title case. Convert to camel case in accordance with our Javascript
+ // naming convention.
+ const DictionaryValue& properties = device->AsDictionary();
+ base::DictionaryValue js_properties;
+ for (DictionaryValue::key_iterator it = properties.begin_keys();
+ it != properties.end_keys(); ++it) {
+ base::Value* child = NULL;
+ properties.GetWithoutPathExpansion(*it, &child);
+ if (child) {
+ std::string js_key = *it;
+ js_key[0] = tolower(js_key[0]);
+ js_properties.SetWithoutPathExpansion(js_key, child->DeepCopy());
+ }
+ }
+ if (params) {
+ js_properties.MergeDictionary(params);
+ }
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.addBluetoothDevice",
+ js_properties);
+}
+
+void BluetoothOptionsHandler::RequestConfirmation(
+ chromeos::BluetoothDevice* device,
+ int passkey) {
+ DictionaryValue params;
+ params.SetString("pairing", "bluetoothConfirmPasskey");
+ params.SetInteger("passkey", passkey);
+ SendDeviceNotification(device, &params);
+}
+
+void BluetoothOptionsHandler::DisplayPasskey(
+ chromeos::BluetoothDevice* device,
+ int passkey,
+ int entered) {
+ DictionaryValue params;
+ params.SetString("pairing", "bluetoothRemotePasskey");
+ params.SetInteger("passkey", passkey);
+ params.SetInteger("entered", entered);
+ SendDeviceNotification(device, &params);
+}
+
+void BluetoothOptionsHandler::RequestPasskey(
+ chromeos::BluetoothDevice* device) {
+ DictionaryValue params;
+ params.SetString("pairing", "bluetoothEnterPasskey");
+ SendDeviceNotification(device, &params);
+}
+
+void BluetoothOptionsHandler::ValidatePasskeyCallback(
+ const base::ListValue* args) {
+ // TODO(kevers): Implement me.
+}
+
+void BluetoothOptionsHandler::DefaultAdapterChanged(
+ chromeos::BluetoothAdapter* adapter) {
+ std::string old_default_adapter_id = default_adapter_id_;
+
+ if (adapter == NULL) {
+ default_adapter_id_.clear();
+ VLOG(2) << "DefaultAdapterChanged: no default bluetooth adapter";
+ } else {
+ default_adapter_id_ = adapter->Id();
+ VLOG(2) << "DefaultAdapterChanged: " << default_adapter_id_;
+ }
+
+ if (default_adapter_id_ == old_default_adapter_id) {
+ return;
+ }
+
+ if (adapter != NULL) {
+ adapter->AddObserver(this);
+ }
+
+ // TODO(vlaviano): Respond to adapter change.
+}
+
+void BluetoothOptionsHandler::DiscoveryStarted(const std::string& adapter_id) {
+ VLOG(2) << "Discovery started on " << adapter_id;
+}
+
+void BluetoothOptionsHandler::DiscoveryEnded(const std::string& adapter_id) {
+ VLOG(2) << "Discovery ended on " << adapter_id;
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.notifyBluetoothSearchComplete");
+
+ // Stop the discovery session.
+ // TODO(vlaviano): We may want to expose DeviceDisappeared, remove the
+ // "Find devices" button, and let the discovery session continue throughout
+ // the time that the page is visible rather than just doing a single discovery
+ // cycle in response to a button click.
+ chromeos::BluetoothManager* bluetooth_manager =
+ chromeos::BluetoothManager::GetInstance();
+ DCHECK(bluetooth_manager);
+
+ chromeos::BluetoothAdapter* default_adapter =
+ bluetooth_manager->DefaultAdapter();
+
+ ValidateDefaultAdapter(default_adapter);
+
+ if (default_adapter == NULL) {
+ VLOG(1) << "DiscoveryEnded: no default adapter";
+ return;
+ }
+
+ default_adapter->StopDiscovery();
+}
+
+void BluetoothOptionsHandler::DeviceFound(const std::string& adapter_id,
+ chromeos::BluetoothDevice* device) {
+ VLOG(2) << "Device found on " << adapter_id;
+ DCHECK(device);
+ SendDeviceNotification(device, NULL);
+}
+
+void BluetoothOptionsHandler::ValidateDefaultAdapter(
+ chromeos::BluetoothAdapter* adapter) {
+ if ((adapter == NULL && !default_adapter_id_.empty()) ||
+ (adapter != NULL && default_adapter_id_ != adapter->Id())) {
+ VLOG(1) << "unexpected default adapter change from \""
+ << default_adapter_id_ << "\" to \"" << adapter->Id() << "\"";
+ DefaultAdapterChanged(adapter);
+ }
+}
+
+void BluetoothOptionsHandler::GenerateFakeDeviceList() {
+ GenerateFakeDevice(
+ "Fake Wireless Keyboard",
+ "01-02-03-04-05-06",
+ "input-keyboard",
+ true,
+ true,
+ "");
+ GenerateFakeDevice(
+ "Fake Wireless Mouse",
+ "02-03-04-05-06-01",
+ "input-mouse",
+ true,
+ false,
+ "");
+ GenerateFakeDevice(
+ "Fake Wireless Headset",
+ "03-04-05-06-01-02",
+ "headset",
+ false,
+ false,
+ "");
+ GenerateFakeDevice(
+ "Fake Connecting Keyboard",
+ "04-05-06-01-02-03",
+ "input-keyboard",
+ false,
+ false,
+ "bluetoothRemotePasskey");
+ GenerateFakeDevice(
+ "Fake Connecting Phone",
+ "05-06-01-02-03-04",
+ "phone",
+ false,
+ false,
+ "bluetoothConfirmPasskey");
+ GenerateFakeDevice(
+ "Fake Connecting Headset",
+ "06-01-02-03-04-05",
+ "headset",
+ false,
+ false,
+ "bluetoothEnterPasskey");
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.notifyBluetoothSearchComplete");
+}
+
+void BluetoothOptionsHandler::GenerateFakeDevice(
+ const std::string& name,
+ const std::string& address,
+ const std::string& icon,
+ bool paired,
+ bool connected,
+ const std::string& pairing) {
+ DictionaryValue properties;
+ properties.SetString(bluetooth_device::kNameProperty, name);
+ properties.SetString(bluetooth_device::kAddressProperty, address);
+ properties.SetString(bluetooth_device::kIconProperty, icon);
+ properties.SetBoolean(bluetooth_device::kPairedProperty, paired);
+ properties.SetBoolean(bluetooth_device::kConnectedProperty, connected);
+ properties.SetInteger(bluetooth_device::kClassProperty, 0);
+ chromeos::BluetoothDevice* device =
+ chromeos::BluetoothDevice::Create(properties);
+ DeviceFound("FakeAdapter", device);
+ if (pairing.compare("bluetoothRemotePasskey") == 0) {
+ DisplayPasskey(device, 12345, 2);
+ } else if (pairing.compare("bluetoothConfirmPasskey") == 0) {
+ RequestConfirmation(device, 12345);
+ } else if (pairing.compare("bluetoothEnterPasskey") == 0) {
+ RequestPasskey(device);
+ }
+ delete device;
+}
+
+} // namespace chromeos
+
diff --git a/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.h
new file mode 100644
index 0000000..c57dbb7
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.h
@@ -0,0 +1,138 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_BLUETOOTH_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_BLUETOOTH_OPTIONS_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h"
+#include "chrome/browser/chromeos/bluetooth/bluetooth_manager.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+// Handler for Bluetooth options on the system options page.
+class BluetoothOptionsHandler : public OptionsPage2UIHandler,
+ public chromeos::BluetoothManager::Observer,
+ public chromeos::BluetoothAdapter::Observer {
+ public:
+ BluetoothOptionsHandler();
+ virtual ~BluetoothOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // Called when the 'Enable bluetooth' checkbox value is changed.
+ // |args| will contain the checkbox checked state as a string
+ // ("true" or "false").
+ void EnableChangeCallback(const base::ListValue* args);
+
+ // Called when the 'Find Devices' button is pressed from the Bluetooth
+ // ssettings.
+ // |args| will be an empty list.
+ void FindDevicesCallback(const base::ListValue* args);
+
+ // Called when the user requests to connect to or disconnect from a Bluetooth
+ // device.
+ // |args| will be a list containing two or three arguments, the first argument
+ // is the device ID and the second is the requested action. If a third
+ // argument is present, it is the passkey for pairing confirmation.
+ void UpdateDeviceCallback(const base::ListValue* args);
+
+ // Sends a notification to the Web UI of the status of a Bluetooth device.
+ // |device| is the Bluetooth device.
+ // |params| is an optional set of parameters.
+ void SendDeviceNotification(chromeos::BluetoothDevice* device,
+ base::DictionaryValue* params);
+
+ // Displays a passkey for a device, requesting user confirmation that the
+ // key matches an expected value (value displayed on a smartphone for
+ // example).
+ // |device| is the Bluetooth device being paired.
+ // |passkey| is the passkey to display for confirmation.
+ void RequestConfirmation(chromeos::BluetoothDevice* device,
+ int passkey);
+
+ // Displays a passkey for a device, which is being typed remotely. During
+ // the pairing process, this method may be called repeatedly to track the
+ // number of characters entered. This method is commonly used for pairing
+ // keyboards.
+ // |device| is the Bluetooth device being paired.
+ // |passkey| is the required passkey.
+ // |entered| is the number of characters that have already been entered on
+ // the remote device.
+ void DisplayPasskey(chromeos::BluetoothDevice* device,
+ int passkey,
+ int entered);
+
+ // Displays a blank field for entering a passkey. The passkey may be
+ // a set value specified by the manufacturer of the Bluetooth device, or
+ // on a remote display. The validation is asychronous, and a call is made
+ // to |ValidatePasskeyCallback| when the passkey entry is complete.
+ // |device| is the Bluetooth device being paired.
+ void RequestPasskey(chromeos::BluetoothDevice* device);
+
+ // Callback to validate a user entered passkey.
+ // |args| is a list containing the device address and entered passkey.
+ void ValidatePasskeyCallback(const base::ListValue* args);
+
+ // chromeos::BluetoothManager::Observer override.
+ virtual void DefaultAdapterChanged(
+ chromeos::BluetoothAdapter* adapter) OVERRIDE;
+
+ // chromeos::BluetoothAdapter::Observer override.
+ virtual void DiscoveryStarted(const std::string& adapter_id) OVERRIDE;
+
+ // chromeos::BluetoothAdapter::Observer override.
+ virtual void DiscoveryEnded(const std::string& adapter_id) OVERRIDE;
+
+ // chromeos::BluetoothAdapter::Observer override.
+ virtual void DeviceFound(const std::string& adapter_id,
+ chromeos::BluetoothDevice* device) OVERRIDE;
+
+ private:
+ // Compares |adapter| with our cached default adapter ID and calls
+ // DefaultAdapterChanged if there has been an unexpected change.
+ void ValidateDefaultAdapter(chromeos::BluetoothAdapter* adapter);
+
+ // Simulates extracting a list of available bluetooth devices.
+ // Called when emulating ChromeOS from a desktop environment.
+ void GenerateFakeDeviceList();
+
+ // Simulates the discovery or pairing of a Bluetooth device. Used when
+ // emulating ChromeOS from a desktop environment.
+ // |name| is the display name for the device.
+ // |address| is the unique Mac address of the device.
+ // |icon| is the base name of the icon to use for the device and corresponds
+ // to the general device category (e.g. mouse or keyboard).
+ // |paired| indicates if the device is paired.
+ // |connected| indicates if the device is connected.
+ // |pairing| indicates the type of pairing operation.
+ void GenerateFakeDevice(const std::string& name,
+ const std::string& address,
+ const std::string& icon,
+ bool paired,
+ bool connected,
+ const std::string& pairing);
+
+ // The id of the current default bluetooth adapter.
+ // The empty string represents "none".
+ std::string default_adapter_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_BLUETOOTH_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.cc
new file mode 100644
index 0000000..88019ac
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.cc
@@ -0,0 +1,344 @@
+// 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/options2/chromeos/change_picture_options_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/metrics/histogram.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/login/camera_detector.h"
+#include "chrome/browser/chromeos/login/default_user_images.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/options2/take_photo_dialog.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/dialog_style.h"
+#include "chrome/browser/ui/views/window.h"
+#include "chrome/browser/ui/webui/web_ui_util.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/common/url_constants.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/widget/widget.h"
+
+namespace chromeos {
+
+namespace {
+
+// Returns info about extensions for files we support as user images.
+SelectFileDialog::FileTypeInfo GetUserImageFileTypeInfo() {
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.resize(5);
+
+ file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("bmp"));
+
+ file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("gif"));
+
+ file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("jpg"));
+ file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("jpeg"));
+
+ file_type_info.extensions[3].push_back(FILE_PATH_LITERAL("png"));
+
+ file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("tif"));
+ file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("tiff"));
+
+ return file_type_info;
+}
+
+} // namespace
+
+ChangePictureOptionsHandler::ChangePictureOptionsHandler()
+ : previous_image_data_url_(chrome::kAboutBlankURL),
+ previous_image_index_(User::kInvalidImageIndex),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
+ content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
+ content::NotificationService::AllSources());
+}
+
+ChangePictureOptionsHandler::~ChangePictureOptionsHandler() {
+ if (select_file_dialog_.get())
+ select_file_dialog_->ListenerDestroyed();
+}
+
+void ChangePictureOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ localized_strings->SetString("changePicturePage",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TITLE));
+ localized_strings->SetString("changePicturePageDescription",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT));
+ localized_strings->SetString("takePhoto",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO));
+ localized_strings->SetString("chooseFile",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_CHOOSE_FILE));
+ localized_strings->SetString("profilePhoto",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_PROFILE_PHOTO));
+ localized_strings->SetString("profilePhotoLoading",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_CHANGE_PICTURE_PROFILE_LOADING_PHOTO));
+}
+
+void ChangePictureOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("chooseFile",
+ base::Bind(&ChangePictureOptionsHandler::HandleChooseFile,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("takePhoto",
+ base::Bind(&ChangePictureOptionsHandler::HandleTakePhoto,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("onChangePicturePageShown",
+ base::Bind(&ChangePictureOptionsHandler::HandlePageShown,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("onChangePicturePageInitialized",
+ base::Bind(&ChangePictureOptionsHandler::HandlePageInitialized,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("selectImage",
+ base::Bind(&ChangePictureOptionsHandler::HandleSelectImage,
+ base::Unretained(this)));
+}
+
+void ChangePictureOptionsHandler::SendDefaultImages() {
+ ListValue image_urls;
+ for (int i = 0; i < kDefaultImagesCount; ++i) {
+ image_urls.Append(new StringValue(GetDefaultImageUrl(i)));
+ }
+ web_ui_->CallJavascriptFunction("ChangePictureOptions.setDefaultImages",
+ image_urls);
+}
+
+void ChangePictureOptionsHandler::HandleChooseFile(const ListValue* args) {
+ DCHECK(args && args->empty());
+ if (!select_file_dialog_.get())
+ select_file_dialog_ = SelectFileDialog::Create(this);
+
+ FilePath downloads_path;
+ if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &downloads_path)) {
+ NOTREACHED();
+ return;
+ }
+
+ // Static so we initialize it only once.
+ CR_DEFINE_STATIC_LOCAL(SelectFileDialog::FileTypeInfo, file_type_info,
+ (GetUserImageFileTypeInfo()));
+
+ select_file_dialog_->SelectFile(
+ SelectFileDialog::SELECT_OPEN_FILE,
+ l10n_util::GetStringUTF16(IDS_DOWNLOAD_TITLE),
+ downloads_path,
+ &file_type_info,
+ 0,
+ FILE_PATH_LITERAL(""),
+ web_ui_->tab_contents(),
+ GetBrowserWindow(),
+ NULL);
+}
+
+void ChangePictureOptionsHandler::HandleTakePhoto(const ListValue* args) {
+ DCHECK(args && args->empty());
+ views::Widget* window = browser::CreateViewsWindow(
+ GetBrowserWindow(),
+ new TakePhotoDialog(this),
+ STYLE_GENERIC);
+ window->SetAlwaysOnTop(true);
+ window->Show();
+}
+
+void ChangePictureOptionsHandler::HandlePageInitialized(
+ const base::ListValue* args) {
+ DCHECK(args && args->empty());
+ // If no camera presence check has been performed in this session,
+ // start one now.
+ if (CameraDetector::camera_presence() ==
+ CameraDetector::kCameraPresenceUnknown) {
+ CheckCameraPresence();
+ }
+
+ // While the check is in progress, use previous camera presence state and
+ // presume it is present if no check has been performed yet.
+ SetCameraPresent(CameraDetector::camera_presence() !=
+ CameraDetector::kCameraAbsent);
+
+ SendDefaultImages();
+}
+
+void ChangePictureOptionsHandler::HandlePageShown(const base::ListValue* args) {
+ DCHECK(args && args->empty());
+ // TODO(ivankr): If user opens settings and goes to Change Picture page right
+ // after the check started |HandlePageInitialized| has been completed,
+ // |CheckCameraPresence| will be called twice, should be throttled.
+ CheckCameraPresence();
+ SendSelectedImage();
+ UpdateProfileImage();
+}
+
+void ChangePictureOptionsHandler::SendSelectedImage() {
+ const User& user = UserManager::Get()->logged_in_user();
+ DCHECK(!user.email().empty());
+
+ previous_image_index_ = user.image_index();
+ switch (previous_image_index_) {
+ case User::kExternalImageIndex: {
+ // User has image from camera/file, record it and add to the image list.
+ previous_image_ = user.image();
+ previous_image_data_url_ = web_ui_util::GetImageDataUrl(previous_image_);
+ web_ui_->CallJavascriptFunction("ChangePictureOptions.setOldImage");
+ break;
+ }
+ case User::kProfileImageIndex: {
+ // User has his/her Profile image as the current image.
+ SendProfileImage(user.image(), true);
+ break;
+ }
+ default: {
+ DCHECK(previous_image_index_ >= 0 &&
+ previous_image_index_ < kDefaultImagesCount);
+ // User has image from the set of default images.
+ base::StringValue image_url(GetDefaultImageUrl(previous_image_index_));
+ web_ui_->CallJavascriptFunction("ChangePictureOptions.setSelectedImage",
+ image_url);
+ }
+ }
+}
+
+void ChangePictureOptionsHandler::SendProfileImage(const SkBitmap& image,
+ bool should_select) {
+ base::StringValue data_url(web_ui_util::GetImageDataUrl(image));
+ base::FundamentalValue select(should_select);
+ web_ui_->CallJavascriptFunction("ChangePictureOptions.setProfileImage",
+ data_url, select);
+}
+
+void ChangePictureOptionsHandler::UpdateProfileImage() {
+ UserManager* user_manager = UserManager::Get();
+
+ // If we have a downloaded profile image and haven't sent it in
+ // |SendSelectedImage|, send it now (without selecting).
+ if (previous_image_index_ != User::kProfileImageIndex &&
+ !user_manager->downloaded_profile_image().empty())
+ SendProfileImage(user_manager->downloaded_profile_image(), false);
+
+ user_manager->DownloadProfileImage();
+}
+
+void ChangePictureOptionsHandler::HandleSelectImage(const ListValue* args) {
+ std::string image_url;
+ if (!args ||
+ args->GetSize() != 1 ||
+ !args->GetString(0, &image_url)) {
+ NOTREACHED();
+ return;
+ }
+ DCHECK(!image_url.empty());
+
+ UserManager* user_manager = UserManager::Get();
+ const User& user = user_manager->logged_in_user();
+ int image_index = User::kInvalidImageIndex;
+
+ if (StartsWithASCII(image_url, chrome::kChromeUIUserImageURL, false)) {
+ // Image from file/camera uses kChromeUIUserImageURL as URL while
+ // current profile image always has a full data URL.
+ // This way transition from (current profile image) to
+ // (profile image, current image from file) is easier.
+
+ DCHECK(!previous_image_.empty());
+ user_manager->SaveUserImage(user.email(), previous_image_);
+
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ kHistogramImageOld,
+ kHistogramImagesCount);
+ VLOG(1) << "Selected old user image";
+ } else if (IsDefaultImageUrl(image_url, &image_index)) {
+ // One of the default user images.
+ user_manager->SaveUserDefaultImageIndex(user.email(), image_index);
+
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ image_index,
+ kHistogramImagesCount);
+ VLOG(1) << "Selected default user image: " << image_index;
+ } else {
+ // Profile image selected. Could be previous (old) user image.
+ user_manager->SaveUserImageFromProfileImage(user.email());
+
+ if (previous_image_index_ == User::kProfileImageIndex) {
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ kHistogramImageOld,
+ kHistogramImagesCount);
+ VLOG(1) << "Selected old (profile) user image";
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ kHistogramImageFromProfile,
+ kHistogramImagesCount);
+ VLOG(1) << "Selected profile image";
+ }
+ }
+}
+
+void ChangePictureOptionsHandler::FileSelected(const FilePath& path,
+ int index,
+ void* params) {
+ UserManager* user_manager = UserManager::Get();
+ user_manager->SaveUserImageFromFile(user_manager->logged_in_user().email(),
+ path);
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ kHistogramImageFromFile,
+ kHistogramImagesCount);
+}
+
+void ChangePictureOptionsHandler::OnPhotoAccepted(const SkBitmap& photo) {
+ UserManager* user_manager = UserManager::Get();
+ user_manager->SaveUserImage(user_manager->logged_in_user().email(), photo);
+ UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
+ kHistogramImageFromCamera,
+ kHistogramImagesCount);
+}
+
+void ChangePictureOptionsHandler::CheckCameraPresence() {
+ CameraDetector::StartPresenceCheck(
+ base::Bind(&ChangePictureOptionsHandler::OnCameraPresenceCheckDone,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ChangePictureOptionsHandler::SetCameraPresent(bool present) {
+ base::FundamentalValue present_value(present);
+ web_ui_->CallJavascriptFunction("ChangePictureOptions.setCameraPresent",
+ present_value);
+}
+
+void ChangePictureOptionsHandler::OnCameraPresenceCheckDone() {
+ SetCameraPresent(CameraDetector::camera_presence() ==
+ CameraDetector::kCameraPresent);
+}
+
+void ChangePictureOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ OptionsPageUIHandler::Observe(type, source, details);
+ if (type == chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED) {
+ // User profile image has been updated.
+ SendProfileImage(*content::Details<const SkBitmap>(details).ptr(), false);
+ }
+}
+
+gfx::NativeWindow ChangePictureOptionsHandler::GetBrowserWindow() const {
+ Browser* browser =
+ BrowserList::FindBrowserWithProfile(Profile::FromWebUI(web_ui_));
+ if (!browser)
+ return NULL;
+ return browser->window()->GetNativeHandle();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.h
new file mode 100644
index 0000000..c71ce01
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.h
@@ -0,0 +1,113 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CHANGE_PICTURE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CHANGE_PICTURE_OPTIONS_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/options2/take_photo_dialog.h"
+#include "chrome/browser/ui/select_file_dialog.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "content/public/browser/notification_registrar.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace chromeos {
+
+// ChromeOS user image options page UI handler.
+class ChangePictureOptionsHandler : public OptionsPage2UIHandler,
+ public SelectFileDialog::Listener,
+ public TakePhotoDialog::Delegate {
+ public:
+ ChangePictureOptionsHandler();
+ virtual ~ChangePictureOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ // Sends list of available default images to the page.
+ void SendDefaultImages();
+
+ // Sends current selection to the page.
+ void SendSelectedImage();
+
+ // Sends the profile image to the page. If |should_select| is true then
+ // the profile image element is selected.
+ void SendProfileImage(const SkBitmap& image, bool should_select);
+
+ // Starts profile image update and shows the last downloaded profile image,
+ // if any, on the page. Shouldn't be called before |SendProfileImage|.
+ void UpdateProfileImage();
+
+ // Starts camera presence check.
+ void CheckCameraPresence();
+
+ // Updates UI with camera presence state.
+ void SetCameraPresent(bool present);
+
+ // Opens a file selection dialog to choose user image from file.
+ void HandleChooseFile(const base::ListValue* args);
+
+ // Opens the camera capture dialog.
+ void HandleTakePhoto(const base::ListValue* args);
+
+ // Gets the list of available user images and sends it to the page.
+ void HandleGetAvailableImages(const base::ListValue* args);
+
+ // Handles page initialized event.
+ void HandlePageInitialized(const base::ListValue* args);
+
+ // Handles page shown event.
+ void HandlePageShown(const base::ListValue* args);
+
+ // Selects one of the available images as user's.
+ void HandleSelectImage(const base::ListValue* args);
+
+ // SelectFileDialog::Delegate implementation.
+ virtual void FileSelected(
+ const FilePath& path,
+ int index, void* params) OVERRIDE;
+
+ // TakePhotoDialog::Delegate implementation.
+ virtual void OnPhotoAccepted(const SkBitmap& photo) OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // Called when the camera presence check has been completed.
+ void OnCameraPresenceCheckDone();
+
+ // Returns handle to browser window or NULL if it can't be found.
+ gfx::NativeWindow GetBrowserWindow() const;
+
+ scoped_refptr<SelectFileDialog> select_file_dialog_;
+
+ // Previous user image from camera/file and its data URL.
+ SkBitmap previous_image_;
+ std::string previous_image_data_url_;
+
+ // Index of the previous user image.
+ int previous_image_index_;
+
+ content::NotificationRegistrar registrar_;
+
+ base::WeakPtrFactory<ChangePictureOptionsHandler> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChangePictureOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CHANGE_PICTURE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.cc
new file mode 100644
index 0000000..7018e02
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.cc
@@ -0,0 +1,268 @@
+// 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/options2/chromeos/core_chromeos_options_handler.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/proxy_config_service_impl.h"
+#include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/prefs/pref_set_observer.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+namespace chromeos {
+
+namespace {
+
+// Create a settings value with "managed" and "disabled" property.
+// "managed" property is true if the setting is managed by administrator.
+// "disabled" property is true if the UI for the setting should be disabled.
+base::Value* CreateSettingsValue(base::Value *value,
+ bool managed,
+ bool disabled) {
+ DictionaryValue* dict = new DictionaryValue;
+ dict->Set("value", value);
+ dict->Set("managed", base::Value::CreateBooleanValue(managed));
+ dict->Set("disabled", base::Value::CreateBooleanValue(disabled));
+ return dict;
+}
+
+// Returns true if |username| is the logged-in owner.
+bool IsLoggedInOwner(const std::string& username) {
+ UserManager* user_manager = UserManager::Get();
+ return user_manager->current_user_is_owner() &&
+ user_manager->logged_in_user().email() == username;
+}
+
+// Creates a user info dictionary to be stored in the |ListValue| that is
+// passed to Javascript for the |kAccountsPrefUsers| preference.
+base::DictionaryValue* CreateUserInfo(const std::string& username,
+ const std::string& display_email,
+ const std::string& display_name) {
+ base::DictionaryValue* user_dict = new DictionaryValue;
+ user_dict->SetString("username", username);
+ user_dict->SetString("name", display_email);
+ user_dict->SetString("email", display_name);
+ user_dict->SetBoolean("owner", IsLoggedInOwner(username));
+ return user_dict;
+}
+
+// This function decorates the bare list of emails with some more information
+// needed by the UI to properly display the Accounts page.
+base::Value* CreateUsersWhitelist(const base::Value *pref_value) {
+ const base::ListValue* list_value =
+ static_cast<const base::ListValue*>(pref_value);
+ base::ListValue* user_list = new base::ListValue();
+ UserManager* user_manager = UserManager::Get();
+
+ for (base::ListValue::const_iterator i = list_value->begin();
+ i != list_value->end(); ++i) {
+ std::string email;
+ if ((*i)->GetAsString(&email)) {
+ // Translate email to the display email.
+ std::string display_email = user_manager->GetUserDisplayEmail(email);
+ // TODO(ivankr): fetch display name for existing users.
+ user_list->Append(CreateUserInfo(email, display_email, std::string()));
+ }
+ }
+ return user_list;
+}
+
+} // namespace
+
+CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler()
+ : handling_change_(false),
+ pointer_factory_(this) {
+}
+
+CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
+ PrefProxyConfigTracker* proxy_tracker =
+ Profile::FromWebUI(web_ui_)->GetProxyConfigTracker();
+ proxy_tracker->RemoveNotificationCallback(
+ base::Bind(&CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged,
+ pointer_factory_.GetWeakPtr()));
+}
+
+void CoreChromeOSOptionsHandler::Initialize() {
+ proxy_prefs_.reset(PrefSetObserver::CreateProxyPrefSetObserver(
+ Profile::FromWebUI(web_ui_)->GetPrefs(), this));
+ // Observe the chromeos::ProxyConfigServiceImpl for changes from the UI.
+ PrefProxyConfigTracker* proxy_tracker =
+ Profile::FromWebUI(web_ui_)->GetProxyConfigTracker();
+ proxy_tracker->AddNotificationCallback(
+ base::Bind(&CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged,
+ pointer_factory_.GetWeakPtr()));
+}
+
+base::Value* CoreChromeOSOptionsHandler::FetchPref(
+ const std::string& pref_name) {
+ if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
+ base::Value *value = NULL;
+ proxy_cros_settings_parser::GetProxyPrefValue(Profile::FromWebUI(web_ui_),
+ pref_name, &value);
+ if (!value)
+ return base::Value::CreateNullValue();
+
+ return value;
+ }
+ if (!CrosSettings::IsCrosSettings(pref_name)) {
+ // Specially handle kUseSharedProxies because kProxy controls it to
+ // determine if it's managed by policy/extension.
+ if (pref_name == prefs::kUseSharedProxies) {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ const PrefService::Preference* pref =
+ pref_service->FindPreference(prefs::kUseSharedProxies);
+ if (!pref)
+ return base::Value::CreateNullValue();
+ const PrefService::Preference* controlling_pref =
+ pref_service->FindPreference(prefs::kProxy);
+ return CreateValueForPref(pref, controlling_pref);
+ }
+ return ::CoreOptionsHandler::FetchPref(pref_name);
+ }
+
+ const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
+ if (!pref_value)
+ return base::Value::CreateNullValue();
+
+ // Lists don't get the standard pref decoration.
+ if (pref_value->GetType() == base::Value::TYPE_LIST) {
+ if (pref_name == kAccountsPrefUsers)
+ return CreateUsersWhitelist(pref_value);
+ // Return a copy because the UI will take ownership of this object.
+ return pref_value->DeepCopy();
+ }
+ // All other prefs are decorated the same way.
+ return CreateSettingsValue(
+ pref_value->DeepCopy(), // The copy will be owned by the dictionary.
+ g_browser_process->browser_policy_connector()->IsEnterpriseManaged(),
+ !UserManager::Get()->current_user_is_owner());
+}
+
+void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
+ if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
+ // We observe those all the time.
+ return;
+ }
+ if (!CrosSettings::IsCrosSettings(pref_name))
+ return ::CoreOptionsHandler::ObservePref(pref_name);
+ CrosSettings::Get()->AddSettingsObserver(pref_name.c_str(), this);
+}
+
+void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
+ const base::Value* value,
+ const std::string& metric) {
+ if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
+ proxy_cros_settings_parser::SetProxyPrefValue(Profile::FromWebUI(web_ui_),
+ pref_name, value);
+ ProcessUserMetric(value, metric);
+ return;
+ }
+ if (!CrosSettings::IsCrosSettings(pref_name))
+ return ::CoreOptionsHandler::SetPref(pref_name, value, metric);
+ handling_change_ = true;
+ CrosSettings::Get()->Set(pref_name, *value);
+ handling_change_ = false;
+
+ ProcessUserMetric(value, metric);
+}
+
+void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
+ if (proxy_cros_settings_parser::IsProxyPref(path))
+ return; // We unregister those in the destructor.
+ // Unregister this instance from observing prefs of chrome os settings.
+ if (CrosSettings::IsCrosSettings(path))
+ CrosSettings::Get()->RemoveSettingsObserver(path.c_str(), this);
+ else // Call base class to handle regular preferences.
+ ::CoreOptionsHandler::StopObservingPref(path);
+}
+
+void CoreChromeOSOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ // Ignore the notification if this instance had caused it.
+ if (handling_change_)
+ return;
+ if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) {
+ NotifySettingsChanged(content::Details<std::string>(details).ptr());
+ return;
+ }
+ // Special handling for preferences kUseSharedProxies and kProxy, the latter
+ // controls the former and decides if it's managed by policy/extension.
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ const PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ std::string* pref_name = content::Details<std::string>(details).ptr();
+ if (content::Source<PrefService>(source).ptr() == pref_service &&
+ (proxy_prefs_->IsObserved(*pref_name) ||
+ *pref_name == prefs::kUseSharedProxies)) {
+ NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
+ return;
+ }
+ }
+ ::CoreOptionsHandler::Observe(type, source, details);
+}
+
+void CoreChromeOSOptionsHandler::NotifySettingsChanged(
+ const std::string* setting_name) {
+ DCHECK(web_ui_);
+ DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name));
+ const base::Value* value = FetchPref(*setting_name);
+ if (!value) {
+ NOTREACHED();
+ return;
+ }
+ std::pair<PreferenceCallbackMap::const_iterator,
+ PreferenceCallbackMap::const_iterator> range =
+ pref_callback_map_.equal_range(*setting_name);
+ for (PreferenceCallbackMap::const_iterator iter = range.first;
+ iter != range.second; ++iter) {
+ const std::wstring& callback_function = iter->second;
+ ListValue result_value;
+ result_value.Append(base::Value::CreateStringValue(setting_name->c_str()));
+ result_value.Append(value->DeepCopy());
+ web_ui_->CallJavascriptFunction(WideToASCII(callback_function),
+ result_value);
+ }
+ if (value)
+ delete value;
+}
+
+void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
+ DCHECK(web_ui_);
+ for (size_t i = 0; i < kProxySettingsCount; ++i) {
+ base::Value* value = NULL;
+ proxy_cros_settings_parser::GetProxyPrefValue(
+ Profile::FromWebUI(web_ui_), kProxySettings[i], &value);
+ DCHECK(value);
+ PreferenceCallbackMap::const_iterator iter =
+ pref_callback_map_.find(kProxySettings[i]);
+ for (; iter != pref_callback_map_.end(); ++iter) {
+ const std::wstring& callback_function = iter->second;
+ ListValue result_value;
+ result_value.Append(base::Value::CreateStringValue(kProxySettings[i]));
+ result_value.Append(value->DeepCopy());
+ web_ui_->CallJavascriptFunction(WideToASCII(callback_function),
+ result_value);
+ }
+ if (value)
+ delete value;
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.h
new file mode 100644
index 0000000..48aa029
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.h
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CORE_CHROMEOS_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CORE_CHROMEOS_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/webui/options2/core_options_handler.h"
+
+class PrefSetObserver;
+
+namespace chromeos {
+
+// CoreChromeOSOptionsHandler handles ChromeOS settings.
+class CoreChromeOSOptionsHandler : public CoreOptionsHandler {
+ public:
+ CoreChromeOSOptionsHandler();
+ virtual ~CoreChromeOSOptionsHandler();
+
+ protected:
+ // ::CoreOptionsHandler overrides
+ virtual void Initialize() OVERRIDE;
+ virtual base::Value* FetchPref(const std::string& pref_name) OVERRIDE;
+ virtual void ObservePref(const std::string& pref_name) OVERRIDE;
+ virtual void SetPref(const std::string& pref_name,
+ const base::Value* value,
+ const std::string& metric) OVERRIDE;
+ virtual void StopObservingPref(const std::string& path) OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // Notifies registered JS callbacks on ChromeOS setting change.
+ void NotifySettingsChanged(const std::string* setting_name);
+ void NotifyProxyPrefsChanged();
+
+ // Keeps the track of change caused by the handler to make sure
+ // it does not signal itself again.
+ bool handling_change_;
+
+ scoped_ptr<PrefSetObserver> proxy_prefs_;
+ base::WeakPtrFactory<CoreChromeOSOptionsHandler> pointer_factory_;
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CORE_CHROMEOS_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.cc
new file mode 100644
index 0000000..ff772d3
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.cc
@@ -0,0 +1,242 @@
+// 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/options2/chromeos/cros_language_options_handler.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/user_metrics.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+
+CrosLanguageOptionsHandler::CrosLanguageOptionsHandler() {
+}
+
+CrosLanguageOptionsHandler::~CrosLanguageOptionsHandler() {
+}
+
+void CrosLanguageOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ LanguageOptionsHandlerCommon::GetLocalizedValues(localized_strings);
+
+ RegisterTitle(localized_strings, "languagePage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_AND_INPUT_DIALOG_TITLE);
+ localized_strings->SetString("ok_button", l10n_util::GetStringUTF16(IDS_OK));
+ localized_strings->SetString("configure",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE));
+ localized_strings->SetString("input_method",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD));
+ localized_strings->SetString("please_add_another_input_method",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_INPUT_METHOD));
+ localized_strings->SetString("input_method_instructions",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD_INSTRUCTIONS));
+ localized_strings->SetString("switch_input_methods_hint",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_SWITCH_INPUT_METHODS_HINT));
+ localized_strings->SetString("select_previous_input_method_hint",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_SELECT_PREVIOUS_INPUT_METHOD_HINT));
+ localized_strings->SetString("restart_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON));
+ localized_strings->SetString("virtual_keyboard_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_VIRTUAL_KEYBOARD_BUTTON));
+
+ input_method::InputMethodManager* manager =
+ input_method::InputMethodManager::GetInstance();
+ // GetSupportedInputMethods() never return NULL.
+ scoped_ptr<input_method::InputMethodDescriptors> descriptors(
+ manager->GetSupportedInputMethods());
+ localized_strings->Set("languageList", GetLanguageList(*descriptors));
+ localized_strings->Set("inputMethodList", GetInputMethodList(*descriptors));
+}
+
+void CrosLanguageOptionsHandler::RegisterMessages() {
+ LanguageOptionsHandlerCommon::RegisterMessages();
+
+ web_ui_->RegisterMessageCallback("inputMethodDisable",
+ base::Bind(&CrosLanguageOptionsHandler::InputMethodDisableCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("inputMethodEnable",
+ base::Bind(&CrosLanguageOptionsHandler::InputMethodEnableCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("inputMethodOptionsOpen",
+ base::Bind(&CrosLanguageOptionsHandler::InputMethodOptionsOpenCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("uiLanguageRestart",
+ base::Bind(&CrosLanguageOptionsHandler::RestartCallback,
+ base::Unretained(this)));
+}
+
+ListValue* CrosLanguageOptionsHandler::GetInputMethodList(
+ const input_method::InputMethodDescriptors& descriptors) {
+ input_method::InputMethodManager* manager =
+ input_method::InputMethodManager::GetInstance();
+
+ ListValue* input_method_list = new ListValue();
+
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ const input_method::InputMethodDescriptor& descriptor =
+ descriptors[i];
+ const std::string language_code =
+ manager->GetInputMethodUtil()->GetLanguageCodeFromDescriptor(
+ descriptor);
+ const std::string display_name =
+ manager->GetInputMethodUtil()->GetInputMethodDisplayNameFromId(
+ descriptor.id());
+
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("id", descriptor.id());
+ dictionary->SetString("displayName", display_name);
+
+ // One input method can be associated with multiple languages, hence
+ // we use a dictionary here.
+ DictionaryValue* language_codes = new DictionaryValue();
+ language_codes->SetBoolean(language_code, true);
+ // Check kExtraLanguages to see if there are languages associated with
+ // this input method. If these are present, add these.
+ for (size_t j = 0; j < input_method::kExtraLanguagesLength; ++j) {
+ const std::string extra_input_method_id =
+ input_method::kExtraLanguages[j].input_method_id;
+ const std::string extra_language_code =
+ input_method::kExtraLanguages[j].language_code;
+ if (extra_input_method_id == descriptor.id()) {
+ language_codes->SetBoolean(extra_language_code, true);
+ }
+ }
+ dictionary->Set("languageCodeSet", language_codes);
+
+ input_method_list->Append(dictionary);
+ }
+
+ return input_method_list;
+}
+
+ListValue* CrosLanguageOptionsHandler::GetLanguageList(
+ const input_method::InputMethodDescriptors& descriptors) {
+ input_method::InputMethodManager* manager =
+ input_method::InputMethodManager::GetInstance();
+
+ std::set<std::string> language_codes;
+ // Collect the language codes from the supported input methods.
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ const input_method::InputMethodDescriptor& descriptor = descriptors[i];
+ const std::string language_code =
+ manager->GetInputMethodUtil()->GetLanguageCodeFromDescriptor(
+ descriptor);
+ language_codes.insert(language_code);
+ }
+ // Collect the language codes from kExtraLanguages.
+ for (size_t i = 0; i < input_method::kExtraLanguagesLength; ++i) {
+ const char* language_code =
+ input_method::kExtraLanguages[i].language_code;
+ language_codes.insert(language_code);
+ }
+
+ // Map of display name -> {language code, native_display_name}.
+ // In theory, we should be able to create a map that is sorted by
+ // display names using ICU comparator, but doing it is hard, thus we'll
+ // use an auxiliary vector to achieve the same result.
+ typedef std::pair<std::string, string16> LanguagePair;
+ typedef std::map<string16, LanguagePair> LanguageMap;
+ LanguageMap language_map;
+ // The auxiliary vector mentioned above.
+ std::vector<string16> display_names;
+
+ // Build the list of display names, and build the language map.
+ for (std::set<std::string>::const_iterator iter = language_codes.begin();
+ iter != language_codes.end(); ++iter) {
+ const string16 display_name =
+ input_method::InputMethodUtil::GetLanguageDisplayNameFromCode(*iter);
+ const string16 native_display_name =
+ input_method::InputMethodUtil::GetLanguageNativeDisplayNameFromCode(
+ *iter);
+ display_names.push_back(display_name);
+ language_map[display_name] =
+ std::make_pair(*iter, native_display_name);
+ }
+ DCHECK_EQ(display_names.size(), language_map.size());
+
+ // Sort display names using locale specific sorter.
+ l10n_util::SortStrings16(g_browser_process->GetApplicationLocale(),
+ &display_names);
+
+ // Build the language list from the language map.
+ ListValue* language_list = new ListValue();
+ for (size_t i = 0; i < display_names.size(); ++i) {
+ const LanguagePair& pair = language_map[display_names[i]];
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("code", pair.first);
+ dictionary->SetString("displayName", display_names[i]);
+ dictionary->SetString("nativeDisplayName", pair.second);
+ language_list->Append(dictionary);
+ }
+
+ return language_list;
+}
+
+string16 CrosLanguageOptionsHandler::GetProductName() {
+ return l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME);
+}
+
+void CrosLanguageOptionsHandler::SetApplicationLocale(
+ const std::string& language_code) {
+ Profile::FromWebUI(web_ui_)->ChangeAppLocale(
+ language_code, Profile::APP_LOCALE_CHANGED_VIA_SETTINGS);
+}
+
+void CrosLanguageOptionsHandler::RestartCallback(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_SignOut"));
+
+ Browser* browser = Browser::GetBrowserForController(
+ &web_ui_->tab_contents()->controller(), NULL);
+ if (browser)
+ browser->ExecuteCommand(IDC_EXIT);
+}
+
+void CrosLanguageOptionsHandler::InputMethodDisableCallback(
+ const ListValue* args) {
+ const std::string input_method_id = UTF16ToASCII(ExtractStringValue(args));
+ const std::string action = base::StringPrintf(
+ "LanguageOptions_DisableInputMethod_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+void CrosLanguageOptionsHandler::InputMethodEnableCallback(
+ const ListValue* args) {
+ const std::string input_method_id = UTF16ToASCII(ExtractStringValue(args));
+ const std::string action = base::StringPrintf(
+ "LanguageOptions_EnableInputMethod_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+void CrosLanguageOptionsHandler::InputMethodOptionsOpenCallback(
+ const ListValue* args) {
+ const std::string input_method_id = UTF16ToASCII(ExtractStringValue(args));
+ const std::string action = base::StringPrintf(
+ "InputMethodOptions_Open_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h
new file mode 100644
index 0000000..aa0464b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CROS_LANGUAGE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CROS_LANGUAGE_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/chromeos/input_method/ibus_controller.h"
+#include "chrome/browser/ui/webui/options2/language_options_handler.h"
+
+namespace chromeos {
+
+// Language options page UI handler for Chrome OS. For non-Chrome OS,
+// see LanguageOptionsHnadler.
+class CrosLanguageOptionsHandler : public LanguageOptionsHandlerCommon {
+ public:
+ CrosLanguageOptionsHandler();
+ virtual ~CrosLanguageOptionsHandler();
+
+ // OptionsPageUIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // DOMMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // The following static methods are public for ease of testing.
+
+ // Gets the list of input methods from the given input descriptors.
+ // The return value will look like:
+ // [{'id': 'pinyin', 'displayName': 'Pinyin',
+ // 'languageCodeSet': {'zh-CW': true}}, ...]
+ //
+ // Note that true in languageCodeSet does not mean anything. We just use
+ // the dictionary as a set.
+ static base::ListValue* GetInputMethodList(
+ const input_method::InputMethodDescriptors& descriptors);
+
+ // Gets the list of languages from the given input descriptors.
+ // The return value will look like:
+ // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
+ // ...]
+ static base::ListValue* GetLanguageList(
+ const input_method::InputMethodDescriptors& descriptors);
+
+ private:
+ // LanguageOptionsHandlerCommon implementation.
+ virtual string16 GetProductName() OVERRIDE;
+ virtual void SetApplicationLocale(const std::string& language_code) OVERRIDE;
+
+ // Called when the sign-out button is clicked.
+ void RestartCallback(const base::ListValue* args);
+
+ // Called when the input method is disabled.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodDisableCallback(const base::ListValue* args);
+
+ // Called when the input method is enabled.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodEnableCallback(const base::ListValue* args);
+
+ // Called when the input method options page is opened.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodOptionsOpenCallback(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(CrosLanguageOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_CROS_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/guest_mode_options_ui_uitest.cc b/chrome/browser/ui/webui/options2/chromeos/guest_mode_options_ui_uitest.cc
new file mode 100644
index 0000000..e001d63
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/guest_mode_options_ui_uitest.cc
@@ -0,0 +1,43 @@
+// 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/options2/options_ui_uitest.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+
+namespace {
+
+// Same as OptionsUITest but launches with Guest mode command line switches.
+class GuestModeOptionsUITest : public OptionsUITest {
+ public:
+ GuestModeOptionsUITest() : OptionsUITest() {
+ launch_arguments_.AppendSwitch(switches::kGuestSession);
+ launch_arguments_.AppendSwitch(switches::kIncognito);
+ }
+};
+
+// See bug 104393.
+#if defined(USE_AURA)
+#define MAYBE_LoadOptionsByURL FAILS_LoadOptionsByURL
+#else
+#define MAYBE_LoadOptionsByURL LoadOptionsByURL
+#endif
+
+TEST_F(GuestModeOptionsUITest, MAYBE_LoadOptionsByURL) {
+ scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+
+ scoped_refptr<TabProxy> tab = browser->GetActiveTab();
+ ASSERT_TRUE(tab.get());
+
+ NavigateToSettings(tab);
+ VerifyTitle(tab);
+ VerifyNavbar(tab);
+ VerifySections(tab);
+}
+
+} // namespace
diff --git a/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.cc
new file mode 100644
index 0000000..ed42aac
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.cc
@@ -0,0 +1,1372 @@
+// 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/options2/chromeos/internet_options_handler.h"
+
+#include <ctype.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/base64.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/i18n/time_formatting.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/choose_mobile_network_dialog.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/mobile_config.h"
+#include "chrome/browser/chromeos/options2/network_config_view.h"
+#include "chrome/browser/chromeos/proxy_config_service_impl.h"
+#include "chrome/browser/chromeos/sim_dialog_delegate.h"
+#include "chrome/browser/chromeos/status/network_menu_icon.h"
+#include "chrome/browser/net/pref_proxy_config_tracker.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/dialog_style.h"
+#include "chrome/browser/ui/views/window.h"
+#include "chrome/browser/ui/webui/web_ui_util.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/time_format.h"
+#include "content/public/browser/notification_service.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+static const char kOtherNetworksFakePath[] = "?";
+
+// Keys for the network description dictionary passed to the web ui. Make sure
+// to keep the strings in sync with what the Javascript side uses.
+const char kNetworkInfoKeyActivationState[] = "activation_state";
+const char kNetworkInfoKeyConnectable[] = "connectable";
+const char kNetworkInfoKeyConnected[] = "connected";
+const char kNetworkInfoKeyConnecting[] = "connecting";
+const char kNetworkInfoKeyIconURL[] = "iconURL";
+const char kNetworkInfoKeyNeedsNewPlan[] = "needs_new_plan";
+const char kNetworkInfoKeyNetworkName[] = "networkName";
+const char kNetworkInfoKeyNetworkStatus[] = "networkStatus";
+const char kNetworkInfoKeyNetworkType[] = "networkType";
+const char kNetworkInfoKeyRemembered[] = "remembered";
+const char kNetworkInfoKeyServicePath[] = "servicePath";
+const char kNetworkInfoKeyPolicyManaged[] = "policyManaged";
+
+// A helper class for building network information dictionaries to be sent to
+// the webui code.
+class NetworkInfoDictionary {
+ public:
+ // Initializes the dictionary with default values.
+ NetworkInfoDictionary();
+
+ // Copies in service path, connect{ing|ed|able} flags and connection type from
+ // the provided network object. Also chooses an appropriate icon based on the
+ // network type.
+ explicit NetworkInfoDictionary(const chromeos::Network* network);
+
+ // Initializes a remembered network entry, pulling information from the passed
+ // network object and the corresponding remembered network object. |network|
+ // may be NULL.
+ NetworkInfoDictionary(const chromeos::Network* network,
+ const chromeos::Network* remembered);
+
+ // Setters for filling in information.
+ void set_service_path(const std::string& service_path) {
+ service_path_ = service_path;
+ }
+ void set_icon(const SkBitmap& icon) {
+ icon_url_ = icon.isNull() ? "" : web_ui_util::GetImageDataUrl(icon);
+ }
+ void set_name(const std::string& name) {
+ name_ = name;
+ }
+ void set_connecting(bool connecting) {
+ connecting_ = connecting;
+ }
+ void set_connected(bool connected) {
+ connected_ = connected;
+ }
+ void set_connectable(bool connectable) {
+ connectable_ = connectable;
+ }
+ void set_connection_type(chromeos::ConnectionType connection_type) {
+ connection_type_ = connection_type;
+ }
+ void set_remembered(bool remembered) {
+ remembered_ = remembered;
+ }
+ void set_shared(bool shared) {
+ shared_ = shared;
+ }
+ void set_activation_state(chromeos::ActivationState activation_state) {
+ activation_state_ = activation_state;
+ }
+ void set_needs_new_plan(bool needs_new_plan) {
+ needs_new_plan_ = needs_new_plan;
+ }
+ void set_policy_managed(bool policy_managed) {
+ policy_managed_ = policy_managed;
+ }
+
+ // Builds the DictionaryValue representation from the previously set
+ // parameters. Ownership of the returned pointer is transferred to the caller.
+ DictionaryValue* BuildDictionary();
+
+ private:
+ // Values to be filled into the dictionary.
+ std::string service_path_;
+ std::string icon_url_;
+ std::string name_;
+ bool connecting_;
+ bool connected_;
+ bool connectable_;
+ chromeos::ConnectionType connection_type_;
+ bool remembered_;
+ bool shared_;
+ chromeos::ActivationState activation_state_;
+ bool needs_new_plan_;
+ bool policy_managed_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkInfoDictionary);
+};
+
+NetworkInfoDictionary::NetworkInfoDictionary() {
+ set_connecting(false);
+ set_connected(false);
+ set_connectable(false);
+ set_remembered(false);
+ set_shared(false);
+ set_activation_state(chromeos::ACTIVATION_STATE_UNKNOWN);
+ set_needs_new_plan(false);
+ set_policy_managed(false);
+}
+
+NetworkInfoDictionary::NetworkInfoDictionary(const chromeos::Network* network) {
+ set_service_path(network->service_path());
+ set_icon(chromeos::NetworkMenuIcon::GetBitmap(network));
+ set_name(network->name());
+ set_connecting(network->connecting());
+ set_connected(network->connected());
+ set_connectable(network->connectable());
+ set_connection_type(network->type());
+ set_remembered(false);
+ set_shared(false);
+ set_needs_new_plan(false);
+ set_policy_managed(chromeos::NetworkUIData::IsManaged(network));
+}
+
+NetworkInfoDictionary::NetworkInfoDictionary(
+ const chromeos::Network* network,
+ const chromeos::Network* remembered) {
+ set_service_path(remembered->service_path());
+ set_icon(
+ chromeos::NetworkMenuIcon::GetBitmap(network ? network : remembered));
+ set_name(remembered->name());
+ set_connecting(network ? network->connecting() : false);
+ set_connected(network ? network->connected() : false);
+ set_connectable(true);
+ set_connection_type(remembered->type());
+ set_remembered(true);
+ set_shared(remembered->profile_type() == chromeos::PROFILE_SHARED);
+ set_needs_new_plan(false);
+ set_policy_managed(
+ network ? chromeos::NetworkUIData::IsManaged(network) : false);
+}
+
+DictionaryValue* NetworkInfoDictionary::BuildDictionary() {
+ std::string status;
+
+ if (remembered_) {
+ if (shared_)
+ status = l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SHARED_NETWORK);
+ } else {
+ // 802.1X networks can be connected but not have saved credentials, and
+ // hence be "not configured". Give preference to the "connected" and
+ // "connecting" states. http://crosbug.com/14459
+ int connection_state = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED;
+ if (connected_)
+ connection_state = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED;
+ else if (connecting_)
+ connection_state = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING;
+ else if (!connectable_)
+ connection_state = IDS_STATUSBAR_NETWORK_DEVICE_NOT_CONFIGURED;
+ status = l10n_util::GetStringUTF8(connection_state);
+ if (connection_type_ == chromeos::TYPE_CELLULAR) {
+ if (needs_new_plan_) {
+ status = l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_NO_PLAN_LABEL);
+ } else if (activation_state_ != chromeos::ACTIVATION_STATE_ACTIVATED) {
+ status.append(" / ");
+ status.append(chromeos::CellularNetwork::ActivationStateToString(
+ activation_state_));
+ }
+ }
+ }
+
+ scoped_ptr<DictionaryValue> network_info(new DictionaryValue());
+ network_info->SetInteger(kNetworkInfoKeyActivationState,
+ static_cast<int>(activation_state_));
+ network_info->SetBoolean(kNetworkInfoKeyConnectable, connectable_);
+ network_info->SetBoolean(kNetworkInfoKeyConnected, connected_);
+ network_info->SetBoolean(kNetworkInfoKeyConnecting, connecting_);
+ network_info->SetString(kNetworkInfoKeyIconURL, icon_url_);
+ network_info->SetBoolean(kNetworkInfoKeyNeedsNewPlan, needs_new_plan_);
+ network_info->SetString(kNetworkInfoKeyNetworkName, name_);
+ network_info->SetString(kNetworkInfoKeyNetworkStatus, status);
+ network_info->SetInteger(kNetworkInfoKeyNetworkType,
+ static_cast<int>(connection_type_));
+ network_info->SetBoolean(kNetworkInfoKeyRemembered, remembered_);
+ network_info->SetString(kNetworkInfoKeyServicePath, service_path_);
+ network_info->SetBoolean(kNetworkInfoKeyPolicyManaged, policy_managed_);
+
+ return network_info.release();
+}
+
+} // namespace
+
+InternetOptionsHandler::InternetOptionsHandler() {
+ registrar_.Add(this, chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
+ content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_ENTER_PIN_ENDED,
+ content::NotificationService::AllSources());
+ cros_ = chromeos::CrosLibrary::Get()->GetNetworkLibrary();
+ if (cros_) {
+ cros_->AddNetworkManagerObserver(this);
+ cros_->AddCellularDataPlanObserver(this);
+ MonitorNetworks();
+ }
+}
+
+InternetOptionsHandler::~InternetOptionsHandler() {
+ if (cros_) {
+ cros_->RemoveNetworkManagerObserver(this);
+ cros_->RemoveCellularDataPlanObserver(this);
+ cros_->RemoveObserverForAllNetworks(this);
+ }
+}
+
+void InternetOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "internetPage",
+ IDS_OPTIONS_INTERNET_TAB_LABEL);
+
+ localized_strings->SetString("wired_title",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRED_NETWORK));
+ localized_strings->SetString("wireless_title",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRELESS_NETWORK));
+ localized_strings->SetString("vpn_title",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_VIRTUAL_NETWORK));
+ localized_strings->SetString("remembered_title",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_REMEMBERED_NETWORK));
+
+ localized_strings->SetString("connect_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_CONNECT));
+ localized_strings->SetString("disconnect_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISCONNECT));
+ localized_strings->SetString("options_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_OPTIONS));
+ localized_strings->SetString("forget_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_FORGET));
+ localized_strings->SetString("activate_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_ACTIVATE));
+ localized_strings->SetString("buyplan_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_BUY_PLAN));
+
+ localized_strings->SetString("changeProxyButton",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CHANGE_PROXY_BUTTON));
+
+ localized_strings->SetString("managedNetwork",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_MANAGED_NETWORK));
+
+ localized_strings->SetString("wifiNetworkTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_WIFI));
+ localized_strings->SetString("vpnTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_VPN));
+ localized_strings->SetString("cellularPlanTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_PLAN));
+ localized_strings->SetString("cellularConnTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_CONNECTION));
+ localized_strings->SetString("cellularDeviceTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_DEVICE));
+ localized_strings->SetString("networkTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_NETWORK));
+ localized_strings->SetString("securityTabLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_TAB_SECURITY));
+
+ localized_strings->SetString("useDHCP",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USE_DHCP));
+ localized_strings->SetString("useStaticIP",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USE_STATIC_IP));
+ localized_strings->SetString("connectionState",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CONNECTION_STATE));
+ localized_strings->SetString("inetAddress",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADDRESS));
+ localized_strings->SetString("inetSubnetAddress",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SUBNETMASK));
+ localized_strings->SetString("inetGateway",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_GATEWAY));
+ localized_strings->SetString("inetDns",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_DNSSERVER));
+ localized_strings->SetString("hardwareAddress",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_HARDWARE_ADDRESS));
+
+ // Wifi Tab.
+ localized_strings->SetString("accessLockedMsg",
+ l10n_util::GetStringUTF16(
+ IDS_STATUSBAR_NETWORK_LOCKED));
+ localized_strings->SetString("inetSsid",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
+ localized_strings->SetString("inetPassProtected",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NET_PROTECTED));
+ localized_strings->SetString("inetNetworkShared",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_SHARED));
+ localized_strings->SetString("inetPreferredNetwork",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PREFER_NETWORK));
+ localized_strings->SetString("inetAutoConnectNetwork",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
+ localized_strings->SetString("inetLogin",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN));
+ localized_strings->SetString("inetShowPass",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHOWPASSWORD));
+ localized_strings->SetString("inetPassPrompt",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSWORD));
+ localized_strings->SetString("inetSsidPrompt",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SSID));
+ localized_strings->SetString("inetStatus",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_STATUS_TITLE));
+ localized_strings->SetString("inetConnect",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CONNECT_TITLE));
+
+ // VPN Tab.
+ localized_strings->SetString("inetServiceName",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME));
+ localized_strings->SetString("inetServerHostname",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME));
+ localized_strings->SetString("inetProviderType",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE));
+ localized_strings->SetString("inetUsername",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME));
+
+ // Cellular Tab.
+ localized_strings->SetString("serviceName",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_SERVICE_NAME));
+ localized_strings->SetString("networkTechnology",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_NETWORK_TECHNOLOGY));
+ localized_strings->SetString("operatorName",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_OPERATOR));
+ localized_strings->SetString("operatorCode",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_OPERATOR_CODE));
+ localized_strings->SetString("activationState",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ACTIVATION_STATE));
+ localized_strings->SetString("roamingState",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ROAMING_STATE));
+ localized_strings->SetString("restrictedPool",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_RESTRICTED_POOL));
+ localized_strings->SetString("errorState",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ERROR_STATE));
+ localized_strings->SetString("manufacturer",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_MANUFACTURER));
+ localized_strings->SetString("modelId",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_MODEL_ID));
+ localized_strings->SetString("firmwareRevision",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_FIRMWARE_REVISION));
+ localized_strings->SetString("hardwareRevision",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_HARDWARE_REVISION));
+ localized_strings->SetString("prlVersion",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_PRL_VERSION));
+ localized_strings->SetString("cellularApnLabel",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN));
+ localized_strings->SetString("cellularApnOther",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_OTHER));
+ localized_strings->SetString("cellularApnUsername",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_USERNAME));
+ localized_strings->SetString("cellularApnPassword",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_PASSWORD));
+ localized_strings->SetString("cellularApnUseDefault",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_CLEAR));
+ localized_strings->SetString("cellularApnSet",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_SET));
+ localized_strings->SetString("cellularApnCancel",
+ l10n_util::GetStringUTF16(
+ IDS_CANCEL));
+
+ localized_strings->SetString("accessSecurityTabLink",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ACCESS_SECURITY_TAB));
+ localized_strings->SetString("lockSimCard",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_LOCK_SIM_CARD));
+ localized_strings->SetString("changePinButton",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_BUTTON));
+
+ localized_strings->SetString("planName",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CELL_PLAN_NAME));
+ localized_strings->SetString("planLoading",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOADING_PLAN));
+ localized_strings->SetString("noPlansFound",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NO_PLANS_FOUND));
+ localized_strings->SetString("purchaseMore",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_MORE));
+ localized_strings->SetString("dataRemaining",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_DATA_REMAINING));
+ localized_strings->SetString("planExpires",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EXPIRES));
+ localized_strings->SetString("showPlanNotifications",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHOW_MOBILE_NOTIFICATION));
+ localized_strings->SetString("autoconnectCellular",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
+ localized_strings->SetString("customerSupport",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CUSTOMER_SUPPORT));
+
+ localized_strings->SetString("enableWifi",
+ l10n_util::GetStringFUTF16(
+ IDS_STATUSBAR_NETWORK_DEVICE_ENABLE,
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI)));
+ localized_strings->SetString("disableWifi",
+ l10n_util::GetStringFUTF16(
+ IDS_STATUSBAR_NETWORK_DEVICE_DISABLE,
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI)));
+ localized_strings->SetString("enableCellular",
+ l10n_util::GetStringFUTF16(
+ IDS_STATUSBAR_NETWORK_DEVICE_ENABLE,
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR)));
+ localized_strings->SetString("disableCellular",
+ l10n_util::GetStringFUTF16(
+ IDS_STATUSBAR_NETWORK_DEVICE_DISABLE,
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR)));
+ localized_strings->SetString("useSharedProxies",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_USE_SHARED_PROXIES));
+ localized_strings->SetString("enableDataRoaming",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_ENABLE_DATA_ROAMING));
+ localized_strings->SetString("generalNetworkingTitle",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_CONTROL_TITLE));
+ localized_strings->SetString("detailsInternetDismiss",
+ l10n_util::GetStringUTF16(IDS_CLOSE));
+ localized_strings->SetString("ownerOnly", l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_OWNER_ONLY));
+ std::string owner;
+ chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
+ localized_strings->SetString("ownerUserId", UTF8ToUTF16(owner));
+
+ FillNetworkInfo(localized_strings);
+}
+
+void InternetOptionsHandler::Initialize() {
+ cros_->RequestNetworkScan();
+}
+
+void InternetOptionsHandler::RegisterMessages() {
+ // Setup handlers specific to this panel.
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("buttonClickCallback",
+ base::Bind(&InternetOptionsHandler::ButtonClickCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("refreshCellularPlan",
+ base::Bind(&InternetOptionsHandler::RefreshCellularPlanCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setPreferNetwork",
+ base::Bind(&InternetOptionsHandler::SetPreferNetworkCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setAutoConnect",
+ base::Bind(&InternetOptionsHandler::SetAutoConnectCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setIPConfig",
+ base::Bind(&InternetOptionsHandler::SetIPConfigCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("enableWifi",
+ base::Bind(&InternetOptionsHandler::EnableWifiCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("disableWifi",
+ base::Bind(&InternetOptionsHandler::DisableWifiCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("enableCellular",
+ base::Bind(&InternetOptionsHandler::EnableCellularCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("disableCellular",
+ base::Bind(&InternetOptionsHandler::DisableCellularCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("buyDataPlan",
+ base::Bind(&InternetOptionsHandler::BuyDataPlanCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("showMorePlanInfo",
+ base::Bind(&InternetOptionsHandler::BuyDataPlanCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setApn",
+ base::Bind(&InternetOptionsHandler::SetApnCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setSimCardLock",
+ base::Bind(&InternetOptionsHandler::SetSimCardLockCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("changePin",
+ base::Bind(&InternetOptionsHandler::ChangePinCallback,
+ base::Unretained(this)));
+}
+
+void InternetOptionsHandler::EnableWifiCallback(const ListValue* args) {
+ cros_->EnableWifiNetworkDevice(true);
+}
+
+void InternetOptionsHandler::DisableWifiCallback(const ListValue* args) {
+ cros_->EnableWifiNetworkDevice(false);
+}
+
+void InternetOptionsHandler::EnableCellularCallback(const ListValue* args) {
+ const chromeos::NetworkDevice* cellular = cros_->FindCellularDevice();
+ if (!cellular) {
+ LOG(ERROR) << "Didn't find cellular device, it should have been available.";
+ cros_->EnableCellularNetworkDevice(true);
+ } else if (cellular->sim_lock_state() == chromeos::SIM_UNLOCKED ||
+ cellular->sim_lock_state() == chromeos::SIM_UNKNOWN) {
+ cros_->EnableCellularNetworkDevice(true);
+ } else {
+ chromeos::SimDialogDelegate::ShowDialog(GetNativeWindow(),
+ chromeos::SimDialogDelegate::SIM_DIALOG_UNLOCK);
+ }
+}
+
+void InternetOptionsHandler::DisableCellularCallback(const ListValue* args) {
+ cros_->EnableCellularNetworkDevice(false);
+}
+
+void InternetOptionsHandler::BuyDataPlanCallback(const ListValue* args) {
+ if (!web_ui_)
+ return;
+ Browser* browser = BrowserList::FindBrowserWithFeature(
+ Profile::FromWebUI(web_ui_), Browser::FEATURE_TABSTRIP);
+ if (browser)
+ browser->OpenMobilePlanTabAndActivate();
+}
+
+void InternetOptionsHandler::SetApnCallback(const ListValue* args) {
+ std::string service_path;
+ std::string apn;
+ std::string username;
+ std::string password;
+ if (args->GetSize() != 4 ||
+ !args->GetString(0, &service_path) ||
+ !args->GetString(1, &apn) ||
+ !args->GetString(2, &username) ||
+ !args->GetString(3, &password)) {
+ NOTREACHED();
+ return;
+ }
+
+ chromeos::CellularNetwork* network =
+ cros_->FindCellularNetworkByPath(service_path);
+ if (network) {
+ network->SetApn(chromeos::CellularApn(
+ apn, network->apn().network_id, username, password));
+ }
+}
+
+void InternetOptionsHandler::SetSimCardLockCallback(const ListValue* args) {
+ bool require_pin_new_value;
+ if (!args->GetBoolean(0, &require_pin_new_value)) {
+ NOTREACHED();
+ return;
+ }
+ // 1. Bring up SIM unlock dialog, pass new RequirePin setting in URL.
+ // 2. Dialog will ask for current PIN in any case.
+ // 3. If card is locked it will first call PIN unlock operation
+ // 4. Then it will call Set RequirePin, passing the same PIN.
+ // 5. We'll get notified by REQUIRE_PIN_SETTING_CHANGE_ENDED notification.
+ chromeos::SimDialogDelegate::SimDialogMode mode;
+ if (require_pin_new_value)
+ mode = chromeos::SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON;
+ else
+ mode = chromeos::SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF;
+ chromeos::SimDialogDelegate::ShowDialog(GetNativeWindow(), mode);
+}
+
+void InternetOptionsHandler::ChangePinCallback(const ListValue* args) {
+ chromeos::SimDialogDelegate::ShowDialog(GetNativeWindow(),
+ chromeos::SimDialogDelegate::SIM_DIALOG_CHANGE_PIN);
+}
+
+void InternetOptionsHandler::RefreshNetworkData() {
+ DictionaryValue dictionary;
+ FillNetworkInfo(&dictionary);
+ web_ui_->CallJavascriptFunction(
+ "options.InternetOptions.refreshNetworkData", dictionary);
+}
+
+void InternetOptionsHandler::OnNetworkManagerChanged(
+ chromeos::NetworkLibrary* cros) {
+ if (!web_ui_)
+ return;
+ MonitorNetworks();
+ RefreshNetworkData();
+}
+
+void InternetOptionsHandler::OnNetworkChanged(
+ chromeos::NetworkLibrary* cros,
+ const chromeos::Network* network) {
+ if (web_ui_)
+ RefreshNetworkData();
+}
+
+// Monitor wireless networks for changes. It is only necessary
+// to set up individual observers for the cellular networks
+// (if any) and for the connected Wi-Fi network (if any). The
+// only change we are interested in for Wi-Fi networks is signal
+// strength. For non-connected Wi-Fi networks, all information is
+// reported via scan results, which trigger network manager
+// updates. Only the connected Wi-Fi network has changes reported
+// via service property updates.
+void InternetOptionsHandler::MonitorNetworks() {
+ cros_->RemoveObserverForAllNetworks(this);
+ const chromeos::WifiNetwork* wifi_network = cros_->wifi_network();
+ if (wifi_network)
+ cros_->AddNetworkObserver(wifi_network->service_path(), this);
+ // Always monitor the cellular networks, if any, so that changes
+ // in network technology, roaming status, and signal strength
+ // will be shown.
+ const chromeos::CellularNetworkVector& cell_networks =
+ cros_->cellular_networks();
+ for (size_t i = 0; i < cell_networks.size(); ++i) {
+ chromeos::CellularNetwork* cell_network = cell_networks[i];
+ cros_->AddNetworkObserver(cell_network->service_path(), this);
+ }
+ const chromeos::VirtualNetwork* virtual_network = cros_->virtual_network();
+ if (virtual_network)
+ cros_->AddNetworkObserver(virtual_network->service_path(), this);
+}
+
+void InternetOptionsHandler::OnCellularDataPlanChanged(
+ chromeos::NetworkLibrary* cros) {
+ if (!web_ui_)
+ return;
+ const chromeos::CellularNetwork* cellular = cros_->cellular_network();
+ if (!cellular)
+ return;
+ const chromeos::CellularDataPlanVector* plans =
+ cros_->GetDataPlans(cellular->service_path());
+ DictionaryValue connection_plans;
+ ListValue* plan_list = new ListValue();
+ if (plans) {
+ for (chromeos::CellularDataPlanVector::const_iterator iter = plans->begin();
+ iter != plans->end(); ++iter) {
+ plan_list->Append(CellularDataPlanToDictionary(*iter));
+ }
+ }
+ connection_plans.SetString("servicePath", cellular->service_path());
+ connection_plans.SetBoolean("needsPlan", cellular->needs_new_plan());
+ connection_plans.SetBoolean("activated",
+ cellular->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED);
+ connection_plans.Set("plans", plan_list);
+ SetActivationButtonVisibility(cellular, &connection_plans);
+ web_ui_->CallJavascriptFunction(
+ "options.InternetOptions.updateCellularPlans", connection_plans);
+}
+
+
+void InternetOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ OptionsPageUIHandler::Observe(type, source, details);
+ if (type == chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED) {
+ base::FundamentalValue require_pin(*content::Details<bool>(details).ptr());
+ web_ui_->CallJavascriptFunction(
+ "options.InternetOptions.updateSecurityTab", require_pin);
+ } else if (type == chrome::NOTIFICATION_ENTER_PIN_ENDED) {
+ // We make an assumption (which is valid for now) that the SIM
+ // unlock dialog is put up only when the user is trying to enable
+ // mobile data.
+ bool cancelled = *content::Details<bool>(details).ptr();
+ if (cancelled) {
+ base::DictionaryValue dictionary;
+ FillNetworkInfo(&dictionary);
+ web_ui_->CallJavascriptFunction(
+ "options.InternetOptions.setupAttributes", dictionary);
+ }
+ // The case in which the correct PIN was entered and the SIM is
+ // now unlocked is handled in NetworkMenuButton.
+ }
+}
+
+DictionaryValue* InternetOptionsHandler::CellularDataPlanToDictionary(
+ const chromeos::CellularDataPlan* plan) {
+ DictionaryValue* plan_dict = new DictionaryValue();
+ plan_dict->SetInteger("planType", plan->plan_type);
+ plan_dict->SetString("name", plan->plan_name);
+ plan_dict->SetString("planSummary", plan->GetPlanDesciption());
+ plan_dict->SetString("dataRemaining", plan->GetDataRemainingDesciption());
+ plan_dict->SetString("planExpires", plan->GetPlanExpiration());
+ plan_dict->SetString("warning", plan->GetRemainingWarning());
+ return plan_dict;
+}
+
+void InternetOptionsHandler::SetPreferNetworkCallback(const ListValue* args) {
+ std::string service_path;
+ std::string prefer_network_str;
+
+ if (args->GetSize() < 2 ||
+ !args->GetString(0, &service_path) ||
+ !args->GetString(1, &prefer_network_str)) {
+ NOTREACHED();
+ return;
+ }
+
+ chromeos::Network* network = cros_->FindNetworkByPath(service_path);
+ if (!network)
+ return;
+
+ bool prefer_network = prefer_network_str == "true";
+ if (prefer_network != network->preferred())
+ network->SetPreferred(prefer_network);
+}
+
+void InternetOptionsHandler::SetAutoConnectCallback(const ListValue* args) {
+ std::string service_path;
+ std::string auto_connect_str;
+
+ if (args->GetSize() < 2 ||
+ !args->GetString(0, &service_path) ||
+ !args->GetString(1, &auto_connect_str)) {
+ NOTREACHED();
+ return;
+ }
+
+ chromeos::Network* network = cros_->FindNetworkByPath(service_path);
+ if (!network)
+ return;
+
+ bool auto_connect = auto_connect_str == "true";
+ if (auto_connect != network->auto_connect())
+ network->SetAutoConnect(auto_connect);
+}
+
+void InternetOptionsHandler::SetIPConfigCallback(const ListValue* args) {
+ std::string service_path;
+ std::string dhcp_str;
+ std::string address;
+ std::string netmask;
+ std::string gateway;
+ std::string name_servers;
+
+ if (args->GetSize() < 6 ||
+ !args->GetString(0, &service_path) ||
+ !args->GetString(1, &dhcp_str) ||
+ !args->GetString(2, &address) ||
+ !args->GetString(3, &netmask) ||
+ !args->GetString(4, &gateway) ||
+ !args->GetString(5, &name_servers)) {
+ NOTREACHED();
+ return;
+ }
+
+ chromeos::Network* network = cros_->FindNetworkByPath(service_path);
+ if (!network)
+ return;
+
+ cros_->SetIPConfig(chromeos::NetworkIPConfig(network->device_path(),
+ dhcp_str == "true" ? chromeos::IPCONFIG_TYPE_DHCP :
+ chromeos::IPCONFIG_TYPE_IPV4,
+ address, netmask, gateway, name_servers));
+}
+
+void InternetOptionsHandler::PopulateDictionaryDetails(
+ const chromeos::Network* network) {
+ DCHECK(network);
+
+ if (web_ui_) {
+ Profile::FromWebUI(web_ui_)->GetProxyConfigTracker()->UISetCurrentNetwork(
+ network->service_path());
+ }
+
+ DictionaryValue dictionary;
+ std::string hardware_address;
+ chromeos::NetworkIPConfigVector ipconfigs = cros_->GetIPConfigs(
+ network->device_path(), &hardware_address,
+ chromeos::NetworkLibrary::FORMAT_COLON_SEPARATED_HEX);
+ if (!hardware_address.empty())
+ dictionary.SetString("hardwareAddress", hardware_address);
+
+ scoped_ptr<DictionaryValue> ipconfig_dhcp;
+ scoped_ptr<DictionaryValue> ipconfig_static;
+ for (chromeos::NetworkIPConfigVector::const_iterator it = ipconfigs.begin();
+ it != ipconfigs.end(); ++it) {
+ const chromeos::NetworkIPConfig& ipconfig = *it;
+ scoped_ptr<DictionaryValue> ipconfig_dict(new DictionaryValue());
+ ipconfig_dict->SetString("address", ipconfig.address);
+ ipconfig_dict->SetString("subnetAddress", ipconfig.netmask);
+ ipconfig_dict->SetString("gateway", ipconfig.gateway);
+ ipconfig_dict->SetString("dns", ipconfig.name_servers);
+ if (ipconfig.type == chromeos::IPCONFIG_TYPE_DHCP)
+ ipconfig_dhcp.reset(ipconfig_dict.release());
+ else if (ipconfig.type == chromeos::IPCONFIG_TYPE_IPV4)
+ ipconfig_static.reset(ipconfig_dict.release());
+ }
+
+ chromeos::NetworkPropertyUIData ipconfig_dhcp_ui_data(network, NULL);
+ SetValueDictionary(&dictionary, "ipconfigDHCP", ipconfig_dhcp.release(),
+ ipconfig_dhcp_ui_data);
+ chromeos::NetworkPropertyUIData ipconfig_static_ui_data(network, NULL);
+ SetValueDictionary(&dictionary, "ipconfigStatic", ipconfig_static.release(),
+ ipconfig_static_ui_data);
+
+ chromeos::ConnectionType type = network->type();
+ dictionary.SetInteger("type", type);
+ dictionary.SetString("servicePath", network->service_path());
+ dictionary.SetBoolean("connecting", network->connecting());
+ dictionary.SetBoolean("connected", network->connected());
+ dictionary.SetString("connectionState", network->GetStateString());
+
+ // Only show proxy for remembered networks.
+ chromeos::NetworkProfileType network_profile = network->profile_type();
+ dictionary.SetBoolean("showProxy", network_profile != chromeos::PROFILE_NONE);
+
+ // Hide the dhcp/static radio if not ethernet or wifi (or if not enabled)
+ bool staticIPConfig = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableStaticIPConfig);
+ dictionary.SetBoolean("showStaticIPConfig", staticIPConfig &&
+ (type == chromeos::TYPE_WIFI || type == chromeos::TYPE_ETHERNET));
+
+ chromeos::NetworkPropertyUIData preferred_ui_data(
+ network, chromeos::NetworkUIData::kPropertyPreferred);
+ if (network_profile == chromeos::PROFILE_USER) {
+ dictionary.SetBoolean("showPreferred", true);
+ SetValueDictionary(&dictionary, "preferred",
+ Value::CreateBooleanValue(network->preferred()),
+ preferred_ui_data);
+ } else {
+ dictionary.SetBoolean("showPreferred", false);
+ SetValueDictionary(&dictionary, "preferred",
+ Value::CreateBooleanValue(network->preferred()),
+ preferred_ui_data);
+ }
+ chromeos::NetworkPropertyUIData auto_connect_ui_data(
+ network, chromeos::NetworkUIData::kPropertyAutoConnect);
+ SetValueDictionary(&dictionary, "autoConnect",
+ Value::CreateBooleanValue(network->auto_connect()),
+ auto_connect_ui_data);
+
+ if (type == chromeos::TYPE_WIFI) {
+ dictionary.SetBoolean("deviceConnected", cros_->wifi_connected());
+ const chromeos::WifiNetwork* wifi =
+ cros_->FindWifiNetworkByPath(network->service_path());
+ if (!wifi) {
+ LOG(WARNING) << "Cannot find network " << network->service_path();
+ } else {
+ PopulateWifiDetails(wifi, &dictionary);
+ }
+ } else if (type == chromeos::TYPE_CELLULAR) {
+ dictionary.SetBoolean("deviceConnected", cros_->cellular_connected());
+ const chromeos::CellularNetwork* cellular =
+ cros_->FindCellularNetworkByPath(network->service_path());
+ if (!cellular) {
+ LOG(WARNING) << "Cannot find network " << network->service_path();
+ } else {
+ PopulateCellularDetails(cellular, &dictionary);
+ }
+ } else if (type == chromeos::TYPE_VPN) {
+ dictionary.SetBoolean("deviceConnected",
+ cros_->virtual_network_connected());
+ const chromeos::VirtualNetwork* vpn =
+ cros_->FindVirtualNetworkByPath(network->service_path());
+ if (!vpn) {
+ LOG(WARNING) << "Cannot find network " << network->service_path();
+ } else {
+ PopulateVPNDetails(vpn, &dictionary);
+ }
+ } else if (type == chromeos::TYPE_ETHERNET) {
+ dictionary.SetBoolean("deviceConnected", cros_->ethernet_connected());
+ }
+
+ web_ui_->CallJavascriptFunction(
+ "options.InternetOptions.showDetailedInfo", dictionary);
+}
+
+void InternetOptionsHandler::PopulateWifiDetails(
+ const chromeos::WifiNetwork* wifi,
+ DictionaryValue* dictionary) {
+ dictionary->SetString("ssid", wifi->name());
+ bool remembered = (wifi->profile_type() != chromeos::PROFILE_NONE);
+ dictionary->SetBoolean("remembered", remembered);
+ dictionary->SetBoolean("encrypted", wifi->encrypted());
+ bool shared = wifi->profile_type() == chromeos::PROFILE_SHARED;
+ dictionary->SetBoolean("shared", shared);
+}
+
+DictionaryValue* InternetOptionsHandler::CreateDictionaryFromCellularApn(
+ const chromeos::CellularApn& apn) {
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("apn", apn.apn);
+ dictionary->SetString("networkId", apn.network_id);
+ dictionary->SetString("username", apn.username);
+ dictionary->SetString("password", apn.password);
+ dictionary->SetString("name", apn.name);
+ dictionary->SetString("localizedName", apn.localized_name);
+ dictionary->SetString("language", apn.language);
+ return dictionary;
+}
+
+void InternetOptionsHandler::PopulateCellularDetails(
+ const chromeos::CellularNetwork* cellular,
+ DictionaryValue* dictionary) {
+ // Cellular network / connection settings.
+ dictionary->SetString("serviceName", cellular->name());
+ dictionary->SetString("networkTechnology",
+ cellular->GetNetworkTechnologyString());
+ dictionary->SetString("operatorName", cellular->operator_name());
+ dictionary->SetString("operatorCode", cellular->operator_code());
+ dictionary->SetString("activationState",
+ cellular->GetActivationStateString());
+ dictionary->SetString("roamingState",
+ cellular->GetRoamingStateString());
+ dictionary->SetString("restrictedPool",
+ cellular->restricted_pool() ?
+ l10n_util::GetStringUTF8(
+ IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL) :
+ l10n_util::GetStringUTF8(
+ IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL));
+ dictionary->SetString("errorState", cellular->GetErrorString());
+ dictionary->SetString("supportUrl", cellular->payment_url());
+ dictionary->SetBoolean("needsPlan", cellular->needs_new_plan());
+
+ dictionary->Set("apn", CreateDictionaryFromCellularApn(cellular->apn()));
+ dictionary->Set("lastGoodApn",
+ CreateDictionaryFromCellularApn(cellular->last_good_apn()));
+
+ // Device settings.
+ const chromeos::NetworkDevice* device =
+ cros_->FindNetworkDeviceByPath(cellular->device_path());
+ if (device) {
+ chromeos::NetworkPropertyUIData cellular_propety_ui_data(cellular, NULL);
+ dictionary->SetString("manufacturer", device->manufacturer());
+ dictionary->SetString("modelId", device->model_id());
+ dictionary->SetString("firmwareRevision", device->firmware_revision());
+ dictionary->SetString("hardwareRevision", device->hardware_revision());
+ dictionary->SetString("prlVersion",
+ base::StringPrintf("%u", device->prl_version()));
+ dictionary->SetString("meid", device->meid());
+ dictionary->SetString("imei", device->imei());
+ dictionary->SetString("mdn", device->mdn());
+ dictionary->SetString("imsi", device->imsi());
+ dictionary->SetString("esn", device->esn());
+ dictionary->SetString("min", device->min());
+ dictionary->SetBoolean("gsm",
+ device->technology_family() == chromeos::TECHNOLOGY_FAMILY_GSM);
+ SetValueDictionary(
+ dictionary, "simCardLockEnabled",
+ Value::CreateBooleanValue(
+ device->sim_pin_required() == chromeos::SIM_PIN_REQUIRED),
+ cellular_propety_ui_data);
+
+ chromeos::MobileConfig* config = chromeos::MobileConfig::GetInstance();
+ if (config->IsReady()) {
+ std::string carrier_id = cros_->GetCellularHomeCarrierId();
+ const chromeos::MobileConfig::Carrier* carrier =
+ config->GetCarrier(carrier_id);
+ if (carrier && !carrier->top_up_url().empty())
+ dictionary->SetString("carrierUrl", carrier->top_up_url());
+ }
+
+ const chromeos::CellularApnList& apn_list = device->provider_apn_list();
+ ListValue* apn_list_value = new ListValue();
+ for (chromeos::CellularApnList::const_iterator it = apn_list.begin();
+ it != apn_list.end(); ++it) {
+ apn_list_value->Append(CreateDictionaryFromCellularApn(*it));
+ }
+ SetValueDictionary(dictionary, "providerApnList", apn_list_value,
+ cellular_propety_ui_data);
+ }
+
+ SetActivationButtonVisibility(cellular, dictionary);
+}
+
+void InternetOptionsHandler::PopulateVPNDetails(
+ const chromeos::VirtualNetwork* vpn,
+ DictionaryValue* dictionary) {
+ dictionary->SetString("service_name", vpn->name());
+ bool remembered = (vpn->profile_type() != chromeos::PROFILE_NONE);
+ dictionary->SetBoolean("remembered", remembered);
+ dictionary->SetString("server_hostname", vpn->server_hostname());
+ dictionary->SetString("provider_type", vpn->GetProviderTypeString());
+ dictionary->SetString("username", vpn->username());
+}
+
+void InternetOptionsHandler::SetActivationButtonVisibility(
+ const chromeos::CellularNetwork* cellular,
+ DictionaryValue* dictionary) {
+ if (cellular->needs_new_plan()) {
+ dictionary->SetBoolean("showBuyButton", true);
+ } else if (cellular->activation_state() !=
+ chromeos::ACTIVATION_STATE_ACTIVATING &&
+ cellular->activation_state() !=
+ chromeos::ACTIVATION_STATE_ACTIVATED) {
+ dictionary->SetBoolean("showActivateButton", true);
+ }
+}
+
+void InternetOptionsHandler::CreateModalPopup(views::WidgetDelegate* view) {
+ views::Widget* window = browser::CreateViewsWindow(GetNativeWindow(),
+ view,
+ STYLE_GENERIC);
+ window->SetAlwaysOnTop(true);
+ window->Show();
+}
+
+gfx::NativeWindow InternetOptionsHandler::GetNativeWindow() const {
+ // TODO(beng): This is an improper direct dependency on Browser. Route this
+ // through some sort of delegate.
+ Browser* browser =
+ BrowserList::FindBrowserWithProfile(Profile::FromWebUI(web_ui_));
+ return browser->window()->GetNativeHandle();
+}
+
+void InternetOptionsHandler::ButtonClickCallback(const ListValue* args) {
+ std::string str_type;
+ std::string service_path;
+ std::string command;
+ if (args->GetSize() != 3 ||
+ !args->GetString(0, &str_type) ||
+ !args->GetString(1, &service_path) ||
+ !args->GetString(2, &command)) {
+ NOTREACHED();
+ return;
+ }
+
+ int type = atoi(str_type.c_str());
+ if (type == chromeos::TYPE_ETHERNET) {
+ const chromeos::EthernetNetwork* ether = cros_->ethernet_network();
+ if (ether)
+ PopulateDictionaryDetails(ether);
+ } else if (type == chromeos::TYPE_WIFI) {
+ HandleWifiButtonClick(service_path, command);
+ } else if (type == chromeos::TYPE_CELLULAR) {
+ HandleCellularButtonClick(service_path, command);
+ } else if (type == chromeos::TYPE_VPN) {
+ HandleVPNButtonClick(service_path, command);
+ } else {
+ NOTREACHED();
+ }
+}
+
+void InternetOptionsHandler::HandleWifiButtonClick(
+ const std::string& service_path,
+ const std::string& command) {
+ chromeos::WifiNetwork* wifi = NULL;
+ if (command == "forget") {
+ cros_->ForgetNetwork(service_path);
+ } else if (service_path == kOtherNetworksFakePath) {
+ // Other wifi networks.
+ CreateModalPopup(new chromeos::NetworkConfigView(chromeos::TYPE_WIFI));
+ } else if ((wifi = cros_->FindWifiNetworkByPath(service_path))) {
+ if (command == "connect") {
+ // Connect to wifi here. Open password page if appropriate.
+ if (wifi->IsPassphraseRequired()) {
+ CreateModalPopup(new chromeos::NetworkConfigView(wifi));
+ } else {
+ cros_->ConnectToWifiNetwork(wifi);
+ }
+ } else if (command == "disconnect") {
+ cros_->DisconnectFromNetwork(wifi);
+ } else if (command == "options") {
+ PopulateDictionaryDetails(wifi);
+ }
+ }
+}
+
+void InternetOptionsHandler::HandleCellularButtonClick(
+ const std::string& service_path,
+ const std::string& command) {
+ chromeos::CellularNetwork* cellular = NULL;
+ if (service_path == kOtherNetworksFakePath) {
+ chromeos::ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
+ } else if ((cellular = cros_->FindCellularNetworkByPath(service_path))) {
+ if (command == "connect") {
+ cros_->ConnectToCellularNetwork(cellular);
+ } else if (command == "disconnect") {
+ cros_->DisconnectFromNetwork(cellular);
+ } else if (command == "activate") {
+ Browser* browser = BrowserList::GetLastActive();
+ if (browser)
+ browser->OpenMobilePlanTabAndActivate();
+ } else if (command == "options") {
+ PopulateDictionaryDetails(cellular);
+ }
+ }
+}
+
+void InternetOptionsHandler::HandleVPNButtonClick(
+ const std::string& service_path,
+ const std::string& command) {
+ chromeos::VirtualNetwork* network = NULL;
+ if (command == "forget") {
+ cros_->ForgetNetwork(service_path);
+ } else if (service_path == kOtherNetworksFakePath) {
+ // TODO(altimofeev): verify if service_path in condition is correct.
+ // Other VPN networks.
+ CreateModalPopup(new chromeos::NetworkConfigView(chromeos::TYPE_VPN));
+ } else if ((network = cros_->FindVirtualNetworkByPath(service_path))) {
+ if (command == "connect") {
+ // Connect to VPN here. Open password page if appropriate.
+ if (network->NeedMoreInfoToConnect()) {
+ CreateModalPopup(new chromeos::NetworkConfigView(network));
+ } else {
+ cros_->ConnectToVirtualNetwork(network);
+ }
+ } else if (command == "disconnect") {
+ cros_->DisconnectFromNetwork(network);
+ } else if (command == "options") {
+ PopulateDictionaryDetails(network);
+ }
+ }
+}
+
+void InternetOptionsHandler::RefreshCellularPlanCallback(
+ const ListValue* args) {
+ std::string service_path;
+ if (args->GetSize() != 1 ||
+ !args->GetString(0, &service_path)) {
+ NOTREACHED();
+ return;
+ }
+ const chromeos::CellularNetwork* cellular =
+ cros_->FindCellularNetworkByPath(service_path);
+ if (cellular)
+ cellular->RefreshDataPlansIfNeeded();
+}
+
+ListValue* InternetOptionsHandler::GetWiredList() {
+ ListValue* list = new ListValue();
+
+ // If ethernet is not enabled, then don't add anything.
+ if (cros_->ethernet_enabled()) {
+ const chromeos::EthernetNetwork* ethernet_network =
+ cros_->ethernet_network();
+ if (ethernet_network) {
+ NetworkInfoDictionary network_dict(ethernet_network);
+ network_dict.set_name(
+ l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET)),
+ list->Append(network_dict.BuildDictionary());
+ }
+ }
+ return list;
+}
+
+ListValue* InternetOptionsHandler::GetWirelessList() {
+ ListValue* list = new ListValue();
+
+ const chromeos::WifiNetworkVector& wifi_networks = cros_->wifi_networks();
+ for (chromeos::WifiNetworkVector::const_iterator it =
+ wifi_networks.begin(); it != wifi_networks.end(); ++it) {
+ NetworkInfoDictionary network_dict(*it);
+ network_dict.set_connectable(cros_->CanConnectToNetwork(*it));
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ // Add "Other WiFi network..." if wifi is enabled.
+ if (cros_->wifi_enabled()) {
+ NetworkInfoDictionary network_dict;
+ network_dict.set_service_path(kOtherNetworksFakePath);
+ network_dict.set_icon(
+ chromeos::NetworkMenuIcon::GetConnectedBitmap(
+ chromeos::NetworkMenuIcon::ARCS));
+ network_dict.set_name(
+ l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS));
+ network_dict.set_connectable(true);
+ network_dict.set_connection_type(chromeos::TYPE_WIFI);
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ const chromeos::CellularNetworkVector cellular_networks =
+ cros_->cellular_networks();
+ for (chromeos::CellularNetworkVector::const_iterator it =
+ cellular_networks.begin(); it != cellular_networks.end(); ++it) {
+ NetworkInfoDictionary network_dict(*it);
+ network_dict.set_connectable(cros_->CanConnectToNetwork(*it));
+ network_dict.set_activation_state((*it)->activation_state());
+ network_dict.set_needs_new_plan(
+ (*it)->SupportsDataPlan() && (*it)->restricted_pool());
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ const chromeos::NetworkDevice* cellular_device = cros_->FindCellularDevice();
+ if (cellular_device && cellular_device->support_network_scan() &&
+ cros_->cellular_enabled()) {
+ NetworkInfoDictionary network_dict;
+ network_dict.set_service_path(kOtherNetworksFakePath);
+ network_dict.set_icon(
+ chromeos::NetworkMenuIcon::GetDisconnectedBitmap(
+ chromeos::NetworkMenuIcon::BARS));
+ network_dict.set_name(
+ l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_OTHER_CELLULAR_NETWORKS));
+ network_dict.set_connectable(true);
+ network_dict.set_connection_type(chromeos::TYPE_CELLULAR);
+ network_dict.set_activation_state(chromeos::ACTIVATION_STATE_ACTIVATED);
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ return list;
+}
+
+ListValue* InternetOptionsHandler::GetVPNList() {
+ ListValue* list = new ListValue();
+
+ const chromeos::VirtualNetworkVector& virtual_networks =
+ cros_->virtual_networks();
+ for (chromeos::VirtualNetworkVector::const_iterator it =
+ virtual_networks.begin(); it != virtual_networks.end(); ++it) {
+ NetworkInfoDictionary network_dict(*it);
+ network_dict.set_connectable(cros_->CanConnectToNetwork(*it));
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ return list;
+}
+
+ListValue* InternetOptionsHandler::GetRememberedList() {
+ ListValue* list = new ListValue();
+
+ for (chromeos::WifiNetworkVector::const_iterator rit =
+ cros_->remembered_wifi_networks().begin();
+ rit != cros_->remembered_wifi_networks().end(); ++rit) {
+ chromeos::WifiNetwork* remembered = *rit;
+ chromeos::WifiNetwork* wifi = static_cast<chromeos::WifiNetwork*>(
+ cros_->FindNetworkByUniqueId(remembered->unique_id()));
+
+ NetworkInfoDictionary network_dict(wifi, remembered);
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ for (chromeos::VirtualNetworkVector::const_iterator rit =
+ cros_->remembered_virtual_networks().begin();
+ rit != cros_->remembered_virtual_networks().end(); ++rit) {
+ chromeos::VirtualNetwork* remembered = *rit;
+ chromeos::VirtualNetwork* vpn = static_cast<chromeos::VirtualNetwork*>(
+ cros_->FindNetworkByUniqueId(remembered->unique_id()));
+
+ NetworkInfoDictionary network_dict(vpn, remembered);
+ list->Append(network_dict.BuildDictionary());
+ }
+
+ return list;
+}
+
+void InternetOptionsHandler::FillNetworkInfo(DictionaryValue* dictionary) {
+ dictionary->SetBoolean("accessLocked", cros_->IsLocked());
+ dictionary->Set("wiredList", GetWiredList());
+ dictionary->Set("wirelessList", GetWirelessList());
+ dictionary->Set("vpnList", GetVPNList());
+ dictionary->Set("rememberedList", GetRememberedList());
+ dictionary->SetBoolean("wifiAvailable", cros_->wifi_available());
+ dictionary->SetBoolean("wifiBusy", cros_->wifi_busy());
+ dictionary->SetBoolean("wifiEnabled", cros_->wifi_enabled());
+ dictionary->SetBoolean("cellularAvailable", cros_->cellular_available());
+ dictionary->SetBoolean("cellularBusy", cros_->cellular_busy());
+ dictionary->SetBoolean("cellularEnabled", cros_->cellular_enabled());
+}
+
+void InternetOptionsHandler::SetValueDictionary(
+ DictionaryValue* settings,
+ const char* key,
+ base::Value* value,
+ const chromeos::NetworkPropertyUIData& ui_data) {
+ DictionaryValue* value_dict = new DictionaryValue();
+ // DictionaryValue::Set() takes ownership of |value|.
+ if (value)
+ value_dict->Set("value", value);
+ const base::Value* default_value = ui_data.default_value();
+ if (default_value)
+ value_dict->Set("default", default_value->DeepCopy());
+ if (ui_data.managed())
+ value_dict->SetString("controlledBy", "policy");
+ else if (ui_data.recommended())
+ value_dict->SetString("controlledBy", "recommended");
+ settings->Set(key, value_dict);
+}
diff --git a/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.h
new file mode 100644
index 0000000..c35c309
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/internet_options_handler.h
@@ -0,0 +1,148 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_INTERNET_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_INTERNET_OPTIONS_HANDLER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/cros/network_ui_data.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "content/public/browser/notification_registrar.h"
+#include "ui/gfx/native_widget_types.h"
+
+class SkBitmap;
+namespace views {
+class WidgetDelegate;
+}
+
+// ChromeOS internet options page UI handler.
+class InternetOptionsHandler
+ : public OptionsPage2UIHandler,
+ public chromeos::NetworkLibrary::NetworkManagerObserver,
+ public chromeos::NetworkLibrary::NetworkObserver,
+ public chromeos::NetworkLibrary::CellularDataPlanObserver {
+ public:
+ InternetOptionsHandler();
+ virtual ~InternetOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // NetworkLibrary::NetworkManagerObserver implementation.
+ virtual void OnNetworkManagerChanged(
+ chromeos::NetworkLibrary* network_lib) OVERRIDE;
+ // NetworkLibrary::NetworkObserver implementation.
+ virtual void OnNetworkChanged(chromeos::NetworkLibrary* network_lib,
+ const chromeos::Network* network) OVERRIDE;
+ // NetworkLibrary::CellularDataPlanObserver implementation.
+ virtual void OnCellularDataPlanChanged(
+ chromeos::NetworkLibrary* network_lib) OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // Opens a modal popup dialog.
+ void CreateModalPopup(views::WidgetDelegate* view);
+ gfx::NativeWindow GetNativeWindow() const;
+
+ // Passes data needed to show details overlay for network.
+ // |args| will be [ network_type, service_path, command ]
+ // And command is one of 'options', 'connect', disconnect', 'activate' or
+ // 'forget'
+ // Handle{Wifi,Cellular}ButtonClick handles button click on a wireless
+ // network item and a cellular network item respectively.
+ void ButtonClickCallback(const base::ListValue* args);
+ void HandleWifiButtonClick(const std::string& service_path,
+ const std::string& command);
+ void HandleCellularButtonClick(const std::string& service_path,
+ const std::string& command);
+ void HandleVPNButtonClick(const std::string& service_path,
+ const std::string& command);
+
+ // Initiates cellular plan data refresh. The results from libcros will be
+ // passed through CellularDataPlanChanged() callback method.
+ // |args| will be [ service_path ]
+ void RefreshCellularPlanCallback(const base::ListValue* args);
+ void SetActivationButtonVisibility(
+ const chromeos::CellularNetwork* cellular,
+ base::DictionaryValue* dictionary);
+
+ void SetPreferNetworkCallback(const base::ListValue* args);
+ void SetAutoConnectCallback(const base::ListValue* args);
+ void SetSharedCallback(const base::ListValue* args);
+ void SetIPConfigCallback(const base::ListValue* args);
+ void EnableWifiCallback(const base::ListValue* args);
+ void DisableWifiCallback(const base::ListValue* args);
+ void EnableCellularCallback(const base::ListValue* args);
+ void DisableCellularCallback(const base::ListValue* args);
+ void BuyDataPlanCallback(const base::ListValue* args);
+ void SetApnCallback(const base::ListValue* args);
+ void SetSimCardLockCallback(const base::ListValue* args);
+ void ChangePinCallback(const base::ListValue* args);
+ void ShareNetworkCallback(const base::ListValue* args);
+
+ // Populates the ui with the details of the given device path. This forces
+ // an overlay to be displayed in the UI.
+ void PopulateDictionaryDetails(const chromeos::Network* network);
+ void PopulateWifiDetails(const chromeos::WifiNetwork* wifi,
+ base::DictionaryValue* dictionary);
+ void PopulateCellularDetails(const chromeos::CellularNetwork* cellular,
+ base::DictionaryValue* dictionary);
+ void PopulateVPNDetails(const chromeos::VirtualNetwork* vpn,
+ base::DictionaryValue* dictionary);
+
+ // Converts CellularDataPlan structure into dictionary for JS. Formats plan
+ // settings into human readable texts.
+ base::DictionaryValue* CellularDataPlanToDictionary(
+ const chromeos::CellularDataPlan* plan);
+
+ // Converts CellularApn stuct into dictionary for JS.
+ base::DictionaryValue* CreateDictionaryFromCellularApn(
+ const chromeos::CellularApn& apn);
+
+ // Creates the map of wired networks.
+ base::ListValue* GetWiredList();
+ // Creates the map of wireless networks.
+ base::ListValue* GetWirelessList();
+ // Creates the map of virtual networks.
+ base::ListValue* GetVPNList();
+ // Creates the map of remembered networks.
+ base::ListValue* GetRememberedList();
+ // Fills network information into JS dictionary for displaying network lists.
+ void FillNetworkInfo(base::DictionaryValue* dictionary);
+ // Refreshes the display of network information.
+ void RefreshNetworkData();
+ // Adds observers for wireless networks, if any, so that we can dynamically
+ // display the correct icon for that network's signal strength and, in the
+ // case of cellular networks, network technology and roaming status.
+ void MonitorNetworks();
+
+ // Stores a dictionary under |key| in |settings| that is suitable to be sent
+ // to the webui that contains the actual value of a setting and whether it's
+ // controlled by policy. Takes ownership of |value|.
+ void SetValueDictionary(DictionaryValue* settings,
+ const char* key,
+ base::Value* value,
+ const chromeos::NetworkPropertyUIData& ui_data);
+
+ // Convenience pointer to netwrok library (will not change).
+ chromeos::NetworkLibrary* cros_;
+
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(InternetOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_INTERNET_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.cc b/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.cc
new file mode 100644
index 0000000..c3c3096
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.cc
@@ -0,0 +1,103 @@
+// 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/options2/chromeos/language_chewing_handler.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_options_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+const char kI18nPrefix[] = "Chewing_";
+} // namespace
+
+namespace chromeos {
+
+LanguageChewingHandler::LanguageChewingHandler() {
+}
+
+LanguageChewingHandler::~LanguageChewingHandler() {
+}
+
+void LanguageChewingHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "languageChewingPage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTINGS_TITLE);
+
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
+ localized_strings->SetString(
+ GetI18nContentValue(language_prefs::kChewingBooleanPrefs[i],
+ kI18nPrefix),
+ l10n_util::GetStringUTF16(
+ language_prefs::kChewingBooleanPrefs[i].message_id));
+ }
+
+ // For maximum Chinese characters in pre-edit buffer, we use slider UI.
+ {
+ const language_prefs::LanguageIntegerRangePreference& preference =
+ language_prefs::kChewingIntegerPrefs[
+ language_prefs::kChewingMaxChiSymbolLenIndex];
+ localized_strings->SetString(
+ GetI18nContentValue(preference, kI18nPrefix),
+ l10n_util::GetStringUTF16(preference.message_id));
+ localized_strings->SetString(
+ GetTemplateDataMinName(preference, kI18nPrefix),
+ base::IntToString(preference.min_pref_value));
+ localized_strings->SetString(
+ GetTemplateDataMaxName(preference, kI18nPrefix),
+ base::IntToString(preference.max_pref_value));
+ }
+
+ // For number of candidates per page, we use select-option UI.
+ {
+ const language_prefs::LanguageIntegerRangePreference& preference =
+ language_prefs::kChewingIntegerPrefs[
+ language_prefs::kChewingCandPerPageIndex];
+ localized_strings->SetString(
+ GetI18nContentValue(preference, kI18nPrefix),
+ l10n_util::GetStringUTF16(preference.message_id));
+ ListValue* list_value = new ListValue();
+ for (int i = preference.min_pref_value; i <= preference.max_pref_value;
+ ++i) {
+ ListValue* option = new ListValue();
+ option->Append(CreateValue(i));
+ option->Append(CreateValue(i));
+ list_value->Append(option);
+ }
+ localized_strings->Set(GetTemplateDataPropertyName(preference, kI18nPrefix),
+ list_value);
+ }
+
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs;
+ ++i) {
+ const language_prefs::LanguageMultipleChoicePreference<const char*>&
+ preference = language_prefs::kChewingMultipleChoicePrefs[i];
+ localized_strings->SetString(
+ GetI18nContentValue(preference, kI18nPrefix),
+ l10n_util::GetStringUTF16(preference.label_message_id));
+ localized_strings->Set(
+ GetTemplateDataPropertyName(preference, kI18nPrefix),
+ CreateMultipleChoiceList(preference));
+ }
+
+ localized_strings->SetString(
+ GetI18nContentValue(language_prefs::kChewingHsuSelKeyType, kI18nPrefix),
+ l10n_util::GetStringUTF16(
+ language_prefs::kChewingHsuSelKeyType.label_message_id));
+ localized_strings->Set(
+ GetTemplateDataPropertyName(language_prefs::kChewingHsuSelKeyType,
+ kI18nPrefix),
+ CreateMultipleChoiceList(language_prefs::kChewingHsuSelKeyType));
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.h b/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.h
new file mode 100644
index 0000000..b251fe7
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.h
@@ -0,0 +1,35 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CHEWING_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CHEWING_HANDLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+// Chewing options page UI handler.
+class LanguageChewingHandler : public OptionsPage2UIHandler {
+ public:
+ LanguageChewingHandler();
+ virtual ~LanguageChewingHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LanguageChewingHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CHEWING_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.cc b/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.cc
new file mode 100644
index 0000000..d95b2ace
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.cc
@@ -0,0 +1,79 @@
+// 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/options2/chromeos/language_customize_modifier_keys_handler.h"
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/input_method/xkeyboard.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+const struct ModifierKeysSelectItem {
+ int message_id;
+ chromeos::input_method::ModifierKey value;
+} kModifierKeysSelectItems[] = {
+ { IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_SEARCH,
+ chromeos::input_method::kSearchKey },
+ { IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_LEFT_CTRL,
+ chromeos::input_method::kLeftControlKey },
+ { IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_LEFT_ALT,
+ chromeos::input_method::kLeftAltKey },
+ { IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_VOID,
+ chromeos::input_method::kVoidKey },
+ { IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_CAPS_LOCK,
+ chromeos::input_method::kCapsLockKey },
+};
+
+const char* kDataValuesNames[] = {
+ "xkbRemapSearchKeyToValue",
+ "xkbRemapControlKeyToValue",
+ "xkbRemapAltKeyToValue",
+};
+} // namespace
+
+namespace chromeos {
+
+LanguageCustomizeModifierKeysHandler::LanguageCustomizeModifierKeysHandler() {
+}
+
+LanguageCustomizeModifierKeysHandler::~LanguageCustomizeModifierKeysHandler() {
+}
+
+void LanguageCustomizeModifierKeysHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ localized_strings->SetString("xkbRemapSearchKeyToContent",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_SEARCH_LABEL));
+ localized_strings->SetString("xkbRemapControlKeyToContent",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_LEFT_CTRL_LABEL));
+ localized_strings->SetString("xkbRemapAltKeyToContent",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_XKB_KEY_LEFT_ALT_LABEL));
+
+ for (size_t i = 0; i < arraysize(kDataValuesNames); ++i) {
+ ListValue* list_value = new ListValue();
+ for (size_t j = 0; j < arraysize(kModifierKeysSelectItems); ++j) {
+ const input_method::ModifierKey value =
+ kModifierKeysSelectItems[j].value;
+ const int message_id = kModifierKeysSelectItems[j].message_id;
+ // Only the seach key can be remapped to the caps lock key.
+ if (kDataValuesNames[i] != std::string("xkbRemapSearchKeyToValue") &&
+ value == input_method::kCapsLockKey) {
+ continue;
+ }
+ ListValue* option = new ListValue();
+ option->Append(Value::CreateIntegerValue(value));
+ option->Append(Value::CreateStringValue(l10n_util::GetStringUTF16(
+ message_id)));
+ list_value->Append(option);
+ }
+ localized_strings->Set(kDataValuesNames[i], list_value);
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.h b/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.h
new file mode 100644
index 0000000..2a1f1a5
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CUSTOMIZE_MODIFIER_KEYS_HANDLER_H_ // NOLINT
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CUSTOMIZE_MODIFIER_KEYS_HANDLER_H_ // NOLINT
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace chromeos {
+
+// Customize modifier keys overlay page UI handler.
+class LanguageCustomizeModifierKeysHandler : public OptionsPage2UIHandler {
+ public:
+ LanguageCustomizeModifierKeysHandler();
+ virtual ~LanguageCustomizeModifierKeysHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LanguageCustomizeModifierKeysHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_CUSTOMIZE_MODIFIER_KEYS_HANDLER_H_ // NOLINT
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.cc b/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.cc
new file mode 100644
index 0000000..5362ccf
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.cc
@@ -0,0 +1,47 @@
+// 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/options2/chromeos/language_hangul_handler.h"
+
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+
+LanguageHangulHandler::LanguageHangulHandler() {
+}
+
+LanguageHangulHandler::~LanguageHangulHandler() {
+}
+
+void LanguageHangulHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "languageHangulPage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_TITLE);
+
+ localized_strings->SetString("hangul_keyboard_layout",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_KEYBOARD_LAYOUT_TEXT));
+
+ localized_strings->Set("HangulkeyboardLayoutList", GetKeyboardLayoutList());
+}
+
+ListValue* LanguageHangulHandler::GetKeyboardLayoutList() {
+ ListValue* keyboard_layout_list = new ListValue();
+ for (size_t i = 0; i < language_prefs::kNumHangulKeyboardNameIDPairs; ++i) {
+ ListValue* option = new ListValue();
+ option->Append(Value::CreateStringValue(
+ language_prefs::kHangulKeyboardNameIDPairs[i].keyboard_id));
+ option->Append(Value::CreateStringValue(l10n_util::GetStringUTF16(
+ language_prefs::kHangulKeyboardNameIDPairs[i].message_id)));
+ keyboard_layout_list->Append(option);
+ }
+ return keyboard_layout_list;
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.h b/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.h
new file mode 100644
index 0000000..47e6d82
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.h
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_HANGUL_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_HANGUL_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace chromeos {
+
+// Hangul options page UI handler.
+class LanguageHangulHandler : public OptionsPage2UIHandler {
+ public:
+ LanguageHangulHandler();
+ virtual ~LanguageHangulHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ // Returns the list of hangul keyboards.
+ static base::ListValue* GetKeyboardLayoutList();
+
+ DISALLOW_COPY_AND_ASSIGN(LanguageHangulHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_HANGUL_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.cc b/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.cc
new file mode 100644
index 0000000..ce8afe9
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.cc
@@ -0,0 +1,70 @@
+// 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/options2/chromeos/language_mozc_handler.h"
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_options_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+const char kI18nPrefix[] = "mozc_";
+} // namespace
+
+namespace chromeos {
+
+LanguageMozcHandler::LanguageMozcHandler() {
+}
+
+LanguageMozcHandler::~LanguageMozcHandler() {
+}
+
+void LanguageMozcHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "languageMozcPage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_SETTINGS_TITLE);
+
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
+ localized_strings->SetString(
+ GetI18nContentValue(language_prefs::kMozcBooleanPrefs[i], kI18nPrefix),
+ l10n_util::GetStringUTF16(
+ language_prefs::kMozcBooleanPrefs[i].message_id));
+ }
+
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
+ const language_prefs::LanguageMultipleChoicePreference<const char*>&
+ preference = language_prefs::kMozcMultipleChoicePrefs[i];
+ localized_strings->SetString(
+ GetI18nContentValue(preference, kI18nPrefix),
+ l10n_util::GetStringUTF16(preference.label_message_id));
+ localized_strings->Set(GetTemplateDataPropertyName(preference, kI18nPrefix),
+ CreateMultipleChoiceList(preference));
+ }
+
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
+ const language_prefs::LanguageIntegerRangePreference& preference =
+ language_prefs::kMozcIntegerPrefs[i];
+ localized_strings->SetString(
+ GetI18nContentValue(preference, kI18nPrefix),
+ l10n_util::GetStringUTF16(preference.message_id));
+ ListValue* list_value = new ListValue();
+ for (int j = preference.min_pref_value; j <= preference.max_pref_value;
+ ++j) {
+ ListValue* option = new ListValue();
+ option->Append(CreateValue(j));
+ option->Append(CreateValue(j));
+ list_value->Append(option);
+ }
+ localized_strings->Set(GetTemplateDataPropertyName(preference, kI18nPrefix),
+ list_value);
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.h b/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.h
new file mode 100644
index 0000000..9069571
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_MOZC_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_MOZC_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+// Mozc options page UI handler.
+class LanguageMozcHandler : public OptionsPage2UIHandler {
+ public:
+ LanguageMozcHandler();
+ virtual ~LanguageMozcHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LanguageMozcHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_MOZC_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_options_util.cc b/chrome/browser/ui/webui/options2/chromeos/language_options_util.cc
new file mode 100644
index 0000000..6108070
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_options_util.cc
@@ -0,0 +1,18 @@
+// 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/options2/chromeos/language_options_util.h"
+
+namespace chromeos {
+
+// See comments in .h.
+Value* CreateValue(const char* in_value) {
+ return Value::CreateStringValue(in_value);
+}
+
+Value* CreateValue(int in_value) {
+ return Value::CreateIntegerValue(in_value);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_options_util.h b/chrome/browser/ui/webui/options2/chromeos/language_options_util.h
new file mode 100644
index 0000000..70f7307
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_options_util.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_OPTIONS_UTIL_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_OPTIONS_UTIL_H_
+#pragma once
+
+#include <string>
+
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace chromeos {
+
+// Returns an i18n-content value corresponding to |preference|.
+template <typename T>
+std::string GetI18nContentValue(const T& preference, const char* prefix) {
+ return std::string(prefix) + preference.ibus_config_name;
+}
+
+// Returns a property name of templateData corresponding to |preference|.
+template <typename T>
+std::string GetTemplateDataPropertyName(const T& preference,
+ const char* prefix) {
+ return std::string(prefix) + preference.ibus_config_name + "Value";
+}
+
+// Returns an property name of templateData corresponding the value of the min
+// attribute.
+template <typename T>
+std::string GetTemplateDataMinName(const T& preference, const char* prefix) {
+ return std::string(prefix) + preference.ibus_config_name + "Min";
+}
+
+// Returns an property name of templateData corresponding the value of the max
+// attribute.
+template <typename T>
+std::string GetTemplateDataMaxName(const T& preference, const char* prefix) {
+ return std::string(prefix) + preference.ibus_config_name + "Max";
+}
+
+// Creates a Value object from the given value. Here we use function
+// overloading to handle string and integer preferences in
+// CreateMultipleChoiceList.
+Value* CreateValue(const char* in_value);
+Value* CreateValue(int in_value);
+
+// Creates a multiple choice list from the given preference.
+template <typename T>
+base::ListValue* CreateMultipleChoiceList(
+ const language_prefs::LanguageMultipleChoicePreference<T>& preference) {
+ int list_length = 0;
+ for (size_t i = 0;
+ i < language_prefs::LanguageMultipleChoicePreference<T>::kMaxItems;
+ ++i) {
+ if (preference.values_and_ids[i].item_message_id == 0)
+ break;
+ ++list_length;
+ }
+ DCHECK_GT(list_length, 0);
+
+ base::ListValue* list_value = new base::ListValue();
+ for (int i = 0; i < list_length; ++i) {
+ base::ListValue* option = new base::ListValue();
+ option->Append(CreateValue(
+ preference.values_and_ids[i].ibus_config_value));
+ option->Append(base::Value::CreateStringValue(l10n_util::GetStringUTF16(
+ preference.values_and_ids[i].item_message_id)));
+ list_value->Append(option);
+ }
+ return list_value;
+}
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_OPTIONS_UTIL_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.cc b/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.cc
new file mode 100644
index 0000000..8e2c19c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.cc
@@ -0,0 +1,67 @@
+// 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/options2/chromeos/language_pinyin_handler.h"
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_options_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+const char kI18nPrefix[] = "Pinyin";
+} // namespace
+
+namespace chromeos {
+
+LanguagePinyinHandler::LanguagePinyinHandler() {
+}
+
+LanguagePinyinHandler::~LanguagePinyinHandler() {
+}
+
+void LanguagePinyinHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "languagePinyinPage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTINGS_TITLE);
+
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
+ localized_strings->SetString(
+ GetI18nContentValue(language_prefs::kPinyinBooleanPrefs[i],
+ kI18nPrefix),
+ l10n_util::GetStringUTF16(
+ language_prefs::kPinyinBooleanPrefs[i].message_id));
+ }
+
+ localized_strings->SetString(
+ GetI18nContentValue(language_prefs::kPinyinDoublePinyinSchema,
+ kI18nPrefix),
+ l10n_util::GetStringUTF16(
+ language_prefs::kPinyinDoublePinyinSchema.label_message_id));
+ ListValue* list_value = new ListValue();
+ for (size_t i = 0;
+ i < language_prefs::LanguageMultipleChoicePreference<int>::kMaxItems;
+ ++i) {
+ if (language_prefs::kPinyinDoublePinyinSchema.values_and_ids[i].
+ item_message_id == 0)
+ break;
+ ListValue* option = new ListValue();
+ option->Append(Value::CreateIntegerValue(
+ language_prefs::kPinyinDoublePinyinSchema.values_and_ids[i].
+ ibus_config_value));
+ option->Append(Value::CreateStringValue(l10n_util::GetStringUTF16(
+ language_prefs::kPinyinDoublePinyinSchema.values_and_ids[i].
+ item_message_id)));
+ list_value->Append(option);
+ }
+ localized_strings->Set(
+ GetTemplateDataPropertyName(language_prefs::kPinyinDoublePinyinSchema,
+ kI18nPrefix),
+ list_value);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.h b/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.h
new file mode 100644
index 0000000..7a81cb5
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_PINYIN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_PINYIN_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+// Pinyin options page UI handler.
+class LanguagePinyinHandler : public OptionsPage2UIHandler {
+ public:
+ LanguagePinyinHandler();
+ virtual ~LanguagePinyinHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LanguagePinyinHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_LANGUAGE_PINYIN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/proxy_handler.cc b/chrome/browser/ui/webui/options2/chromeos/proxy_handler.cc
new file mode 100644
index 0000000..773fe51
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/proxy_handler.cc
@@ -0,0 +1,86 @@
+// 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/options2/chromeos/proxy_handler.h"
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/stl_util.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.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"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace chromeos {
+
+ProxyHandler::ProxyHandler() {
+}
+
+ProxyHandler::~ProxyHandler() {
+}
+
+void ProxyHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ // Proxy page - ChromeOS
+ localized_strings->SetString("proxyPage",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_PROXY_TAB_LABEL));
+ localized_strings->SetString("proxyPageTitleFormat",
+ l10n_util::GetStringUTF16(IDS_PROXY_PAGE_TITLE_FORMAT));
+ localized_strings->SetString("proxy_config_title",
+ l10n_util::GetStringUTF16(IDS_PROXY_CONFIG_TITLE));
+ localized_strings->SetString("proxyDirectInternetConnection",
+ l10n_util::GetStringUTF16(IDS_PROXY_DIRECT_CONNECTION));
+
+ localized_strings->SetString("proxyManual",
+ l10n_util::GetStringUTF16(IDS_PROXY_MANUAL_CONFIG));
+ localized_strings->SetString("sameProxyProtocols",
+ l10n_util::GetStringUTF16(IDS_PROXY_SAME_FORALL));
+
+ localized_strings->SetString("httpProxy",
+ l10n_util::GetStringUTF16(IDS_PROXY_HTTP_PROXY));
+ localized_strings->SetString("secureHttpProxy",
+ l10n_util::GetStringUTF16(IDS_PROXY_HTTP_SECURE_HTTP_PROXY));
+ localized_strings->SetString("ftpProxy",
+ l10n_util::GetStringUTF16(IDS_PROXY_FTP_PROXY));
+ localized_strings->SetString("socksHost",
+ l10n_util::GetStringUTF16(IDS_PROXY_SOCKS_HOST));
+ localized_strings->SetString("proxyAutomatic",
+ l10n_util::GetStringUTF16(IDS_PROXY_AUTOMATIC));
+ localized_strings->SetString("proxyConfigUrl",
+ l10n_util::GetStringUTF16(IDS_PROXY_CONFIG_URL));
+ localized_strings->SetString("advanced_proxy_config",
+ l10n_util::GetStringUTF16(IDS_PROXY_ADVANCED_CONFIG));
+ localized_strings->SetString("addHost",
+ l10n_util::GetStringUTF16(IDS_PROXY_ADD_HOST));
+ localized_strings->SetString("removeHost",
+ l10n_util::GetStringUTF16(IDS_PROXY_REMOVE_HOST));
+ localized_strings->SetString("proxyPort",
+ l10n_util::GetStringUTF16(IDS_PROXY_PORT));
+ localized_strings->SetString("proxyBypass",
+ l10n_util::GetStringUTF16(IDS_PROXY_BYPASS));
+ localized_strings->SetString("policyManagedPrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_POLICY_MANAGED_PREFS));
+ localized_strings->SetString("extensionManagedPrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_EXTENSION_MANAGED_PREFS));
+ localized_strings->SetString("unmodifiablePrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_UNMODIFIABLE_PREFS));
+ localized_strings->SetString("enableSharedProxiesBannerText",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ENABLE_SHARED_PROXIES_HINT,
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_USE_SHARED_PROXIES)));
+}
+
+void ProxyHandler::SetNetworkName(const std::string& name) {
+ StringValue network(name);
+ web_ui_->CallJavascriptFunction("options.ProxyOptions.setNetworkName",
+ network);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/proxy_handler.h b/chrome/browser/ui/webui/options2/chromeos/proxy_handler.h
new file mode 100644
index 0000000..e164642
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/proxy_handler.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_PROXY_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_PROXY_HANDLER_H_
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace chromeos {
+
+// ChromeOS proxy options page UI handler.
+class ProxyHandler : public OptionsPage2UIHandler {
+ public:
+ explicit ProxyHandler();
+ virtual ~ProxyHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // Set network name for proxy page title.
+ void SetNetworkName(const std::string& name);
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_PROXY_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.cc
new file mode 100644
index 0000000..998e1b5
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.cc
@@ -0,0 +1,45 @@
+// 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/options2/chromeos/stats_options_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/browser/user_metrics.h"
+
+namespace chromeos {
+
+StatsOptionsHandler::StatsOptionsHandler() {
+}
+
+// OptionsPageUIHandler implementation.
+void StatsOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+}
+
+void StatsOptionsHandler::Initialize() {
+}
+
+// WebUIMessageHandler implementation.
+void StatsOptionsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("metricsReportingCheckboxAction",
+ base::Bind(&StatsOptionsHandler::HandleMetricsReportingCheckbox,
+ base::Unretained(this)));
+}
+
+void StatsOptionsHandler::HandleMetricsReportingCheckbox(
+ const ListValue* args) {
+#if defined(GOOGLE_CHROME_BUILD)
+ const std::string checked_str = UTF16ToUTF8(ExtractStringValue(args));
+ const bool enabled = (checked_str == "true");
+ UserMetrics::RecordAction(
+ enabled ?
+ UserMetricsAction("Options_MetricsReportingCheckbox_Enable") :
+ UserMetricsAction("Options_MetricsReportingCheckbox_Disable"));
+#endif
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.h
new file mode 100644
index 0000000..2212064
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/stats_options_handler.h
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_STATS_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_STATS_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace chromeos {
+
+// ChromeOS handler for "Stats/crash reporting to Google" option of the Advanced
+// settings page. This handler does only ChromeOS-specific actions while default
+// code is in Chrome's AdvancedOptionsHandler
+// (chrome/browser/webui/advanced_options_handler.cc).
+class StatsOptionsHandler : public OptionsPage2UIHandler {
+ public:
+ StatsOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ void HandleMetricsReportingCheckbox(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(StatsOptionsHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_STATS_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/system_options_handler.cc b/chrome/browser/ui/webui/options2/chromeos/system_options_handler.cc
new file mode 100644
index 0000000..62261ee
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/system_options_handler.cc
@@ -0,0 +1,170 @@
+// 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/options2/chromeos/system_options_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/json/json_value_serializer.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_util.h"
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
+#include "chrome/browser/chromeos/dbus/power_manager_client.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/chromeos/system/touchpad_settings.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/browser_resources.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"
+#include "ui/base/resource/resource_bundle.h"
+
+using content::BrowserThread;
+
+namespace {
+
+void TouchpadExistsFileThread(bool* exists) {
+ *exists = chromeos::system::touchpad_settings::TouchpadExists();
+}
+
+}
+
+SystemOptionsHandler::SystemOptionsHandler() {
+}
+
+SystemOptionsHandler::~SystemOptionsHandler() {
+}
+
+void SystemOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "systemPage", IDS_OPTIONS_SYSTEM_TAB_LABEL);
+ localized_strings->SetString("datetimeTitle",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME));
+ localized_strings->SetString("timezone",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION));
+ localized_strings->SetString("use24HourClock",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_USE_24HOUR_CLOCK_DESCRIPTION));
+
+ localized_strings->SetString("screen",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_SCREEN));
+ localized_strings->SetString("brightness",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BRIGHTNESS_DESCRIPTION));
+ localized_strings->SetString("brightnessDecrease",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BRIGHTNESS_DECREASE));
+ localized_strings->SetString("brightnessIncrease",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_BRIGHTNESS_INCREASE));
+
+ localized_strings->SetString("touchpad",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD));
+ localized_strings->SetString("enableTapToClick",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION));
+ localized_strings->SetString("sensitivity",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION));
+ localized_strings->SetString("sensitivityLess",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SENSITIVITY_LESS_DESCRIPTION));
+ localized_strings->SetString("sensitivityMore",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SENSITIVITY_MORE_DESCRIPTION));
+
+ localized_strings->SetString("language",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE));
+ localized_strings->SetString("languageCustomize",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE));
+ localized_strings->SetString("modifierKeysCustomize",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_MODIFIER_KEYS_CUSTOMIZE));
+
+ localized_strings->SetString("accessibilityTitle",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY));
+ localized_strings->SetString("accessibility",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_ACCESSIBILITY_DESCRIPTION));
+
+ // TODO(pastarmovj): replace this with a call to the CrosSettings list
+ // handling functionality to come.
+ localized_strings->Set("timezoneList",
+ static_cast<chromeos::SystemSettingsProvider*>(
+ chromeos::CrosSettings::Get()->GetProvider(
+ chromeos::kSystemTimezone))->GetTimezoneList());
+}
+
+void SystemOptionsHandler::Initialize() {
+ DCHECK(web_ui_);
+ PrefService* pref_service = g_browser_process->local_state();
+ bool acc_enabled = pref_service->GetBoolean(prefs::kSpokenFeedbackEnabled);
+ base::FundamentalValue checked(acc_enabled);
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.SetAccessibilityCheckboxState", checked);
+
+ bool* exists = new bool;
+ BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&TouchpadExistsFileThread, exists),
+ base::Bind(&SystemOptionsHandler::TouchpadExists, AsWeakPtr(), exists));
+}
+
+void SystemOptionsHandler::TouchpadExists(bool* exists) {
+ if (*exists)
+ web_ui_->CallJavascriptFunction(
+ "options.SystemOptions.showTouchpadControls");
+ delete exists;
+}
+
+void SystemOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("accessibilityChange",
+ base::Bind(&SystemOptionsHandler::AccessibilityChangeCallback,
+ base::Unretained(this)));
+
+ web_ui_->RegisterMessageCallback("decreaseScreenBrightness",
+ base::Bind(&SystemOptionsHandler::DecreaseScreenBrightnessCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("increaseScreenBrightness",
+ base::Bind(&SystemOptionsHandler::IncreaseScreenBrightnessCallback,
+ base::Unretained(this)));
+}
+
+void SystemOptionsHandler::AccessibilityChangeCallback(const ListValue* args) {
+ std::string checked_str;
+ args->GetString(0, &checked_str);
+ bool accessibility_enabled = (checked_str == "true");
+
+ chromeos::accessibility::EnableAccessibility(accessibility_enabled, NULL);
+}
+
+void SystemOptionsHandler::DecreaseScreenBrightnessCallback(
+ const ListValue* args) {
+ // Do not allow the options button to turn off the backlight, as that
+ // can make it very difficult to see the increase brightness button.
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ DecreaseScreenBrightness(false);
+}
+
+void SystemOptionsHandler::IncreaseScreenBrightnessCallback(
+ const ListValue* args) {
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
+ IncreaseScreenBrightness();
+}
diff --git a/chrome/browser/ui/webui/options2/chromeos/system_options_handler.h b/chrome/browser/ui/webui/options2/chromeos/system_options_handler.h
new file mode 100644
index 0000000..021712a
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/system_options_handler.h
@@ -0,0 +1,50 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/memory/weak_ptr.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+// ChromeOS system options page UI handler.
+class SystemOptionsHandler
+ : public OptionsPage2UIHandler,
+ public base::SupportsWeakPtr<SystemOptionsHandler> {
+ public:
+ SystemOptionsHandler();
+ virtual ~SystemOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ virtual void RegisterMessages() OVERRIDE;
+
+ // Called when the accessibility checkbox value is changed.
+ // |args| will contain the checkbox checked state as a string
+ // ("true" or "false").
+ void AccessibilityChangeCallback(const base::ListValue* args);
+
+ // Called when the System configuration screen is used to adjust
+ // the screen brightness.
+ // |args| will be an empty list.
+ void DecreaseScreenBrightnessCallback(const base::ListValue* args);
+ void IncreaseScreenBrightnessCallback(const base::ListValue* args);
+
+ private:
+ // Callback for TouchpadHelper.
+ void TouchpadExists(bool* exists);
+
+ DISALLOW_COPY_AND_ASSIGN(SystemOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.cc b/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.cc
new file mode 100644
index 0000000..9ad4cc1
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.cc
@@ -0,0 +1,331 @@
+// 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/options2/chromeos/system_settings_provider.h"
+
+#include <string>
+
+#include "base/i18n/rtl.h"
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "unicode/calendar.h"
+#include "unicode/timezone.h"
+#include "unicode/ures.h"
+
+namespace {
+
+// TODO(jungshik): Using Enumerate method in ICU gives 600+ timezones.
+// Even after filtering out duplicate entries with a strict identity check,
+// we still have 400+ zones. Relaxing the criteria for the timezone
+// identity is likely to cut down the number to < 100. Until we
+// come up with a better list, we hard-code the following list as used by
+// Android.
+static const char* kTimeZones[] = {
+ "Pacific/Majuro",
+ "Pacific/Midway",
+ "Pacific/Honolulu",
+ "America/Anchorage",
+ "America/Los_Angeles",
+ "America/Tijuana",
+ "America/Denver",
+ "America/Phoenix",
+ "America/Chihuahua",
+ "America/Chicago",
+ "America/Mexico_City",
+ "America/Costa_Rica",
+ "America/Regina",
+ "America/New_York",
+ "America/Bogota",
+ "America/Caracas",
+ "America/Barbados",
+ "America/Manaus",
+ "America/Santiago",
+ "America/St_Johns",
+ "America/Sao_Paulo",
+ "America/Araguaina",
+ "America/Argentina/Buenos_Aires",
+ "America/Godthab",
+ "America/Montevideo",
+ "Atlantic/South_Georgia",
+ "Atlantic/Azores",
+ "Atlantic/Cape_Verde",
+ "Africa/Casablanca",
+ "Europe/London",
+ "Europe/Amsterdam",
+ "Europe/Belgrade",
+ "Europe/Brussels",
+ "Europe/Sarajevo",
+ "Africa/Windhoek",
+ "Africa/Brazzaville",
+ "Asia/Amman",
+ "Europe/Athens",
+ "Asia/Beirut",
+ "Africa/Cairo",
+ "Europe/Helsinki",
+ "Asia/Jerusalem",
+ "Europe/Minsk",
+ "Africa/Harare",
+ "Asia/Baghdad",
+ "Europe/Moscow",
+ "Asia/Kuwait",
+ "Africa/Nairobi",
+ "Asia/Tehran",
+ "Asia/Baku",
+ "Asia/Tbilisi",
+ "Asia/Yerevan",
+ "Asia/Dubai",
+ "Asia/Kabul",
+ "Asia/Karachi",
+ "Asia/Oral",
+ "Asia/Yekaterinburg",
+ "Asia/Calcutta",
+ "Asia/Colombo",
+ "Asia/Katmandu",
+ "Asia/Almaty",
+ "Asia/Rangoon",
+ "Asia/Krasnoyarsk",
+ "Asia/Bangkok",
+ "Asia/Shanghai",
+ "Asia/Hong_Kong",
+ "Asia/Irkutsk",
+ "Asia/Kuala_Lumpur",
+ "Australia/Perth",
+ "Asia/Taipei",
+ "Asia/Seoul",
+ "Asia/Tokyo",
+ "Asia/Yakutsk",
+ "Australia/Adelaide",
+ "Australia/Darwin",
+ "Australia/Brisbane",
+ "Australia/Hobart",
+ "Australia/Sydney",
+ "Asia/Vladivostok",
+ "Pacific/Guam",
+ "Asia/Magadan",
+ "Pacific/Auckland",
+ "Pacific/Fiji",
+ "Pacific/Tongatapu",
+};
+
+static base::LazyInstance<base::Lock,
+ base::LeakyLazyInstanceTraits<base::Lock> >
+ g_timezone_bundle_lock = LAZY_INSTANCE_INITIALIZER;
+
+struct UResClose {
+ inline void operator() (UResourceBundle* b) const {
+ ures_close(b);
+ }
+};
+
+string16 GetExemplarCity(const icu::TimeZone& zone) {
+ // TODO(jungshik): After upgrading to ICU 4.6, use U_ICUDATA_ZONE
+ static const char* zone_bundle_name = NULL;
+
+ // These will be leaked at the end.
+ static UResourceBundle *zone_bundle = NULL;
+ static UResourceBundle *zone_strings = NULL;
+
+ UErrorCode status = U_ZERO_ERROR;
+ {
+ base::AutoLock lock(g_timezone_bundle_lock.Get());
+ if (zone_bundle == NULL)
+ zone_bundle = ures_open(zone_bundle_name, uloc_getDefault(), &status);
+
+ if (zone_strings == NULL)
+ zone_strings = ures_getByKey(zone_bundle, "zone_strings", NULL, &status);
+ }
+
+ icu::UnicodeString zone_id;
+ zone.getID(zone_id);
+ std::string zone_id_str;
+ zone_id.toUTF8String(zone_id_str);
+
+ // resource keys for timezones use ':' in place of '/'.
+ ReplaceSubstringsAfterOffset(&zone_id_str, 0, "/", ":");
+ scoped_ptr_malloc<UResourceBundle, UResClose> zone_item(
+ ures_getByKey(zone_strings, zone_id_str.c_str(), NULL, &status));
+ icu::UnicodeString city;
+ if (!U_FAILURE(status)) {
+ city = icu::ures_getUnicodeStringByKey(zone_item.get(), "ec", &status);
+ if (U_SUCCESS(status))
+ return string16(city.getBuffer(), city.length());
+ }
+
+ // Fallback case in case of failure.
+ ReplaceSubstringsAfterOffset(&zone_id_str, 0, ":", "/");
+ // Take the last component of a timezone id (e.g. 'Baz' in 'Foo/Bar/Baz').
+ // Depending on timezones, keeping all but the 1st component
+ // (e.g. Bar/Baz) may be better, but our current list does not have
+ // any timezone for which that's the case.
+ std::string::size_type slash_pos = zone_id_str.rfind('/');
+ if (slash_pos != std::string::npos && slash_pos < zone_id_str.size())
+ zone_id_str.erase(0, slash_pos + 1);
+ // zone id has '_' in place of ' '.
+ ReplaceSubstringsAfterOffset(&zone_id_str, 0, "_", " ");
+ return ASCIIToUTF16(zone_id_str);
+}
+
+} // namespace anonymous
+
+namespace chromeos {
+
+SystemSettingsProvider::SystemSettingsProvider() {
+ for (size_t i = 0; i < arraysize(kTimeZones); i++) {
+ timezones_.push_back(icu::TimeZone::createTimeZone(
+ icu::UnicodeString(kTimeZones[i], -1, US_INV)));
+ }
+ system::TimezoneSettings::GetInstance()->AddObserver(this);
+ timezone_value_.reset(base::Value::CreateStringValue(GetKnownTimezoneID(
+ system::TimezoneSettings::GetInstance()->GetTimezone())));
+}
+
+SystemSettingsProvider::~SystemSettingsProvider() {
+ system::TimezoneSettings::GetInstance()->RemoveObserver(this);
+ STLDeleteElements(&timezones_);
+}
+
+void SystemSettingsProvider::DoSet(const std::string& path,
+ const base::Value& in_value) {
+ // Non-guest users can change the time zone.
+ if (UserManager::Get()->IsLoggedInAsGuest())
+ return;
+
+ if (path == kSystemTimezone) {
+ string16 value;
+ if (!in_value.IsType(Value::TYPE_STRING) || !in_value.GetAsString(&value))
+ return;
+ const icu::TimeZone* timezone = GetTimezone(value);
+ if (!timezone)
+ return;
+ system::TimezoneSettings::GetInstance()->SetTimezone(*timezone);
+ timezone_value_.reset(
+ base::Value::CreateStringValue(GetKnownTimezoneID(*timezone)));
+ }
+}
+
+const base::Value* SystemSettingsProvider::Get(const std::string& path) const {
+ if (path == kSystemTimezone)
+ return timezone_value_.get();
+ return NULL;
+}
+
+// The timezone is always trusted.
+bool SystemSettingsProvider::GetTrusted(const std::string& path,
+ const base::Closure& callback) {
+ return true;
+}
+
+bool SystemSettingsProvider::HandlesSetting(const std::string& path) const {
+ return path == kSystemTimezone;
+}
+
+void SystemSettingsProvider::Reload() {
+ // TODO(pastarmovj): We can actually cache the timezone here to make returning
+ // it faster.
+}
+
+void SystemSettingsProvider::TimezoneChanged(const icu::TimeZone& timezone) {
+ // Fires system setting change notification.
+ timezone_value_.reset(
+ base::Value::CreateStringValue(GetKnownTimezoneID(timezone)));
+ CrosSettings::Get()->FireObservers(kSystemTimezone);
+}
+
+ListValue* SystemSettingsProvider::GetTimezoneList() {
+ ListValue* timezoneList = new ListValue();
+ for (std::vector<icu::TimeZone*>::iterator iter = timezones_.begin();
+ iter != timezones_.end(); ++iter) {
+ const icu::TimeZone* timezone = *iter;
+ ListValue* option = new ListValue();
+ option->Append(Value::CreateStringValue(GetTimezoneID(*timezone)));
+ option->Append(Value::CreateStringValue(GetTimezoneName(*timezone)));
+ timezoneList->Append(option);
+ }
+ return timezoneList;
+}
+
+string16 SystemSettingsProvider::GetTimezoneName(
+ const icu::TimeZone& timezone) {
+ // Instead of using the raw_offset, use the offset in effect now.
+ // For instance, US Pacific Time, the offset shown will be -7 in summer
+ // while it'll be -8 in winter.
+ int raw_offset, dst_offset;
+ UDate now = icu::Calendar::getNow();
+ UErrorCode status = U_ZERO_ERROR;
+ timezone.getOffset(now, false, raw_offset, dst_offset, status);
+ DCHECK(U_SUCCESS(status));
+ int offset = raw_offset + dst_offset;
+ // offset is in msec.
+ int minute_offset = std::abs(offset) / 60000;
+ int hour_offset = minute_offset / 60;
+ int min_remainder = minute_offset % 60;
+ // Some timezones have a non-integral hour offset. So, we need to
+ // use hh:mm form.
+ std::string offset_str = base::StringPrintf(offset >= 0 ?
+ "UTC+%d:%02d" : "UTC-%d:%02d", hour_offset, min_remainder);
+
+ // TODO(jungshik): When coming up with a better list of timezones, we also
+ // have to come up with better 'display' names. One possibility is to list
+ // multiple cities (e.g. "Los Angeles, Vancouver .." in the order of
+ // the population of a country the city belongs to.).
+ // We can also think of using LONG_GENERIC or LOCATION once we upgrade
+ // to ICU 4.6.
+ // In the meantime, we use "LONG" name with "Exemplar City" to distinguish
+ // multiple timezones with the same "LONG" name but with different
+ // rules (e.g. US Mountain Time in Denver vs Phoenix).
+ icu::UnicodeString name;
+ timezone.getDisplayName(dst_offset != 0, icu::TimeZone::LONG, name);
+ string16 result(l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_TIMEZONE_DISPLAY_TEMPLATE, ASCIIToUTF16(offset_str),
+ string16(name.getBuffer(), name.length()), GetExemplarCity(timezone)));
+ base::i18n::AdjustStringForLocaleDirection(&result);
+ return result;
+}
+
+string16 SystemSettingsProvider::GetTimezoneID(
+ const icu::TimeZone& timezone) {
+ icu::UnicodeString id;
+ timezone.getID(id);
+ return string16(id.getBuffer(), id.length());
+}
+
+const icu::TimeZone* SystemSettingsProvider::GetTimezone(
+ const string16& timezone_id) {
+ for (std::vector<icu::TimeZone*>::iterator iter = timezones_.begin();
+ iter != timezones_.end(); ++iter) {
+ const icu::TimeZone* timezone = *iter;
+ if (GetTimezoneID(*timezone) == timezone_id) {
+ return timezone;
+ }
+ }
+ return NULL;
+}
+
+string16 SystemSettingsProvider::GetKnownTimezoneID(
+ const icu::TimeZone& timezone) const {
+ for (std::vector<icu::TimeZone*>::const_iterator iter = timezones_.begin();
+ iter != timezones_.end(); ++iter) {
+ const icu::TimeZone* known_timezone = *iter;
+ if (known_timezone->hasSameRules(timezone))
+ return GetTimezoneID(*known_timezone);
+ }
+
+ // Not able to find a matching timezone in our list.
+ return string16();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h b/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h
new file mode 100644
index 0000000..e39fa2b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/system_settings_provider.h
@@ -0,0 +1,76 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_SETTINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_SETTINGS_PROVIDER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/string16.h"
+#include "chrome/browser/chromeos/cros_settings_provider.h"
+#include "chrome/browser/chromeos/system/timezone_settings.h"
+#include "third_party/icu/public/i18n/unicode/timezone.h"
+
+namespace base {
+class Value;
+class ListValue;
+class StringValue;
+}
+
+namespace chromeos {
+
+class SystemSettingsProvider : public CrosSettingsProvider,
+ public system::TimezoneSettings::Observer {
+ public:
+ SystemSettingsProvider();
+ virtual ~SystemSettingsProvider();
+
+ // CrosSettingsProvider overrides.
+ virtual const base::Value* Get(const std::string& path) const OVERRIDE;
+ virtual bool GetTrusted(const std::string& path,
+ const base::Closure& callback) OVERRIDE;
+ virtual bool HandlesSetting(const std::string& path) const OVERRIDE;
+ virtual void Reload() OVERRIDE;
+
+ // Overridden from TimezoneSettings::Observer:
+ virtual void TimezoneChanged(const icu::TimeZone& timezone) OVERRIDE;
+
+ // Creates the map of timezones used by the options page.
+ base::ListValue* GetTimezoneList();
+
+ private:
+ // CrosSettingsProvider overrides.
+ virtual void DoSet(const std::string& path,
+ const base::Value& in_value) OVERRIDE;
+
+ // Gets timezone name.
+ static string16 GetTimezoneName(const icu::TimeZone& timezone);
+
+ // Gets timezone ID which is also used as timezone pref value.
+ static string16 GetTimezoneID(const icu::TimeZone& timezone);
+
+ // Gets timezone object from its id.
+ const icu::TimeZone* GetTimezone(const string16& timezone_id);
+
+ // Gets a timezone id from a timezone in |timezones_| that has the same
+ // rule of given |timezone|.
+ // One timezone could have multiple timezones,
+ // e.g.
+ // US/Pacific == America/Los_Angeles
+ // We should always use the known timezone id when passing back as
+ // pref values.
+ string16 GetKnownTimezoneID(const icu::TimeZone& timezone) const;
+
+ // Timezones.
+ std::vector<icu::TimeZone*> timezones_;
+
+ scoped_ptr<base::Value> timezone_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemSettingsProvider);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_SYSTEM_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/user_image_source.cc b/chrome/browser/ui/webui/options2/chromeos/user_image_source.cc
new file mode 100644
index 0000000..f259c03
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/user_image_source.cc
@@ -0,0 +1,53 @@
+// 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/options2/chromeos/user_image_source.h"
+
+#include "base/memory/ref_counted_memory.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/common/url_constants.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
+
+namespace chromeos {
+
+std::vector<unsigned char> UserImageSource::GetUserImage(
+ const std::string& email) const {
+ std::vector<unsigned char> user_image;
+ const chromeos::User* user = chromeos::UserManager::Get()->FindUser(email);
+ if (user) {
+ gfx::PNGCodec::EncodeBGRASkBitmap(user->image(), false, &user_image);
+ return user_image;
+ }
+ gfx::PNGCodec::EncodeBGRASkBitmap(
+ *ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_LOGIN_DEFAULT_USER),
+ false,
+ &user_image);
+ return user_image;
+}
+
+UserImageSource::UserImageSource()
+ : DataSource(chrome::kChromeUIUserImageHost, MessageLoop::current()) {
+}
+
+UserImageSource::~UserImageSource() {}
+
+void UserImageSource::StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id) {
+ // Strip the query param value - we only use it as a hack to ensure our
+ // image gets reloaded instead of being pulled from the browser cache
+ std::string email = path.substr(0, path.find_first_of("?"));
+ SendResponse(request_id, new RefCountedBytes(GetUserImage(email)));
+}
+
+std::string UserImageSource::GetMimeType(const std::string&) const {
+ // We need to explicitly return a mime type, otherwise if the user tries to
+ // drag the image they get no extension.
+ return "image/png";
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/user_image_source.h b/chrome/browser/ui/webui/options2/chromeos/user_image_source.h
new file mode 100644
index 0000000..ea38b49
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/user_image_source.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_USER_IMAGE_SOURCE_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_USER_IMAGE_SOURCE_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
+
+namespace chromeos {
+
+// UserImageSource is the data source that serves user images for users that
+// have it.
+class UserImageSource : public ChromeURLDataManager::DataSource {
+ public:
+ UserImageSource();
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id) OVERRIDE;
+
+ virtual std::string GetMimeType(const std::string&) const OVERRIDE;
+
+ // Returns PNG encoded image for user with specified email.
+ // If there's no user with such email, returns the default image.
+ std::vector<unsigned char> GetUserImage(const std::string& email) const;
+
+ private:
+ virtual ~UserImageSource();
+
+ DISALLOW_COPY_AND_ASSIGN(UserImageSource);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_USER_IMAGE_SOURCE_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.cc b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.cc
new file mode 100644
index 0000000..22c0fe6
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.cc
@@ -0,0 +1,237 @@
+// 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/options2/chromeos/virtual_keyboard_manager_handler.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"
+#include "chrome/browser/chromeos/preferences.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace ime = ::chromeos::input_method;
+
+namespace chromeos {
+
+VirtualKeyboardManagerHandler::VirtualKeyboardManagerHandler() {
+}
+
+VirtualKeyboardManagerHandler::~VirtualKeyboardManagerHandler() {
+}
+
+void VirtualKeyboardManagerHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static const OptionsStringResource resources[] = {
+ { "virtualKeyboardLayoutColumnTitle",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_VIRTUAL_KEYBOARD_LAYOUT_COLUMN_TITLE },
+ { "virtualKeyboardKeyboardColumnTitle",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_VIRTUAL_KEYBOARD_KEYBOARD_COLUMN_TITLE },
+ { "defaultVirtualKeyboard",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_DEFAULT_VIRTUAL_KEYBOARD },
+ };
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+
+ RegisterTitle(localized_strings, "virtualKeyboardPage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_VIRTUAL_KEYBOARD_SETTINGS_TITLE);
+
+ // Do not call GetVirtualKeyboardList() here since |web_ui_| is not ready yet.
+}
+
+void VirtualKeyboardManagerHandler::Initialize() {
+}
+
+void VirtualKeyboardManagerHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ // Register handler functions for chrome.send().
+ web_ui_->RegisterMessageCallback("updateVirtualKeyboardList",
+ base::Bind(&VirtualKeyboardManagerHandler::UpdateVirtualKeyboardList,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setVirtualKeyboardPreference",
+ base::Bind(&VirtualKeyboardManagerHandler::SetVirtualKeyboardPreference,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("clearVirtualKeyboardPreference",
+ base::Bind(&VirtualKeyboardManagerHandler::ClearVirtualKeyboardPreference,
+ base::Unretained(this)));
+}
+
+ListValue* VirtualKeyboardManagerHandler::GetVirtualKeyboardList() {
+ DCHECK(web_ui_);
+ ime::InputMethodManager* input_method =
+ ime::InputMethodManager::GetInstance();
+
+ // Get a multi map from layout name (e.g. "us(dvorak)"), to virtual keyboard
+ // extension.
+ const LayoutToKeyboard& layout_to_keyboard =
+ input_method->GetLayoutNameToKeyboardMapping();
+ const UrlToKeyboard& url_to_keyboard =
+ input_method->GetUrlToKeyboardMapping();
+
+ // Get the current pref values.
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+ DCHECK(prefs);
+ const DictionaryValue* virtual_keyboard_pref =
+ prefs->GetDictionary(prefs::kLanguagePreferredVirtualKeyboard);
+
+ return CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, virtual_keyboard_pref);
+}
+
+void VirtualKeyboardManagerHandler::UpdateVirtualKeyboardList(
+ const ListValue* args) {
+ scoped_ptr<Value> virtual_keyboards(GetVirtualKeyboardList());
+ DCHECK(virtual_keyboards.get());
+ web_ui_->CallJavascriptFunction(
+ "VirtualKeyboardManager.updateVirtualKeyboardList", *virtual_keyboards);
+}
+
+void VirtualKeyboardManagerHandler::SetVirtualKeyboardPreference(
+ const ListValue* args) {
+ DCHECK(web_ui_);
+ std::string layout, url;
+ if (!args || !args->GetString(0, &layout) || !args->GetString(1, &url)) {
+ LOG(ERROR) << "SetVirtualKeyboardPreference: Invalid argument";
+ return;
+ }
+
+ // Validate args.
+ ime::InputMethodManager* input_method =
+ ime::InputMethodManager::GetInstance();
+ if (!ValidateUrl(input_method->GetUrlToKeyboardMapping(), layout, url)) {
+ LOG(ERROR) << "SetVirtualKeyboardPreference: Invalid args: "
+ << "layout=" << layout << ", url=" << url;
+ return;
+ }
+
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+ DCHECK(prefs);
+ {
+ DictionaryPrefUpdate updater(
+ prefs, prefs::kLanguagePreferredVirtualKeyboard);
+ DictionaryValue* pref_value = updater.Get();
+ pref_value->SetWithoutPathExpansion(layout, new StringValue(url));
+ }
+ Preferences::UpdateVirturalKeyboardPreference(prefs);
+}
+
+void VirtualKeyboardManagerHandler::ClearVirtualKeyboardPreference(
+ const ListValue* args) {
+ DCHECK(web_ui_);
+ std::string layout;
+ if (!args || !args->GetString(0, &layout)) {
+ LOG(ERROR) << "ClearVirtualKeyboardPreference: Invalid argument";
+ return;
+ }
+
+ // Validate |layout|.
+ ime::InputMethodManager* input_method =
+ ime::InputMethodManager::GetInstance();
+ if (!input_method->GetLayoutNameToKeyboardMapping().count(layout)) {
+ LOG(ERROR) << "ClearVirtualKeyboardPreference: Invalid layout: " << layout;
+ return;
+ }
+
+ PrefService* prefs = Profile::FromWebUI(web_ui_)->GetPrefs();
+ DCHECK(prefs);
+ {
+ DictionaryPrefUpdate updater(
+ prefs, prefs::kLanguagePreferredVirtualKeyboard);
+ DictionaryValue* pref_value = updater.Get();
+ pref_value->RemoveWithoutPathExpansion(layout, NULL);
+ }
+ Preferences::UpdateVirturalKeyboardPreference(prefs);
+}
+
+// static
+bool VirtualKeyboardManagerHandler::ValidateUrl(
+ const UrlToKeyboard& url_to_keyboard,
+ const std::string& layout,
+ const std::string& url) {
+ UrlToKeyboard::const_iterator iter = url_to_keyboard.find(GURL(url));
+ if (iter == url_to_keyboard.end() ||
+ !iter->second->supported_layouts().count(layout)) {
+ return false;
+ }
+ return true;
+}
+
+// static
+ListValue* VirtualKeyboardManagerHandler::CreateVirtualKeyboardList(
+ const LayoutToKeyboard& layout_to_keyboard,
+ const UrlToKeyboard& url_to_keyboard,
+ const DictionaryValue* virtual_keyboard_pref) {
+ ListValue* layout_list = new ListValue;
+
+ // |dictionary| points to an element in the |layout_list|. One dictionary
+ // element is created for one layout.
+ DictionaryValue* dictionary = NULL;
+
+ LayoutToKeyboard::const_iterator i;
+ for (i = layout_to_keyboard.begin(); i != layout_to_keyboard.end(); ++i) {
+ const std::string& layout_id = i->first;
+
+ std::string string_value;
+ // Check the "layout" value in the current dictionary.
+ if (dictionary) {
+ dictionary->GetString("layout", &string_value);
+ }
+
+ if (string_value != layout_id) {
+ // New layout is found. Add the layout to |layout_list|.
+ dictionary = new DictionaryValue;
+ layout_list->Append(dictionary);
+
+ // Set layout id as well as its human readable form.
+ ime::InputMethodManager* manager = ime::InputMethodManager::GetInstance();
+ const ime::InputMethodDescriptor* desc =
+ manager->GetInputMethodUtil()->GetInputMethodDescriptorFromXkbId(
+ layout_id);
+ const std::string layout_name = desc ?
+ manager->GetInputMethodUtil()->GetInputMethodDisplayNameFromId(
+ desc->id()) : layout_id;
+ dictionary->SetString("layout", layout_id);
+ dictionary->SetString("layoutName", layout_name);
+
+ // Check if the layout is in user pref.
+ if (virtual_keyboard_pref &&
+ virtual_keyboard_pref->GetString(layout_id, &string_value) &&
+ ValidateUrl(url_to_keyboard, layout_id, string_value)) {
+ dictionary->SetString("preferredKeyboard", string_value);
+ }
+ dictionary->Set("supportedKeyboards", new ListValue);
+ }
+
+ ListValue* supported_keyboards = NULL;
+ dictionary->GetList("supportedKeyboards", &supported_keyboards);
+ DCHECK(supported_keyboards);
+
+ DictionaryValue* virtual_keyboard = new DictionaryValue;
+ virtual_keyboard->SetString("name", i->second->name());
+ virtual_keyboard->SetBoolean("isSystem", i->second->is_system());
+ virtual_keyboard->SetString("url", i->second->url().spec());
+ supported_keyboards->Append(virtual_keyboard);
+ }
+
+ return layout_list;
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.h b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.h
new file mode 100644
index 0000000..5da4142
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.h
@@ -0,0 +1,78 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_VIRTUAL_KEYBOARD_MANAGER_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_VIRTUAL_KEYBOARD_MANAGER_HANDLER_H_
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "googleurl/src/gurl.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+} // namespace base
+
+namespace chromeos {
+
+namespace input_method {
+class VirtualKeyboard;
+} // namespace input_method;
+
+// A class which provides information to virtual_keyboard.js.
+class VirtualKeyboardManagerHandler : public OptionsPage2UIHandler {
+ public:
+ VirtualKeyboardManagerHandler();
+ virtual ~VirtualKeyboardManagerHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ protected:
+ typedef std::multimap<
+ std::string, const input_method::VirtualKeyboard*> LayoutToKeyboard;
+ typedef std::map<GURL, const input_method::VirtualKeyboard*> UrlToKeyboard;
+
+ // Returns true if |layout_to_keyboard| contains |layout| as a key, and the
+ // value for |layout| contains |url|. This function is protected for
+ // testability.
+ static bool ValidateUrl(const UrlToKeyboard& url_to_keyboard,
+ const std::string& layout,
+ const std::string& url);
+
+ // Builds a list from |layout_to_keyboard| and |virtual_keyboard_user_pref|.
+ // See virtual_keyboard_list.js for an example of the format the list should
+ // take. This function is protected for testability.
+ static base::ListValue* CreateVirtualKeyboardList(
+ const LayoutToKeyboard& layout_to_keyboard,
+ const UrlToKeyboard& url_to_keyboard,
+ const base::DictionaryValue* virtual_keyboard_user_pref);
+
+ private:
+ // Reads user pref and create a list using CreateVirtualKeyboardList().
+ base::ListValue* GetVirtualKeyboardList();
+
+ // Handles chrome.send("updateVirtualKeyboardList") JS call.
+ // TODO(yusukes): This function should also be called when user pref is
+ // updated by chrome://settings page in other tab.
+ void UpdateVirtualKeyboardList(const base::ListValue* args);
+
+ // Handles chrome.send("setVirtualKeyboardPreference") JS call.
+ void SetVirtualKeyboardPreference(const base::ListValue* args);
+ // Handles chrome.send("clearVirtualKeyboardPreference") JS call.
+ void ClearVirtualKeyboardPreference(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardManagerHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CHROMEOS_VIRTUAL_KEYBOARD_MANAGER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler_unittest.cc b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler_unittest.cc
new file mode 100644
index 0000000..5783401
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler_unittest.cc
@@ -0,0 +1,550 @@
+// 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/options2/chromeos/virtual_keyboard_manager_handler.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+typedef std::multimap<
+ std::string, const chromeos::input_method::VirtualKeyboard*> LayoutToKeyboard;
+typedef std::map<
+ GURL, const chromeos::input_method::VirtualKeyboard*> UrlToKeyboard;
+
+template <size_t L>
+std::set<std::string> CreateLayoutSet(const char* (&layouts)[L]) {
+ return std::set<std::string>(layouts, layouts + L);
+}
+
+} // namespace
+
+namespace chromeos {
+
+class Testee : public VirtualKeyboardManagerHandler {
+ public:
+ // Change access rights.
+ using VirtualKeyboardManagerHandler::ValidateUrl;
+ using VirtualKeyboardManagerHandler::CreateVirtualKeyboardList;
+};
+
+TEST(VirtualKeyboardManagerHandler, TestValidateUrl) {
+ static const char* layouts1[] = { "a", "b" };
+ static const char* layouts2[] = { "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts1), true);
+ input_method::VirtualKeyboard virtual_keyboard_2(
+ GURL("http://url2/"), "name 2", CreateLayoutSet(layouts2), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_2.url(),
+ virtual_keyboard_2.name(),
+ virtual_keyboard_2.supported_layouts(),
+ virtual_keyboard_2.is_system()));
+
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(2U, url_to_keyboard.size());
+
+ EXPECT_TRUE(Testee::ValidateUrl(url_to_keyboard, "a", "http://url1/"));
+ EXPECT_TRUE(Testee::ValidateUrl(url_to_keyboard, "b", "http://url1/"));
+ EXPECT_TRUE(Testee::ValidateUrl(url_to_keyboard, "b", "http://url2/"));
+
+ EXPECT_FALSE(Testee::ValidateUrl(url_to_keyboard, "a", "http://url3/"));
+ EXPECT_FALSE(Testee::ValidateUrl(url_to_keyboard, "b", "http://url3/"));
+ EXPECT_FALSE(Testee::ValidateUrl(url_to_keyboard, "c", "http://url1/"));
+ EXPECT_FALSE(Testee::ValidateUrl(url_to_keyboard, "c", "http://url2/"));
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboard) {
+ static const char* layouts[] = { "a", "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts), layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(1U, url_to_keyboard.size());
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, NULL));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(arraysize(layouts), keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboardWithPref) {
+ static const char* layouts[] = { "a", "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts), layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(1U, url_to_keyboard.size());
+
+ // create pref object.
+ scoped_ptr<DictionaryValue> pref(new DictionaryValue);
+ pref->SetString("b", "http://url1/");
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, pref.get()));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(arraysize(layouts), keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_TRUE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboardWithTwoPrefs) {
+ static const char* layouts[] = { "a", "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts), layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(1U, url_to_keyboard.size());
+
+ // create pref object.
+ scoped_ptr<DictionaryValue> pref(new DictionaryValue);
+ pref->SetString("a", "http://url1/");
+ pref->SetString("b", "http://url1/");
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, pref.get()));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(arraysize(layouts), keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_TRUE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_TRUE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboardWithBadPref1) {
+ static const char* layouts[] = { "a", "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts), layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(1U, url_to_keyboard.size());
+
+ // create pref object.
+ scoped_ptr<DictionaryValue> pref(new DictionaryValue);
+ pref->SetString("unknownlayout", "http://url1/");
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, pref.get()));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(arraysize(layouts), keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboardWithBadPref2) {
+ static const char* layouts[] = { "a", "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts), layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(1U, url_to_keyboard.size());
+
+ // create pref object.
+ scoped_ptr<DictionaryValue> pref(new DictionaryValue);
+ pref->SetString("a", "http://unknownurl/");
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, pref.get()));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(arraysize(layouts), keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestSingleKeyboardWithBadPref3) {
+ static const char* layout1[] = { "a" };
+ static const char* layout2[] = { "b" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layout1), true);
+ input_method::VirtualKeyboard virtual_keyboard_2(
+ GURL("http://url2/"), "name 2", CreateLayoutSet(layout2), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_2.url(),
+ virtual_keyboard_2.name(),
+ virtual_keyboard_2.supported_layouts(),
+ virtual_keyboard_2.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(2U, layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(2U, url_to_keyboard.size());
+
+ // create pref object.
+ scoped_ptr<DictionaryValue> pref(new DictionaryValue);
+ pref->SetString("a", "http://url2/"); // url2 does not support "a".
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, pref.get()));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(2U, keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url2/", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 2", string_value);
+}
+
+TEST(VirtualKeyboardManagerHandler, TestMultipleKeyboards) {
+ static const char* layouts1[] = { "a", "b" };
+ static const char* layouts2[] = { "c" };
+ static const char* layouts3[] = { "b", "d" };
+ input_method::VirtualKeyboard virtual_keyboard_1(
+ GURL("http://url1/"), "name 1", CreateLayoutSet(layouts1), true);
+ input_method::VirtualKeyboard virtual_keyboard_2(
+ GURL("http://url2/"), "name 2", CreateLayoutSet(layouts2), false);
+ input_method::VirtualKeyboard virtual_keyboard_3(
+ GURL("http://url3/"), "name 3", CreateLayoutSet(layouts3), true);
+
+ input_method::VirtualKeyboardSelector selector;
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_1.url(),
+ virtual_keyboard_1.name(),
+ virtual_keyboard_1.supported_layouts(),
+ virtual_keyboard_1.is_system()));
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_2.url(),
+ virtual_keyboard_2.name(),
+ virtual_keyboard_2.supported_layouts(),
+ virtual_keyboard_2.is_system()));
+ ASSERT_TRUE(selector.AddVirtualKeyboard(
+ virtual_keyboard_3.url(),
+ virtual_keyboard_3.name(),
+ virtual_keyboard_3.supported_layouts(),
+ virtual_keyboard_3.is_system()));
+
+ const LayoutToKeyboard& layout_to_keyboard = selector.layout_to_keyboard();
+ ASSERT_EQ(arraysize(layouts1) + arraysize(layouts2) + arraysize(layouts3),
+ layout_to_keyboard.size());
+ const UrlToKeyboard& url_to_keyboard = selector.url_to_keyboard();
+ ASSERT_EQ(3U, url_to_keyboard.size());
+
+ scoped_ptr<ListValue> keyboards(Testee::CreateVirtualKeyboardList(
+ layout_to_keyboard, url_to_keyboard, NULL));
+ ASSERT_TRUE(keyboards.get());
+ ASSERT_EQ(4U /* a, b, c, and d */, keyboards->GetSize());
+
+ DictionaryValue* dictionary_value;
+ std::string string_value;
+ ListValue* list_value;
+ bool boolean_value = false;
+
+ // Check the first element (for the layout "a").
+ ASSERT_TRUE(keyboards->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("a", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetBoolean("isSystem", &boolean_value));
+ EXPECT_TRUE(boolean_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+
+ // Check the second element (for the layout "b").
+ ASSERT_TRUE(keyboards->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("b", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(2U, list_value->GetSize()); // keyboard1 and 3.
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url1/", string_value);
+ EXPECT_TRUE(dictionary_value->GetBoolean("isSystem", &boolean_value));
+ EXPECT_TRUE(boolean_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 1", string_value);
+ ASSERT_TRUE(list_value->GetDictionary(1, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url3/", string_value);
+ EXPECT_TRUE(dictionary_value->GetBoolean("isSystem", &boolean_value));
+ EXPECT_TRUE(boolean_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 3", string_value);
+
+ // 3rd.
+ ASSERT_TRUE(keyboards->GetDictionary(2, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("c", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url2/", string_value);
+ EXPECT_TRUE(dictionary_value->GetBoolean("isSystem", &boolean_value));
+ EXPECT_FALSE(boolean_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 2", string_value);
+
+ // 4th.
+ ASSERT_TRUE(keyboards->GetDictionary(3, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("layout", &string_value));
+ EXPECT_EQ("d", string_value);
+ EXPECT_TRUE(dictionary_value->GetString("layoutName", &string_value));
+ EXPECT_FALSE(dictionary_value->GetString("preferredKeyboard", &string_value));
+ ASSERT_TRUE(dictionary_value->GetList("supportedKeyboards", &list_value));
+ ASSERT_EQ(1U, list_value->GetSize());
+ ASSERT_TRUE(list_value->GetDictionary(0, &dictionary_value));
+ EXPECT_TRUE(dictionary_value->GetString("url", &string_value));
+ EXPECT_EQ("http://url3/", string_value);
+ EXPECT_TRUE(dictionary_value->GetBoolean("isSystem", &boolean_value));
+ EXPECT_TRUE(boolean_value);
+ EXPECT_TRUE(dictionary_value->GetString("name", &string_value));
+ EXPECT_EQ("name 3", string_value);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options2/clear_browser_data_handler.cc b/chrome/browser/ui/webui/options2/clear_browser_data_handler.cc
new file mode 100644
index 0000000..306050e
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/clear_browser_data_handler.cc
@@ -0,0 +1,143 @@
+// 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/options2/clear_browser_data_handler.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/string16.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_details.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ClearBrowserDataHandler::ClearBrowserDataHandler() : remover_(NULL) {
+}
+
+ClearBrowserDataHandler::~ClearBrowserDataHandler() {
+ if (remover_)
+ remover_->RemoveObserver(this);
+}
+
+void ClearBrowserDataHandler::Initialize() {
+ clear_plugin_lso_data_enabled_.Init(prefs::kClearPluginLSODataEnabled,
+ Profile::FromWebUI(web_ui_)->GetPrefs(),
+ NULL);
+}
+
+void ClearBrowserDataHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "clearBrowserDataLabel", IDS_CLEAR_BROWSING_DATA_LABEL },
+ { "deleteBrowsingHistoryCheckbox", IDS_DEL_BROWSING_HISTORY_CHKBOX },
+ { "deleteDownloadHistoryCheckbox", IDS_DEL_DOWNLOAD_HISTORY_CHKBOX },
+ { "deleteCacheCheckbox", IDS_DEL_CACHE_CHKBOX },
+ { "deleteCookiesCheckbox", IDS_DEL_COOKIES_CHKBOX },
+ { "deleteCookiesFlashCheckbox", IDS_DEL_COOKIES_FLASH_CHKBOX },
+ { "deletePasswordsCheckbox", IDS_DEL_PASSWORDS_CHKBOX },
+ { "deleteFormDataCheckbox", IDS_DEL_FORM_DATA_CHKBOX },
+ { "clearBrowserDataCommit", IDS_CLEAR_BROWSING_DATA_COMMIT },
+ { "flashStorageSettings", IDS_FLASH_STORAGE_SETTINGS },
+ { "flash_storage_url", IDS_FLASH_STORAGE_URL },
+ { "clearDataDeleting", IDS_CLEAR_DATA_DELETING },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "clearBrowserDataOverlay",
+ IDS_CLEAR_BROWSING_DATA_TITLE);
+
+ ListValue* time_list = new ListValue;
+ for (int i = 0; i < 5; i++) {
+ string16 label_string;
+ switch (i) {
+ case 0:
+ label_string = l10n_util::GetStringUTF16(IDS_CLEAR_DATA_HOUR);
+ break;
+ case 1:
+ label_string = l10n_util::GetStringUTF16(IDS_CLEAR_DATA_DAY);
+ break;
+ case 2:
+ label_string = l10n_util::GetStringUTF16(IDS_CLEAR_DATA_WEEK);
+ break;
+ case 3:
+ label_string = l10n_util::GetStringUTF16(IDS_CLEAR_DATA_4WEEKS);
+ break;
+ case 4:
+ label_string = l10n_util::GetStringUTF16(IDS_CLEAR_DATA_EVERYTHING);
+ break;
+ }
+ ListValue* option = new ListValue();
+ option->Append(Value::CreateIntegerValue(i));
+ option->Append(Value::CreateStringValue(label_string));
+ time_list->Append(option);
+ }
+ localized_strings->Set("clearBrowserDataTimeList", time_list);
+}
+
+void ClearBrowserDataHandler::RegisterMessages() {
+ // Setup handlers specific to this panel.
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("performClearBrowserData",
+ base::Bind(&ClearBrowserDataHandler::HandleClearBrowserData,
+ base::Unretained(this)));
+}
+
+void ClearBrowserDataHandler::HandleClearBrowserData(const ListValue* value) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ PrefService* prefs = profile->GetPrefs();
+
+ int remove_mask = 0;
+ if (prefs->GetBoolean(prefs::kDeleteBrowsingHistory))
+ remove_mask |= BrowsingDataRemover::REMOVE_HISTORY;
+ if (prefs->GetBoolean(prefs::kDeleteDownloadHistory))
+ remove_mask |= BrowsingDataRemover::REMOVE_DOWNLOADS;
+ if (prefs->GetBoolean(prefs::kDeleteCache))
+ remove_mask |= BrowsingDataRemover::REMOVE_CACHE;
+ if (prefs->GetBoolean(prefs::kDeleteCookies)) {
+ int site_data_mask = BrowsingDataRemover::REMOVE_SITE_DATA;
+ // Don't try to clear LSO data if it's not supported.
+ if (!*clear_plugin_lso_data_enabled_)
+ site_data_mask &= ~BrowsingDataRemover::REMOVE_LSO_DATA;
+ remove_mask |= site_data_mask;
+ }
+ if (prefs->GetBoolean(prefs::kDeletePasswords))
+ remove_mask |= BrowsingDataRemover::REMOVE_PASSWORDS;
+ if (prefs->GetBoolean(prefs::kDeleteFormData))
+ remove_mask |= BrowsingDataRemover::REMOVE_FORM_DATA;
+
+ int period_selected = prefs->GetInteger(prefs::kDeleteTimePeriod);
+
+ base::FundamentalValue state(true);
+ web_ui_->CallJavascriptFunction("ClearBrowserDataOverlay.setClearingState",
+ state);
+
+ // If we are still observing a previous data remover, we need to stop
+ // observing.
+ if (remover_)
+ remover_->RemoveObserver(this);
+
+ // BrowsingDataRemover deletes itself when done.
+ remover_ = new BrowsingDataRemover(profile,
+ static_cast<BrowsingDataRemover::TimePeriod>(period_selected),
+ base::Time());
+ remover_->AddObserver(this);
+ remover_->Remove(remove_mask);
+}
+
+void ClearBrowserDataHandler::OnBrowsingDataRemoverDone() {
+ // No need to remove ourselves as an observer as BrowsingDataRemover deletes
+ // itself after we return.
+ remover_ = NULL;
+ DCHECK(web_ui_);
+ web_ui_->CallJavascriptFunction("ClearBrowserDataOverlay.doneClearing");
+}
diff --git a/chrome/browser/ui/webui/options2/clear_browser_data_handler.h b/chrome/browser/ui/webui/options2/clear_browser_data_handler.h
new file mode 100644
index 0000000..9793626
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/clear_browser_data_handler.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CLEAR_BROWSER_DATA_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CLEAR_BROWSER_DATA_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+// Clear browser data handler page UI handler.
+class ClearBrowserDataHandler : public OptionsPage2UIHandler,
+ public BrowsingDataRemover::Observer {
+ public:
+ ClearBrowserDataHandler();
+ virtual ~ClearBrowserDataHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void Initialize() OVERRIDE;
+
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ // Javascript callback to start clearing data.
+ void HandleClearBrowserData(const ListValue* value);
+
+ // Callback from BrowsingDataRemover. Closes the dialog.
+ virtual void OnBrowsingDataRemoverDone() OVERRIDE;
+
+ // If non-null it means removal is in progress. BrowsingDataRemover takes care
+ // of deleting itself when done.
+ BrowsingDataRemover* remover_;
+
+ // Keeps track of whether clearing LSO data is supported.
+ BooleanPrefMember clear_plugin_lso_data_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClearBrowserDataHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CLEAR_BROWSER_DATA_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/content_options_browsertest.js b/chrome/browser/ui/webui/options2/content_options_browsertest.js
new file mode 100644
index 0000000..605660a
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/content_options_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for content options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function ContentOptionsWebUITest() {}
+
+ContentOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to content options.
+ **/
+ browsePreload: 'chrome://settings/content',
+};
+
+// Test opening the content options has correct location.
+TEST_F('ContentOptionsWebUITest', 'testOpenContentOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/content_settings_exception_area_browsertest.js b/chrome/browser/ui/webui/options2/content_settings_exception_area_browsertest.js
new file mode 100644
index 0000000..33b3fd2
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/content_settings_exception_area_browsertest.js
@@ -0,0 +1,26 @@
+// 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.
+
+/**
+ * TestFixture for content settings exception area WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function ContentSettingsExceptionAreaWebUITest() {}
+
+ContentSettingsExceptionAreaWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the content settings exception area.
+ **/
+ browsePreload: 'chrome://settings/contentExceptions',
+};
+
+// Test opening the content settings exception area has correct location.
+TEST_F('ContentSettingsExceptionAreaWebUITest',
+ 'testOpenContentSettingsExceptionArea',
+ function() {
+ assertEquals(this.browsePreload, document.location.href);
+ });
diff --git a/chrome/browser/ui/webui/options2/content_settings_handler.cc b/chrome/browser/ui/webui/options2/content_settings_handler.cc
new file mode 100644
index 0000000..8b45b28
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/content_settings_handler.cc
@@ -0,0 +1,877 @@
+// 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/options2/content_settings_handler.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/content_settings/content_settings_details.h"
+#include "chrome/browser/content_settings/content_settings_utils.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/content_settings_pattern.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/common/content_switches.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+struct ContentSettingsTypeNameEntry {
+ ContentSettingsType type;
+ const char* name;
+};
+
+typedef std::map<ContentSettingsPattern, ContentSetting> OnePatternSettings;
+typedef std::map<ContentSettingsPattern, OnePatternSettings>
+ AllPatternsSettings;
+
+const char* kDisplayPattern = "displayPattern";
+const char* kSetting = "setting";
+const char* kOrigin = "origin";
+const char* kSource = "source";
+const char* kEmbeddingOrigin = "embeddingOrigin";
+
+const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
+ {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
+ {CONTENT_SETTINGS_TYPE_IMAGES, "images"},
+ {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"},
+ {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"},
+ {CONTENT_SETTINGS_TYPE_POPUPS, "popups"},
+ {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"},
+ {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"},
+ {CONTENT_SETTINGS_TYPE_INTENTS, "intents"},
+ {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"},
+ {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"},
+ {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"},
+};
+COMPILE_ASSERT(arraysize(kContentSettingsTypeGroupNames) ==
+ CONTENT_SETTINGS_NUM_TYPES,
+ MISSING_CONTENT_SETTINGS_TYPE);
+
+ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
+ for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
+ if (name == kContentSettingsTypeGroupNames[i].name)
+ return kContentSettingsTypeGroupNames[i].type;
+ }
+
+ NOTREACHED() << name << " is not a recognized content settings type.";
+ return CONTENT_SETTINGS_TYPE_DEFAULT;
+}
+
+std::string ContentSettingToString(ContentSetting setting) {
+ switch (setting) {
+ case CONTENT_SETTING_ALLOW:
+ return "allow";
+ case CONTENT_SETTING_ASK:
+ return "ask";
+ case CONTENT_SETTING_BLOCK:
+ return "block";
+ case CONTENT_SETTING_SESSION_ONLY:
+ return "session";
+ case CONTENT_SETTING_DEFAULT:
+ return "default";
+ case CONTENT_SETTING_NUM_SETTINGS:
+ NOTREACHED();
+ }
+
+ return "";
+}
+
+ContentSetting ContentSettingFromString(const std::string& name) {
+ if (name == "allow")
+ return CONTENT_SETTING_ALLOW;
+ if (name == "ask")
+ return CONTENT_SETTING_ASK;
+ if (name == "block")
+ return CONTENT_SETTING_BLOCK;
+ if (name == "session")
+ return CONTENT_SETTING_SESSION_ONLY;
+
+ NOTREACHED() << name << " is not a recognized content setting.";
+ return CONTENT_SETTING_DEFAULT;
+}
+
+std::string GeolocationExceptionToString(
+ const ContentSettingsPattern& origin,
+ const ContentSettingsPattern& embedding_origin) {
+ if (origin == embedding_origin)
+ return origin.ToString();
+
+ // TODO(estade): the page needs to use CSS to indent the string.
+ std::string indent(" ");
+
+ if (embedding_origin == ContentSettingsPattern::Wildcard()) {
+ // NOTE: As long as the user cannot add/edit entries from the exceptions
+ // dialog, it's impossible to actually have a non-default setting for some
+ // origin "embedded on any other site", so this row will never appear. If
+ // we add the ability to add/edit exceptions, we'll need to decide when to
+ // display this and how "removing" it will function.
+ return indent +
+ l10n_util::GetStringUTF8(IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ANY_OTHER);
+ }
+
+ return indent + l10n_util::GetStringFUTF8(
+ IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST,
+ UTF8ToUTF16(embedding_origin.ToString()));
+}
+
+// Create a DictionaryValue* that will act as a data source for a single row
+// in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
+// Ownership of the pointer is passed to the caller.
+DictionaryValue* GetExceptionForPage(
+ const ContentSettingsPattern& pattern,
+ ContentSetting setting,
+ std::string provider_name) {
+ DictionaryValue* exception = new DictionaryValue();
+ exception->SetString(kDisplayPattern, pattern.ToString());
+ exception->SetString(kSetting, ContentSettingToString(setting));
+ exception->SetString(kSource, provider_name);
+ return exception;
+}
+
+// Create a DictionaryValue* that will act as a data source for a single row
+// in the Geolocation exceptions table. Ownership of the pointer is passed to
+// the caller.
+DictionaryValue* GetGeolocationExceptionForPage(
+ const ContentSettingsPattern& origin,
+ const ContentSettingsPattern& embedding_origin,
+ ContentSetting setting) {
+ DictionaryValue* exception = new DictionaryValue();
+ exception->SetString(kDisplayPattern,
+ GeolocationExceptionToString(origin, embedding_origin));
+ exception->SetString(kSetting, ContentSettingToString(setting));
+ exception->SetString(kOrigin, origin.ToString());
+ exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
+ return exception;
+}
+
+// Create a DictionaryValue* that will act as a data source for a single row
+// in the desktop notifications exceptions table. Ownership of the pointer is
+// passed to the caller.
+DictionaryValue* GetNotificationExceptionForPage(
+ const ContentSettingsPattern& pattern,
+ ContentSetting setting,
+ const std::string& provider_name) {
+ DictionaryValue* exception = new DictionaryValue();
+ exception->SetString(kDisplayPattern, pattern.ToString());
+ exception->SetString(kSetting, ContentSettingToString(setting));
+ exception->SetString(kOrigin, pattern.ToString());
+ exception->SetString(kSource, provider_name);
+ return exception;
+}
+
+} // namespace
+
+ContentSettingsHandler::ContentSettingsHandler() {
+}
+
+ContentSettingsHandler::~ContentSettingsHandler() {
+}
+
+void ContentSettingsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON },
+ { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
+ { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
+ { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
+ { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
+ { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON },
+ { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON },
+ { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON },
+ { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
+ { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE },
+ { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
+ { "manage_exceptions", IDS_EXCEPTIONS_MANAGE },
+ { "manage_handlers", IDS_HANDLERS_MANAGE },
+ { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
+ { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
+ // Cookies filter.
+ { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
+ { "cookies_header", IDS_COOKIES_HEADER },
+ { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
+ { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
+ { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO },
+ { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
+ { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
+ { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
+ { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
+ { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
+ { "flash_storage_url", IDS_FLASH_STORAGE_URL },
+ // Image filter.
+ { "images_tab_label", IDS_IMAGES_TAB_LABEL },
+ { "images_header", IDS_IMAGES_HEADER },
+ { "images_allow", IDS_IMAGES_LOAD_RADIO },
+ { "images_block", IDS_IMAGES_NOLOAD_RADIO },
+ // JavaScript filter.
+ { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
+ { "javascript_header", IDS_JAVASCRIPT_HEADER },
+ { "javascript_allow", IDS_JS_ALLOW_RADIO },
+ { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
+ // Plug-ins filter.
+ { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
+ { "plugins_header", IDS_PLUGIN_HEADER },
+ { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
+ { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
+ { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
+ { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE },
+ // Pop-ups filter.
+ { "popups_tab_label", IDS_POPUP_TAB_LABEL },
+ { "popups_header", IDS_POPUP_HEADER },
+ { "popups_allow", IDS_POPUP_ALLOW_RADIO },
+ { "popups_block", IDS_POPUP_BLOCK_RADIO },
+ // Location filter.
+ { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
+ { "location_header", IDS_GEOLOCATION_HEADER },
+ { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
+ { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
+ { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
+ // Notifications filter.
+ { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
+ { "notifications_header", IDS_NOTIFICATIONS_HEADER },
+ { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
+ { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
+ { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
+ // Intents filter.
+ { "intentsTabLabel", IDS_INTENTS_TAB_LABEL },
+ { "intentsAllow", IDS_INTENTS_ALLOW_RADIO },
+ { "intentsAsk", IDS_INTENTS_ASK_RADIO },
+ { "intentsBlock", IDS_INTENTS_BLOCK_RADIO },
+ { "intents_header", IDS_INTENTS_HEADER },
+ // Fullscreen filter.
+ { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL },
+ { "fullscreen_header", IDS_FULLSCREEN_HEADER },
+ // Mouse Lock filter.
+ { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL },
+ { "mouselock_header", IDS_MOUSE_LOCK_HEADER },
+ { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO },
+ { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO },
+ { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "contentSettingsPage",
+ IDS_CONTENT_SETTINGS_TITLE);
+ localized_strings->SetBoolean("enable_click_to_play",
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableClickToPlay));
+ localized_strings->SetBoolean("enable_web_intents",
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWebIntents));
+}
+
+void ContentSettingsHandler::Initialize() {
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_PROFILE_CREATED,
+ content::NotificationService::AllSources());
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_PROFILE_DESTROYED,
+ content::NotificationService::AllSources());
+
+ UpdateHandlersEnabledRadios();
+ UpdateAllExceptionsViewsFromModel();
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
+ content::NotificationService::AllSources());
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
+ content::NotificationService::AllSources());
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
+ content::Source<Profile>(profile));
+
+ PrefService* prefs = profile->GetPrefs();
+ pref_change_registrar_.Init(prefs);
+ pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this);
+}
+
+void ContentSettingsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_PROFILE_DESTROYED: {
+ if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) {
+ web_ui_->CallJavascriptFunction(
+ "ContentSettingsExceptionsArea.OTRProfileDestroyed");
+ }
+ break;
+ }
+
+ case chrome::NOTIFICATION_PROFILE_CREATED: {
+ if (content::Source<Profile>(source).ptr()->IsOffTheRecord())
+ UpdateAllOTRExceptionsViewsFromModel();
+ break;
+ }
+
+ case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: {
+ // Filter out notifications from other profiles.
+ HostContentSettingsMap* map =
+ content::Source<HostContentSettingsMap>(source).ptr();
+ if (map != GetContentSettingsMap() &&
+ map != GetOTRContentSettingsMap())
+ break;
+
+ const ContentSettingsDetails* settings_details =
+ content::Details<const ContentSettingsDetails>(details).ptr();
+
+ // TODO(estade): we pretend update_all() is always true.
+ if (settings_details->update_all_types())
+ UpdateAllExceptionsViewsFromModel();
+ else
+ UpdateExceptionsViewFromModel(settings_details->type());
+ break;
+ }
+
+ case chrome::NOTIFICATION_PREF_CHANGED: {
+ const std::string& pref_name =
+ *content::Details<std::string>(details).ptr();
+ if (pref_name == prefs::kGeolocationContentSettings)
+ UpdateGeolocationExceptionsView();
+ break;
+ }
+
+ case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
+ UpdateNotificationExceptionsView();
+ break;
+ }
+
+ case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
+ UpdateHandlersEnabledRadios();
+ break;
+ }
+
+ default:
+ OptionsPage2UIHandler::Observe(type, source, details);
+ }
+}
+
+void ContentSettingsHandler::UpdateSettingDefaultFromModel(
+ ContentSettingsType type) {
+ DictionaryValue filter_settings;
+ std::string provider_id;
+ filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
+ GetSettingDefaultFromModel(type, &provider_id));
+ filter_settings.SetString(
+ ContentSettingsTypeToGroupName(type) + ".managedBy",
+ provider_id);
+
+ web_ui_->CallJavascriptFunction(
+ "ContentSettings.setContentFilterSettingsValue", filter_settings);
+}
+
+std::string ContentSettingsHandler::GetSettingDefaultFromModel(
+ ContentSettingsType type, std::string* provider_id) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ ContentSetting default_setting;
+ if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+ default_setting =
+ DesktopNotificationServiceFactory::GetForProfile(profile)->
+ GetDefaultContentSetting(provider_id);
+ } else {
+ default_setting =
+ profile->GetHostContentSettingsMap()->
+ GetDefaultContentSetting(type, provider_id);
+ }
+
+ return ContentSettingToString(default_setting);
+}
+
+void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
+#if defined(ENABLE_REGISTER_PROTOCOL_HANDLER)
+ DCHECK(web_ui_);
+ base::FundamentalValue handlers_enabled(
+ GetProtocolHandlerRegistry()->enabled());
+
+ web_ui_->CallJavascriptFunction("ContentSettings.updateHandlersEnabledRadios",
+ handlers_enabled);
+#endif // defined(ENABLE_REGISTER_PROTOCOL_HANDLER)
+}
+
+void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
+ for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
+ type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
+ // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
+ // is supposed to be set by policy only. Hence there is no user facing UI
+ // for this content type and we skip it here.
+ if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE)
+ continue;
+ UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
+ }
+}
+
+void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
+ for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
+ type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
+ UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
+ }
+}
+
+void ContentSettingsHandler::UpdateExceptionsViewFromModel(
+ ContentSettingsType type) {
+ // Skip updating intents unless it's enabled from the command line.
+ if (type == CONTENT_SETTINGS_TYPE_INTENTS &&
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWebIntents))
+ return;
+
+ switch (type) {
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION:
+ UpdateGeolocationExceptionsView();
+ break;
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
+ UpdateNotificationExceptionsView();
+ break;
+ default:
+ UpdateExceptionsViewFromHostContentSettingsMap(type);
+ break;
+ }
+}
+
+void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
+ ContentSettingsType type) {
+ switch (type) {
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION:
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
+ case CONTENT_SETTINGS_TYPE_INTENTS:
+ case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
+ break;
+ default:
+ UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
+ break;
+ }
+}
+
+void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
+
+ ContentSettingsForOneType all_settings;
+ map->GetSettingsForOneType(
+ CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ std::string(),
+ &all_settings);
+
+ // Group geolocation settings by primary_pattern.
+ AllPatternsSettings all_patterns_settings;
+ for (ContentSettingsForOneType::iterator i =
+ all_settings.begin();
+ i != all_settings.end();
+ ++i) {
+ // Don't add default settings.
+ if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
+ i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
+ i->source != "preferences") {
+ continue;
+ }
+ all_patterns_settings[i->primary_pattern][i->secondary_pattern] =
+ i->setting;
+ }
+
+ ListValue exceptions;
+ for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
+ i != all_patterns_settings.end();
+ ++i) {
+ const ContentSettingsPattern& primary_pattern = i->first;
+ const OnePatternSettings& one_settings = i->second;
+
+ OnePatternSettings::const_iterator parent =
+ one_settings.find(primary_pattern);
+
+ // Add the "parent" entry for the non-embedded setting.
+ ContentSetting parent_setting =
+ parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
+ exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
+ primary_pattern,
+ parent_setting));
+
+ // Add the "children" for any embedded settings.
+ for (OnePatternSettings::const_iterator j = one_settings.begin();
+ j != one_settings.end();
+ ++j) {
+ // Skip the non-embedded setting which we already added above.
+ if (j == parent)
+ continue;
+
+ exceptions.Append(
+ GetGeolocationExceptionForPage(primary_pattern, j->first, j->second));
+ }
+ }
+
+ StringValue type_string(
+ ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
+ web_ui_->CallJavascriptFunction("ContentSettings.setExceptions",
+ type_string, exceptions);
+
+ // This is mainly here to keep this function ideologically parallel to
+ // UpdateExceptionsViewFromHostContentSettingsMap().
+ UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
+}
+
+void ContentSettingsHandler::UpdateNotificationExceptionsView() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ DesktopNotificationService* service =
+ DesktopNotificationServiceFactory::GetForProfile(profile);
+
+ ContentSettingsForOneType settings;
+ service->GetNotificationsSettings(&settings);
+
+ ListValue exceptions;
+ for (ContentSettingsForOneType::const_iterator i =
+ settings.begin();
+ i != settings.end();
+ ++i) {
+ // Don't add default settings.
+ if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
+ i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
+ i->source != "preferences") {
+ continue;
+ }
+
+ exceptions.Append(
+ GetNotificationExceptionForPage(i->primary_pattern, i->setting,
+ i->source));
+ }
+
+ StringValue type_string(
+ ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
+ web_ui_->CallJavascriptFunction("ContentSettings.setExceptions",
+ type_string, exceptions);
+
+ // This is mainly here to keep this function ideologically parallel to
+ // UpdateExceptionsViewFromHostContentSettingsMap().
+ UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
+}
+
+void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
+ ContentSettingsType type) {
+ ContentSettingsForOneType entries;
+ GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries);
+
+ ListValue exceptions;
+ for (size_t i = 0; i < entries.size(); ++i) {
+ // Skip default settings from extensions and policy, and the default content
+ // settings; all of them will affect the default setting UI.
+ if (entries[i].primary_pattern == ContentSettingsPattern::Wildcard() &&
+ entries[i].secondary_pattern == ContentSettingsPattern::Wildcard() &&
+ entries[i].source != "preference") {
+ continue;
+ }
+ // The content settings UI does not support secondary content settings
+ // pattern yet. For content settings set through the content settings UI the
+ // secondary pattern is by default a wildcard pattern. Hence users are not
+ // able to modify content settings with a secondary pattern other than the
+ // wildcard pattern. So only show settings that the user is able to modify.
+ // TODO(bauerb): Support a read-only view for those patterns.
+ if (entries[i].secondary_pattern == ContentSettingsPattern::Wildcard()) {
+ exceptions.Append(
+ GetExceptionForPage(entries[i].primary_pattern, entries[i].setting,
+ entries[i].source));
+ } else {
+ LOG(ERROR) << "Secondary content settings patterns are not "
+ << "supported by the content settings UI";
+ }
+ }
+
+ StringValue type_string(ContentSettingsTypeToGroupName(type));
+ web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
+ exceptions);
+
+ UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
+
+ // TODO(koz): The default for fullscreen is always 'ask'.
+ // http://crbug.com/104683
+ if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
+ return;
+
+ // The default may also have changed (we won't get a separate notification).
+ // If it hasn't changed, this call will be harmless.
+ UpdateSettingDefaultFromModel(type);
+}
+
+void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
+ ContentSettingsType type) {
+ const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
+ if (!otr_settings_map)
+ return;
+
+ ContentSettingsForOneType otr_entries;
+ otr_settings_map->GetSettingsForOneType(type, "", &otr_entries);
+
+ ListValue otr_exceptions;
+ for (size_t i = 0; i < otr_entries.size(); ++i) {
+ // Off-the-record HostContentSettingsMap contains incognito content settings
+ // as well as normal content settings. Here, we use the incongnito settings
+ // only.
+ if (!otr_entries[i].incognito)
+ continue;
+ // The content settings UI does not support secondary content settings
+ // pattern yet. For content settings set through the content settings UI the
+ // secondary pattern is by default a wildcard pattern. Hence users are not
+ // able to modify content settings with a secondary pattern other than the
+ // wildcard pattern. So only show settings that the user is able to modify.
+ // TODO(bauerb): Support a read-only view for those patterns.
+ if (otr_entries[i].secondary_pattern ==
+ ContentSettingsPattern::Wildcard()) {
+ otr_exceptions.Append(
+ GetExceptionForPage(otr_entries[i].primary_pattern,
+ otr_entries[i].setting,
+ otr_entries[i].source));
+ } else {
+ LOG(ERROR) << "Secondary content settings patterns are not "
+ << "supported by the content settings UI";
+ }
+ }
+
+ StringValue type_string(ContentSettingsTypeToGroupName(type));
+ web_ui_->CallJavascriptFunction("ContentSettings.setOTRExceptions",
+ type_string, otr_exceptions);
+}
+
+void ContentSettingsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("setContentFilter",
+ base::Bind(&ContentSettingsHandler::SetContentFilter,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeException",
+ base::Bind(&ContentSettingsHandler::RemoveException,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setException",
+ base::Bind(&ContentSettingsHandler::SetException,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("checkExceptionPatternValidity",
+ base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity,
+ base::Unretained(this)));
+}
+
+void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
+ DCHECK_EQ(2U, args->GetSize());
+ std::string group, setting;
+ if (!(args->GetString(0, &group) &&
+ args->GetString(1, &setting))) {
+ NOTREACHED();
+ return;
+ }
+
+ ContentSetting default_setting = ContentSettingFromString(setting);
+ ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
+ if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ DesktopNotificationServiceFactory::GetForProfile(profile)->
+ SetDefaultContentSetting(default_setting);
+ } else {
+ GetContentSettingsMap()->
+ SetDefaultContentSetting(content_type, default_setting);
+ }
+ switch (content_type) {
+ case CONTENT_SETTINGS_TYPE_COOKIES:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultCookieSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_IMAGES:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultImagesSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_PLUGINS:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultPluginsSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_POPUPS:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultPopupsSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_INTENTS:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultHandlersSettingChanged"));
+ break;
+ case CONTENT_SETTINGS_TYPE_MOUSELOCK:
+ UserMetrics::RecordAction(
+ UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
+ break;
+ default:
+ break;
+ }
+}
+
+void ContentSettingsHandler::RemoveException(const ListValue* args) {
+ size_t arg_i = 0;
+ std::string type_string;
+ CHECK(args->GetString(arg_i++, &type_string));
+
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
+ if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
+ std::string origin;
+ std::string embedding_origin;
+ bool rv = args->GetString(arg_i++, &origin);
+ DCHECK(rv);
+ rv = args->GetString(arg_i++, &embedding_origin);
+ DCHECK(rv);
+
+ profile->GetHostContentSettingsMap()->
+ SetContentSetting(ContentSettingsPattern::FromString(origin),
+ ContentSettingsPattern::FromString(embedding_origin),
+ CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ std::string(),
+ CONTENT_SETTING_DEFAULT);
+ } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+ std::string origin;
+ std::string setting;
+ bool rv = args->GetString(arg_i++, &origin);
+ DCHECK(rv);
+ rv = args->GetString(arg_i++, &setting);
+ DCHECK(rv);
+ ContentSetting content_setting = ContentSettingFromString(setting);
+
+ DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
+ content_setting == CONTENT_SETTING_BLOCK);
+ DesktopNotificationServiceFactory::GetForProfile(profile)->
+ ClearSetting(ContentSettingsPattern::FromString(origin));
+ } else {
+ std::string mode;
+ bool rv = args->GetString(arg_i++, &mode);
+ DCHECK(rv);
+
+ std::string pattern;
+ rv = args->GetString(arg_i++, &pattern);
+ DCHECK(rv);
+
+ HostContentSettingsMap* settings_map =
+ mode == "normal" ? GetContentSettingsMap() :
+ GetOTRContentSettingsMap();
+ // The settings map could be null if the mode was OTR but the OTR profile
+ // got destroyed before we received this message.
+ if (settings_map) {
+ settings_map->SetContentSetting(
+ ContentSettingsPattern::FromString(pattern),
+ ContentSettingsPattern::Wildcard(),
+ ContentSettingsTypeFromGroupName(type_string),
+ "",
+ CONTENT_SETTING_DEFAULT);
+ }
+ }
+}
+
+void ContentSettingsHandler::SetException(const ListValue* args) {
+ size_t arg_i = 0;
+ std::string type_string;
+ CHECK(args->GetString(arg_i++, &type_string));
+ std::string mode;
+ CHECK(args->GetString(arg_i++, &mode));
+ std::string pattern;
+ CHECK(args->GetString(arg_i++, &pattern));
+ std::string setting;
+ CHECK(args->GetString(arg_i++, &setting));
+
+ ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
+ if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
+ type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
+ NOTREACHED();
+ return;
+ }
+
+ HostContentSettingsMap* settings_map =
+ mode == "normal" ? GetContentSettingsMap() :
+ GetOTRContentSettingsMap();
+
+ // The settings map could be null if the mode was OTR but the OTR profile
+ // got destroyed before we received this message.
+ if (!settings_map)
+ return;
+ settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern),
+ ContentSettingsPattern::Wildcard(),
+ type,
+ "",
+ ContentSettingFromString(setting));
+}
+
+void ContentSettingsHandler::CheckExceptionPatternValidity(
+ const ListValue* args) {
+ size_t arg_i = 0;
+ Value* type;
+ CHECK(args->Get(arg_i++, &type));
+ std::string mode_string;
+ CHECK(args->GetString(arg_i++, &mode_string));
+ std::string pattern_string;
+ CHECK(args->GetString(arg_i++, &pattern_string));
+
+ ContentSettingsPattern pattern =
+ ContentSettingsPattern::FromString(pattern_string);
+
+ scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string));
+ scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string));
+ scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid()));
+
+ web_ui_->CallJavascriptFunction(
+ "ContentSettings.patternValidityCheckComplete",
+ *type,
+ *mode_value.get(),
+ *pattern_value.get(),
+ *valid_value.get());
+}
+
+// static
+std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
+ ContentSettingsType type) {
+ for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
+ if (type == kContentSettingsTypeGroupNames[i].type)
+ return kContentSettingsTypeGroupNames[i].name;
+ }
+
+ NOTREACHED();
+ return std::string();
+}
+
+HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
+ return Profile::FromWebUI(web_ui_)->GetHostContentSettingsMap();
+}
+
+ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() {
+ return Profile::FromWebUI(web_ui_)->GetProtocolHandlerRegistry();
+}
+
+HostContentSettingsMap*
+ ContentSettingsHandler::GetOTRContentSettingsMap() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ if (profile->HasOffTheRecordProfile())
+ return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
+ return NULL;
+}
diff --git a/chrome/browser/ui/webui/options2/content_settings_handler.h b/chrome/browser/ui/webui/options2/content_settings_handler.h
new file mode 100644
index 0000000..3678344
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/content_settings_handler.h
@@ -0,0 +1,113 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CONTENT_SETTINGS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CONTENT_SETTINGS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/plugin_data_remover_helper.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "chrome/common/content_settings_types.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class HostContentSettingsMap;
+class ProtocolHandlerRegistry;
+
+class ContentSettingsHandler : public OptionsPage2UIHandler {
+ public:
+ ContentSettingsHandler();
+ virtual ~ContentSettingsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+
+ virtual void Initialize() OVERRIDE;
+
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // Gets a string identifier for the group name, for use in HTML.
+ static std::string ContentSettingsTypeToGroupName(ContentSettingsType type);
+
+ private:
+ // Functions that call into the page -----------------------------------------
+
+ // Updates the page with the default settings (allow, ask, block, etc.)
+ void UpdateSettingDefaultFromModel(ContentSettingsType type);
+
+ // Clobbers and rebuilds the specific content setting type exceptions table.
+ void UpdateExceptionsViewFromModel(ContentSettingsType type);
+ // Clobbers and rebuilds the specific content setting type exceptions
+ // OTR table.
+ void UpdateOTRExceptionsViewFromModel(ContentSettingsType type);
+ // Clobbers and rebuilds all the exceptions tables in the page (both normal
+ // and OTR tables).
+ void UpdateAllExceptionsViewsFromModel();
+ // As above, but only OTR tables.
+ void UpdateAllOTRExceptionsViewsFromModel();
+ // Clobbers and rebuilds just the geolocation exception table.
+ void UpdateGeolocationExceptionsView();
+ // Clobbers and rebuilds just the desktop notification exception table.
+ void UpdateNotificationExceptionsView();
+ // Clobbers and rebuilds an exception table that's managed by the host content
+ // settings map.
+ void UpdateExceptionsViewFromHostContentSettingsMap(ContentSettingsType type);
+ // As above, but acts on the OTR table for the content setting type.
+ void UpdateExceptionsViewFromOTRHostContentSettingsMap(
+ ContentSettingsType type);
+ // Updates the radio buttons for enabling / disabling handlers.
+ void UpdateHandlersEnabledRadios();
+
+ // Callbacks used by the page ------------------------------------------------
+
+ // Sets the default value for a specific content type. |args| includes the
+ // content type and a string describing the new default the user has
+ // chosen.
+ void SetContentFilter(const ListValue* args);
+
+ // Removes the given row from the table. The first entry in |args| is the
+ // content type, and the rest of the arguments depend on the content type
+ // to be removed.
+ void RemoveException(const ListValue* args);
+
+ // Changes the value of an exception. Called after the user is done editing an
+ // exception.
+ void SetException(const ListValue* args);
+
+ // Called to decide whether a given pattern is valid, or if it should be
+ // rejected. Called while the user is editing an exception pattern.
+ void CheckExceptionPatternValidity(const ListValue* args);
+
+ // Utility functions ---------------------------------------------------------
+
+ // Gets the HostContentSettingsMap for the normal profile.
+ HostContentSettingsMap* GetContentSettingsMap();
+
+ // Gets the HostContentSettingsMap for the incognito profile, or NULL if there
+ // is no active incognito session.
+ HostContentSettingsMap* GetOTRContentSettingsMap();
+
+ // Gets the default setting in string form. If |provider_id| is not NULL, the
+ // id of the provider which provided the default setting is assigned to it.
+ std::string GetSettingDefaultFromModel(ContentSettingsType type,
+ std::string* provider_id);
+
+ // Gets the ProtocolHandlerRegistry for the normal profile.
+ ProtocolHandlerRegistry* GetProtocolHandlerRegistry();
+
+ // Member variables ---------------------------------------------------------
+
+ content::NotificationRegistrar notification_registrar_;
+ PrefChangeRegistrar pref_change_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentSettingsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CONTENT_SETTINGS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/cookies_view_browsertest.js b/chrome/browser/ui/webui/options2/cookies_view_browsertest.js
new file mode 100644
index 0000000..43213cb
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/cookies_view_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for cookies view WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function CookiesViewWebUITest() {}
+
+CookiesViewWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the cookies view.
+ **/
+ browsePreload: 'chrome://settings/cookies',
+};
+
+// Test opening the cookies view has correct location.
+TEST_F('CookiesViewWebUITest', 'testOpenCookiesView', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/cookies_view_handler.cc b/chrome/browser/ui/webui/options2/cookies_view_handler.cc
new file mode 100644
index 0000000..6d86eb2
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/cookies_view_handler.cc
@@ -0,0 +1,222 @@
+// 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/options2/cookies_view_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/browsing_data_cookie_helper.h"
+#include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_file_system_helper.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data_quota_helper.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/cookies_tree_model_util.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+CookiesViewHandler::CookiesViewHandler() : batch_update_(false) {
+}
+
+CookiesViewHandler::~CookiesViewHandler() {
+}
+
+void CookiesViewHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "label_cookie_name", IDS_COOKIES_COOKIE_NAME_LABEL },
+ { "label_cookie_content", IDS_COOKIES_COOKIE_CONTENT_LABEL },
+ { "label_cookie_domain", IDS_COOKIES_COOKIE_DOMAIN_LABEL },
+ { "label_cookie_path", IDS_COOKIES_COOKIE_PATH_LABEL },
+ { "label_cookie_send_for", IDS_COOKIES_COOKIE_SENDFOR_LABEL },
+ { "label_cookie_accessible_to_script",
+ IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_LABEL },
+ { "label_cookie_created", IDS_COOKIES_COOKIE_CREATED_LABEL },
+ { "label_cookie_expires", IDS_COOKIES_COOKIE_EXPIRES_LABEL },
+ { "label_webdb_desc", IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL },
+ { "label_local_storage_size",
+ IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL },
+ { "label_local_storage_last_modified",
+ IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL },
+ { "label_local_storage_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
+ { "label_indexed_db_size", IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL },
+ { "label_indexed_db_last_modified",
+ IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL },
+ { "label_indexed_db_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
+ { "label_app_cache_manifest",
+ IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL },
+ { "label_cookie_last_accessed", IDS_COOKIES_LAST_ACCESSED_LABEL },
+ { "cookie_domain", IDS_COOKIES_DOMAIN_COLUMN_HEADER },
+ { "cookie_local_data", IDS_COOKIES_DATA_COLUMN_HEADER },
+ { "cookie_singular", IDS_COOKIES_SINGLE_COOKIE },
+ { "cookie_plural", IDS_COOKIES_PLURAL_COOKIES },
+ { "cookie_database_storage", IDS_COOKIES_DATABASE_STORAGE },
+ { "cookie_indexed_db", IDS_COOKIES_INDEXED_DB },
+ { "cookie_local_storage", IDS_COOKIES_LOCAL_STORAGE },
+ { "cookie_app_cache", IDS_COOKIES_APPLICATION_CACHE },
+ { "search_cookies", IDS_COOKIES_SEARCH_COOKIES },
+ { "remove_cookie", IDS_COOKIES_REMOVE_LABEL },
+ { "remove_all_cookie", IDS_COOKIES_REMOVE_ALL_LABEL },
+ { "cookie_file_system", IDS_COOKIES_FILE_SYSTEM },
+ { "label_file_system_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
+ { "label_file_system_temporary_usage",
+ IDS_COOKIES_FILE_SYSTEM_TEMPORARY_USAGE_LABEL },
+ { "label_file_system_persistent_usage",
+ IDS_COOKIES_FILE_SYSTEM_PERSISTENT_USAGE_LABEL },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "cookiesViewPage",
+ IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE);
+}
+
+void CookiesViewHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("updateCookieSearchResults",
+ base::Bind(&CookiesViewHandler::UpdateSearchResults,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeAllCookies",
+ base::Bind(&CookiesViewHandler::RemoveAll,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeCookie",
+ base::Bind(&CookiesViewHandler::Remove,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("loadCookie",
+ base::Bind(&CookiesViewHandler::LoadChildren,
+ base::Unretained(this)));
+}
+
+void CookiesViewHandler::TreeNodesAdded(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) {
+ // Skip if there is a batch update in progress.
+ if (batch_update_)
+ return;
+
+ CookieTreeNode* parent_node = cookies_tree_model_->AsNode(parent);
+
+ ListValue* children = new ListValue;
+ cookies_tree_model_util::GetChildNodeList(parent_node, start, count,
+ children);
+
+ ListValue args;
+ args.Append(parent == cookies_tree_model_->GetRoot() ?
+ Value::CreateNullValue() :
+ Value::CreateStringValue(
+ cookies_tree_model_util::GetTreeNodeId(parent_node)));
+ args.Append(Value::CreateIntegerValue(start));
+ args.Append(children);
+ web_ui_->CallJavascriptFunction("CookiesView.onTreeItemAdded", args);
+}
+
+void CookiesViewHandler::TreeNodesRemoved(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) {
+ // Skip if there is a batch update in progress.
+ if (batch_update_)
+ return;
+
+ ListValue args;
+ args.Append(parent == cookies_tree_model_->GetRoot() ?
+ Value::CreateNullValue() :
+ Value::CreateStringValue(cookies_tree_model_util::GetTreeNodeId(
+ cookies_tree_model_->AsNode(parent))));
+ args.Append(Value::CreateIntegerValue(start));
+ args.Append(Value::CreateIntegerValue(count));
+ web_ui_->CallJavascriptFunction("CookiesView.onTreeItemRemoved", args);
+}
+
+void CookiesViewHandler::TreeModelBeginBatch(CookiesTreeModel* model) {
+ DCHECK(!batch_update_); // There should be no nested batch begin.
+ batch_update_ = true;
+}
+
+void CookiesViewHandler::TreeModelEndBatch(CookiesTreeModel* model) {
+ DCHECK(batch_update_);
+ batch_update_ = false;
+
+ SendChildren(cookies_tree_model_->GetRoot());
+}
+
+void CookiesViewHandler::EnsureCookiesTreeModelCreated() {
+ if (!cookies_tree_model_.get()) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ cookies_tree_model_.reset(new CookiesTreeModel(
+ new BrowsingDataCookieHelper(profile),
+ new BrowsingDataDatabaseHelper(profile),
+ new BrowsingDataLocalStorageHelper(profile),
+ NULL,
+ new BrowsingDataAppCacheHelper(profile),
+ BrowsingDataIndexedDBHelper::Create(profile),
+ BrowsingDataFileSystemHelper::Create(profile),
+ BrowsingDataQuotaHelper::Create(profile),
+ false));
+ cookies_tree_model_->AddCookiesTreeObserver(this);
+ }
+}
+
+void CookiesViewHandler::UpdateSearchResults(const ListValue* args) {
+ std::string query;
+ if (!args->GetString(0, &query)) {
+ return;
+ }
+
+ EnsureCookiesTreeModelCreated();
+
+ cookies_tree_model_->UpdateSearchResults(UTF8ToWide(query));
+}
+
+void CookiesViewHandler::RemoveAll(const ListValue* args) {
+ EnsureCookiesTreeModelCreated();
+ cookies_tree_model_->DeleteAllStoredObjects();
+}
+
+void CookiesViewHandler::Remove(const ListValue* args) {
+ std::string node_path;
+ if (!args->GetString(0, &node_path)) {
+ return;
+ }
+
+ EnsureCookiesTreeModelCreated();
+
+ CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath(
+ cookies_tree_model_->GetRoot(), node_path);
+ if (node)
+ cookies_tree_model_->DeleteCookieNode(node);
+}
+
+void CookiesViewHandler::LoadChildren(const ListValue* args) {
+ std::string node_path;
+ if (!args->GetString(0, &node_path)) {
+ return;
+ }
+
+ EnsureCookiesTreeModelCreated();
+
+ CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath(
+ cookies_tree_model_->GetRoot(), node_path);
+ if (node)
+ SendChildren(node);
+}
+
+void CookiesViewHandler::SendChildren(CookieTreeNode* parent) {
+ ListValue* children = new ListValue;
+ cookies_tree_model_util::GetChildNodeList(parent, 0, parent->child_count(),
+ children);
+
+ ListValue args;
+ args.Append(parent == cookies_tree_model_->GetRoot() ?
+ Value::CreateNullValue() :
+ Value::CreateStringValue(cookies_tree_model_util::GetTreeNodeId(parent)));
+ args.Append(children);
+
+ web_ui_->CallJavascriptFunction("CookiesView.loadChildren", args);
+}
diff --git a/chrome/browser/ui/webui/options2/cookies_view_handler.h b/chrome/browser/ui/webui/options2/cookies_view_handler.h
new file mode 100644
index 0000000..4055733
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/cookies_view_handler.h
@@ -0,0 +1,69 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_COOKIES_VIEW_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_COOKIES_VIEW_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/cookies_tree_model.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+class CookiesViewHandler : public OptionsPage2UIHandler,
+ public CookiesTreeModel::Observer {
+ public:
+ CookiesViewHandler();
+ virtual ~CookiesViewHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // CookiesTreeModel::Observer implementation.
+ virtual void TreeNodesAdded(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) OVERRIDE;
+ virtual void TreeNodesRemoved(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) OVERRIDE;
+ virtual void TreeNodeChanged(ui::TreeModel* model,
+ ui::TreeModelNode* node) OVERRIDE {}
+ virtual void TreeModelBeginBatch(CookiesTreeModel* model) OVERRIDE;
+ virtual void TreeModelEndBatch(CookiesTreeModel* model) OVERRIDE;
+
+ private:
+ // Creates the CookiesTreeModel if neccessary.
+ void EnsureCookiesTreeModelCreated();
+
+ // Updates search filter for cookies tree model.
+ void UpdateSearchResults(const base::ListValue* args);
+
+ // Remove all sites data.
+ void RemoveAll(const base::ListValue* args);
+
+ // Remove selected sites data.
+ void Remove(const base::ListValue* args);
+
+ // Get the tree node using the tree path info in |args| and call
+ // SendChildren to pass back children nodes data to WebUI.
+ void LoadChildren(const base::ListValue* args);
+
+ // Get children nodes data and pass it to 'CookiesView.loadChildren' to
+ // update the WebUI.
+ void SendChildren(CookieTreeNode* parent);
+
+ // The Cookies Tree model
+ scoped_ptr<CookiesTreeModel> cookies_tree_model_;
+
+ // Flag to indicate whether there is a batch update in progress.
+ bool batch_update_;
+
+ DISALLOW_COPY_AND_ASSIGN(CookiesViewHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_COOKIES_VIEW_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/core_options_handler.cc b/chrome/browser/ui/webui/options2/core_options_handler.cc
new file mode 100644
index 0000000..b6e8d3c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/core_options_handler.cc
@@ -0,0 +1,464 @@
+// 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/options2/core_options_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_types.h"
+#include "googleurl/src/gurl.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"
+
+CoreOptionsHandler::CoreOptionsHandler()
+ : handlers_host_(NULL) {
+}
+
+CoreOptionsHandler::~CoreOptionsHandler() {}
+
+void CoreOptionsHandler::Initialize() {
+ clear_plugin_lso_data_enabled_.Init(prefs::kClearPluginLSODataEnabled,
+ Profile::FromWebUI(web_ui_),
+ this);
+ UpdateClearPluginLSOData();
+}
+
+void CoreOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ GetStaticLocalizedValues(localized_strings);
+}
+
+void CoreOptionsHandler::GetStaticLocalizedValues(
+ base::DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ // Main
+ localized_strings->SetString("title",
+ l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
+
+ // Managed prefs
+ localized_strings->SetString("policyManagedPrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_POLICY_MANAGED_PREFS));
+ localized_strings->SetString("extensionManagedPrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_EXTENSION_MANAGED_PREFS));
+ localized_strings->SetString("policyAndExtensionManagedPrefsBannerText",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_POLICY_EXTENSION_MANAGED_PREFS));
+
+ // Controlled settings bubble.
+ localized_strings->SetString("controlledSettingPolicy",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY));
+ localized_strings->SetString("controlledSettingExtension",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION));
+ localized_strings->SetString("controlledSettingRecommended",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_RECOMMENDED));
+ localized_strings->SetString("controlledSettingApplyRecommendation",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_CONTROLLED_SETTING_APPLY_RECOMMENDATION));
+
+ // Search
+ RegisterTitle(localized_strings, "searchPage", IDS_OPTIONS_SEARCH_PAGE_TITLE);
+ localized_strings->SetString("searchPlaceholder",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PLACEHOLDER));
+ localized_strings->SetString("searchPageNoMatches",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
+ localized_strings->SetString("searchPageHelpLabel",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_LABEL));
+ localized_strings->SetString("searchPageHelpTitle",
+ l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_TITLE,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+ localized_strings->SetString("searchPageHelpURL",
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kChromeHelpURL)).spec());
+
+ // Common
+ localized_strings->SetString("ok",
+ l10n_util::GetStringUTF16(IDS_OK));
+ localized_strings->SetString("cancel",
+ l10n_util::GetStringUTF16(IDS_CANCEL));
+ localized_strings->SetString("learnMore",
+ l10n_util::GetStringUTF16(IDS_LEARN_MORE));
+ localized_strings->SetString("close",
+ l10n_util::GetStringUTF16(IDS_CLOSE));
+}
+
+void CoreOptionsHandler::Uninitialize() {
+ std::string last_pref;
+ for (PreferenceCallbackMap::const_iterator iter = pref_callback_map_.begin();
+ iter != pref_callback_map_.end();
+ ++iter) {
+ if (last_pref != iter->first) {
+ StopObservingPref(iter->first);
+ last_pref = iter->first;
+ }
+ }
+}
+
+WebUIMessageHandler* CoreOptionsHandler::Attach(WebUI* web_ui) {
+ WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
+ DCHECK(web_ui_);
+ registrar_.Init(Profile::FromWebUI(web_ui_)->GetPrefs());
+ return result;
+}
+
+void CoreOptionsHandler::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ std::string* pref_name = content::Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kClearPluginLSODataEnabled) {
+ // This preference is stored in Local State, not in the user preferences.
+ UpdateClearPluginLSOData();
+ return;
+ }
+ NotifyPrefChanged(*pref_name, std::string());
+ }
+}
+
+void CoreOptionsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("coreOptionsInitialize",
+ base::Bind(&CoreOptionsHandler::HandleInitialize,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("fetchPrefs",
+ base::Bind(&CoreOptionsHandler::HandleFetchPrefs,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("observePrefs",
+ base::Bind(&CoreOptionsHandler::HandleObservePrefs,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setBooleanPref",
+ base::Bind(&CoreOptionsHandler::HandleSetBooleanPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setIntegerPref",
+ base::Bind(&CoreOptionsHandler::HandleSetIntegerPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setDoublePref",
+ base::Bind(&CoreOptionsHandler::HandleSetDoublePref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setStringPref",
+ base::Bind(&CoreOptionsHandler::HandleSetStringPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setURLPref",
+ base::Bind(&CoreOptionsHandler::HandleSetURLPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setListPref",
+ base::Bind(&CoreOptionsHandler::HandleSetListPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("clearPref",
+ base::Bind(&CoreOptionsHandler::HandleClearPref,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("coreOptionsUserMetricsAction",
+ base::Bind(&CoreOptionsHandler::HandleUserMetricsAction,
+ base::Unretained(this)));
+}
+
+void CoreOptionsHandler::HandleInitialize(const ListValue* args) {
+ DCHECK(handlers_host_);
+ handlers_host_->InitializeHandlers();
+}
+
+base::Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+
+ const PrefService::Preference* pref =
+ pref_service->FindPreference(pref_name.c_str());
+ if (!pref)
+ return base::Value::CreateNullValue();
+
+ return CreateValueForPref(pref, NULL);
+}
+
+void CoreOptionsHandler::ObservePref(const std::string& pref_name) {
+ registrar_.Add(pref_name.c_str(), this);
+}
+
+void CoreOptionsHandler::SetPref(const std::string& pref_name,
+ const base::Value* value,
+ const std::string& metric) {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+
+ switch (value->GetType()) {
+ case base::Value::TYPE_BOOLEAN:
+ case base::Value::TYPE_INTEGER:
+ case base::Value::TYPE_DOUBLE:
+ case base::Value::TYPE_STRING:
+ pref_service->Set(pref_name.c_str(), *value);
+ break;
+
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ pref_service->ScheduleSavePersistentPrefs();
+
+ ProcessUserMetric(value, metric);
+}
+
+void CoreOptionsHandler::ClearPref(const std::string& pref_name,
+ const std::string& metric) {
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ pref_service->ClearPref(pref_name.c_str());
+ pref_service->ScheduleSavePersistentPrefs();
+
+ if (!metric.empty())
+ UserMetrics::RecordComputedAction(metric);
+}
+
+void CoreOptionsHandler::ProcessUserMetric(const base::Value* value,
+ const std::string& metric) {
+ if (metric.empty())
+ return;
+
+ std::string metric_string = metric;
+ if (value->IsType(base::Value::TYPE_BOOLEAN)) {
+ bool bool_value;
+ CHECK(value->GetAsBoolean(&bool_value));
+ metric_string += bool_value ? "_Enable" : "_Disable";
+ }
+
+ UserMetrics::RecordComputedAction(metric_string);
+}
+
+void CoreOptionsHandler::NotifyPrefChanged(
+ const std::string& pref_name,
+ const std::string& controlling_pref_name) {
+ const PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ const PrefService::Preference* pref =
+ pref_service->FindPreference(pref_name.c_str());
+ if (!pref)
+ return;
+ const PrefService::Preference* controlling_pref =
+ !controlling_pref_name.empty() ?
+ pref_service->FindPreference(controlling_pref_name.c_str()) : NULL;
+ std::pair<PreferenceCallbackMap::const_iterator,
+ PreferenceCallbackMap::const_iterator> range;
+ range = pref_callback_map_.equal_range(pref_name);
+ for (PreferenceCallbackMap::const_iterator iter = range.first;
+ iter != range.second; ++iter) {
+ const std::wstring& callback_function = iter->second;
+ ListValue result_value;
+ result_value.Append(base::Value::CreateStringValue(pref_name.c_str()));
+ result_value.Append(CreateValueForPref(pref, controlling_pref));
+ web_ui_->CallJavascriptFunction(WideToASCII(callback_function),
+ result_value);
+ }
+}
+
+DictionaryValue* CoreOptionsHandler::CreateValueForPref(
+ const PrefService::Preference* pref,
+ const PrefService::Preference* controlling_pref) {
+ DictionaryValue* dict = new DictionaryValue;
+ dict->Set("value", pref->GetValue()->DeepCopy());
+ if (!controlling_pref) // No controlling pref is managing actual pref.
+ controlling_pref = pref; // This means pref is controlling itself.
+ if (controlling_pref->IsManaged()) {
+ dict->SetString("controlledBy", "policy");
+ } else if (controlling_pref->IsExtensionControlled()) {
+ dict->SetString("controlledBy", "extension");
+ } else if (controlling_pref->IsRecommended()) {
+ dict->SetString("controlledBy", "recommended");
+ }
+ dict->SetBoolean("disabled", !controlling_pref->IsUserModifiable());
+ return dict;
+}
+
+void CoreOptionsHandler::StopObservingPref(const std::string& path) {
+ registrar_.Remove(path.c_str(), this);
+}
+
+void CoreOptionsHandler::HandleFetchPrefs(const ListValue* args) {
+ // First param is name of callback function, so, there needs to be at least
+ // one more element for the actual preference identifier.
+ DCHECK_GE(static_cast<int>(args->GetSize()), 2);
+
+ // Get callback JS function name.
+ base::Value* callback;
+ if (!args->Get(0, &callback) || !callback->IsType(base::Value::TYPE_STRING))
+ return;
+
+ string16 callback_function;
+ if (!callback->GetAsString(&callback_function))
+ return;
+
+ // Get the list of name for prefs to build the response dictionary.
+ DictionaryValue result_value;
+ base::Value* list_member;
+
+ for (size_t i = 1; i < args->GetSize(); i++) {
+ if (!args->Get(i, &list_member))
+ break;
+
+ if (!list_member->IsType(base::Value::TYPE_STRING))
+ continue;
+
+ std::string pref_name;
+ if (!list_member->GetAsString(&pref_name))
+ continue;
+
+ result_value.Set(pref_name.c_str(), FetchPref(pref_name));
+ }
+ web_ui_->CallJavascriptFunction(UTF16ToASCII(callback_function),
+ result_value);
+}
+
+void CoreOptionsHandler::HandleObservePrefs(const ListValue* args) {
+ // First param is name is JS callback function name, the rest are pref
+ // identifiers that we are observing.
+ DCHECK_GE(static_cast<int>(args->GetSize()), 2);
+
+ // Get preference change callback function name.
+ string16 callback_func_name;
+ if (!args->GetString(0, &callback_func_name))
+ return;
+
+ // Get all other parameters - pref identifiers.
+ for (size_t i = 1; i < args->GetSize(); i++) {
+ base::Value* list_member;
+ if (!args->Get(i, &list_member))
+ break;
+
+ // Just ignore bad pref identifiers for now.
+ std::string pref_name;
+ if (!list_member->IsType(base::Value::TYPE_STRING) ||
+ !list_member->GetAsString(&pref_name))
+ continue;
+
+ if (pref_callback_map_.find(pref_name) == pref_callback_map_.end())
+ ObservePref(pref_name);
+
+ pref_callback_map_.insert(
+ PreferenceCallbackMap::value_type(pref_name,
+ UTF16ToWideHack(callback_func_name)));
+ }
+}
+
+void CoreOptionsHandler::HandleSetBooleanPref(const ListValue* args) {
+ HandleSetPref(args, TYPE_BOOLEAN);
+}
+
+void CoreOptionsHandler::HandleSetIntegerPref(const ListValue* args) {
+ HandleSetPref(args, TYPE_INTEGER);
+}
+
+void CoreOptionsHandler::HandleSetDoublePref(const ListValue* args) {
+ HandleSetPref(args, TYPE_DOUBLE);
+}
+
+void CoreOptionsHandler::HandleSetStringPref(const ListValue* args) {
+ HandleSetPref(args, TYPE_STRING);
+}
+
+void CoreOptionsHandler::HandleSetURLPref(const ListValue* args) {
+ HandleSetPref(args, TYPE_URL);
+}
+
+void CoreOptionsHandler::HandleSetListPref(const ListValue* args) {
+ HandleSetPref(args, TYPE_LIST);
+}
+
+void CoreOptionsHandler::HandleSetPref(const ListValue* args, PrefType type) {
+ DCHECK_GT(static_cast<int>(args->GetSize()), 1);
+
+ std::string pref_name;
+ if (!args->GetString(0, &pref_name))
+ return;
+
+ base::Value* value;
+ if (!args->Get(1, &value))
+ return;
+
+ scoped_ptr<base::Value> temp_value;
+
+ switch (type) {
+ case TYPE_BOOLEAN:
+ CHECK_EQ(base::Value::TYPE_BOOLEAN, value->GetType());
+ break;
+ case TYPE_INTEGER: {
+ // In JS all numbers are doubles.
+ double double_value;
+ CHECK(value->GetAsDouble(&double_value));
+ int int_value = static_cast<int>(double_value);
+ temp_value.reset(base::Value::CreateIntegerValue(int_value));
+ value = temp_value.get();
+ break;
+ }
+ case TYPE_DOUBLE:
+ CHECK_EQ(base::Value::TYPE_DOUBLE, value->GetType());
+ break;
+ case TYPE_STRING:
+ CHECK_EQ(base::Value::TYPE_STRING, value->GetType());
+ break;
+ case TYPE_URL: {
+ std::string original;
+ CHECK(value->GetAsString(&original));
+ GURL fixed = URLFixerUpper::FixupURL(original, std::string());
+ temp_value.reset(base::Value::CreateStringValue(fixed.spec()));
+ value = temp_value.get();
+ break;
+ }
+ case TYPE_LIST: {
+ // In case we have a List pref we got a JSON string.
+ std::string json_string;
+ CHECK(value->GetAsString(&json_string));
+ temp_value.reset(
+ base::JSONReader().JsonToValue(json_string,
+ false, // no check_root
+ false)); // no trailing comma
+ value = temp_value.get();
+ CHECK_EQ(base::Value::TYPE_LIST, value->GetType());
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ std::string metric;
+ if (args->GetSize() > 2 && !args->GetString(2, &metric))
+ LOG(WARNING) << "Invalid metric parameter: " << pref_name;
+ SetPref(pref_name, value, metric);
+}
+
+void CoreOptionsHandler::HandleClearPref(const ListValue* args) {
+ DCHECK_GT(static_cast<int>(args->GetSize()), 0);
+
+ std::string pref_name;
+ if (!args->GetString(0, &pref_name))
+ return;
+
+ std::string metric;
+ if (args->GetSize() > 1)
+ args->GetString(1, &metric);
+
+ ClearPref(pref_name, metric);
+}
+
+void CoreOptionsHandler::HandleUserMetricsAction(const ListValue* args) {
+ std::string metric = UTF16ToUTF8(ExtractStringValue(args));
+ if (!metric.empty())
+ UserMetrics::RecordComputedAction(metric);
+}
+
+void CoreOptionsHandler::UpdateClearPluginLSOData() {
+ scoped_ptr<base::Value> enabled(
+ base::Value::CreateBooleanValue(
+ clear_plugin_lso_data_enabled_.GetValue()));
+ web_ui_->CallJavascriptFunction(
+ "OptionsPage.setClearPluginLSODataEnabled", *enabled);
+}
diff --git a/chrome/browser/ui/webui/options2/core_options_handler.h b/chrome/browser/ui/webui/options2/core_options_handler.h
new file mode 100644
index 0000000..355195a
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/core_options_handler.h
@@ -0,0 +1,151 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_CORE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_CORE_OPTIONS_HANDLER_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/values.h"
+#include "chrome/browser/plugin_data_remover_helper.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+// Core options UI handler.
+// Handles resource and JS calls common to all options sub-pages.
+class CoreOptionsHandler : public OptionsPage2UIHandler {
+ public:
+ CoreOptionsHandler();
+ virtual ~CoreOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void Initialize() OVERRIDE;
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Uninitialize() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+ virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
+
+ void set_handlers_host(OptionsPage2UIHandlerHost* handlers_host) {
+ handlers_host_ = handlers_host;
+ }
+
+ // Adds localized strings to |localized_strings|.
+ static void GetStaticLocalizedValues(
+ base::DictionaryValue* localized_strings);
+
+ protected:
+ // Fetches a pref value of given |pref_name|.
+ // Note that caller owns the returned Value.
+ virtual base::Value* FetchPref(const std::string& pref_name);
+
+ // Observes a pref of given |pref_name|.
+ virtual void ObservePref(const std::string& pref_name);
+
+ // Sets a pref |value| to given |pref_name|.
+ virtual void SetPref(const std::string& pref_name,
+ const base::Value* value,
+ const std::string& metric);
+
+ // Clears pref value for given |pref_name|.
+ void ClearPref(const std::string& pref_name, const std::string& metric);
+
+ // Stops observing given preference identified by |path|.
+ virtual void StopObservingPref(const std::string& path);
+
+ // Records a user metric action for the given value.
+ void ProcessUserMetric(const base::Value* value,
+ const std::string& metric);
+
+ // Notifies registered JS callbacks on change in |pref_name| preference.
+ // |controlling_pref_name| controls if |pref_name| is managed by
+ // policy/extension; empty |controlling_pref_name| indicates no other pref is
+ // controlling |pref_name|.
+ void NotifyPrefChanged(const std::string& pref_name,
+ const std::string& controlling_pref_name);
+
+ // Creates dictionary value for |pref|, |controlling_pref| controls if |pref|
+ // is managed by policy/extension; NULL indicates no other pref is controlling
+ // |pref|.
+ DictionaryValue* CreateValueForPref(
+ const PrefService::Preference* pref,
+ const PrefService::Preference* controlling_pref);
+
+ typedef std::multimap<std::string, std::wstring> PreferenceCallbackMap;
+ PreferenceCallbackMap pref_callback_map_;
+
+ private:
+ // Type of preference value received from the page. This doesn't map 1:1 to
+ // Value::Type, since a TYPE_STRING can require custom processing.
+ enum PrefType {
+ TYPE_BOOLEAN = 0,
+ TYPE_INTEGER,
+ TYPE_DOUBLE,
+ TYPE_STRING,
+ TYPE_URL,
+ TYPE_LIST,
+ };
+
+ // Callback for the "coreOptionsInitialize" message. This message will
+ // trigger the Initialize() method of all other handlers so that final
+ // setup can be performed before the page is shown.
+ void HandleInitialize(const ListValue* args);
+
+ // Callback for the "fetchPrefs" message. This message accepts the list of
+ // preference names passed as the |args| parameter (ListValue). It passes
+ // results dictionary of preference values by calling prefsFetched() JS method
+ // on the page.
+ void HandleFetchPrefs(const ListValue* args);
+
+ // Callback for the "observePrefs" message. This message initiates
+ // notification observing for given array of preference names.
+ void HandleObservePrefs(const ListValue* args);
+
+ // Callbacks for the "set<type>Pref" message. This message saves the new
+ // preference value. |args| is an array of parameters as follows:
+ // item 0 - name of the preference.
+ // item 1 - the value of the preference in string form.
+ // item 2 - name of the metric identifier (optional).
+ void HandleSetBooleanPref(const ListValue* args);
+ void HandleSetIntegerPref(const ListValue* args);
+ void HandleSetDoublePref(const ListValue* args);
+ void HandleSetStringPref(const ListValue* args);
+ void HandleSetURLPref(const ListValue* args);
+ void HandleSetListPref(const ListValue* args);
+
+ void HandleSetPref(const ListValue* args, PrefType type);
+
+ // Callback for the "clearPref" message. This message clears a preference
+ // value. |args| is an array of parameters as follows:
+ // item 0 - name of the preference.
+ // item 1 - name of the metric identifier (optional).
+ void HandleClearPref(const ListValue* args);
+
+ // Callback for the "coreOptionsUserMetricsAction" message. This records
+ // an action that should be tracked if metrics recording is enabled. |args|
+ // is an array that contains a single item, the name of the metric identifier.
+ void HandleUserMetricsAction(const ListValue* args);
+
+ void UpdateClearPluginLSOData();
+
+ OptionsPage2UIHandlerHost* handlers_host_;
+ PrefChangeRegistrar registrar_;
+
+ // Used for asynchronously updating the preference stating whether clearing
+ // LSO data is supported.
+ PluginDataRemoverHelper clear_plugin_lso_data_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(CoreOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_CORE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/extension_settings_handler.cc b/chrome/browser/ui/webui/options2/extension_settings_handler.cc
new file mode 100644
index 0000000..cc6f548
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/extension_settings_handler.cc
@@ -0,0 +1,785 @@
+// 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/options2/extension_settings_handler.h"
+
+#include "base/auto_reset.h"
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/debugger/devtools_window.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_updater.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
+#include "chrome/browser/extensions/unpacked_installer.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/tab_contents/background_contents.h"
+#include "chrome/browser/ui/webui/extension_icon_source.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_view_type.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/browsing_instance.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+bool ShouldShowExtension(const Extension* extension) {
+ // Don't show themes since this page's UI isn't really useful for themes.
+ if (extension->is_theme())
+ return false;
+
+ // Don't show component extensions because they are only extensions as an
+ // implementation detail of Chrome.
+ if (extension->location() == Extension::COMPONENT &&
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kShowComponentExtensionOptions))
+ return false;
+
+ // Always show unpacked extensions and apps.
+ if (extension->location() == Extension::LOAD)
+ return true;
+
+ // Unless they are unpacked, never show hosted apps.
+ if (extension->is_hosted_app())
+ return false;
+
+ return true;
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ExtensionSettingsHandler
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ExtensionSettingsHandler::ExtensionSettingsHandler()
+ : extension_service_(NULL),
+ ignore_notifications_(false),
+ deleting_rvh_(NULL),
+ registered_for_notifications_(false) {
+}
+
+ExtensionSettingsHandler::~ExtensionSettingsHandler() {
+ // There may be pending file dialogs, we need to tell them that we've gone
+ // away so they don't try and call back to us.
+ if (load_extension_dialog_.get())
+ load_extension_dialog_->ListenerDestroyed();
+
+ registrar_.RemoveAll();
+}
+
+// static
+void ExtensionSettingsHandler::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterBooleanPref(prefs::kExtensionsUIDeveloperMode,
+ false,
+ PrefService::SYNCABLE_PREF);
+}
+
+void ExtensionSettingsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("extensionSettingsRequestExtensionsData",
+ base::Bind(&ExtensionSettingsHandler::HandleRequestExtensionsData,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsToggleDeveloperMode",
+ base::Bind(&ExtensionSettingsHandler::HandleToggleDeveloperMode,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsInspect",
+ base::Bind(&ExtensionSettingsHandler::HandleInspectMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsReload",
+ base::Bind(&ExtensionSettingsHandler::HandleReloadMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsEnable",
+ base::Bind(&ExtensionSettingsHandler::HandleEnableMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsEnableIncognito",
+ base::Bind(&ExtensionSettingsHandler::HandleEnableIncognitoMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsAllowFileAccess",
+ base::Bind(&ExtensionSettingsHandler::HandleAllowFileAccessMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsUninstall",
+ base::Bind(&ExtensionSettingsHandler::HandleUninstallMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsOptions",
+ base::Bind(&ExtensionSettingsHandler::HandleOptionsMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsShowButton",
+ base::Bind(&ExtensionSettingsHandler::HandleShowButtonMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsLoad",
+ base::Bind(&ExtensionSettingsHandler::HandleLoadMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsAutoupdate",
+ base::Bind(&ExtensionSettingsHandler::HandleAutoUpdateMessage,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("extensionSettingsSelectFilePath",
+ base::Bind(&ExtensionSettingsHandler::HandleSelectFilePathMessage,
+ base::Unretained(this)));
+}
+
+void ExtensionSettingsHandler::HandleRequestExtensionsData(
+ const ListValue* args) {
+ DictionaryValue results;
+
+ // Add the extensions to the results structure.
+ ListValue *extensions_list = new ListValue();
+
+ ExtensionWarningSet* warnings = extension_service_->extension_warnings();
+
+ const ExtensionSet* extensions = extension_service_->extensions();
+ for (ExtensionSet::const_iterator extension = extensions->begin();
+ extension != extensions->end(); ++extension) {
+ if (ShouldShowExtension(*extension)) {
+ extensions_list->Append(CreateExtensionDetailValue(
+ extension_service_,
+ *extension,
+ GetActivePagesForExtension(*extension),
+ warnings,
+ true, false)); // enabled, terminated
+ }
+ }
+ extensions = extension_service_->disabled_extensions();
+ for (ExtensionSet::const_iterator extension = extensions->begin();
+ extension != extensions->end(); ++extension) {
+ if (ShouldShowExtension(*extension)) {
+ extensions_list->Append(CreateExtensionDetailValue(
+ extension_service_,
+ *extension,
+ GetActivePagesForExtension(*extension),
+ warnings,
+ false, false)); // enabled, terminated
+ }
+ }
+ extensions = extension_service_->terminated_extensions();
+ std::vector<ExtensionPage> empty_pages;
+ for (ExtensionSet::const_iterator extension = extensions->begin();
+ extension != extensions->end(); ++extension) {
+ if (ShouldShowExtension(*extension)) {
+ extensions_list->Append(CreateExtensionDetailValue(
+ extension_service_,
+ *extension,
+ empty_pages, // Terminated process has no active pages.
+ warnings,
+ false, true)); // enabled, terminated
+ }
+ }
+ results.Set("extensions", extensions_list);
+
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ bool developer_mode =
+ profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
+ results.SetBoolean("developerMode", developer_mode);
+
+ web_ui_->CallJavascriptFunction("ExtensionSettings.returnExtensionsData",
+ results);
+
+ MaybeRegisterForNotifications();
+}
+
+void ExtensionSettingsHandler::MaybeRegisterForNotifications() {
+ if (registered_for_notifications_)
+ return;
+
+ registered_for_notifications_ = true;
+ Profile* profile = Profile::FromWebUI(web_ui_);
+
+ // Register for notifications that we need to reload the page.
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
+ content::Source<Profile>(profile));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
+ content::Source<Profile>(profile));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED,
+ content::Source<Profile>(profile));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ content::NOTIFICATION_RENDER_VIEW_HOST_DELETED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(
+ this,
+ chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
+ content::Source<ExtensionPrefs>(profile->GetExtensionService()->
+ extension_prefs()));
+}
+
+ExtensionUninstallDialog*
+ExtensionSettingsHandler::GetExtensionUninstallDialog() {
+ if (!extension_uninstall_dialog_.get()) {
+ extension_uninstall_dialog_.reset(
+ ExtensionUninstallDialog::Create(Profile::FromWebUI(web_ui_), this));
+ }
+ return extension_uninstall_dialog_.get();
+}
+
+void ExtensionSettingsHandler::HandleToggleDeveloperMode(
+ const ListValue* args) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ bool developer_mode =
+ profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
+ profile->GetPrefs()->SetBoolean(
+ prefs::kExtensionsUIDeveloperMode, !developer_mode);
+ HandleRequestExtensionsData(NULL);
+}
+
+void ExtensionSettingsHandler::HandleInspectMessage(const ListValue* args) {
+ std::string render_process_id_str;
+ std::string render_view_id_str;
+ int render_process_id;
+ int render_view_id;
+ CHECK_EQ(2U, args->GetSize());
+ CHECK(args->GetString(0, &render_process_id_str));
+ CHECK(args->GetString(1, &render_view_id_str));
+ CHECK(base::StringToInt(render_process_id_str, &render_process_id));
+ CHECK(base::StringToInt(render_view_id_str, &render_view_id));
+ RenderViewHost* host = RenderViewHost::FromID(render_process_id,
+ render_view_id);
+ if (!host) {
+ // This can happen if the host has gone away since the page was displayed.
+ return;
+ }
+
+ DevToolsWindow::OpenDevToolsWindow(host);
+}
+
+void ExtensionSettingsHandler::HandleReloadMessage(const ListValue* args) {
+ std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
+ CHECK(!extension_id.empty());
+ extension_service_->ReloadExtension(extension_id);
+}
+
+void ExtensionSettingsHandler::HandleEnableMessage(const ListValue* args) {
+ CHECK_EQ(2U, args->GetSize());
+ std::string extension_id, enable_str;
+ CHECK(args->GetString(0, &extension_id));
+ CHECK(args->GetString(1, &enable_str));
+
+ const Extension* extension =
+ extension_service_->GetExtensionById(extension_id, true);
+ if (!Extension::UserMayDisable(extension->location())) {
+ LOG(ERROR) << "Attempt to enable an extension that is non-usermanagable was"
+ << "made. Extension id: " << extension->id();
+ return;
+ }
+
+ if (enable_str == "true") {
+ ExtensionPrefs* prefs = extension_service_->extension_prefs();
+ if (prefs->DidExtensionEscalatePermissions(extension_id)) {
+ ShowExtensionDisabledDialog(extension_service_,
+ Profile::FromWebUI(web_ui_), extension);
+ } else {
+ extension_service_->EnableExtension(extension_id);
+ }
+ } else {
+ extension_service_->DisableExtension(extension_id);
+ }
+}
+
+void ExtensionSettingsHandler::HandleEnableIncognitoMessage(
+ const ListValue* args) {
+ CHECK_EQ(2U, args->GetSize());
+ std::string extension_id, enable_str;
+ CHECK(args->GetString(0, &extension_id));
+ CHECK(args->GetString(1, &enable_str));
+ const Extension* extension =
+ extension_service_->GetExtensionById(extension_id, true);
+ DCHECK(extension);
+
+ // Flipping the incognito bit will generate unload/load notifications for the
+ // extension, but we don't want to reload the page, because a) we've already
+ // updated the UI to reflect the change, and b) we want the yellow warning
+ // text to stay until the user has left the page.
+ //
+ // TODO(aa): This creates crapiness in some cases. For example, in a main
+ // window, when toggling this, the browser action will flicker because it gets
+ // unloaded, then reloaded. It would be better to have a dedicated
+ // notification for this case.
+ //
+ // Bug: http://crbug.com/41384
+ AutoReset<bool> auto_reset_ignore_notifications(&ignore_notifications_, true);
+ extension_service_->SetIsIncognitoEnabled(extension->id(),
+ enable_str == "true");
+}
+
+void ExtensionSettingsHandler::HandleAllowFileAccessMessage(
+ const ListValue* args) {
+ CHECK_EQ(2U, args->GetSize());
+ std::string extension_id, allow_str;
+ CHECK(args->GetString(0, &extension_id));
+ CHECK(args->GetString(1, &allow_str));
+ const Extension* extension =
+ extension_service_->GetExtensionById(extension_id, true);
+ DCHECK(extension);
+
+ if (!Extension::UserMayDisable(extension->location())) {
+ LOG(ERROR) << "Attempt to change allow file access of an extension that is "
+ << "non-usermanagable was made. Extension id : "
+ << extension->id();
+ return;
+ }
+
+ extension_service_->SetAllowFileAccess(extension, allow_str == "true");
+}
+
+void ExtensionSettingsHandler::HandleUninstallMessage(const ListValue* args) {
+ std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
+ CHECK(!extension_id.empty());
+ const Extension* extension =
+ extension_service_->GetExtensionById(extension_id, true);
+ if (!extension)
+ extension = extension_service_->GetTerminatedExtension(extension_id);
+ if (!extension)
+ return;
+
+ if (!Extension::UserMayDisable(extension->location())) {
+ LOG(ERROR) << "Attempt to uninstall an extension that is non-usermanagable "
+ << "was made. Extension id : " << extension->id();
+ return;
+ }
+
+ if (!extension_id_prompting_.empty())
+ return; // Only one prompt at a time.
+
+ extension_id_prompting_ = extension_id;
+
+ GetExtensionUninstallDialog()->ConfirmUninstall(extension);
+}
+
+void ExtensionSettingsHandler::ExtensionUninstallAccepted() {
+ DCHECK(!extension_id_prompting_.empty());
+
+ bool was_terminated = false;
+
+ // The extension can be uninstalled in another window while the UI was
+ // showing. Do nothing in that case.
+ const Extension* extension =
+ extension_service_->GetExtensionById(extension_id_prompting_, true);
+ if (!extension) {
+ extension = extension_service_->GetTerminatedExtension(
+ extension_id_prompting_);
+ was_terminated = true;
+ }
+ if (!extension)
+ return;
+
+ extension_service_->UninstallExtension(extension_id_prompting_,
+ false, // External uninstall.
+ NULL); // Error.
+ extension_id_prompting_ = "";
+
+ // There will be no EXTENSION_UNLOADED notification for terminated
+ // extensions as they were already unloaded.
+ if (was_terminated)
+ HandleRequestExtensionsData(NULL);
+}
+
+void ExtensionSettingsHandler::ExtensionUninstallCanceled() {
+ extension_id_prompting_ = "";
+}
+
+void ExtensionSettingsHandler::HandleOptionsMessage(const ListValue* args) {
+ const Extension* extension = GetExtension(args);
+ if (!extension || extension->options_url().is_empty())
+ return;
+ Profile::FromWebUI(web_ui_)->GetExtensionProcessManager()->OpenOptionsPage(
+ extension, NULL);
+}
+
+void ExtensionSettingsHandler::HandleShowButtonMessage(const ListValue* args) {
+ const Extension* extension = GetExtension(args);
+ extension_service_->SetBrowserActionVisibility(extension, true);
+}
+
+void ExtensionSettingsHandler::HandleLoadMessage(const ListValue* args) {
+ FilePath::StringType string_path;
+ CHECK_EQ(1U, args->GetSize()) << args->GetSize();
+ CHECK(args->GetString(0, &string_path));
+ extensions::UnpackedInstaller::Create(extension_service_)->
+ Load(FilePath(string_path));
+}
+
+void ExtensionSettingsHandler::ShowAlert(const std::string& message) {
+ ListValue arguments;
+ arguments.Append(Value::CreateStringValue(message));
+ web_ui_->CallJavascriptFunction("alert", arguments);
+}
+
+void ExtensionSettingsHandler::HandleAutoUpdateMessage(const ListValue* args) {
+ ExtensionUpdater* updater = extension_service_->updater();
+ if (updater)
+ updater->CheckNow();
+}
+
+void ExtensionSettingsHandler::HandleSelectFilePathMessage(
+ const ListValue* args) {
+ std::string select_type;
+ std::string operation;
+ CHECK_EQ(2U, args->GetSize());
+ CHECK(args->GetString(0, &select_type));
+ CHECK(args->GetString(1, &operation));
+
+ SelectFileDialog::Type type = SelectFileDialog::SELECT_FOLDER;
+ SelectFileDialog::FileTypeInfo info;
+ int file_type_index = 0;
+ if (select_type == "file")
+ type = SelectFileDialog::SELECT_OPEN_FILE;
+
+ string16 select_title;
+ if (operation == "load") {
+ select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
+ } else if (operation == "packRoot") {
+ select_title = l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PACK_DIALOG_SELECT_ROOT);
+ } else if (operation == "pem") {
+ select_title = l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
+ info.extensions.push_back(std::vector<FilePath::StringType>());
+ info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
+ info.extension_description_overrides.push_back(
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
+ info.include_all_files = true;
+ file_type_index = 1;
+ } else {
+ NOTREACHED();
+ return;
+ }
+
+ load_extension_dialog_ = SelectFileDialog::Create(this);
+ load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info,
+ file_type_index, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
+ web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+}
+
+
+void ExtensionSettingsHandler::FileSelected(const FilePath& path, int index,
+ void* params) {
+ // Add the extensions to the results structure.
+ ListValue results;
+ results.Append(Value::CreateStringValue(path.value()));
+ web_ui_->CallJavascriptFunction("window.handleFilePathSelected", results);
+}
+
+void ExtensionSettingsHandler::MultiFilesSelected(
+ const std::vector<FilePath>& files, void* params) {
+ NOTREACHED();
+}
+
+void ExtensionSettingsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "extensionSettings",
+ IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);
+
+ localized_strings->SetString("extensionSettingsVisitWebsite",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE));
+
+ localized_strings->SetString("extensionSettingsDeveloperMode",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_LINK));
+ localized_strings->SetString("extensionSettingsNoExtensions",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_NONE_INSTALLED));
+ localized_strings->SetString("extensionSettingsSuggestGallery",
+ l10n_util::GetStringFUTF16(IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY,
+ ASCIIToUTF16("<a href='") +
+ ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
+ GURL(extension_urls::GetWebstoreLaunchURL())).spec()) +
+ ASCIIToUTF16("'>"),
+ ASCIIToUTF16("</a>")));
+ localized_strings->SetString("extensionSettingsGetMoreExtensions",
+ ASCIIToUTF16("<a href='") +
+ ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
+ GURL(extension_urls::GetWebstoreLaunchURL())).spec()) +
+ ASCIIToUTF16("'>") +
+ l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS) +
+ ASCIIToUTF16("</a>"));
+ localized_strings->SetString("extensionSettingsExtensionId",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID));
+ localized_strings->SetString("extensionSettingsExtensionPath",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_PATH));
+ localized_strings->SetString("extensionSettingsInspectViews",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_VIEWS));
+ localized_strings->SetString("viewIncognito",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO));
+ localized_strings->SetString("extensionSettingsEnable",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE));
+ localized_strings->SetString("extensionSettingsEnabled",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLED));
+ localized_strings->SetString("extensionSettingsRemove",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_REMOVE));
+ localized_strings->SetString("extensionSettingsEnableIncognito",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_INCOGNITO));
+ localized_strings->SetString("extensionSettingsAllowFileAccess",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_FILE_ACCESS));
+ localized_strings->SetString("extensionSettingsIncognitoWarning",
+ l10n_util::GetStringFUTF16(IDS_EXTENSIONS_INCOGNITO_WARNING,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+ localized_strings->SetString("extensionSettingsReload",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD));
+ localized_strings->SetString("extensionSettingsOptions",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS));
+ localized_strings->SetString("extensionSettingsPolicyControlled",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED));
+ localized_strings->SetString("extensionSettingsShowButton",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON));
+ localized_strings->SetString("extensionSettingsLoadUnpackedButton",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON));
+ localized_strings->SetString("extensionSettingsPackButton",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_PACK_BUTTON));
+ localized_strings->SetString("extensionSettingsUpdateButton",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_UPDATE_BUTTON));
+ localized_strings->SetString("extensionSettingsCrashMessage",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION));
+ localized_strings->SetString("extensionSettingsInDevelopment",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT));
+ localized_strings->SetString("extensionSettingsWarningsTitle",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_TITLE));
+ localized_strings->SetString("extensionSettingsShowDetails",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS));
+ localized_strings->SetString("extensionSettingsHideDetails",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS));
+}
+
+void ExtensionSettingsHandler::Initialize() {
+}
+
+WebUIMessageHandler* ExtensionSettingsHandler::Attach(WebUI* web_ui) {
+ // Call through to superclass.
+ WebUIMessageHandler* handler = OptionsPage2UIHandler::Attach(web_ui);
+
+ extension_service_ = Profile::FromWebUI(web_ui_)
+ ->GetOriginalProfile()->GetExtensionService();
+
+ // Return result from the superclass.
+ return handler;
+}
+
+void ExtensionSettingsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ Profile* source_profile = NULL;
+ switch (type) {
+ // We listen for notifications that will result in the page being
+ // repopulated with data twice for the same event in certain cases.
+ // For instance, EXTENSION_LOADED & EXTENSION_HOST_CREATED because
+ // we don't know about the views for an extension at EXTENSION_LOADED, but
+ // if we only listen to EXTENSION_HOST_CREATED, we'll miss extensions
+ // that don't have a process at startup.
+ //
+ // Doing it this way gets everything but causes the page to be rendered
+ // more than we need. It doesn't seem to result in any noticeable flicker.
+ case content::NOTIFICATION_RENDER_VIEW_HOST_DELETED:
+ deleting_rvh_ = content::Source<RenderViewHost>(source).ptr();
+ // Fall through.
+ case content::NOTIFICATION_RENDER_VIEW_HOST_CREATED:
+ source_profile = Profile::FromBrowserContext(
+ content::Source<RenderViewHost>(source)->site_instance()->
+ browsing_instance()->browser_context());
+ if (!profile->IsSameProfile(source_profile))
+ return;
+ MaybeUpdateAfterNotification();
+ break;
+ case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED:
+ deleting_rvh_ = content::Details<BackgroundContents>(details)->
+ tab_contents()->render_view_host();
+ // Fall through.
+ case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED:
+ case chrome::NOTIFICATION_EXTENSION_HOST_CREATED:
+ source_profile = content::Source<Profile>(source).ptr();
+ if (!profile->IsSameProfile(source_profile))
+ return;
+ MaybeUpdateAfterNotification();
+ break;
+ case chrome::NOTIFICATION_EXTENSION_LOADED:
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED:
+ case chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED:
+ case chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED:
+ case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED:
+ MaybeUpdateAfterNotification();
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+const Extension* ExtensionSettingsHandler::GetExtension(const ListValue* args) {
+ std::string extension_id = UTF16ToUTF8(ExtractStringValue(args));
+ CHECK(!extension_id.empty());
+ return extension_service_->GetExtensionById(extension_id, true);
+}
+
+void ExtensionSettingsHandler::MaybeUpdateAfterNotification() {
+ TabContents* contents = web_ui_->tab_contents();
+ if (!ignore_notifications_ && contents && contents->render_view_host())
+ HandleRequestExtensionsData(NULL);
+ deleting_rvh_ = NULL;
+}
+
+// Static
+DictionaryValue* ExtensionSettingsHandler::CreateExtensionDetailValue(
+ ExtensionService* service, const Extension* extension,
+ const std::vector<ExtensionPage>& pages,
+ const ExtensionWarningSet* warnings_set,
+ bool enabled, bool terminated) {
+ DictionaryValue* extension_data = new DictionaryValue();
+ GURL icon =
+ ExtensionIconSource::GetIconURL(extension,
+ Extension::EXTENSION_ICON_MEDIUM,
+ ExtensionIconSet::MATCH_BIGGER,
+ !enabled, NULL);
+ extension_data->SetString("id", extension->id());
+ extension_data->SetString("name", extension->name());
+ extension_data->SetString("description", extension->description());
+ if (extension->location() == Extension::LOAD)
+ extension_data->SetString("path", extension->path().value());
+ extension_data->SetString("version", extension->version()->GetString());
+ extension_data->SetString("icon", icon.spec());
+ extension_data->SetBoolean("isUnpacked",
+ extension->location() == Extension::LOAD);
+ extension_data->SetBoolean("mayDisable",
+ Extension::UserMayDisable(extension->location()));
+ extension_data->SetBoolean("enabled", enabled);
+ extension_data->SetBoolean("terminated", terminated);
+ extension_data->SetBoolean("enabledIncognito",
+ service ? service->IsIncognitoEnabled(extension->id()) : false);
+ extension_data->SetBoolean("wantsFileAccess", extension->wants_file_access());
+ extension_data->SetBoolean("allowFileAccess",
+ service ? service->AllowFileAccess(extension) : false);
+ extension_data->SetBoolean("allow_reload",
+ extension->location() == Extension::LOAD);
+ extension_data->SetBoolean("is_hosted_app", extension->is_hosted_app());
+
+ // Determine the sort order: Extensions loaded through --load-extensions show
+ // up at the top. Disabled extensions show up at the bottom.
+ if (extension->location() == Extension::LOAD)
+ extension_data->SetInteger("order", 1);
+ else
+ extension_data->SetInteger("order", 2);
+
+ if (!extension->options_url().is_empty() && enabled)
+ extension_data->SetString("options_url", extension->options_url().spec());
+
+ if (service && !service->GetBrowserActionVisibility(extension))
+ extension_data->SetBoolean("enable_show_button", true);
+
+ // Add views
+ ListValue* views = new ListValue;
+ for (std::vector<ExtensionPage>::const_iterator iter = pages.begin();
+ iter != pages.end(); ++iter) {
+ DictionaryValue* view_value = new DictionaryValue;
+ if (iter->url.scheme() == chrome::kExtensionScheme) {
+ // No leading slash.
+ view_value->SetString("path", iter->url.path().substr(1));
+ } else {
+ // For live pages, use the full URL.
+ view_value->SetString("path", iter->url.spec());
+ }
+ view_value->SetInteger("renderViewId", iter->render_view_id);
+ view_value->SetInteger("renderProcessId", iter->render_process_id);
+ view_value->SetBoolean("incognito", iter->incognito);
+ views->Append(view_value);
+ }
+ extension_data->Set("views", views);
+ extension_data->SetBoolean("hasPopupAction",
+ extension->browser_action() || extension->page_action());
+ extension_data->SetString("homepageUrl", extension->GetHomepageURL().spec());
+
+ // Add warnings.
+ ListValue* warnings_list = new ListValue;
+ if (warnings_set) {
+ std::set<ExtensionWarningSet::WarningType> warnings;
+ warnings_set->GetWarningsAffectingExtension(extension->id(), &warnings);
+
+ for (std::set<ExtensionWarningSet::WarningType>::const_iterator iter =
+ warnings.begin();
+ iter != warnings.end();
+ ++iter) {
+ string16 warning_string(ExtensionWarningSet::GetLocalizedWarning(*iter));
+ warnings_list->Append(Value::CreateStringValue(warning_string));
+ }
+ }
+ extension_data->Set("warnings", warnings_list);
+
+ return extension_data;
+}
+
+std::vector<ExtensionPage> ExtensionSettingsHandler::GetActivePagesForExtension(
+ const Extension* extension) {
+ std::vector<ExtensionPage> result;
+
+ // Get the extension process's active views.
+ ExtensionProcessManager* process_manager =
+ extension_service_->profile()->GetExtensionProcessManager();
+ GetActivePagesForExtensionProcess(
+ process_manager->GetRenderViewHostsForExtension(
+ extension->id()), &result);
+
+ // Repeat for the incognito process, if applicable.
+ if (extension_service_->profile()->HasOffTheRecordProfile() &&
+ extension->incognito_split_mode()) {
+ ExtensionProcessManager* process_manager =
+ extension_service_->profile()->GetOffTheRecordProfile()->
+ GetExtensionProcessManager();
+ GetActivePagesForExtensionProcess(
+ process_manager->GetRenderViewHostsForExtension(
+ extension->id()), &result);
+ }
+
+ return result;
+}
+
+void ExtensionSettingsHandler::GetActivePagesForExtensionProcess(
+ const std::set<RenderViewHost*>& views,
+ std::vector<ExtensionPage> *result) {
+ for (std::set<RenderViewHost*>::const_iterator iter = views.begin();
+ iter != views.end(); ++iter) {
+ RenderViewHost* host = *iter;
+ int host_type = host->delegate()->GetRenderViewType();
+ if (host == deleting_rvh_ ||
+ chrome::VIEW_TYPE_EXTENSION_POPUP == host_type ||
+ chrome::VIEW_TYPE_EXTENSION_DIALOG == host_type)
+ continue;
+
+ GURL url = host->delegate()->GetURL();
+ content::RenderProcessHost* process = host->process();
+ result->push_back(
+ ExtensionPage(url, process->GetID(), host->routing_id(),
+ process->GetBrowserContext()->IsOffTheRecord()));
+ }
+}
diff --git a/chrome/browser/ui/webui/options2/extension_settings_handler.h b/chrome/browser/ui/webui/options2/extension_settings_handler.h
new file mode 100644
index 0000000..a03908d
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/extension_settings_handler.h
@@ -0,0 +1,200 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_EXTENSION_SETTINGS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_EXTENSION_SETTINGS_HANDLER_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/extensions/extension_uninstall_dialog.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
+#include "chrome/browser/ui/select_file_dialog.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "chrome/browser/ui/webui/chrome_web_ui.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "googleurl/src/gurl.h"
+
+class Extension;
+class ExtensionService;
+class FilePath;
+class PrefService;
+class UserScript;
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+// Information about a page running in an extension, for example a popup bubble,
+// a background page, or a tab contents.
+struct ExtensionPage {
+ ExtensionPage(const GURL& url, int render_process_id, int render_view_id,
+ bool incognito)
+ : url(url),
+ render_process_id(render_process_id),
+ render_view_id(render_view_id),
+ incognito(incognito) {}
+ GURL url;
+ int render_process_id;
+ int render_view_id;
+ bool incognito;
+};
+
+// Extension Settings UI handler.
+class ExtensionSettingsHandler : public OptionsPage2UIHandler,
+ public SelectFileDialog::Listener,
+ public ExtensionUninstallDialog::Delegate {
+ public:
+ ExtensionSettingsHandler();
+ virtual ~ExtensionSettingsHandler();
+
+ static void RegisterUserPrefs(PrefService* prefs);
+
+ // Extension Detail JSON Struct for page. (static for ease of testing).
+ // Note: |service| and |warnings| can be NULL in unit tests.
+ static base::DictionaryValue* CreateExtensionDetailValue(
+ ExtensionService* service,
+ const Extension* extension,
+ const std::vector<ExtensionPage>& pages,
+ const ExtensionWarningSet* warnings,
+ bool enabled,
+ bool terminated);
+
+ // ContentScript JSON Struct for page. (static for ease of testing).
+ static base::DictionaryValue* CreateContentScriptDetailValue(
+ const UserScript& script,
+ const FilePath& extension_path);
+
+ // Callback for "requestExtensionsData" message.
+ void HandleRequestExtensionsData(const base::ListValue* args);
+
+ // Callback for "toggleDeveloperMode" message.
+ void HandleToggleDeveloperMode(const base::ListValue* args);
+
+ // Callback for "inspect" message.
+ void HandleInspectMessage(const base::ListValue* args);
+
+ // Callback for "reload" message.
+ void HandleReloadMessage(const base::ListValue* args);
+
+ // Callback for "enable" message.
+ void HandleEnableMessage(const base::ListValue* args);
+
+ // Callback for "enableIncognito" message.
+ void HandleEnableIncognitoMessage(const base::ListValue* args);
+
+ // Callback for "allowFileAcces" message.
+ void HandleAllowFileAccessMessage(const base::ListValue* args);
+
+ // Callback for "uninstall" message.
+ void HandleUninstallMessage(const base::ListValue* args);
+
+ // Callback for "options" message.
+ void HandleOptionsMessage(const base::ListValue* args);
+
+ // Callback for "showButton" message.
+ void HandleShowButtonMessage(const base::ListValue* args);
+
+ // Callback for "load" message.
+ void HandleLoadMessage(const base::ListValue* args);
+
+ // Callback for "pack" message.
+ void HandlePackMessage(const base::ListValue* args);
+
+ // Callback for "autoupdate" message.
+ void HandleAutoUpdateMessage(const base::ListValue* args);
+
+ // Utility for calling javascript window.alert in the page.
+ void ShowAlert(const std::string& message);
+
+ // Callback for "selectFilePath" message.
+ void HandleSelectFilePathMessage(const base::ListValue* args);
+
+ // Utility for callbacks that get an extension ID as the sole argument.
+ const Extension* GetExtension(const base::ListValue* args);
+
+ // Forces a UI update if appropriate after a notification is received.
+ void MaybeUpdateAfterNotification();
+
+ // Register for notifications that we need to reload the page.
+ void MaybeRegisterForNotifications();
+
+ // SelectFileDialog::Listener
+ virtual void FileSelected(const FilePath& path,
+ int index, void* params) OVERRIDE;
+ virtual void MultiFilesSelected(
+ const std::vector<FilePath>& files, void* params) OVERRIDE;
+ virtual void FileSelectionCanceled(void* params) OVERRIDE {}
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+ virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
+
+ // OptionsUIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // ExtensionUninstallDialog::Delegate implementation, used for receiving
+ // notification about uninstall confirmation dialog selections.
+ virtual void ExtensionUninstallAccepted() OVERRIDE;
+ virtual void ExtensionUninstallCanceled() OVERRIDE;
+
+ private:
+ // Helper that lists the current active html pages for an extension.
+ std::vector<ExtensionPage> GetActivePagesForExtension(
+ const Extension* extension);
+ void GetActivePagesForExtensionProcess(
+ const std::set<RenderViewHost*>& views,
+ std::vector<ExtensionPage> *result);
+
+ // Returns the ExtensionUninstallDialog object for this class, creating it if
+ // needed.
+ ExtensionUninstallDialog* GetExtensionUninstallDialog();
+
+ // Our model. Outlives us since it's owned by our containing profile.
+ ExtensionService* extension_service_;
+
+ // Used to pick the directory when loading an extension.
+ scoped_refptr<SelectFileDialog> load_extension_dialog_;
+
+ // Used to show confirmation UI for uninstalling extensions in incognito mode.
+ scoped_ptr<ExtensionUninstallDialog> extension_uninstall_dialog_;
+
+ // The id of the extension we are prompting the user about.
+ std::string extension_id_prompting_;
+
+ // If true, we will ignore notifications in ::Observe(). This is needed
+ // to prevent reloading the page when we were the cause of the
+ // notification.
+ bool ignore_notifications_;
+
+ // The page may be refreshed in response to a RENDER_VIEW_HOST_DELETED,
+ // but the iteration over RenderViewHosts will include the host because the
+ // notification is sent when it is in the process of being deleted (and before
+ // it is removed from the process). Keep a pointer to it so we can exclude
+ // it from the active views.
+ RenderViewHost* deleting_rvh_;
+
+ // We want to register for notifications only after we've responded at least
+ // once to the page, otherwise we'd be calling javacsript functions on objects
+ // that don't exist yet when notifications come in. This variable makes sure
+ // we do so only once.
+ bool registered_for_notifications_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionSettingsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_EXTENSION_SETTINGS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/font_settings_browsertest.js b/chrome/browser/ui/webui/options2/font_settings_browsertest.js
new file mode 100644
index 0000000..9800b41
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for font settings WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function FontSettingsWebUITest() {}
+
+FontSettingsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the font settings page.
+ **/
+ browsePreload: 'chrome://settings/fonts',
+};
+
+// Test opening font settings has correct location.
+TEST_F('FontSettingsWebUITest', 'testOpenFontSettings', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/font_settings_handler.cc b/chrome/browser/ui/webui/options2/font_settings_handler.cc
new file mode 100644
index 0000000..2ffef10b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_handler.cc
@@ -0,0 +1,211 @@
+// 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/options2/font_settings_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/i18n/rtl.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/options2/font_settings_utils.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_details.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+FontSettingsHandler::FontSettingsHandler() {
+}
+
+FontSettingsHandler::~FontSettingsHandler() {
+}
+
+void FontSettingsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "fontSettingsStandard",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_STANDARD_LABEL },
+ { "fontSettingsSerif",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SERIF_LABEL },
+ { "fontSettingsSansSerif",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL },
+ { "fontSettingsFixedWidth",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL },
+ { "fontSettingsMinimumSize",
+ IDS_FONT_LANGUAGE_SETTING_MINIMUM_FONT_SIZE_TITLE },
+ { "fontSettingsEncoding",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE },
+ { "fontSettingsSizeTiny",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_TINY },
+ { "fontSettingsSizeHuge",
+ IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_HUGE },
+ { "fontSettingsLoremIpsum",
+ IDS_FONT_LANGUAGE_SETTING_LOREM_IPSUM },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "fontSettingsPage",
+ IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE);
+ localized_strings->SetString("fontSettingsPlaceholder",
+ l10n_util::GetStringUTF16(
+ IDS_FONT_LANGUAGE_SETTING_PLACEHOLDER));
+}
+
+void FontSettingsHandler::Initialize() {
+ DCHECK(web_ui_);
+ SetUpStandardFontSample();
+ SetUpSerifFontSample();
+ SetUpSansSerifFontSample();
+ SetUpFixedFontSample();
+ SetUpMinimumFontSample();
+}
+
+WebUIMessageHandler* FontSettingsHandler::Attach(WebUI* web_ui) {
+ // Call through to superclass.
+ WebUIMessageHandler* handler = OptionsPage2UIHandler::Attach(web_ui);
+
+ // Perform validation for saved fonts.
+ DCHECK(web_ui_);
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ FontSettingsUtilities::ValidateSavedFonts(pref_service);
+
+ // Register for preferences that we need to observe manually.
+ standard_font_.Init(prefs::kWebKitStandardFontFamily, pref_service, this);
+ serif_font_.Init(prefs::kWebKitSerifFontFamily, pref_service, this);
+ sans_serif_font_.Init(prefs::kWebKitSansSerifFontFamily, pref_service, this);
+ fixed_font_.Init(prefs::kWebKitFixedFontFamily, pref_service, this);
+ font_encoding_.Init(prefs::kDefaultCharset, pref_service, this);
+ default_font_size_.Init(prefs::kWebKitDefaultFontSize, pref_service, this);
+ default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize,
+ pref_service, this);
+ minimum_font_size_.Init(prefs::kWebKitMinimumFontSize, pref_service, this);
+
+ // Return result from the superclass.
+ return handler;
+}
+
+void FontSettingsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("fetchFontsData",
+ base::Bind(&FontSettingsHandler::HandleFetchFontsData,
+ base::Unretained(this)));
+}
+
+void FontSettingsHandler::HandleFetchFontsData(const ListValue* args) {
+ content::GetFontListAsync(
+ base::Bind(&FontSettingsHandler::FontsListHasLoaded,
+ base::Unretained(this)));
+}
+
+void FontSettingsHandler::FontsListHasLoaded(
+ scoped_refptr<content::FontListResult> list) {
+ ListValue encoding_list;
+ const std::vector<CharacterEncoding::EncodingInfo>* encodings;
+ PrefService* pref_service = Profile::FromWebUI(web_ui_)->GetPrefs();
+ encodings = CharacterEncoding::GetCurrentDisplayEncodings(
+ g_browser_process->GetApplicationLocale(),
+ pref_service->GetString(prefs::kStaticEncodings),
+ pref_service->GetString(prefs::kRecentlySelectedEncoding));
+ DCHECK(encodings);
+ DCHECK(!encodings->empty());
+
+ std::vector<CharacterEncoding::EncodingInfo>::const_iterator it;
+ for (it = encodings->begin(); it != encodings->end(); ++it) {
+ ListValue* option = new ListValue();
+ if (it->encoding_id) {
+ int cmd_id = it->encoding_id;
+ std::string encoding =
+ CharacterEncoding::GetCanonicalEncodingNameByCommandId(cmd_id);
+ string16 name = it->encoding_display_name;
+ base::i18n::AdjustStringForLocaleDirection(&name);
+ option->Append(Value::CreateStringValue(encoding));
+ option->Append(Value::CreateStringValue(name));
+ } else {
+ // Add empty name/value to indicate a separator item.
+ option->Append(Value::CreateStringValue(""));
+ option->Append(Value::CreateStringValue(""));
+ }
+ encoding_list.Append(option);
+ }
+
+ ListValue selected_values;
+ selected_values.Append(Value::CreateStringValue(standard_font_.GetValue()));
+ selected_values.Append(Value::CreateStringValue(serif_font_.GetValue()));
+ selected_values.Append(Value::CreateStringValue(sans_serif_font_.GetValue()));
+ selected_values.Append(Value::CreateStringValue(fixed_font_.GetValue()));
+ selected_values.Append(Value::CreateStringValue(font_encoding_.GetValue()));
+
+ web_ui_->CallJavascriptFunction("FontSettings.setFontsData",
+ *list->list.get(), encoding_list,
+ selected_values);
+}
+
+void FontSettingsHandler::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ std::string* pref_name = content::Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kWebKitStandardFontFamily) {
+ SetUpStandardFontSample();
+ } else if (*pref_name == prefs::kWebKitSerifFontFamily) {
+ SetUpSerifFontSample();
+ } else if (*pref_name == prefs::kWebKitSansSerifFontFamily) {
+ SetUpSansSerifFontSample();
+ } else if (*pref_name == prefs::kWebKitFixedFontFamily ||
+ *pref_name == prefs::kWebKitDefaultFixedFontSize) {
+ SetUpFixedFontSample();
+ } else if (*pref_name == prefs::kWebKitDefaultFontSize) {
+ SetUpStandardFontSample();
+ SetUpSerifFontSample();
+ SetUpSansSerifFontSample();
+ } else if (*pref_name == prefs::kWebKitMinimumFontSize) {
+ SetUpMinimumFontSample();
+ }
+ }
+}
+
+void FontSettingsHandler::SetUpStandardFontSample() {
+ base::StringValue font_value(standard_font_.GetValue());
+ base::FundamentalValue size_value(default_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "FontSettings.setUpStandardFontSample", font_value, size_value);
+}
+
+void FontSettingsHandler::SetUpSerifFontSample() {
+ base::StringValue font_value(serif_font_.GetValue());
+ base::FundamentalValue size_value(default_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "FontSettings.setUpSerifFontSample", font_value, size_value);
+}
+
+void FontSettingsHandler::SetUpSansSerifFontSample() {
+ base::StringValue font_value(sans_serif_font_.GetValue());
+ base::FundamentalValue size_value(default_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "FontSettings.setUpSansSerifFontSample", font_value, size_value);
+}
+
+void FontSettingsHandler::SetUpFixedFontSample() {
+ base::StringValue font_value(fixed_font_.GetValue());
+ base::FundamentalValue size_value(default_fixed_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction(
+ "FontSettings.setUpFixedFontSample", font_value, size_value);
+}
+
+void FontSettingsHandler::SetUpMinimumFontSample() {
+ base::FundamentalValue size_value(minimum_font_size_.GetValue());
+ web_ui_->CallJavascriptFunction("FontSettings.setUpMinimumFontSample",
+ size_value);
+}
diff --git a/chrome/browser/ui/webui/options2/font_settings_handler.h b/chrome/browser/ui/webui/options2/font_settings_handler.h
new file mode 100644
index 0000000..ff45f47
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_handler.h
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "content/browser/font_list_async.h"
+
+// Font settings overlay page UI handler.
+class FontSettingsHandler : public OptionsPage2UIHandler {
+ public:
+ FontSettingsHandler();
+ virtual ~FontSettingsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ void HandleFetchFontsData(const ListValue* args);
+
+ void FontsListHasLoaded(scoped_refptr<content::FontListResult> list);
+
+ void SetUpStandardFontSample();
+ void SetUpSerifFontSample();
+ void SetUpSansSerifFontSample();
+ void SetUpFixedFontSample();
+ void SetUpMinimumFontSample();
+
+ StringPrefMember standard_font_;
+ StringPrefMember serif_font_;
+ StringPrefMember sans_serif_font_;
+ StringPrefMember fixed_font_;
+ StringPrefMember font_encoding_;
+ IntegerPrefMember default_font_size_;
+ IntegerPrefMember default_fixed_font_size_;
+ IntegerPrefMember minimum_font_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontSettingsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/font_settings_utils.h b/chrome/browser/ui/webui/options2/font_settings_utils.h
new file mode 100644
index 0000000..9fb435c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_utils.h
@@ -0,0 +1,22 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_UTILS_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_UTILS_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+class PrefService;
+
+// Chrome advanced options utility methods.
+class FontSettingsUtilities {
+ public:
+ static void ValidateSavedFonts(PrefService* prefs);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FontSettingsUtilities);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_FONT_SETTINGS_UTILS_H_
diff --git a/chrome/browser/ui/webui/options2/font_settings_utils_mac.mm b/chrome/browser/ui/webui/options2/font_settings_utils_mac.mm
new file mode 100644
index 0000000..0d26d83
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_utils_mac.mm
@@ -0,0 +1,38 @@
+// 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/options2/font_settings_utils.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/sys_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+
+static void ValidateFontFamily(PrefService* prefs,
+ const char* family_pref_name) {
+ // The native font settings dialog saved fonts by the font name, rather
+ // than the family name. This worked for the old dialog since
+ // -[NSFont fontWithName:size] accepted a font or family name, but the
+ // behavior was technically wrong. Since we really need the family name for
+ // the dom-ui options window, we will fix the saved preference if necessary.
+ NSString *family_name =
+ base::SysUTF8ToNSString(prefs->GetString(family_pref_name));
+ NSFont *font = [NSFont fontWithName:family_name
+ size:[NSFont systemFontSize]];
+ if (font &&
+ [[font familyName] caseInsensitiveCompare:family_name] != NSOrderedSame) {
+ std::string new_family_name = base::SysNSStringToUTF8([font familyName]);
+ prefs->SetString(family_pref_name, new_family_name);
+ }
+}
+
+// static
+void FontSettingsUtilities::ValidateSavedFonts(PrefService* prefs) {
+ ValidateFontFamily(prefs, prefs::kWebKitSerifFontFamily);
+ ValidateFontFamily(prefs, prefs::kWebKitSansSerifFontFamily);
+ ValidateFontFamily(prefs, prefs::kWebKitFixedFontFamily);
+}
diff --git a/chrome/browser/ui/webui/options2/font_settings_utils_win.cc b/chrome/browser/ui/webui/options2/font_settings_utils_win.cc
new file mode 100644
index 0000000..3c5ff5e
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_utils_win.cc
@@ -0,0 +1,11 @@
+// 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/options2/font_settings_utils.h"
+
+// static
+void FontSettingsUtilities::ValidateSavedFonts(PrefService* prefs) {
+ // Nothing to do for Windows.
+}
+
diff --git a/chrome/browser/ui/webui/options2/font_settings_utils_x11.cc b/chrome/browser/ui/webui/options2/font_settings_utils_x11.cc
new file mode 100644
index 0000000..61c2c6e
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/font_settings_utils_x11.cc
@@ -0,0 +1,10 @@
+// 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/options2/font_settings_utils.h"
+
+// static
+void FontSettingsUtilities::ValidateSavedFonts(PrefService* prefs) {
+ // Nothing to do for X11.
+}
diff --git a/chrome/browser/ui/webui/options2/handler_options_handler.cc b/chrome/browser/ui/webui/options2/handler_options_handler.cc
new file mode 100644
index 0000000..4c4c30f
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/handler_options_handler.cc
@@ -0,0 +1,207 @@
+// 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/options2/handler_options_handler.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+
+HandlerOptionsHandler::HandlerOptionsHandler() {
+}
+
+HandlerOptionsHandler::~HandlerOptionsHandler() {
+}
+
+void HandlerOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "handlers_tab_label", IDS_HANDLERS_TAB_LABEL },
+ { "handlers_allow", IDS_HANDLERS_ALLOW_RADIO },
+ { "handlers_block", IDS_HANDLERS_DONOTALLOW_RADIO },
+ { "handlers_type_column_header", IDS_HANDLERS_TYPE_COLUMN_HEADER },
+ { "handlers_site_column_header", IDS_HANDLERS_SITE_COLUMN_HEADER },
+ { "handlers_remove_link", IDS_HANDLERS_REMOVE_HANDLER_LINK },
+ { "handlers_none_handler", IDS_HANDLERS_NONE_HANDLER },
+ { "handlers_active_heading", IDS_HANDLERS_ACTIVE_HEADING },
+ { "handlers_ignored_heading", IDS_HANDLERS_IGNORED_HEADING },
+ };
+ RegisterTitle(localized_strings, "handlersPage",
+ IDS_HANDLER_OPTIONS_WINDOW_TITLE);
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+}
+
+void HandlerOptionsHandler::Initialize() {
+ UpdateHandlerList();
+ notification_registrar_.Add(
+ this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
+ content::Source<Profile>(Profile::FromWebUI(web_ui_)));
+}
+
+void HandlerOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("clearDefault",
+ base::Bind(&HandlerOptionsHandler::ClearDefault,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeHandler",
+ base::Bind(&HandlerOptionsHandler::RemoveHandler,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setHandlersEnabled",
+ base::Bind(&HandlerOptionsHandler::SetHandlersEnabled,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("setDefault",
+ base::Bind(&HandlerOptionsHandler::SetDefault,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeIgnoredHandler",
+ base::Bind(&HandlerOptionsHandler::RemoveIgnoredHandler,
+ base::Unretained(this)));
+}
+
+ProtocolHandlerRegistry* HandlerOptionsHandler::GetProtocolHandlerRegistry() {
+ DCHECK(web_ui_);
+ return Profile::FromWebUI(web_ui_)->GetProtocolHandlerRegistry();
+}
+
+static void GetHandlersAsListValue(
+ const ProtocolHandlerRegistry::ProtocolHandlerList& handlers,
+ ListValue* handler_list) {
+ ProtocolHandlerRegistry::ProtocolHandlerList::const_iterator handler;
+ for (handler = handlers.begin(); handler != handlers.end(); ++handler) {
+ ListValue* handlerValue = new ListValue();
+ handlerValue->Append(Value::CreateStringValue(handler->protocol()));
+ handlerValue->Append(Value::CreateStringValue(handler->url().spec()));
+ handlerValue->Append(Value::CreateStringValue(handler->title()));
+ handler_list->Append(handlerValue);
+ }
+}
+
+void HandlerOptionsHandler::GetHandlersForProtocol(
+ const std::string& protocol,
+ DictionaryValue* handlers_value) {
+ ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+ handlers_value->SetString("protocol", protocol);
+ handlers_value->SetInteger("default_handler",
+ registry->GetHandlerIndex(protocol));
+
+ ListValue* handlers_list = new ListValue();
+ GetHandlersAsListValue(registry->GetHandlersFor(protocol), handlers_list);
+ handlers_value->Set("handlers", handlers_list);
+}
+
+void HandlerOptionsHandler::GetIgnoredHandlers(ListValue* handlers) {
+ ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+ ProtocolHandlerRegistry::ProtocolHandlerList ignored_handlers =
+ registry->GetIgnoredHandlers();
+ return GetHandlersAsListValue(ignored_handlers, handlers);
+}
+
+void HandlerOptionsHandler::UpdateHandlerList() {
+#if defined(ENABLE_REGISTER_PROTOCOL_HANDLER)
+ ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+ std::vector<std::string> protocols;
+ registry->GetRegisteredProtocols(&protocols);
+
+ ListValue handlers;
+ for (std::vector<std::string>::iterator protocol = protocols.begin();
+ protocol != protocols.end(); protocol++) {
+ DictionaryValue* handler_value = new DictionaryValue();
+ GetHandlersForProtocol(*protocol, handler_value);
+ handlers.Append(handler_value);
+ }
+
+ scoped_ptr<ListValue> ignored_handlers(new ListValue());
+ GetIgnoredHandlers(ignored_handlers.get());
+ web_ui_->CallJavascriptFunction("HandlerOptions.setHandlers", handlers);
+ web_ui_->CallJavascriptFunction("HandlerOptions.setIgnoredHandlers",
+ *ignored_handlers);
+#endif // defined(ENABLE_REGISTER_PROTOCOL_HANDLER)
+}
+
+void HandlerOptionsHandler::RemoveHandler(const ListValue* args) {
+ ListValue* list;
+ if (!args->GetList(0, &list)) {
+ NOTREACHED();
+ return;
+ }
+
+ ProtocolHandler handler(ParseHandlerFromArgs(list));
+ GetProtocolHandlerRegistry()->RemoveHandler(handler);
+
+ // No need to call UpdateHandlerList() - we should receive a notification
+ // that the ProtocolHandlerRegistry has changed and we will update the view
+ // then.
+}
+
+void HandlerOptionsHandler::RemoveIgnoredHandler(const ListValue* args) {
+ ListValue* list;
+ if (!args->GetList(0, &list)) {
+ NOTREACHED();
+ return;
+ }
+
+ ProtocolHandler handler(ParseHandlerFromArgs(list));
+ GetProtocolHandlerRegistry()->RemoveIgnoredHandler(handler);
+}
+
+void HandlerOptionsHandler::SetHandlersEnabled(const ListValue* args) {
+ bool enabled = true;
+ CHECK(args->GetBoolean(0, &enabled));
+ if (enabled)
+ GetProtocolHandlerRegistry()->Enable();
+ else
+ GetProtocolHandlerRegistry()->Disable();
+}
+
+void HandlerOptionsHandler::ClearDefault(const ListValue* args) {
+ Value* value;
+ CHECK(args->Get(0, &value));
+ std::string protocol_to_clear;
+ CHECK(value->GetAsString(&protocol_to_clear));
+ GetProtocolHandlerRegistry()->ClearDefault(protocol_to_clear);
+}
+
+void HandlerOptionsHandler::SetDefault(const ListValue* args) {
+ Value* value;
+ CHECK(args->Get(0, &value));
+ ListValue* list;
+ CHECK(args->GetList(0, &list));
+ const ProtocolHandler& handler(ParseHandlerFromArgs(list));
+ CHECK(!handler.IsEmpty());
+ GetProtocolHandlerRegistry()->OnAcceptRegisterProtocolHandler(handler);
+}
+
+ProtocolHandler HandlerOptionsHandler::ParseHandlerFromArgs(
+ const ListValue* args) const {
+ string16 protocol;
+ string16 url;
+ string16 title;
+ bool ok = args->GetString(0, &protocol) && args->GetString(1, &url) &&
+ args->GetString(2, &title);
+ if (!ok)
+ return ProtocolHandler::EmptyProtocolHandler();
+ return ProtocolHandler::CreateProtocolHandler(UTF16ToUTF8(protocol),
+ GURL(UTF16ToUTF8(url)),
+ title);
+}
+
+void HandlerOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED)
+ UpdateHandlerList();
+ else
+ NOTREACHED();
+}
diff --git a/chrome/browser/ui/webui/options2/handler_options_handler.h b/chrome/browser/ui/webui/options2/handler_options_handler.h
new file mode 100644
index 0000000..87f9149
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/handler_options_handler.h
@@ -0,0 +1,76 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_HANDLER_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_HANDLER_OPTIONS_HANDLER_H_
+
+#include <string>
+
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "chrome/common/custom_handlers/protocol_handler.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+class HandlerOptionsHandler : public OptionsPage2UIHandler {
+ public:
+ HandlerOptionsHandler();
+ virtual ~HandlerOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // Called when the user toggles whether custom handlers are enabled.
+ void SetHandlersEnabled(const ListValue* args);
+
+ // Called when the user sets a new default handler for a protocol.
+ void SetDefault(const ListValue* args);
+
+ // Called when the user clears the default handler for a protocol.
+ // |args| is the string name of the protocol to clear.
+ void ClearDefault(const ListValue* args);
+
+ // Parses a ProtocolHandler out of the arguments passed back from the view.
+ // |args| is a list of [protocol, url, title].
+ ProtocolHandler ParseHandlerFromArgs(const ListValue* args) const;
+
+ // Returns a JSON object describing the set of protocol handlers for the
+ // given protocol.
+ void GetHandlersForProtocol(const std::string& protocol,
+ base::DictionaryValue* value);
+
+ // Returns a JSON list of the ignored protocol handlers.
+ void GetIgnoredHandlers(ListValue* handlers);
+
+ // Called when the JS PasswordManager object is initialized.
+ void UpdateHandlerList();
+
+ // Remove a handler.
+ // |args| is a list of [protocol, url, title].
+ void RemoveHandler(const ListValue* args);
+
+ // Remove an ignored handler.
+ // |args| is a list of [protocol, url, title].
+ void RemoveIgnoredHandler(const ListValue* args);
+
+ ProtocolHandlerRegistry* GetProtocolHandlerRegistry();
+
+ content::NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandlerOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_HANDLER_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/import_data_handler.cc b/chrome/browser/ui/webui/options2/import_data_handler.cc
new file mode 100644
index 0000000..76e5b83
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/import_data_handler.cc
@@ -0,0 +1,177 @@
+// 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/options2/import_data_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/importer/external_process_importer_host.h"
+#include "chrome/browser/importer/importer_host.h"
+#include "chrome/browser/importer/importer_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ImportDataHandler::ImportDataHandler() : importer_host_(NULL),
+ import_did_succeed_(false) {
+}
+
+ImportDataHandler::~ImportDataHandler() {
+ if (importer_list_)
+ importer_list_->SetObserver(NULL);
+
+ if (importer_host_)
+ importer_host_->SetObserver(NULL);
+}
+
+void ImportDataHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "importFromLabel", IDS_IMPORT_FROM_LABEL },
+ { "importLoading", IDS_IMPORT_LOADING_PROFILES },
+ { "importDescription", IDS_IMPORT_ITEMS_LABEL },
+ { "importHistory", IDS_IMPORT_HISTORY_CHKBOX },
+ { "importFavorites", IDS_IMPORT_FAVORITES_CHKBOX },
+ { "importSearch", IDS_IMPORT_SEARCH_ENGINES_CHKBOX },
+ { "importPasswords", IDS_IMPORT_PASSWORDS_CHKBOX },
+ { "importCommit", IDS_IMPORT_COMMIT },
+ { "noProfileFound", IDS_IMPORT_NO_PROFILE_FOUND },
+ { "importSucceeded", IDS_IMPORT_SUCCEEDED },
+ { "findYourImportedBookmarks", IDS_IMPORT_FIND_YOUR_BOOKMARKS },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "importDataOverlay",
+ IDS_IMPORT_SETTINGS_TITLE);
+}
+
+void ImportDataHandler::Initialize() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ importer_list_ = new ImporterList(profile->GetRequestContext());
+ importer_list_->DetectSourceProfiles(this);
+}
+
+void ImportDataHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("importData",
+ base::Bind(&ImportDataHandler::ImportData, base::Unretained(this)));
+}
+
+void ImportDataHandler::ImportData(const ListValue* args) {
+ std::string string_value;
+
+ int browser_index;
+ if (!args->GetString(0, &string_value) ||
+ !base::StringToInt(string_value, &browser_index)) {
+ NOTREACHED();
+ return;
+ }
+
+ uint16 selected_items = importer::NONE;
+ if (args->GetString(1, &string_value) && string_value == "true") {
+ selected_items |= importer::HISTORY;
+ }
+ if (args->GetString(2, &string_value) && string_value == "true") {
+ selected_items |= importer::FAVORITES;
+ }
+ if (args->GetString(3, &string_value) && string_value == "true") {
+ selected_items |= importer::PASSWORDS;
+ }
+ if (args->GetString(4, &string_value) && string_value == "true") {
+ selected_items |= importer::SEARCH_ENGINES;
+ }
+
+ const importer::SourceProfile& source_profile =
+ importer_list_->GetSourceProfileAt(browser_index);
+ uint16 supported_items = source_profile.services_supported;
+
+ uint16 import_services = (selected_items & supported_items);
+ if (import_services) {
+ base::FundamentalValue state(true);
+ web_ui_->CallJavascriptFunction("ImportDataOverlay.setImportingState",
+ state);
+ import_did_succeed_ = false;
+
+ // TODO(csilv): Out-of-process import has only been qualified on MacOS X,
+ // so we will only use it on that platform since it is required. Remove this
+ // conditional logic once oop import is qualified for Linux/Windows.
+ // http://crbug.com/22142
+#if defined(OS_MACOSX)
+ importer_host_ = new ExternalProcessImporterHost;
+#else
+ importer_host_ = new ImporterHost;
+#endif
+ importer_host_->SetObserver(this);
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ importer_host_->StartImportSettings(source_profile, profile,
+ import_services,
+ new ProfileWriter(profile), false);
+ } else {
+ LOG(WARNING) << "There were no settings to import from '"
+ << source_profile.importer_name << "'.";
+ }
+}
+
+void ImportDataHandler::OnSourceProfilesLoaded() {
+ ListValue browser_profiles;
+ for (size_t i = 0; i < importer_list_->count(); ++i) {
+ const importer::SourceProfile& source_profile =
+ importer_list_->GetSourceProfileAt(i);
+ uint16 browser_services = source_profile.services_supported;
+
+ DictionaryValue* browser_profile = new DictionaryValue();
+ browser_profile->SetString("name", source_profile.importer_name);
+ browser_profile->SetInteger("index", i);
+ browser_profile->SetBoolean("history",
+ (browser_services & importer::HISTORY) != 0);
+ browser_profile->SetBoolean("favorites",
+ (browser_services & importer::FAVORITES) != 0);
+ browser_profile->SetBoolean("passwords",
+ (browser_services & importer::PASSWORDS) != 0);
+ browser_profile->SetBoolean("search",
+ (browser_services & importer::SEARCH_ENGINES) != 0);
+
+ browser_profiles.Append(browser_profile);
+ }
+
+ web_ui_->CallJavascriptFunction("ImportDataOverlay.updateSupportedBrowsers",
+ browser_profiles);
+}
+
+void ImportDataHandler::ImportStarted() {
+}
+
+void ImportDataHandler::ImportItemStarted(importer::ImportItem item) {
+ // TODO(csilv): show progress detail in the web view.
+}
+
+void ImportDataHandler::ImportItemEnded(importer::ImportItem item) {
+ // TODO(csilv): show progress detail in the web view.
+ import_did_succeed_ = true;
+}
+
+void ImportDataHandler::ImportEnded() {
+ importer_host_->SetObserver(NULL);
+ importer_host_ = NULL;
+
+ if (import_did_succeed_) {
+ web_ui_->CallJavascriptFunction("ImportDataOverlay.confirmSuccess");
+ } else {
+ base::FundamentalValue state(false);
+ web_ui_->CallJavascriptFunction("ImportDataOverlay.setImportingState",
+ state);
+ web_ui_->CallJavascriptFunction("ImportDataOverlay.dismiss");
+ }
+}
diff --git a/chrome/browser/ui/webui/options2/import_data_handler.h b/chrome/browser/ui/webui/options2/import_data_handler.h
new file mode 100644
index 0000000..da6b82c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/import_data_handler.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_IMPORT_DATA_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_IMPORT_DATA_HANDLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/importer/importer_data_types.h"
+#include "chrome/browser/importer/importer_list_observer.h"
+#include "chrome/browser/importer/importer_progress_observer.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+class ImporterHost;
+class ImporterList;
+
+// Chrome personal stuff import data overlay UI handler.
+class ImportDataHandler : public OptionsPage2UIHandler,
+ public importer::ImporterListObserver,
+ public importer::ImporterProgressObserver {
+ public:
+ ImportDataHandler();
+ virtual ~ImportDataHandler();
+
+ // OptionsPage2UIHandler:
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler:
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ void ImportData(const base::ListValue* args);
+
+ // importer::ImporterListObserver:
+ virtual void OnSourceProfilesLoaded() OVERRIDE;
+
+ // importer::ImporterProgressObserver:
+ virtual void ImportStarted() OVERRIDE;
+ virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE;
+ virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE;
+ virtual void ImportEnded() OVERRIDE;
+
+ scoped_refptr<ImporterList> importer_list_;
+
+ // If non-null it means importing is in progress. ImporterHost takes care
+ // of deleting itself when import is complete.
+ ImporterHost* importer_host_; // weak
+
+ bool import_did_succeed_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImportDataHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_IMPORT_DATA_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/language_options_browsertest.js b/chrome/browser/ui/webui/options2/language_options_browsertest.js
new file mode 100644
index 0000000..4f1b87c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for languages options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function LanguagesOptionsWebUITest() {}
+
+LanguagesOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to languages options.
+ **/
+ browsePreload: 'chrome://settings/languages',
+};
+
+// Test opening languages options has correct location.
+TEST_F('LanguagesOptionsWebUITest', 'testOpenLanguagesOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/language_options_handler.cc b/chrome/browser/ui/webui/options2/language_options_handler.cc
new file mode 100644
index 0000000..c521b2c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_handler.cc
@@ -0,0 +1,116 @@
+// 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/options2/language_options_handler.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/i18n/rtl.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "content/browser/user_metrics.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+LanguageOptionsHandler::LanguageOptionsHandler() {
+}
+
+LanguageOptionsHandler::~LanguageOptionsHandler() {
+}
+
+void LanguageOptionsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ LanguageOptionsHandlerCommon::GetLocalizedValues(localized_strings);
+
+ RegisterTitle(localized_strings, "languagePage",
+ IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE);
+ localized_strings->SetString("restart_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON));
+ localized_strings->Set("languageList", GetLanguageList());
+}
+
+void LanguageOptionsHandler::RegisterMessages() {
+ LanguageOptionsHandlerCommon::RegisterMessages();
+
+ web_ui_->RegisterMessageCallback("uiLanguageRestart",
+ base::Bind(&LanguageOptionsHandler::RestartCallback,
+ base::Unretained(this)));
+}
+
+ListValue* LanguageOptionsHandler::GetLanguageList() {
+ // Collect the language codes from the supported accept-languages.
+ const std::string app_locale = g_browser_process->GetApplicationLocale();
+ std::vector<std::string> language_codes;
+ l10n_util::GetAcceptLanguagesForLocale(app_locale, &language_codes);
+
+ // Map of display name -> {language code, native_display_name}.
+ // In theory, we should be able to create a map that is sorted by
+ // display names using ICU comparator, but doing it is hard, thus we'll
+ // use an auxiliary vector to achieve the same result.
+ typedef std::pair<std::string, string16> LanguagePair;
+ typedef std::map<string16, LanguagePair> LanguageMap;
+ LanguageMap language_map;
+ // The auxiliary vector mentioned above.
+ std::vector<string16> display_names;
+
+ // Build the list of display names, and build the language map.
+ for (size_t i = 0; i < language_codes.size(); ++i) {
+ string16 display_name =
+ l10n_util::GetDisplayNameForLocale(language_codes[i], app_locale,
+ false);
+ base::i18n::AdjustStringForLocaleDirection(&display_name);
+ string16 native_display_name =
+ l10n_util::GetDisplayNameForLocale(language_codes[i], language_codes[i],
+ false);
+ base::i18n::AdjustStringForLocaleDirection(&native_display_name);
+ display_names.push_back(display_name);
+ language_map[display_name] =
+ std::make_pair(language_codes[i], native_display_name);
+ }
+ DCHECK_EQ(display_names.size(), language_map.size());
+
+ // Sort display names using locale specific sorter.
+ l10n_util::SortStrings16(app_locale, &display_names);
+
+ // Build the language list from the language map.
+ ListValue* language_list = new ListValue();
+ for (size_t i = 0; i < display_names.size(); ++i) {
+ const LanguagePair& pair = language_map[display_names[i]];
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("code", pair.first);
+ dictionary->SetString("displayName", display_names[i]);
+ dictionary->SetString("nativeDisplayName", pair.second);
+ language_list->Append(dictionary);
+ }
+
+ return language_list;
+}
+
+string16 LanguageOptionsHandler::GetProductName() {
+ return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
+}
+
+void LanguageOptionsHandler::SetApplicationLocale(
+ const std::string& language_code) {
+ PrefService* pref_service = g_browser_process->local_state();
+ pref_service->SetString(prefs::kApplicationLocale, language_code);
+}
+
+void LanguageOptionsHandler::RestartCallback(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Restart"));
+ BrowserList::AttemptRestart();
+}
diff --git a/chrome/browser/ui/webui/options2/language_options_handler.h b/chrome/browser/ui/webui/options2/language_options_handler.h
new file mode 100644
index 0000000..1131b32
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_handler.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/ui/webui/options2/language_options_handler_common.h"
+
+// Language options UI page handler for non-Chrome OS platforms. For Chrome OS,
+// see chromeos::CrosLanguageOptionsHandler.
+class LanguageOptionsHandler : public LanguageOptionsHandlerCommon {
+ public:
+ LanguageOptionsHandler();
+ virtual ~LanguageOptionsHandler();
+
+ // OptionsPageUIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // The following static method is public for ease of testing.
+
+ // Gets the list of languages from the given input descriptors.
+ // The return value will look like:
+ // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
+ // ...]
+ static base::ListValue* GetLanguageList();
+
+ private:
+ // LanguageOptionsHandlerCommon implementation.
+ virtual string16 GetProductName() OVERRIDE;
+ virtual void SetApplicationLocale(const std::string& language_code) OVERRIDE;
+
+ // Called when the restart button is clicked.
+ void RestartCallback(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/language_options_handler_common.cc b/chrome/browser/ui/webui/options2/language_options_handler_common.cc
new file mode 100644
index 0000000..138db7c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_handler_common.cc
@@ -0,0 +1,163 @@
+// 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/options2/language_options_handler_common.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/spellcheck_common.h"
+#include "content/browser/user_metrics.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+LanguageOptionsHandlerCommon::LanguageOptionsHandlerCommon() {
+}
+
+LanguageOptionsHandlerCommon::~LanguageOptionsHandlerCommon() {
+}
+
+void LanguageOptionsHandlerCommon::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ string16 product_name = GetProductName();
+ localized_strings->SetString("add_button",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON));
+ localized_strings->SetString("languages",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES));
+ localized_strings->SetString("please_add_another_language",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_LANGUAGE));
+ localized_strings->SetString("remove_button",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON));
+ localized_strings->SetString("add_language_instructions",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS));
+ localized_strings->SetString("cannot_be_displayed_in_this_language",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
+ product_name));
+ localized_strings->SetString("is_displayed_in_this_language",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
+ product_name));
+ localized_strings->SetString("display_in_this_language",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
+ product_name));
+ localized_strings->SetString("this_language_is_currently_in_use",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_THIS_LANGUAGE_IS_CURRENTLY_IN_USE,
+ product_name));
+ localized_strings->SetString("use_this_for_spell_checking",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_USE_THIS_FOR_SPELL_CHECKING));
+ localized_strings->SetString("cannot_be_used_for_spell_checking",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_CANNOT_BE_USED_FOR_SPELL_CHECKING));
+ localized_strings->SetString("is_used_for_spell_checking",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_IS_USED_FOR_SPELL_CHECKING));
+ localized_strings->SetString("restart_required",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_RELAUNCH_REQUIRED));
+ localized_strings->SetString("enable_spell_check",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_SPELLCHECK));
+ localized_strings->SetString("enable_auto_spell_correction",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_ENABLE_AUTO_SPELL_CORRECTION));
+ localized_strings->SetString("add_language_title",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_LANGUAGES_ADD_TITLE));
+ localized_strings->SetString("add_language_select_label",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_LANGUAGES_ADD_SELECT_LABEL));
+ localized_strings->SetString("restart_button",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON));
+
+ // The following are resources, rather than local strings.
+ localized_strings->SetString("currentUiLanguageCode",
+ g_browser_process->GetApplicationLocale());
+ localized_strings->Set("spellCheckLanguageCodeSet",
+ GetSpellCheckLanguageCodeSet());
+ localized_strings->Set("uiLanguageCodeSet", GetUILanguageCodeSet());
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool experimental_spell_check_features =
+ command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures);
+ localized_strings->SetBoolean("experimentalSpellCheckFeatures",
+ experimental_spell_check_features);
+}
+
+void LanguageOptionsHandlerCommon::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("languageOptionsOpen",
+ base::Bind(
+ &LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("spellCheckLanguageChange",
+ base::Bind(
+ &LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("uiLanguageChange",
+ base::Bind(
+ &LanguageOptionsHandlerCommon::UiLanguageChangeCallback,
+ base::Unretained(this)));
+}
+
+DictionaryValue* LanguageOptionsHandlerCommon::GetUILanguageCodeSet() {
+ DictionaryValue* dictionary = new DictionaryValue();
+ const std::vector<std::string>& available_locales =
+ l10n_util::GetAvailableLocales();
+ for (size_t i = 0; i < available_locales.size(); ++i) {
+ dictionary->SetBoolean(available_locales[i], true);
+ }
+ return dictionary;
+}
+
+DictionaryValue* LanguageOptionsHandlerCommon::GetSpellCheckLanguageCodeSet() {
+ DictionaryValue* dictionary = new DictionaryValue();
+ std::vector<std::string> spell_check_languages;
+ SpellCheckCommon::SpellCheckLanguages(&spell_check_languages);
+ for (size_t i = 0; i < spell_check_languages.size(); ++i) {
+ dictionary->SetBoolean(spell_check_languages[i], true);
+ }
+ return dictionary;
+}
+
+void LanguageOptionsHandlerCommon::LanguageOptionsOpenCallback(
+ const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Open"));
+}
+
+void LanguageOptionsHandlerCommon::UiLanguageChangeCallback(
+ const ListValue* args) {
+ const std::string language_code = UTF16ToASCII(ExtractStringValue(args));
+ CHECK(!language_code.empty());
+ const std::string action = base::StringPrintf(
+ "LanguageOptions_UiLanguageChange_%s", language_code.c_str());
+ UserMetrics::RecordComputedAction(action);
+ SetApplicationLocale(language_code);
+ web_ui_->CallJavascriptFunction("options.LanguageOptions.uiLanguageSaved");
+}
+
+void LanguageOptionsHandlerCommon::SpellCheckLanguageChangeCallback(
+ const ListValue* args) {
+ const std::string language_code = UTF16ToASCII(ExtractStringValue(args));
+ CHECK(!language_code.empty());
+ const std::string action = base::StringPrintf(
+ "LanguageOptions_SpellCheckLanguageChange_%s", language_code.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
diff --git a/chrome/browser/ui/webui/options2/language_options_handler_common.h b/chrome/browser/ui/webui/options2/language_options_handler_common.h
new file mode 100644
index 0000000..88ba713
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_handler_common.h
@@ -0,0 +1,69 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
+#pragma once
+
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+// The base class for language options page UI handlers. This class has code
+// common to the Chrome OS and non-Chrome OS implementation of the handler.
+class LanguageOptionsHandlerCommon : public OptionsPage2UIHandler {
+ public:
+ LanguageOptionsHandlerCommon();
+ virtual ~LanguageOptionsHandlerCommon();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // DOMMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // The following static methods are public for ease of testing.
+
+ // Gets the set of language codes that can be used as UI language.
+ // The return value will look like:
+ // {'en-US': true, 'fi': true, 'fr': true, ...}
+ //
+ // Note that true in values does not mean anything. We just use the
+ // dictionary as a set.
+ static base::DictionaryValue* GetUILanguageCodeSet();
+
+ // Gets the set of language codes that can be used for spellchecking.
+ // The return value will look like:
+ // {'en-US': true, 'fi': true, 'fr': true, ...}
+ //
+ // Note that true in values does not mean anything. We just use the
+ // dictionary as a set.
+ static base::DictionaryValue* GetSpellCheckLanguageCodeSet();
+
+ private:
+ // Returns the name of the product (ex. "Chrome" or "Chrome OS").
+ virtual string16 GetProductName() = 0;
+
+ // Sets the application locale.
+ virtual void SetApplicationLocale(const std::string& language_code) = 0;
+
+ // Called when the language options is opened.
+ void LanguageOptionsOpenCallback(const base::ListValue* args);
+
+ // Called when the UI language is changed.
+ // |args| will contain the language code as string (ex. "fr").
+ void UiLanguageChangeCallback(const base::ListValue* args);
+
+ // Called when the spell check language is changed.
+ // |args| will contain the language code as string (ex. "fr").
+ void SpellCheckLanguageChangeCallback(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandlerCommon);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_LANGUAGE_OPTIONS_HANDLER_COMMON_H_
diff --git a/chrome/browser/ui/webui/options2/language_options_handler_unittest.cc b/chrome/browser/ui/webui/options2/language_options_handler_unittest.cc
new file mode 100644
index 0000000..c889818
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/language_options_handler_unittest.cc
@@ -0,0 +1,198 @@
+// 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/options2/language_options_handler.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/input_method/ibus_controller.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager.h"
+#include "chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h"
+#endif // defined(OS_CHROMEOS)
+
+#if defined(OS_CHROMEOS)
+
+using chromeos::input_method::IBusController;
+using chromeos::input_method::InputMethodDescriptor;
+using chromeos::input_method::InputMethodDescriptors;
+
+static InputMethodDescriptor GetDesc(IBusController* controller,
+ const std::string& id,
+ const std::string& raw_layout,
+ const std::string& language_code) {
+ return controller->CreateInputMethodDescriptor(id, "", raw_layout,
+ language_code);
+}
+
+static InputMethodDescriptors CreateInputMethodDescriptors() {
+ scoped_ptr<IBusController> controller(IBusController::Create());
+
+ InputMethodDescriptors descriptors;
+ descriptors.push_back(GetDesc(controller.get(), "xkb:us::eng", "us", "eng"));
+ descriptors.push_back(GetDesc(controller.get(), "xkb:fr::fra", "fr", "fra"));
+ descriptors.push_back(GetDesc(controller.get(), "xkb:be::fra", "be", "fr"));
+ descriptors.push_back(GetDesc(controller.get(), "mozc", "us", "ja"));
+ return descriptors;
+}
+
+TEST(LanguageOptionsHandlerTest, GetInputMethodList) {
+ InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
+ scoped_ptr<ListValue> list(
+ chromeos::CrosLanguageOptionsHandler::GetInputMethodList(descriptors));
+ ASSERT_EQ(4U, list->GetSize());
+
+ DictionaryValue* entry = NULL;
+ DictionaryValue *language_code_set = NULL;
+ std::string input_method_id;
+ std::string display_name;
+ std::string language_code;
+
+ // As shown below, the list should be input method ids should appear in
+ // the same order of the descriptors.
+ ASSERT_TRUE(list->GetDictionary(0, &entry));
+ ASSERT_TRUE(entry->GetString("id", &input_method_id));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+ EXPECT_EQ("xkb:us::eng", input_method_id);
+ // Commented out as it depends on translation in generated_resources.grd
+ // (i.e. makes the test fragile).
+ // EXPECT_EQ("English (USA) keyboard layout", display_name);
+ ASSERT_TRUE(language_code_set->HasKey("en-US"));
+ ASSERT_TRUE(language_code_set->HasKey("id")); // From kExtraLanguages.
+ ASSERT_TRUE(language_code_set->HasKey("fil")); // From kExtraLanguages.
+
+ ASSERT_TRUE(list->GetDictionary(1, &entry));
+ ASSERT_TRUE(entry->GetString("id", &input_method_id));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+ EXPECT_EQ("xkb:fr::fra", input_method_id);
+ // Commented out. See above.
+ // EXPECT_EQ("French keyboard layout", display_name);
+ ASSERT_TRUE(language_code_set->HasKey("fr"));
+
+ ASSERT_TRUE(list->GetDictionary(2, &entry));
+ ASSERT_TRUE(entry->GetString("id", &input_method_id));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+ EXPECT_EQ("xkb:be::fra", input_method_id);
+ // Commented out. See above.
+ // EXPECT_EQ("Belgian keyboard layout", display_name);
+ ASSERT_TRUE(language_code_set->HasKey("fr"));
+
+ ASSERT_TRUE(list->GetDictionary(3, &entry));
+ ASSERT_TRUE(entry->GetString("id", &input_method_id));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set));
+ EXPECT_EQ("mozc", input_method_id);
+ // Commented out. See above.
+ // EXPECT_EQ("Japanese input method (for US keyboard)", display_name);
+ ASSERT_TRUE(language_code_set->HasKey("ja"));
+}
+
+TEST(LanguageOptionsHandlerTest, GetLanguageList) {
+ InputMethodDescriptors descriptors = CreateInputMethodDescriptors();
+ scoped_ptr<ListValue> list(
+ chromeos::CrosLanguageOptionsHandler::GetLanguageList(descriptors));
+ ASSERT_EQ(8U, list->GetSize());
+
+ DictionaryValue* entry = NULL;
+ std::string language_code;
+ std::string display_name;
+ std::string native_display_name;
+
+ // As shown below, the list should be sorted by the display names,
+ // and these names should not have duplicates.
+
+ // This comes from kExtraLanguages.
+ ASSERT_TRUE(list->GetDictionary(0, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("nl", language_code);
+ EXPECT_EQ("Dutch", display_name);
+ EXPECT_EQ("Nederlands", native_display_name);
+
+ // This comes from kExtraLanguages.
+ ASSERT_TRUE(list->GetDictionary(1, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("en-AU", language_code);
+ EXPECT_EQ("English (Australia)", display_name);
+ EXPECT_EQ("English (Australia)", native_display_name);
+
+ ASSERT_TRUE(list->GetDictionary(2, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("en-US", language_code);
+ EXPECT_EQ("English (United States)", display_name);
+ EXPECT_EQ("English (United States)", native_display_name);
+
+ // This comes from kExtraLanguages.
+ ASSERT_TRUE(list->GetDictionary(3, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("fil", language_code);
+ EXPECT_EQ("Filipino", display_name);
+ EXPECT_EQ("Filipino", native_display_name);
+
+ ASSERT_TRUE(list->GetDictionary(4, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("fr", language_code);
+ EXPECT_EQ("French", display_name);
+ EXPECT_EQ("fran\u00E7ais", native_display_name);
+
+ // This comes from kExtraLanguages.
+ ASSERT_TRUE(list->GetDictionary(5, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("id", language_code);
+ EXPECT_EQ("Indonesian", display_name);
+ EXPECT_EQ("Bahasa Indonesia", native_display_name);
+
+ ASSERT_TRUE(list->GetDictionary(6, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("ja", language_code);
+ EXPECT_EQ("Japanese", display_name);
+ EXPECT_EQ("\u65E5\u672C\u8A9E", native_display_name);
+
+ // This comes from kExtraLanguages.
+ ASSERT_TRUE(list->GetDictionary(7, &entry));
+ ASSERT_TRUE(entry->GetString("code", &language_code));
+ ASSERT_TRUE(entry->GetString("displayName", &display_name));
+ ASSERT_TRUE(entry->GetString("nativeDisplayName", &native_display_name));
+ EXPECT_EQ("es-419", language_code);
+ EXPECT_EQ("Spanish (Latin America)", display_name);
+ EXPECT_EQ("espa\u00F1ol (Latinoam\u00E9rica)", native_display_name);
+}
+#endif // defined(OS_CHROMEOS)
+
+#if !defined(OS_MACOSX)
+TEST(LanguageOptionsHandlerTest, GetUILanguageCodeSet) {
+ scoped_ptr<DictionaryValue> dictionary(
+ LanguageOptionsHandler::GetUILanguageCodeSet());
+ EXPECT_TRUE(dictionary->HasKey("en-US"));
+ // Note that we don't test a false case, as such an expectation will
+ // fail when we add support for the language.
+ // EXPECT_FALSE(dictionary->HasKey("no"));
+}
+#endif // !defined(OS_MACOSX)
+
+TEST(LanguageOptionsHandlerTest, GetSpellCheckLanguageCodeSet) {
+ scoped_ptr<DictionaryValue> dictionary(
+ LanguageOptionsHandler::GetSpellCheckLanguageCodeSet());
+ EXPECT_TRUE(dictionary->HasKey("en-US"));
+}
diff --git a/chrome/browser/ui/webui/options2/manage_profile_handler.cc b/chrome/browser/ui/webui/options2/manage_profile_handler.cc
new file mode 100644
index 0000000..4c29788
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/manage_profile_handler.cc
@@ -0,0 +1,300 @@
+// 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/options2/manage_profile_handler.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/value_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/gaia_info_update_service.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/ui/webui/web_ui_util.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/public/browser/notification_service.h"
+#include "grit/generated_resources.h"
+
+ManageProfileHandler::ManageProfileHandler() {
+}
+
+ManageProfileHandler::~ManageProfileHandler() {
+}
+
+void ManageProfileHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "manageProfilesTitle", IDS_PROFILES_MANAGE_TITLE },
+ { "manageProfilesNameLabel", IDS_PROFILES_MANAGE_NAME_LABEL },
+ { "manageProfilesDuplicateNameError",
+ IDS_PROFILES_MANAGE_DUPLICATE_NAME_ERROR },
+ { "manageProfilesIconLabel", IDS_PROFILES_MANAGE_ICON_LABEL },
+ { "deleteProfileTitle", IDS_PROFILES_DELETE_TITLE },
+ { "deleteProfileOK", IDS_PROFILES_DELETE_OK_BUTTON_LABEL },
+ { "deleteProfileMessage", IDS_PROFILES_DELETE_MESSAGE },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+}
+
+void ManageProfileHandler::Initialize() {
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources());
+ SendProfileNames();
+}
+
+void ManageProfileHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("setProfileNameAndIcon",
+ base::Bind(&ManageProfileHandler::SetProfileNameAndIcon,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("deleteProfile",
+ base::Bind(&ManageProfileHandler::DeleteProfile,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("requestDefaultProfileIcons",
+ base::Bind(&ManageProfileHandler::RequestDefaultProfileIcons,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("requestProfileInfo",
+ base::Bind(&ManageProfileHandler::RequestProfileInfo,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("profileIconSelectionChanged",
+ base::Bind(&ManageProfileHandler::ProfileIconSelectionChanged,
+ base::Unretained(this)));
+}
+
+void ManageProfileHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED) {
+ SendProfileNames();
+ SendProfileIcons();
+ } else {
+ OptionsPage2UIHandler::Observe(type, source, details);
+ }
+}
+
+void ManageProfileHandler::RequestDefaultProfileIcons(const ListValue* args) {
+ SendProfileIcons();
+}
+
+void ManageProfileHandler::SendProfileIcons() {
+ ListValue image_url_list;
+
+ // First add the GAIA picture if it's available.
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ size_t profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath());
+ if (profile_index != std::string::npos) {
+ const gfx::Image* icon =
+ cache.GetGAIAPictureOfProfileAtIndex(profile_index);
+ if (icon) {
+ gfx::Image icon2 = profiles::GetAvatarIconForWebUI(*icon, true);
+ gaia_picture_url_ = web_ui_util::GetImageDataUrl(icon2);
+ image_url_list.Append(Value::CreateStringValue(gaia_picture_url_));
+ }
+ }
+
+ // Next add the default avatar icons.
+ for (size_t i = 0; i < ProfileInfoCache::GetDefaultAvatarIconCount(); i++) {
+ std::string url = ProfileInfoCache::GetDefaultAvatarIconUrl(i);
+ image_url_list.Append(Value::CreateStringValue(url));
+ }
+
+ web_ui_->CallJavascriptFunction(
+ "ManageProfileOverlay.receiveDefaultProfileIcons",
+ image_url_list);
+}
+
+void ManageProfileHandler::SendProfileNames() {
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ DictionaryValue profile_name_dict;
+ for (size_t i = 0, e = cache.GetNumberOfProfiles(); i < e; ++i)
+ profile_name_dict.SetBoolean(UTF16ToUTF8(cache.GetNameOfProfileAtIndex(i)),
+ true);
+
+ web_ui_->CallJavascriptFunction("ManageProfileOverlay.receiveProfileNames",
+ profile_name_dict);
+}
+
+void ManageProfileHandler::SetProfileNameAndIcon(const ListValue* args) {
+ DCHECK(args);
+
+ Value* file_path_value;
+ FilePath profile_file_path;
+ if (!args->Get(0, &file_path_value) ||
+ !base::GetValueAsFilePath(*file_path_value, &profile_file_path))
+ return;
+
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ size_t profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
+ if (profile_index == std::string::npos)
+ return;
+
+ string16 new_profile_name;
+ if (!args->GetString(1, &new_profile_name))
+ return;
+
+ if (new_profile_name == cache.GetGAIANameOfProfileAtIndex(profile_index)) {
+ // Set the profile to use the GAIA name as the profile name. Note, this
+ // is a little weird if the user typed their GAIA name manually but
+ // it's not a big deal.
+ cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, true);
+ // Using the GAIA name as the profile name can invalidate the profile index.
+ profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
+ if (profile_index == std::string::npos)
+ return;
+ } else {
+ cache.SetNameOfProfileAtIndex(profile_index, new_profile_name);
+ // Changing the profile name can invalidate the profile index.
+ profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
+ if (profile_index == std::string::npos)
+ return;
+
+ cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, false);
+ // Unsetting the GAIA name as the profile name can invalidate the profile
+ // index.
+ profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
+ if (profile_index == std::string::npos)
+ return;
+ }
+
+ std::string icon_url;
+ if (!args->GetString(2, &icon_url))
+ return;
+
+ // Metrics logging variable.
+ bool previously_using_gaia_icon =
+ cache.IsUsingGAIANameOfProfileAtIndex(profile_index);
+
+ size_t new_icon_index;
+ if (icon_url == gaia_picture_url_) {
+ cache.SetIsUsingGAIAPictureOfProfileAtIndex(profile_index, true);
+ if (!previously_using_gaia_icon) {
+ // Only log if they changed to the GAIA photo.
+ // Selection of GAIA photo as avatar is logged as part of the function
+ // below.
+ ProfileMetrics::LogProfileSwitchGaia(ProfileMetrics::GAIA_OPT_IN);
+ }
+ } else if (cache.IsDefaultAvatarIconUrl(icon_url, &new_icon_index)) {
+ ProfileMetrics::LogProfileAvatarSelection(new_icon_index);
+ cache.SetAvatarIconOfProfileAtIndex(profile_index, new_icon_index);
+ cache.SetIsUsingGAIAPictureOfProfileAtIndex(profile_index, false);
+ }
+
+ ProfileMetrics::LogProfileUpdate(profile_file_path);
+}
+
+void ManageProfileHandler::DeleteProfile(const ListValue* args) {
+ DCHECK(args);
+
+ ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED);
+
+ Value* file_path_value;
+ FilePath profile_file_path;
+ if (!args->Get(0, &file_path_value) ||
+ !base::GetValueAsFilePath(*file_path_value, &profile_file_path))
+ return;
+
+ g_browser_process->profile_manager()->ScheduleProfileForDeletion(
+ profile_file_path);
+}
+
+void ManageProfileHandler::RequestProfileInfo(const ListValue* args) {
+ DCHECK(args);
+
+ Value* index_value;
+ double index_double;
+ if (!args->Get(0, &index_value) || !index_value->GetAsDouble(&index_double))
+ return;
+
+ int index = static_cast<int>(index_double);
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ int profile_count = cache.GetNumberOfProfiles();
+ if (index < 0 && index >= profile_count)
+ return;
+
+ FilePath profile_path = cache.GetPathOfProfileAtIndex(index);
+ FilePath current_profile_path = Profile::FromWebUI(web_ui_)->GetPath();
+ bool is_current_profile =
+ profile_path == Profile::FromWebUI(web_ui_)->GetPath();
+
+ DictionaryValue profile_value;
+ profile_value.SetString("name", cache.GetNameOfProfileAtIndex(index));
+ profile_value.Set("filePath", base::CreateFilePathValue(profile_path));
+ profile_value.SetBoolean("isCurrentProfile", is_current_profile);
+
+ bool is_gaia_picture =
+ cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
+ cache.GetGAIAPictureOfProfileAtIndex(index);
+ if (is_gaia_picture) {
+ gfx::Image icon = profiles::GetAvatarIconForWebUI(
+ cache.GetAvatarIconOfProfileAtIndex(index), true);
+ profile_value.SetString("iconURL", web_ui_util::GetImageDataUrl(icon));
+ } else {
+ size_t icon_index = cache.GetAvatarIconIndexOfProfileAtIndex(index);
+ profile_value.SetString("iconURL",
+ cache.GetDefaultAvatarIconUrl(icon_index));
+ }
+
+ web_ui_->CallJavascriptFunction("ManageProfileOverlay.setProfileInfo",
+ profile_value);
+
+ // Ensure that we have the most up to date GAIA picture.
+ if (is_current_profile) {
+ GAIAInfoUpdateService* service =
+ Profile::FromWebUI(web_ui_)->GetGAIAInfoUpdateService();
+ if (service)
+ service->Update();
+ }
+}
+
+void ManageProfileHandler::ProfileIconSelectionChanged(
+ const base::ListValue* args) {
+ DCHECK(args);
+
+ Value* file_path_value;
+ FilePath file_path;
+ if (!args->Get(0, &file_path_value) ||
+ !base::GetValueAsFilePath(*file_path_value, &file_path)) {
+ return;
+ }
+
+ // Currently this only supports editing the current profile's info.
+ if (file_path != Profile::FromWebUI(web_ui_)->GetPath())
+ return;
+
+ std::string icon_url;
+ if (!args->GetString(1, &icon_url))
+ return;
+
+ if (icon_url != gaia_picture_url_)
+ return;
+
+ // If the selection is the GAIA picture then also show the GAIA name in the
+ // text field.
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ size_t i = cache.GetIndexOfProfileWithPath(file_path);
+ if (i == std::string::npos)
+ return;
+ string16 gaia_name = cache.GetGAIANameOfProfileAtIndex(i);
+ if (gaia_name.empty())
+ return;
+
+ StringValue gaia_name_value(gaia_name);
+ web_ui_->CallJavascriptFunction("ManageProfileOverlay.setProfileName",
+ gaia_name_value);
+}
diff --git a/chrome/browser/ui/webui/options2/manage_profile_handler.h b/chrome/browser/ui/webui/options2/manage_profile_handler.h
new file mode 100644
index 0000000..5daa742
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/manage_profile_handler.h
@@ -0,0 +1,82 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_MANAGE_PROFILE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_MANAGE_PROFILE_HANDLER_H_
+#pragma once
+
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+// Chrome personal stuff profiles manage overlay UI handler.
+class ManageProfileHandler : public OptionsPage2UIHandler {
+ public:
+ ManageProfileHandler();
+ virtual ~ManageProfileHandler();
+
+ // OptionsPage2UIHandler:
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler:
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // Callback for the "requestDefaultProfileIcons" message.
+ // Sends the array of default profile icon URLs to WebUI.
+ // |args| is of the form: [ {string} iconURL ]
+ void RequestDefaultProfileIcons(const base::ListValue* args);
+
+ // Sends an object to WebUI of the form:
+ // profileNames = {
+ // "Profile Name 1": true,
+ // "Profile Name 2": true,
+ // ...
+ // };
+ // This is used to detect duplicate profile names.
+ void SendProfileNames();
+
+ // Callback for the "setProfileNameAndIcon" message. Sets the name and icon
+ // of a given profile.
+ // |args| is of the form: [
+ // /*string*/ profileFilePath,
+ // /*string*/ newProfileName,
+ // /*string*/ newProfileIconURL
+ // ]
+ void SetProfileNameAndIcon(const base::ListValue* args);
+
+ // Callback for the "deleteProfile" message. Deletes the given profile.
+ // |args| is of the form: [ {string} profileFilePath ]
+ void DeleteProfile(const base::ListValue* args);
+
+ // Callback for the "requestProfileInfo" message.
+ // Given |args| of the form: [ {number} profileIndex ]
+ // Sends an object to WebUI of the form:
+ // profileInfo = {
+ // name: "Profile Name",
+ // iconURL: "chrome://path/to/icon/image",
+ // filePath: "/path/to/profile/data/on/disk"
+ // isCurrentProfile: false,
+ // };
+ void RequestProfileInfo(const base::ListValue* args);
+
+ // Callback for the 'profileIconSelectionChanged' message. Used to update the
+ // name in the manager profile dialog based on the selected icon.
+ void ProfileIconSelectionChanged(const base::ListValue* args);
+
+ // Send all profile icons to the overlay.
+ void SendProfileIcons();
+
+ // URL for the current profile's GAIA picture.
+ std::string gaia_picture_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManageProfileHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_MANAGE_PROFILE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/options_browsertest.js b/chrome/browser/ui/webui/options2/options_browsertest.js
new file mode 100644
index 0000000..9be9041
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_browsertest.js
@@ -0,0 +1,93 @@
+// 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.
+
+/**
+ * TestFixture for OptionsPage WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ */
+function OptionsWebUITest() {}
+
+OptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the options page & call our preLoad().
+ */
+ browsePreload: 'chrome://settings',
+
+ /**
+ * Register a mock handler to ensure expectations are met and options pages
+ * behave correctly.
+ */
+ preLoad: function() {
+ this.makeAndRegisterMockHandler(
+ ['coreOptionsInitialize',
+ 'fetchPrefs',
+ 'observePrefs',
+ 'setBooleanPref',
+ 'setIntegerPref',
+ 'setDoublePref',
+ 'setStringPref',
+ 'setObjectPref',
+ 'clearPref',
+ 'coreOptionsUserMetricsAction',
+ // TODO(scr): Handle this new message:
+ // getInstantFieldTrialStatus: function() {},
+ ]);
+
+ // Register stubs for methods expected to be called before our tests run.
+ // Specific expectations can be made in the tests themselves.
+ this.mockHandler.stubs().fetchPrefs(ANYTHING);
+ this.mockHandler.stubs().observePrefs(ANYTHING);
+ this.mockHandler.stubs().coreOptionsInitialize();
+ },
+};
+
+// Crashes on Mac only. See http://crbug.com/79181
+GEN('#if defined(OS_MACOSX)');
+GEN('#define MAYBE_testSetBooleanPrefTriggers ' +
+ 'DISABLED_testSetBooleanPrefTriggers');
+GEN('#else');
+GEN('#define MAYBE_testSetBooleanPrefTriggers testSetBooleanPrefTriggers');
+GEN('#endif // defined(OS_MACOSX)');
+
+TEST_F('OptionsWebUITest', 'MAYBE_testSetBooleanPrefTriggers', function() {
+ // TODO(dtseng): make generic to click all buttons.
+ var showHomeButton = $('toolbarShowHomeButton');
+ var trueListValue = [
+ 'browser.show_home_button',
+ true,
+ 'Options_Homepage_HomeButton',
+ ];
+ // Note: this expectation is checked in testing::Test::tearDown.
+ this.mockHandler.expects(once()).setBooleanPref(trueListValue);
+
+ // Cause the handler to be called.
+ showHomeButton.click();
+ showHomeButton.blur();
+});
+
+// Not meant to run on ChromeOS at this time.
+// Not finishing in windows. http://crbug.com/81723
+GEN('#if defined(OS_CHROMEOS) || defined(OS_MACOSX) || defined(OS_WIN)');
+GEN('#define MAYBE_testRefreshStaysOnCurrentPage \\');
+GEN(' DISABLED_testRefreshStaysOnCurrentPage');
+GEN('#else');
+GEN('#define MAYBE_testRefreshStaysOnCurrentPage ' +
+ 'testRefreshStaysOnCurrentPage');
+GEN('#endif');
+
+TEST_F('OptionsWebUITest', 'MAYBE_testRefreshStaysOnCurrentPage', function() {
+ var item = $('advancedPageNav');
+ item.onclick();
+ window.location.reload();
+ var pageInstance = AdvancedOptions.getInstance();
+ var topPage = OptionsPage.getTopmostVisiblePage();
+ var expectedTitle = pageInstance.title;
+ var actualTitle = document.title;
+ assertEquals("chrome://settings/advanced", document.location.href);
+ assertEquals(expectedTitle, actualTitle);
+ assertEquals(pageInstance, topPage);
+});
diff --git a/chrome/browser/ui/webui/options2/options_sync_setup_handler.cc b/chrome/browser/ui/webui/options2/options_sync_setup_handler.cc
new file mode 100644
index 0000000..872c28b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_sync_setup_handler.cc
@@ -0,0 +1,37 @@
+// 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/options2/options_sync_setup_handler.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+
+OptionsSyncSetupHandler::OptionsSyncSetupHandler(
+ ProfileManager* profile_manager) : SyncSetupHandler2(profile_manager) {
+}
+
+OptionsSyncSetupHandler::~OptionsSyncSetupHandler() {
+}
+
+void OptionsSyncSetupHandler::ShowSetupUI() {
+ ProfileSyncService* service =
+ Profile::FromWebUI(web_ui_)->GetProfileSyncService();
+ DCHECK(service);
+
+ // The user is trying to manually load a syncSetup URL. We should bring up
+ // either a login or a configure flow based on the state of sync.
+ if (service->HasSyncSetupCompleted()) {
+ if (service->IsPassphraseRequiredForDecryption()) {
+ service->get_wizard().Step(SyncSetupWizard::ENTER_PASSPHRASE);
+ } else {
+ service->get_wizard().Step(SyncSetupWizard::CONFIGURE);
+ }
+ } else {
+ service->get_wizard().Step(SyncSetupWizard::GetLoginState());
+ }
+
+ // Show the Sync Setup page.
+ scoped_ptr<Value> page(Value::CreateStringValue("syncSetup"));
+ web_ui_->CallJavascriptFunction("OptionsPage.navigateToPage", *page);
+}
diff --git a/chrome/browser/ui/webui/options2/options_sync_setup_handler.h b/chrome/browser/ui/webui/options2/options_sync_setup_handler.h
new file mode 100644
index 0000000..291fdbe
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_sync_setup_handler.h
@@ -0,0 +1,21 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_SYNC_SETUP_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_SYNC_SETUP_HANDLER_H_
+
+#include "chrome/browser/ui/webui/sync_setup_handler2.h"
+
+// The handler for Javascript messages related to sync setup UI in the options
+// page.
+class OptionsSyncSetupHandler : public SyncSetupHandler2 {
+ public:
+ explicit OptionsSyncSetupHandler(ProfileManager* profile_manager);
+ virtual ~OptionsSyncSetupHandler();
+
+ protected:
+ virtual void ShowSetupUI() OVERRIDE;
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_SYNC_SETUP_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/options_ui.cc b/chrome/browser/ui/webui/options2/options_ui.cc
new file mode 100644
index 0000000..9b74dd6
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_ui.cc
@@ -0,0 +1,369 @@
+// 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/options2/options_ui.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "base/values.h"
+#include "chrome/browser/browser_about_handler.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/options2/advanced_options_handler.h"
+#include "chrome/browser/ui/webui/options2/autofill_options_handler.h"
+#include "chrome/browser/ui/webui/options2/browser_options_handler.h"
+#include "chrome/browser/ui/webui/options2/clear_browser_data_handler.h"
+#include "chrome/browser/ui/webui/options2/content_settings_handler.h"
+#include "chrome/browser/ui/webui/options2/cookies_view_handler.h"
+#include "chrome/browser/ui/webui/options2/core_options_handler.h"
+#include "chrome/browser/ui/webui/options2/extension_settings_handler.h"
+#include "chrome/browser/ui/webui/options2/font_settings_handler.h"
+#include "chrome/browser/ui/webui/options2/handler_options_handler.h"
+#include "chrome/browser/ui/webui/options2/import_data_handler.h"
+#include "chrome/browser/ui/webui/options2/language_options_handler.h"
+#include "chrome/browser/ui/webui/options2/manage_profile_handler.h"
+#include "chrome/browser/ui/webui/options2/options_sync_setup_handler.h"
+#include "chrome/browser/ui/webui/options2/pack_extension_handler.h"
+#include "chrome/browser/ui/webui/options2/password_manager_handler.h"
+#include "chrome/browser/ui/webui/options2/personal_options_handler.h"
+#include "chrome/browser/ui/webui/options2/search_engine_manager_handler.h"
+#include "chrome/browser/ui/webui/options2/stop_syncing_handler.h"
+#include "chrome/browser/ui/webui/options2/web_intents_settings_handler.h"
+#include "chrome/browser/ui/webui/theme_source.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/time_format.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_delegate.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_types.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "grit/options2_resources.h"
+#include "grit/theme_resources.h"
+#include "grit/theme_resources_standard.h"
+#include "net/base/escape.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/webui/options2/chromeos/about_page_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/accounts_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/bluetooth_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/core_chromeos_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/cros_language_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/internet_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_chewing_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_customize_modifier_keys_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_hangul_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_mozc_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/language_pinyin_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/proxy_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/stats_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/system_options_handler.h"
+#include "chrome/browser/ui/webui/options2/chromeos/user_image_source.h"
+#include "chrome/browser/ui/webui/options2/chromeos/virtual_keyboard_manager_handler.h"
+#endif
+
+#if defined(USE_NSS)
+#include "chrome/browser/ui/webui/options2/certificate_manager_handler.h"
+#endif
+
+static const char kLocalizedStringsFile[] = "strings.js";
+static const char kOptionsBundleJsFile[] = "options_bundle.js";
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Options2UIHTMLSource
+//
+////////////////////////////////////////////////////////////////////////////////
+
+class Options2UIHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+ // The constructor takes over ownership of |localized_strings|.
+ explicit Options2UIHTMLSource(DictionaryValue* localized_strings);
+ virtual ~Options2UIHTMLSource();
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id);
+ virtual std::string GetMimeType(const std::string&) const;
+
+ private:
+ // Localized strings collection.
+ scoped_ptr<DictionaryValue> localized_strings_;
+
+ DISALLOW_COPY_AND_ASSIGN(Options2UIHTMLSource);
+};
+
+Options2UIHTMLSource::Options2UIHTMLSource(DictionaryValue* localized_strings)
+ : DataSource(chrome::kChromeUISettingsFrameHost, MessageLoop::current()) {
+ DCHECK(localized_strings);
+ localized_strings_.reset(localized_strings);
+}
+
+Options2UIHTMLSource::~Options2UIHTMLSource() {}
+
+void Options2UIHTMLSource::StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id) {
+ scoped_refptr<RefCountedMemory> response_bytes;
+ SetFontAndTextDirection(localized_strings_.get());
+
+ if (path == kLocalizedStringsFile) {
+ // Return dynamically-generated strings from memory.
+ std::string strings_js;
+ jstemplate_builder::AppendJsonJS(localized_strings_.get(), &strings_js);
+ response_bytes = base::RefCountedString::TakeString(&strings_js);
+ } else if (path == kOptionsBundleJsFile) {
+ // Return (and cache) the options javascript code.
+ response_bytes = ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+ IDR_OPTIONS2_BUNDLE_JS);
+ } else {
+ // Return (and cache) the main options html page as the default.
+ response_bytes = ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+ IDR_OPTIONS2_HTML);
+ }
+
+ SendResponse(request_id, response_bytes);
+}
+
+std::string Options2UIHTMLSource::GetMimeType(const std::string& path) const {
+ if (path == kLocalizedStringsFile || path == kOptionsBundleJsFile)
+ return "application/javascript";
+
+ return "text/html";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// OptionsPage2UIHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+
+OptionsPage2UIHandler::OptionsPage2UIHandler() {
+}
+
+OptionsPage2UIHandler::~OptionsPage2UIHandler() {
+}
+
+bool OptionsPage2UIHandler::IsEnabled() {
+ return true;
+}
+
+// static
+void OptionsPage2UIHandler::RegisterStrings(
+ DictionaryValue* localized_strings,
+ const OptionsStringResource* resources,
+ size_t length) {
+ for (size_t i = 0; i < length; ++i) {
+ localized_strings->SetString(
+ resources[i].name, l10n_util::GetStringUTF16(resources[i].id));
+ }
+}
+
+void OptionsPage2UIHandler::RegisterTitle(DictionaryValue* localized_strings,
+ const std::string& variable_name,
+ int title_id) {
+ localized_strings->SetString(variable_name,
+ l10n_util::GetStringUTF16(title_id));
+ localized_strings->SetString(variable_name + "TabTitle",
+ l10n_util::GetStringFUTF16(IDS_OPTIONS_TAB_TITLE,
+ l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE),
+ l10n_util::GetStringUTF16(title_id)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Options2UI
+//
+////////////////////////////////////////////////////////////////////////////////
+
+Options2UI::Options2UI(TabContents* contents)
+ : ChromeWebUI(contents),
+ initialized_handlers_(false) {
+ DictionaryValue* localized_strings = new DictionaryValue();
+
+ CoreOptionsHandler* core_handler;
+#if defined(OS_CHROMEOS)
+ core_handler = new chromeos::CoreChromeOSOptionsHandler();
+#else
+ core_handler = new CoreOptionsHandler();
+#endif
+ core_handler->set_handlers_host(this);
+ AddOptionsPageUIHandler(localized_strings, core_handler);
+
+ AddOptionsPageUIHandler(localized_strings, new AdvancedOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new AutofillOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new BrowserOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new ClearBrowserDataHandler());
+ AddOptionsPageUIHandler(localized_strings, new ContentSettingsHandler());
+ AddOptionsPageUIHandler(localized_strings, new CookiesViewHandler());
+ AddOptionsPageUIHandler(localized_strings, new ExtensionSettingsHandler());
+ AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler());
+ AddOptionsPageUIHandler(localized_strings, new WebIntentsSettingsHandler());
+#if defined(OS_CHROMEOS)
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::CrosLanguageOptionsHandler());
+#else
+ AddOptionsPageUIHandler(localized_strings, new LanguageOptionsHandler());
+#endif
+ AddOptionsPageUIHandler(localized_strings, new ManageProfileHandler());
+ AddOptionsPageUIHandler(localized_strings, new PackExtensionHandler());
+ AddOptionsPageUIHandler(localized_strings, new PasswordManagerHandler());
+ AddOptionsPageUIHandler(localized_strings, new PersonalOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new SearchEngineManagerHandler());
+ AddOptionsPageUIHandler(localized_strings, new ImportDataHandler());
+ AddOptionsPageUIHandler(localized_strings, new StopSyncingHandler());
+ AddOptionsPageUIHandler(localized_strings, new OptionsSyncSetupHandler(
+ g_browser_process->profile_manager()));
+#if defined(OS_CHROMEOS)
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::AboutPageHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::AccountsOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::BluetoothOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new InternetOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::LanguageChewingHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::LanguageCustomizeModifierKeysHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::LanguageHangulHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::LanguageMozcHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::LanguagePinyinHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::VirtualKeyboardManagerHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::ProxyHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::ChangePictureOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings,
+ new chromeos::StatsOptionsHandler());
+ AddOptionsPageUIHandler(localized_strings, new SystemOptionsHandler());
+#endif
+#if defined(USE_NSS)
+ AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler());
+#endif
+ AddOptionsPageUIHandler(localized_strings, new HandlerOptionsHandler());
+
+ // |localized_strings| ownership is taken over by this constructor.
+ Options2UIHTMLSource* html_source =
+ new Options2UIHTMLSource(localized_strings);
+
+ // Set up the chrome://settings-frame/ source.
+ Profile* profile = Profile::FromBrowserContext(contents->browser_context());
+ profile->GetChromeURLDataManager()->AddDataSource(html_source);
+
+ // Set up the chrome://theme/ source.
+ ThemeSource* theme = new ThemeSource(profile);
+ profile->GetChromeURLDataManager()->AddDataSource(theme);
+
+#if defined(OS_CHROMEOS)
+ // Set up the chrome://userimage/ source.
+ chromeos::UserImageSource* user_image_source =
+ new chromeos::UserImageSource();
+ profile->GetChromeURLDataManager()->AddDataSource(user_image_source);
+#endif
+}
+
+Options2UI::~Options2UI() {
+ // Uninitialize all registered handlers. The base class owns them and it will
+ // eventually delete them. Skip over the generic handler.
+ for (std::vector<WebUIMessageHandler*>::iterator iter = handlers_.begin() + 1;
+ iter != handlers_.end();
+ ++iter) {
+ static_cast<OptionsPage2UIHandler*>(*iter)->Uninitialize();
+ }
+}
+
+// Override.
+void Options2UI::RenderViewCreated(RenderViewHost* render_view_host) {
+ SetCommandLineString(render_view_host);
+ ChromeWebUI::RenderViewCreated(render_view_host);
+}
+
+void Options2UI::RenderViewReused(RenderViewHost* render_view_host) {
+ SetCommandLineString(render_view_host);
+ ChromeWebUI::RenderViewReused(render_view_host);
+}
+
+void Options2UI::DidBecomeActiveForReusedRenderView() {
+ // When the renderer is re-used (e.g., for back/forward navigation within
+ // options), the handlers are torn down and rebuilt, so are no longer
+ // initialized, but the web page's DOM may remain intact, in which case onload
+ // won't fire to initilize the handlers. To make sure initialization always
+ // happens, call reinitializeCore (which is a no-op unless the DOM was already
+ // initialized).
+ CallJavascriptFunction("OptionsPage.reinitializeCore");
+
+ ChromeWebUI::DidBecomeActiveForReusedRenderView();
+}
+
+// static
+RefCountedMemory* Options2UI::GetFaviconResourceBytes() {
+ return ResourceBundle::GetSharedInstance().
+ LoadDataResourceBytes(IDR_SETTINGS_FAVICON);
+}
+
+void Options2UI::InitializeHandlers() {
+ DCHECK(!GetProfile()->IsOffTheRecord() || Profile::IsGuestSession());
+
+ // The reinitialize call from DidBecomeActiveForReusedRenderView end up being
+ // delivered after a new web page DOM has been brought up in an existing
+ // renderer (due to IPC delays), causing this method to be called twice. If
+ // that happens, ignore the second call.
+ if (initialized_handlers_)
+ return;
+ initialized_handlers_ = true;
+
+ std::vector<WebUIMessageHandler*>::iterator iter;
+ // Skip over the generic handler.
+ for (iter = handlers_.begin() + 1; iter != handlers_.end(); ++iter) {
+ (static_cast<OptionsPage2UIHandler*>(*iter))->Initialize();
+ }
+}
+
+void Options2UI::AddOptionsPageUIHandler(DictionaryValue* localized_strings,
+ OptionsPage2UIHandler* handler_raw) {
+ scoped_ptr<OptionsPage2UIHandler> handler(handler_raw);
+ DCHECK(handler.get());
+ // Add only if handler's service is enabled.
+ if (handler->IsEnabled()) {
+ handler->GetLocalizedValues(localized_strings);
+ // Add handler to the list and also pass the ownership.
+ AddMessageHandler(handler.release()->Attach(this));
+ }
+}
+
+void Options2UI::SetCommandLineString(RenderViewHost* render_view_host) {
+ std::string command_line_string;
+
+#if defined(OS_WIN)
+ command_line_string =
+ WideToASCII(CommandLine::ForCurrentProcess()->GetCommandLineString());
+#else
+ command_line_string =
+ CommandLine::ForCurrentProcess()->GetCommandLineString();
+#endif
+
+ render_view_host->SetWebUIProperty("commandLineString", command_line_string);
+}
diff --git a/chrome/browser/ui/webui/options2/options_ui.h b/chrome/browser/ui/webui/options2/options_ui.h
new file mode 100644
index 0000000..9a7a759
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_ui.h
@@ -0,0 +1,111 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_H_
+#pragma once
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
+#include "chrome/browser/ui/webui/chrome_web_ui.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_types.h"
+
+// The base class handler of Javascript messages of options pages.
+class OptionsPage2UIHandler : public WebUIMessageHandler,
+ public content::NotificationObserver {
+ public:
+ OptionsPage2UIHandler();
+ virtual ~OptionsPage2UIHandler();
+
+ // Is this handler enabled?
+ virtual bool IsEnabled();
+
+ // Collects localized strings for options page.
+ virtual void GetLocalizedValues(base::DictionaryValue* localized_strings) = 0;
+
+ // Initialize the page. Called once the DOM is available for manipulation.
+ // This will be called only once.
+ virtual void Initialize() {}
+
+ // Uninitializes the page. Called just before the object is destructed.
+ virtual void Uninitialize() {}
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE {}
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {}
+
+ protected:
+ struct OptionsStringResource {
+ // The name of the resource in templateData.
+ const char* name;
+ // The .grd ID for the resource (IDS_*).
+ int id;
+ };
+ // A helper for simplifying the process of registering strings in WebUI.
+ static void RegisterStrings(base::DictionaryValue* localized_strings,
+ const OptionsStringResource* resources,
+ size_t length);
+
+ // Registers string resources for a page's header and tab title.
+ static void RegisterTitle(base::DictionaryValue* localized_strings,
+ const std::string& variable_name,
+ int title_id);
+
+ content::NotificationRegistrar registrar_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OptionsPage2UIHandler);
+};
+
+// An interface for common operations that a host of OptionsPage2UIHandlers
+// should provide.
+class OptionsPage2UIHandlerHost {
+ public:
+ virtual void InitializeHandlers() = 0;
+
+ protected:
+ virtual ~OptionsPage2UIHandlerHost() {}
+};
+
+// The WebUI for chrome:settings-frame.
+class Options2UI : public ChromeWebUI,
+ public OptionsPage2UIHandlerHost {
+ public:
+ explicit Options2UI(TabContents* contents);
+ virtual ~Options2UI();
+
+ static RefCountedMemory* GetFaviconResourceBytes();
+
+ // WebUI implementation.
+ virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
+ virtual void RenderViewReused(RenderViewHost* render_view_host) OVERRIDE;
+ virtual void DidBecomeActiveForReusedRenderView() OVERRIDE;
+
+ // Overridden from OptionsPage2UIHandlerHost:
+ virtual void InitializeHandlers() OVERRIDE;
+
+ private:
+ // Adds OptionsPageUiHandler to the handlers list if handler is enabled.
+ void AddOptionsPageUIHandler(base::DictionaryValue* localized_strings,
+ OptionsPage2UIHandler* handler);
+
+ // Sets the WebUI CommandLineString property with arguments passed while
+ // launching chrome.
+ void SetCommandLineString(RenderViewHost* render_view_host);
+
+ bool initialized_handlers_;
+
+ DISALLOW_COPY_AND_ASSIGN(Options2UI);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_H_
diff --git a/chrome/browser/ui/webui/options2/options_ui_uitest.cc b/chrome/browser/ui/webui/options2/options_ui_uitest.cc
new file mode 100644
index 0000000..b292213
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_ui_uitest.cc
@@ -0,0 +1,65 @@
+// 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/options2/options_ui_uitest.h"
+
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+OptionsUITest::OptionsUITest() {
+ dom_automation_enabled_ = true;
+}
+
+void OptionsUITest::NavigateToSettings(scoped_refptr<TabProxy> tab) {
+ const GURL& url = GURL(chrome::kChromeUISettingsURL);
+ ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
+ tab->NavigateToURLBlockUntilNavigationsComplete(url, 1)) << url.spec();
+}
+
+void OptionsUITest::VerifyNavbar(scoped_refptr<TabProxy> tab) {
+ bool navbar_exist = false;
+ EXPECT_TRUE(tab->ExecuteAndExtractBool(L"",
+ L"domAutomationController.send("
+ L"!!document.getElementById('navbar'))", &navbar_exist));
+ EXPECT_EQ(true, navbar_exist);
+}
+
+void OptionsUITest::VerifyTitle(scoped_refptr<TabProxy> tab) {
+ std::wstring title;
+ EXPECT_TRUE(tab->GetTabTitle(&title));
+ string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
+ EXPECT_NE(WideToUTF16Hack(title).find(expected_title), string16::npos);
+}
+
+void OptionsUITest::VerifySections(scoped_refptr<TabProxy> tab) {
+#if defined(OS_CHROMEOS)
+ const int kExpectedSections = 1 + 7;
+#else
+ const int kExpectedSections = 1 + 4;
+#endif
+ int num_of_sections = 0;
+ EXPECT_TRUE(tab->ExecuteAndExtractInt(L"",
+ L"domAutomationController.send("
+ L"document.getElementById('navbar').children.length)", &num_of_sections));
+ EXPECT_EQ(kExpectedSections, num_of_sections);
+}
+
+TEST_F(OptionsUITest, LoadOptionsByURL) {
+ scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+
+ scoped_refptr<TabProxy> tab = browser->GetActiveTab();
+ ASSERT_TRUE(tab.get());
+
+ NavigateToSettings(tab);
+ VerifyTitle(tab);
+ VerifyNavbar(tab);
+ VerifySections(tab);
+}
diff --git a/chrome/browser/ui/webui/options2/options_ui_uitest.h b/chrome/browser/ui/webui/options2/options_ui_uitest.h
new file mode 100644
index 0000000..3cc6806
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/options_ui_uitest.h
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_UITEST_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_UITEST_H_
+#pragma once
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/test/ui/ui_test.h"
+
+class TabProxy;
+
+class OptionsUITest : public UITest {
+ public:
+ OptionsUITest();
+
+ // Navigate to the settings tab and block until complete.
+ void NavigateToSettings(scoped_refptr<TabProxy> tab);
+
+ // Check navbar's existence.
+ void VerifyNavbar(scoped_refptr<TabProxy> tab);
+
+ // Verify that the page title is correct.
+ // The only guarantee we can make about the title of a settings tab is that
+ // it should contain IDS_SETTINGS_TITLE somewhere.
+ void VerifyTitle(scoped_refptr<TabProxy> tab);
+
+ // Check section headers in navbar.
+ // For ChromeOS, there should be 1 + 7:
+ // Search, Basics, Personal, System, Internet, Under the Hood,
+ // Users and Extensions.
+ // For other platforms, there should 1 + 4:
+ // Search, Basics, Personal, Under the Hood and Extensions.
+ void VerifySections(scoped_refptr<TabProxy> tab);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_OPTIONS_UI_UITEST_H_
diff --git a/chrome/browser/ui/webui/options2/pack_extension_handler.cc b/chrome/browser/ui/webui/options2/pack_extension_handler.cc
new file mode 100644
index 0000000..0790482
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/pack_extension_handler.cc
@@ -0,0 +1,101 @@
+// 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/options2/pack_extension_handler.h"
+
+#include "base/bind.h"
+#include "base/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+PackExtensionHandler::PackExtensionHandler() {
+}
+
+PackExtensionHandler::~PackExtensionHandler() {
+ if (pack_job_.get())
+ pack_job_->ClearClient();
+}
+
+void PackExtensionHandler::Initialize() {
+}
+
+void PackExtensionHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ RegisterTitle(localized_strings, "clearBrowserDataOverlay",
+ IDS_CLEAR_BROWSING_DATA_TITLE);
+
+ localized_strings->SetString("packExtensionOverlay",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_TITLE));
+ localized_strings->SetString("packExtensionHeading",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_HEADING));
+ localized_strings->SetString("packExtensionCommit",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_BUTTON));
+ localized_strings->SetString("packExtensionRootDir",
+ l10n_util::GetStringUTF16(
+ IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL));
+ localized_strings->SetString("packExtensionPrivateKey",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL));
+ localized_strings->SetString("packExtensionBrowseButton",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_BROWSE));
+}
+
+void PackExtensionHandler::RegisterMessages() {
+ // Setup handlers specific to this panel.
+ web_ui_->RegisterMessageCallback("pack",
+ base::Bind(&PackExtensionHandler::HandlePackMessage,
+ base::Unretained(this)));
+}
+
+void PackExtensionHandler::OnPackSuccess(const FilePath& crx_file,
+ const FilePath& pem_file) {
+ ListValue results;
+ web_ui_->CallJavascriptFunction("OptionsPage.closeOverlay", results);
+
+ ShowAlert(UTF16ToUTF8(PackExtensionJob::StandardSuccessMessage(crx_file,
+ pem_file)));
+}
+
+void PackExtensionHandler::OnPackFailure(const std::string& error) {
+ ShowAlert(error);
+}
+
+void PackExtensionHandler::HandlePackMessage(const ListValue* args) {
+ std::string extension_path;
+ std::string private_key_path;
+ CHECK_EQ(2U, args->GetSize());
+ CHECK(args->GetString(0, &extension_path));
+ CHECK(args->GetString(1, &private_key_path));
+
+ FilePath root_directory =
+ FilePath::FromWStringHack(UTF8ToWide(extension_path));
+ FilePath key_file = FilePath::FromWStringHack(UTF8ToWide(private_key_path));
+
+ if (root_directory.empty()) {
+ if (extension_path.empty()) {
+ ShowAlert(l10n_util::GetStringUTF8(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED));
+ } else {
+ ShowAlert(l10n_util::GetStringUTF8(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID));
+ }
+
+ return;
+ }
+
+ if (!private_key_path.empty() && key_file.empty()) {
+ ShowAlert(l10n_util::GetStringUTF8(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID));
+ return;
+ }
+
+ pack_job_ = new PackExtensionJob(this, root_directory, key_file);
+ pack_job_->Start();
+}
+
+void PackExtensionHandler::ShowAlert(const std::string& message) {
+ ListValue arguments;
+ arguments.Append(Value::CreateStringValue(message));
+ web_ui_->CallJavascriptFunction("alert", arguments);
+}
diff --git a/chrome/browser/ui/webui/options2/pack_extension_handler.h b/chrome/browser/ui/webui/options2/pack_extension_handler.h
new file mode 100644
index 0000000..1ae63c4
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/pack_extension_handler.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_PACK_EXTENSION_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_PACK_EXTENSION_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/extensions/pack_extension_job.h"
+#include "chrome/browser/plugin_data_remover_helper.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+// Clear browser data handler page UI handler.
+class PackExtensionHandler : public OptionsPage2UIHandler,
+ public PackExtensionJob::Client {
+ public:
+ PackExtensionHandler();
+ virtual ~PackExtensionHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void Initialize() OVERRIDE;
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // ExtensionPackJob::Client
+ virtual void OnPackSuccess(const FilePath& crx_file,
+ const FilePath& key_file) OVERRIDE;
+
+ virtual void OnPackFailure(const std::string& error) OVERRIDE;
+
+ private:
+ // Javascript callback to start packing an extension.
+ void HandlePackMessage(const ListValue* args);
+
+ // A function to ask the webpage to show an alert.
+ void ShowAlert(const std::string& message);
+
+ // Used to package the extension.
+ scoped_refptr<PackExtensionJob> pack_job_;
+
+ DISALLOW_COPY_AND_ASSIGN(PackExtensionHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_PACK_EXTENSION_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/password_manager_browsertest.js b/chrome/browser/ui/webui/options2/password_manager_browsertest.js
new file mode 100644
index 0000000..98c632d
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/password_manager_browsertest.js
@@ -0,0 +1,25 @@
+// 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.
+
+/**
+ * TestFixture for password manager WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function PasswordManagerWebUITest() {}
+
+PasswordManagerWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the password manager.
+ **/
+ browsePreload: 'chrome://settings/passwords',
+};
+
+// Test opening the password manager has correct location.
+TEST_F('PasswordManagerWebUITest', 'testOpenPasswordManager',
+ function() {
+ assertEquals(this.browsePreload, document.location.href);
+ });
diff --git a/chrome/browser/ui/webui/options2/password_manager_handler.cc b/chrome/browser/ui/webui/options2/password_manager_handler.cc
new file mode 100644
index 0000000..b0990bb
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/password_manager_handler.cc
@@ -0,0 +1,291 @@
+// 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/options2/password_manager_handler.h"
+
+#include "base/bind.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "net/base/net_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "webkit/glue/password_form.h"
+
+PasswordManagerHandler::PasswordManagerHandler()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(populater_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(exception_populater_(this)) {
+}
+
+PasswordManagerHandler::~PasswordManagerHandler() {
+ PasswordStore* store = GetPasswordStore();
+ if (store)
+ store->RemoveObserver(this);
+}
+
+void PasswordManagerHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static const OptionsStringResource resources[] = {
+ { "savedPasswordsTitle",
+ IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE },
+ { "passwordExceptionsTitle",
+ IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE },
+ { "passwordSearchPlaceholder",
+ IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS },
+ { "passwordShowButton",
+ IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON },
+ { "passwordHideButton",
+ IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON },
+ { "passwordsSiteColumn",
+ IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN },
+ { "passwordsUsernameColumn",
+ IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN },
+ { "passwordsRemoveButton",
+ IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON },
+ { "passwordsNoPasswordsDescription",
+ IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION },
+ { "passwordsNoExceptionsDescription",
+ IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
+ { "passwordsRemoveAllButton",
+ IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON },
+ { "passwordsRemoveAllTitle",
+ IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS },
+ { "passwordsRemoveAllWarning",
+ IDS_PASSWORDS_PAGE_VIEW_TEXT_DELETE_ALL_PASSWORDS },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "passwordsPage",
+ IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
+
+ localized_strings->SetString("passwordManagerLearnMoreURL",
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kPasswordManagerLearnMoreURL)).spec());
+}
+
+void PasswordManagerHandler::Initialize() {
+ // Due to the way that handlers are (re)initialized under certain types of
+ // navigation, we may already be initialized. (See bugs 88986 and 86448.)
+ // If this is the case, return immediately. This is a hack.
+ // TODO(mdm): remove this hack once it is no longer necessary.
+ if (!show_passwords_.GetPrefName().empty())
+ return;
+
+ show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
+ Profile::FromWebUI(web_ui_)->GetPrefs(), this);
+ // We should not cache web_ui_->GetProfile(). See crosbug.com/6304.
+ PasswordStore* store = GetPasswordStore();
+ if (store)
+ store->AddObserver(this);
+}
+
+void PasswordManagerHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+
+ web_ui_->RegisterMessageCallback("updatePasswordLists",
+ base::Bind(&PasswordManagerHandler::UpdatePasswordLists,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeSavedPassword",
+ base::Bind(&PasswordManagerHandler::RemoveSavedPassword,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removePasswordException",
+ base::Bind(&PasswordManagerHandler::RemovePasswordException,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeAllSavedPasswords",
+ base::Bind(&PasswordManagerHandler::RemoveAllSavedPasswords,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("removeAllPasswordExceptions",
+ base::Bind(&PasswordManagerHandler::RemoveAllPasswordExceptions,
+ base::Unretained(this)));
+}
+
+void PasswordManagerHandler::OnLoginsChanged() {
+ UpdatePasswordLists(NULL);
+}
+
+PasswordStore* PasswordManagerHandler::GetPasswordStore() {
+ return Profile::FromWebUI(web_ui_)->
+ GetPasswordStore(Profile::EXPLICIT_ACCESS);
+}
+
+void PasswordManagerHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ std::string* pref_name = content::Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kPasswordManagerAllowShowPasswords) {
+ UpdatePasswordLists(NULL);
+ }
+ }
+
+ OptionsPage2UIHandler::Observe(type, source, details);
+}
+
+void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) {
+ // Reset the current lists.
+ password_list_.reset();
+ password_exception_list_.reset();
+
+ languages_ = Profile::FromWebUI(web_ui_)->GetPrefs()->
+ GetString(prefs::kAcceptLanguages);
+ populater_.Populate();
+ exception_populater_.Populate();
+}
+
+void PasswordManagerHandler::RemoveSavedPassword(const ListValue* args) {
+ PasswordStore* store = GetPasswordStore();
+ if (!store)
+ return;
+ std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
+ int index;
+ if (base::StringToInt(string_value, &index) && index >= 0 &&
+ static_cast<size_t>(index) < password_list_.size())
+ store->RemoveLogin(*password_list_[index]);
+}
+
+void PasswordManagerHandler::RemovePasswordException(
+ const ListValue* args) {
+ PasswordStore* store = GetPasswordStore();
+ if (!store)
+ return;
+ std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
+ int index;
+ if (base::StringToInt(string_value, &index) && index >= 0 &&
+ static_cast<size_t>(index) < password_exception_list_.size())
+ store->RemoveLogin(*password_exception_list_[index]);
+}
+
+void PasswordManagerHandler::RemoveAllSavedPasswords(
+ const ListValue* args) {
+ // TODO(jhawkins): This will cause a list refresh for every password in the
+ // list. Add PasswordStore::RemoveAllLogins().
+ PasswordStore* store = GetPasswordStore();
+ if (!store)
+ return;
+ for (size_t i = 0; i < password_list_.size(); ++i)
+ store->RemoveLogin(*password_list_[i]);
+}
+
+void PasswordManagerHandler::RemoveAllPasswordExceptions(
+ const ListValue* args) {
+ PasswordStore* store = GetPasswordStore();
+ if (!store)
+ return;
+ for (size_t i = 0; i < password_exception_list_.size(); ++i)
+ store->RemoveLogin(*password_exception_list_[i]);
+}
+
+void PasswordManagerHandler::SetPasswordList() {
+ // Due to the way that handlers are (re)initialized under certain types of
+ // navigation, we may not be initialized yet. (See bugs 88986 and 86448.)
+ // If this is the case, initialize on demand. This is a hack.
+ // TODO(mdm): remove this hack once it is no longer necessary.
+ if (show_passwords_.GetPrefName().empty())
+ Initialize();
+
+ ListValue entries;
+ bool show_passwords = *show_passwords_;
+ string16 empty;
+ for (size_t i = 0; i < password_list_.size(); ++i) {
+ ListValue* entry = new ListValue();
+ entry->Append(new StringValue(net::FormatUrl(password_list_[i]->origin,
+ languages_)));
+ entry->Append(new StringValue(password_list_[i]->username_value));
+ entry->Append(new StringValue(
+ show_passwords ? password_list_[i]->password_value : empty));
+ entries.Append(entry);
+ }
+
+ web_ui_->CallJavascriptFunction("PasswordManager.setSavedPasswordsList",
+ entries);
+}
+
+void PasswordManagerHandler::SetPasswordExceptionList() {
+ ListValue entries;
+ for (size_t i = 0; i < password_exception_list_.size(); ++i) {
+ entries.Append(new StringValue(
+ net::FormatUrl(password_exception_list_[i]->origin, languages_)));
+ }
+
+ web_ui_->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
+ entries);
+}
+
+PasswordManagerHandler::ListPopulater::ListPopulater(
+ PasswordManagerHandler* page)
+ : page_(page),
+ pending_login_query_(0) {
+}
+
+PasswordManagerHandler::ListPopulater::~ListPopulater() {
+}
+
+PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater(
+ PasswordManagerHandler* page) : ListPopulater(page) {
+}
+
+void PasswordManagerHandler::PasswordListPopulater::Populate() {
+ PasswordStore* store = page_->GetPasswordStore();
+ if (store != NULL) {
+ if (pending_login_query_)
+ store->CancelRequest(pending_login_query_);
+
+ pending_login_query_ = store->GetAutofillableLogins(this);
+ } else {
+ LOG(ERROR) << "No password store! Cannot display passwords.";
+ }
+}
+
+void PasswordManagerHandler::PasswordListPopulater::
+ OnPasswordStoreRequestDone(
+ CancelableRequestProvider::Handle handle,
+ const std::vector<webkit_glue::PasswordForm*>& result) {
+ DCHECK_EQ(pending_login_query_, handle);
+ pending_login_query_ = 0;
+ page_->password_list_.reset();
+ page_->password_list_.insert(page_->password_list_.end(),
+ result.begin(), result.end());
+ page_->SetPasswordList();
+}
+
+PasswordManagerHandler::PasswordExceptionListPopulater::
+ PasswordExceptionListPopulater(PasswordManagerHandler* page)
+ : ListPopulater(page) {
+}
+
+void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() {
+ PasswordStore* store = page_->GetPasswordStore();
+ if (store != NULL) {
+ if (pending_login_query_)
+ store->CancelRequest(pending_login_query_);
+
+ pending_login_query_ = store->GetBlacklistLogins(this);
+ } else {
+ LOG(ERROR) << "No password store! Cannot display exceptions.";
+ }
+}
+
+void PasswordManagerHandler::PasswordExceptionListPopulater::
+ OnPasswordStoreRequestDone(
+ CancelableRequestProvider::Handle handle,
+ const std::vector<webkit_glue::PasswordForm*>& result) {
+ DCHECK_EQ(pending_login_query_, handle);
+ pending_login_query_ = 0;
+ page_->password_exception_list_.reset();
+ page_->password_exception_list_.insert(page_->password_exception_list_.end(),
+ result.begin(), result.end());
+ page_->SetPasswordExceptionList();
+}
diff --git a/chrome/browser/ui/webui/options2/password_manager_handler.h b/chrome/browser/ui/webui/options2/password_manager_handler.h
new file mode 100644
index 0000000..a475055
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/password_manager_handler.h
@@ -0,0 +1,129 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_PASSWORD_MANAGER_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_PASSWORD_MANAGER_HANDLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/password_manager/password_store_consumer.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+class PasswordManagerHandler : public OptionsPage2UIHandler,
+ public PasswordStore::Observer {
+ public:
+ PasswordManagerHandler();
+ virtual ~PasswordManagerHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // PasswordStore::Observer implementation.
+ virtual void OnLoginsChanged() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ // The password store associated with the currently active profile.
+ PasswordStore* GetPasswordStore();
+
+ // Called when the JS PasswordManager object is initialized.
+ void UpdatePasswordLists(const ListValue* args);
+
+ // Remove an entry.
+ // @param value the entry index to be removed.
+ void RemoveSavedPassword(const ListValue* args);
+
+ // Remove an password exception.
+ // @param value the entry index to be removed.
+ void RemovePasswordException(const ListValue* args);
+
+ // Remove all saved passwords
+ void RemoveAllSavedPasswords(const ListValue* args);
+
+ // Remove All password exceptions
+ void RemoveAllPasswordExceptions(const ListValue* args);
+
+ // Get password value for the selected entry.
+ // @param value the selected entry index.
+ void ShowSelectedPassword(const ListValue* args);
+
+ // Sets the password and exception list contents to the given data.
+ // We take ownership of the PasswordForms in the vector.
+ void SetPasswordList();
+ void SetPasswordExceptionList();
+
+ // A short class to mediate requests to the password store.
+ class ListPopulater : public PasswordStoreConsumer {
+ public:
+ explicit ListPopulater(PasswordManagerHandler* page);
+ virtual ~ListPopulater();
+
+ // Send a query to the password store to populate a list.
+ virtual void Populate() = 0;
+
+ // Send the password store's reply back to the handler.
+ virtual void OnPasswordStoreRequestDone(
+ CancelableRequestProvider::Handle handle,
+ const std::vector<webkit_glue::PasswordForm*>& result) = 0;
+
+ protected:
+ PasswordManagerHandler* page_;
+ CancelableRequestProvider::Handle pending_login_query_;
+ };
+
+ // A short class to mediate requests to the password store for passwordlist.
+ class PasswordListPopulater : public ListPopulater {
+ public:
+ explicit PasswordListPopulater(PasswordManagerHandler* page);
+
+ // Send a query to the password store to populate a password list.
+ virtual void Populate() OVERRIDE;
+
+ // Send the password store's reply back to the handler.
+ virtual void OnPasswordStoreRequestDone(
+ CancelableRequestProvider::Handle handle,
+ const std::vector<webkit_glue::PasswordForm*>& result) OVERRIDE;
+ };
+
+ // A short class to mediate requests to the password store for exceptions.
+ class PasswordExceptionListPopulater : public ListPopulater {
+ public:
+ explicit PasswordExceptionListPopulater(PasswordManagerHandler* page);
+
+ // Send a query to the password store to populate a passwordException list.
+ virtual void Populate() OVERRIDE;
+
+ // Send the password store's reply back to the handler.
+ virtual void OnPasswordStoreRequestDone(
+ CancelableRequestProvider::Handle handle,
+ const std::vector<webkit_glue::PasswordForm*>& result) OVERRIDE;
+ };
+
+ // Password store consumer for populating the password list and exceptions.
+ PasswordListPopulater populater_;
+ PasswordExceptionListPopulater exception_populater_;
+
+ ScopedVector<webkit_glue::PasswordForm> password_list_;
+ ScopedVector<webkit_glue::PasswordForm> password_exception_list_;
+
+ // User's pref
+ std::string languages_;
+
+ // Whether to show stored passwords or not.
+ BooleanPrefMember show_passwords_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordManagerHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_PASSWORD_MANAGER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/personal_options_browsertest.js b/chrome/browser/ui/webui/options2/personal_options_browsertest.js
new file mode 100644
index 0000000..222adfa
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/personal_options_browsertest.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TestFixture for personal options WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function PersonalOptionsWebUITest() {}
+
+PersonalOptionsWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to personal options.
+ **/
+ browsePreload: 'chrome://settings/personal',
+};
+
+// Test opening personal options has correct location.
+TEST_F('PersonalOptionsWebUITest', 'testOpenPersonalOptions', function() {
+ assertEquals(this.browsePreload, document.location.href);
+});
diff --git a/chrome/browser/ui/webui/options2/personal_options_handler.cc b/chrome/browser/ui/webui/options2/personal_options_handler.cc
new file mode 100644
index 0000000..e50f810
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/personal_options_handler.cc
@@ -0,0 +1,442 @@
+// 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/options2/personal_options_handler.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/value_conversions.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_info_util.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/webui/web_ui_util.h"
+#include "chrome/common/chrome_notification_types.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/browser/tab_contents/tab_contents.h"
+#include "content/browser/user_metrics.h"
+#include "content/public/browser/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/options2/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"
+#endif // defined(OS_CHROMEOS)
+#if defined(TOOLKIT_GTK)
+#include "chrome/browser/ui/gtk/gtk_theme_service.h"
+#endif // defined(TOOLKIT_GTK)
+
+PersonalOptionsHandler::PersonalOptionsHandler() {
+ multiprofile_ = ProfileManager::IsMultipleProfilesEnabled();
+#if defined(OS_CHROMEOS)
+ registrar_.Add(this,
+ chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
+ content::NotificationService::AllSources());
+#endif
+}
+
+PersonalOptionsHandler::~PersonalOptionsHandler() {
+ ProfileSyncService* sync_service =
+ Profile::FromWebUI(web_ui_)->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("syncSection",
+ l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME));
+ localized_strings->SetString("customizeSync",
+ l10n_util::GetStringUTF16(IDS_SYNC_CUSTOMIZE_BUTTON_LABEL));
+ localized_strings->SetString("syncLearnMoreURL",
+ google_util::StringAppendGoogleLocaleParam(chrome::kSyncLearnMoreURL));
+
+ localized_strings->SetString("profiles",
+ l10n_util::GetStringUTF16(IDS_PROFILES_OPTIONS_GROUP_NAME));
+ localized_strings->SetString("profilesCreate",
+ l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_BUTTON_LABEL));
+ localized_strings->SetString("profilesManage",
+ l10n_util::GetStringUTF16(IDS_PROFILES_MANAGE_BUTTON_LABEL));
+ localized_strings->SetString("profilesDelete",
+ l10n_util::GetStringUTF16(IDS_PROFILES_DELETE_BUTTON_LABEL));
+ localized_strings->SetString("profilesDeleteSingle",
+ l10n_util::GetStringUTF16(IDS_PROFILES_DELETE_SINGLE_BUTTON_LABEL));
+ localized_strings->SetString("profilesListItemCurrent",
+ l10n_util::GetStringUTF16(IDS_PROFILES_LIST_ITEM_CURRENT));
+ localized_strings->SetString("profilesSingleUser",
+ l10n_util::GetStringFUTF16(IDS_PROFILES_SINGLE_USER_MESSAGE,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+
+ 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));
+#if defined(OS_MACOSX)
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ if (profile_manager->GetNumberOfProfiles() > 1) {
+ localized_strings->SetString("macPasswordsWarning",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MAC_WARNING));
+ }
+#endif
+ localized_strings->SetString("autologinEnabled",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_AUTOLOGIN));
+
+ 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_TABS));
+
+#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));
+ if (chromeos::UserManager::Get()->user_is_logged_in()) {
+ localized_strings->SetString("username",
+ chromeos::UserManager::Get()->logged_in_user().email());
+ }
+#endif
+}
+
+void PersonalOptionsHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback(
+ "themesReset",
+ base::Bind(&PersonalOptionsHandler::ThemesReset,
+ base::Unretained(this)));
+#if defined(TOOLKIT_GTK)
+ web_ui_->RegisterMessageCallback(
+ "themesSetGTK",
+ base::Bind(&PersonalOptionsHandler::ThemesSetGTK,
+ base::Unretained(this)));
+#endif
+ web_ui_->RegisterMessageCallback(
+ "createProfile",
+ base::Bind(&PersonalOptionsHandler::CreateProfile,
+ base::Unretained(this)));
+}
+
+void PersonalOptionsHandler::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
+ ObserveThemeChanged();
+ } else if (multiprofile_ &&
+ type == chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED) {
+ SendProfilesInfo();
+#if defined(OS_CHROMEOS)
+ } else if (type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) {
+ UpdateAccountPicture();
+#endif
+ } else {
+ OptionsPage2UIHandler::Observe(type, source, details);
+ }
+}
+
+void PersonalOptionsHandler::OnStateChanged() {
+ string16 status_label;
+ string16 link_label;
+ ProfileSyncService* service =
+ Profile::FromWebUI(web_ui_)->GetProfileSyncService();
+ DCHECK(service);
+ bool managed = service->IsManaged();
+ bool sync_setup_completed = service->HasSyncSetupCompleted();
+ bool status_has_error = sync_ui_util::GetStatusLabels(
+ service, sync_ui_util::WITH_HTML, &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 =
+ 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 =
+ l10n_util::GetStringFUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL,
+ l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
+ 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);
+
+ enabled.reset(Value::CreateBooleanValue(
+ !service->unrecoverable_error_detected()));
+ web_ui_->CallJavascriptFunction(
+ "PersonalOptions.setCustomizeSyncButtonEnabled",
+ *enabled);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin)) {
+ visible.reset(Value::CreateBooleanValue(
+ service->AreCredentialsAvailable()));
+ web_ui_->CallJavascriptFunction("PersonalOptions.setAutoLoginVisible",
+ *visible);
+ }
+
+ // Set profile creation text and button if multi-profiles switch is on.
+ visible.reset(Value::CreateBooleanValue(multiprofile_));
+ web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesSectionVisible",
+ *visible);
+ if (multiprofile_)
+ SendProfilesInfo();
+}
+
+void PersonalOptionsHandler::ObserveThemeChanged() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+#if defined(TOOLKIT_GTK)
+ GtkThemeService* theme_service = GtkThemeService::GetFrom(profile);
+ bool is_gtk_theme = theme_service->UsingNativeTheme();
+ base::FundamentalValue gtk_enabled(!is_gtk_theme);
+ web_ui_->CallJavascriptFunction(
+ "options.PersonalOptions.setGtkThemeButtonEnabled", gtk_enabled);
+#else
+ ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile);
+ bool is_gtk_theme = false;
+#endif
+
+ bool is_classic_theme = !is_gtk_theme && theme_service->UsingDefaultTheme();
+ base::FundamentalValue enabled(!is_classic_theme);
+ web_ui_->CallJavascriptFunction(
+ "options.PersonalOptions.setThemesResetButtonEnabled", enabled);
+}
+
+void PersonalOptionsHandler::Initialize() {
+ Profile* profile = Profile::FromWebUI(web_ui_);
+
+ // Listen for theme installation.
+ registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+ content::Source<ThemeService>(
+ ThemeServiceFactory::GetForProfile(profile)));
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources());
+ ObserveThemeChanged();
+
+ ProfileSyncService* sync_service = profile->GetProfileSyncService();
+ if (sync_service) {
+ sync_service->AddObserver(this);
+ OnStateChanged();
+ } else {
+ web_ui_->CallJavascriptFunction("options.PersonalOptions.hideSyncSection");
+ }
+}
+
+void PersonalOptionsHandler::ThemesReset(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_ThemesReset"));
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ ThemeServiceFactory::GetForProfile(profile)->UseDefaultTheme();
+}
+
+#if defined(TOOLKIT_GTK)
+void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("Options_GtkThemeSet"));
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ ThemeServiceFactory::GetForProfile(profile)->SetNativeTheme();
+}
+#endif
+
+#if defined(OS_CHROMEOS)
+void PersonalOptionsHandler::UpdateAccountPicture() {
+ std::string email = chromeos::UserManager::Get()->logged_in_user().email();
+ if (!email.empty()) {
+ web_ui_->CallJavascriptFunction("PersonalOptions.updateAccountPicture");
+ base::StringValue email_value(email);
+ web_ui_->CallJavascriptFunction("AccountsOptions.updateAccountPicture",
+ email_value);
+ }
+}
+#endif
+
+void PersonalOptionsHandler::SendProfilesInfo() {
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ ListValue profile_info_list;
+ FilePath current_profile_path =
+ web_ui_->tab_contents()->browser_context()->GetPath();
+ for (size_t i = 0, e = cache.GetNumberOfProfiles(); i < e; ++i) {
+ DictionaryValue* profile_value = new DictionaryValue();
+ FilePath profile_path = cache.GetPathOfProfileAtIndex(i);
+ profile_value->SetString("name", cache.GetNameOfProfileAtIndex(i));
+ profile_value->Set("filePath", base::CreateFilePathValue(profile_path));
+ profile_value->SetBoolean("isCurrentProfile",
+ profile_path == current_profile_path);
+
+ bool is_gaia_picture =
+ cache.IsUsingGAIAPictureOfProfileAtIndex(i) &&
+ cache.GetGAIAPictureOfProfileAtIndex(i);
+ if (is_gaia_picture) {
+ gfx::Image icon = profiles::GetAvatarIconForWebUI(
+ cache.GetAvatarIconOfProfileAtIndex(i), true);
+ profile_value->SetString("iconURL", web_ui_util::GetImageDataUrl(icon));
+ } else {
+ size_t icon_index = cache.GetAvatarIconIndexOfProfileAtIndex(i);
+ profile_value->SetString("iconURL",
+ cache.GetDefaultAvatarIconUrl(icon_index));
+ }
+
+ profile_info_list.Append(profile_value);
+ }
+
+ web_ui_->CallJavascriptFunction("PersonalOptions.setProfilesInfo",
+ profile_info_list);
+}
+
+void PersonalOptionsHandler::CreateProfile(const ListValue* args) {
+ ProfileManager::CreateMultiProfileAsync();
+}
diff --git a/chrome/browser/ui/webui/options2/personal_options_handler.h b/chrome/browser/ui/webui/options2/personal_options_handler.h
new file mode 100644
index 0000000..06e364b
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/personal_options_handler.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_PERSONAL_OPTIONS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_PERSONAL_OPTIONS_HANDLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#if defined(OS_CHROMEOS)
+#include "content/public/browser/notification_registrar.h"
+#endif
+
+// Chrome personal options page UI handler.
+class PersonalOptionsHandler : public OptionsPage2UIHandler,
+ public ProfileSyncServiceObserver {
+ public:
+ PersonalOptionsHandler();
+ virtual ~PersonalOptionsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings) OVERRIDE;
+ virtual void Initialize() OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // ProfileSyncServiceObserver implementation.
+ virtual void OnStateChanged() OVERRIDE;
+
+ private:
+ void ObserveThemeChanged();
+ void ThemesReset(const ListValue* args);
+#if defined(TOOLKIT_GTK)
+ void ThemesSetGTK(const ListValue* args);
+#endif
+
+#if defined(OS_CHROMEOS)
+ void UpdateAccountPicture();
+ content::NotificationRegistrar registrar_;
+#endif
+
+ // Sends an array of Profile objects to javascript.
+ // Each object is of the form:
+ // profileInfo = {
+ // name: "Profile Name",
+ // iconURL: "chrome://path/to/icon/image",
+ // filePath: "/path/to/profile/data/on/disk",
+ // isCurrentProfile: false
+ // };
+ void SendProfilesInfo();
+
+ // Asynchronously opens a new browser window to create a new profile.
+ // |args| is not used.
+ void CreateProfile(const ListValue* args);
+
+ // True if the multiprofiles switch is enabled.
+ bool multiprofile_;
+
+ DISALLOW_COPY_AND_ASSIGN(PersonalOptionsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_PERSONAL_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/search_engine_manager_browsertest.js b/chrome/browser/ui/webui/options2/search_engine_manager_browsertest.js
new file mode 100644
index 0000000..9fe2165
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/search_engine_manager_browsertest.js
@@ -0,0 +1,33 @@
+// 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.
+
+/**
+ * TestFixture for search engine manager WebUI testing.
+ * @extends {testing.Test}
+ * @constructor
+ **/
+function SearchEngineManagerWebUITest() {}
+
+SearchEngineManagerWebUITest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /**
+ * Browse to the search engine manager.
+ **/
+ browsePreload: 'chrome://settings/searchEngines',
+};
+
+// See crosbug.com/22673
+GEN('#if defined(OS_CHROMEOS)');
+GEN('#define MAYBE_testOpenSearchEngineManager ' +
+ 'DISABLED_testOpenSearchEngineManager');
+GEN('#else');
+GEN('#define MAYBE_testOpenSearchEngineManager testOpenSearchEngineManager');
+GEN('#endif // defined(OS_CHROMEOS)');
+
+// Test opening the search engine manager has correct location.
+TEST_F('SearchEngineManagerWebUITest', 'MAYBE_testOpenSearchEngineManager',
+ function() {
+ assertEquals(this.browsePreload, document.location.href);
+ });
diff --git a/chrome/browser/ui/webui/options2/search_engine_manager_handler.cc b/chrome/browser/ui/webui/options2/search_engine_manager_handler.cc
new file mode 100644
index 0000000..1e289d8
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/search_engine_manager_handler.cc
@@ -0,0 +1,313 @@
+// 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/options2/search_engine_manager_handler.h"
+
+#include "base/bind.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
+#include "chrome/browser/ui/search_engines/template_url_table_model.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/url_constants.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+enum EngineInfoIndexes {
+ ENGINE_NAME,
+ ENGINE_KEYWORD,
+ ENGINE_URL,
+};
+
+}; // namespace
+
+SearchEngineManagerHandler::SearchEngineManagerHandler() {
+}
+
+SearchEngineManagerHandler::~SearchEngineManagerHandler() {
+ if (list_controller_.get() && list_controller_->table_model())
+ list_controller_->table_model()->SetObserver(NULL);
+}
+
+void SearchEngineManagerHandler::Initialize() {
+ list_controller_.reset(
+ new KeywordEditorController(Profile::FromWebUI(web_ui_)));
+ if (list_controller_.get()) {
+ list_controller_->table_model()->SetObserver(this);
+ OnModelChanged();
+ }
+}
+
+void SearchEngineManagerHandler::GetLocalizedValues(
+ base::DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ RegisterTitle(localized_strings, "searchEngineManagerPage",
+ IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE);
+ localized_strings->SetString("defaultSearchEngineListTitle",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR));
+ localized_strings->SetString("otherSearchEngineListTitle",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR));
+ localized_strings->SetString("extensionKeywordsListTitle",
+ l10n_util::GetStringUTF16(
+ IDS_SEARCH_ENGINES_EDITOR_EXTENSIONS_SEPARATOR));
+ localized_strings->SetString("manageExtensionsLinkText",
+ l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS));
+ localized_strings->SetString("searchEngineTableNameHeader",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
+ localized_strings->SetString("searchEngineTableKeywordHeader",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
+ localized_strings->SetString("searchEngineTableURLHeader",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
+ localized_strings->SetString("makeDefaultSearchEngineButton",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
+ localized_strings->SetString("searchEngineTableNamePlaceholder",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_NAME_PLACEHOLDER));
+ localized_strings->SetString("searchEngineTableKeywordPlaceholder",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_KEYWORD_PLACEHOLDER));
+ localized_strings->SetString("searchEngineTableURLPlaceholder",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINE_ADD_NEW_URL_PLACEHOLDER));
+ localized_strings->SetString("editSearchEngineInvalidTitleToolTip",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_TITLE_TT));
+ localized_strings->SetString("editSearchEngineInvalidKeywordToolTip",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT));
+ localized_strings->SetString("editSearchEngineInvalidURLToolTip",
+ l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_INVALID_URL_TT));
+}
+
+void SearchEngineManagerHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback(
+ "managerSetDefaultSearchEngine",
+ base::Bind(&SearchEngineManagerHandler::SetDefaultSearchEngine,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "removeSearchEngine",
+ base::Bind(&SearchEngineManagerHandler::RemoveSearchEngine,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "editSearchEngine",
+ base::Bind(&SearchEngineManagerHandler::EditSearchEngine,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "checkSearchEngineInfoValidity",
+ base::Bind(&SearchEngineManagerHandler::CheckSearchEngineInfoValidity,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "searchEngineEditCancelled",
+ base::Bind(&SearchEngineManagerHandler::EditCancelled,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback(
+ "searchEngineEditCompleted",
+ base::Bind(&SearchEngineManagerHandler::EditCompleted,
+ base::Unretained(this)));
+}
+
+void SearchEngineManagerHandler::OnModelChanged() {
+ if (!list_controller_->loaded())
+ return;
+
+ // Find the default engine.
+ const TemplateURL* default_engine =
+ list_controller_->url_model()->GetDefaultSearchProvider();
+ int default_index = list_controller_->table_model()->IndexOfTemplateURL(
+ default_engine);
+
+ // Build the first list (default search engine options).
+ ListValue defaults_list;
+ int last_default_engine_index =
+ list_controller_->table_model()->last_search_engine_index();
+ for (int i = 0; i < last_default_engine_index; ++i) {
+ defaults_list.Append(CreateDictionaryForEngine(i, i == default_index));
+ }
+
+ // Build the second list (other search templates).
+ ListValue others_list;
+ if (last_default_engine_index < 0)
+ last_default_engine_index = 0;
+ int engine_count = list_controller_->table_model()->RowCount();
+ for (int i = last_default_engine_index; i < engine_count; ++i) {
+ others_list.Append(CreateDictionaryForEngine(i, i == default_index));
+ }
+
+ // Build the extension keywords list.
+ ListValue keyword_list;
+ ExtensionService* extension_service =
+ Profile::FromWebUI(web_ui_)->GetExtensionService();
+ if (extension_service) {
+ const ExtensionSet* extensions = extension_service->extensions();
+ for (ExtensionSet::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ if ((*it)->omnibox_keyword().size() > 0)
+ keyword_list.Append(CreateDictionaryForExtension(*(*it)));
+ }
+ }
+
+ web_ui_->CallJavascriptFunction("SearchEngineManager.updateSearchEngineList",
+ defaults_list, others_list, keyword_list);
+}
+
+void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
+ OnModelChanged();
+}
+
+void SearchEngineManagerHandler::OnItemsAdded(int start, int length) {
+ OnModelChanged();
+}
+
+void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
+ OnModelChanged();
+}
+
+base::DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForExtension(
+ const Extension& extension) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ dict->SetString("name", extension.name());
+ dict->SetString("displayName", extension.name());
+ dict->SetString("keyword", extension.omnibox_keyword());
+ GURL icon = extension.GetIconURL(16, ExtensionIconSet::MATCH_BIGGER);
+ dict->SetString("iconURL", icon.spec());
+ dict->SetString("url", string16());
+ return dict;
+}
+
+base::DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
+ int index, bool is_default) {
+ TemplateURLTableModel* table_model = list_controller_->table_model();
+ const TemplateURL* template_url = list_controller_->GetTemplateURL(index);
+
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ dict->SetString("name", template_url->short_name());
+ dict->SetString("displayName", table_model->GetText(
+ index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
+ dict->SetString("keyword", table_model->GetText(
+ index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
+ dict->SetString("url", template_url->url()->DisplayURL());
+ dict->SetBoolean("urlLocked", template_url->prepopulate_id() > 0);
+ GURL icon_url = template_url->GetFaviconURL();
+ if (icon_url.is_valid())
+ dict->SetString("iconURL", icon_url.spec());
+ dict->SetString("modelIndex", base::IntToString(index));
+
+ if (list_controller_->CanRemove(template_url))
+ dict->SetString("canBeRemoved", "1");
+ if (list_controller_->CanMakeDefault(template_url))
+ dict->SetString("canBeDefault", "1");
+ if (is_default)
+ dict->SetString("default", "1");
+ if (list_controller_->CanEdit(template_url))
+ dict->SetString("canBeEdited", "1");
+
+ return dict;
+}
+
+void SearchEngineManagerHandler::SetDefaultSearchEngine(const ListValue* args) {
+ int index;
+ if (!ExtractIntegerValue(args, &index)) {
+ NOTREACHED();
+ return;
+ }
+ if (index < 0 || index >= list_controller_->table_model()->RowCount())
+ return;
+
+ list_controller_->MakeDefaultTemplateURL(index);
+}
+
+void SearchEngineManagerHandler::RemoveSearchEngine(const ListValue* args) {
+ int index;
+ if (!ExtractIntegerValue(args, &index)) {
+ NOTREACHED();
+ return;
+ }
+ if (index < 0 || index >= list_controller_->table_model()->RowCount())
+ return;
+
+ if (list_controller_->CanRemove(list_controller_->GetTemplateURL(index)))
+ list_controller_->RemoveTemplateURL(index);
+}
+
+void SearchEngineManagerHandler::EditSearchEngine(const ListValue* args) {
+ int index;
+ if (!ExtractIntegerValue(args, &index)) {
+ NOTREACHED();
+ return;
+ }
+ // Allow -1, which means we are adding a new engine.
+ if (index < -1 || index >= list_controller_->table_model()->RowCount())
+ return;
+
+ const TemplateURL* edit_url = NULL;
+ if (index != -1)
+ edit_url = list_controller_->GetTemplateURL(index);
+ edit_controller_.reset(new EditSearchEngineController(
+ edit_url, this, Profile::FromWebUI(web_ui_)));
+}
+
+void SearchEngineManagerHandler::OnEditedKeyword(
+ const TemplateURL* template_url,
+ const string16& title,
+ const string16& keyword,
+ const std::string& url) {
+ if (template_url) {
+ list_controller_->ModifyTemplateURL(template_url, title, keyword, url);
+ } else {
+ list_controller_->AddTemplateURL(title, keyword, url);
+ }
+ edit_controller_.reset();
+}
+
+void SearchEngineManagerHandler::CheckSearchEngineInfoValidity(
+ const ListValue* args)
+{
+ if (!edit_controller_.get())
+ return;
+ string16 name;
+ string16 keyword;
+ std::string url;
+ std::string modelIndex;
+ if (!args->GetString(ENGINE_NAME, &name) ||
+ !args->GetString(ENGINE_KEYWORD, &keyword) ||
+ !args->GetString(ENGINE_URL, &url) ||
+ !args->GetString(3, &modelIndex)) {
+ NOTREACHED();
+ return;
+ }
+
+ base::DictionaryValue validity;
+ validity.SetBoolean("name", edit_controller_->IsTitleValid(name));
+ validity.SetBoolean("keyword", edit_controller_->IsKeywordValid(keyword));
+ validity.SetBoolean("url", edit_controller_->IsURLValid(url));
+ StringValue indexValue(modelIndex);
+ web_ui_->CallJavascriptFunction("SearchEngineManager.validityCheckCallback",
+ validity, indexValue);
+}
+
+void SearchEngineManagerHandler::EditCancelled(const ListValue* args) {
+ if (!edit_controller_.get())
+ return;
+ edit_controller_->CleanUpCancelledAdd();
+ edit_controller_.reset();
+}
+
+void SearchEngineManagerHandler::EditCompleted(const ListValue* args) {
+ if (!edit_controller_.get())
+ return;
+ string16 name;
+ string16 keyword;
+ std::string url;
+ if (!args->GetString(ENGINE_NAME, &name) ||
+ !args->GetString(ENGINE_KEYWORD, &keyword) ||
+ !args->GetString(ENGINE_URL, &url)) {
+ NOTREACHED();
+ return;
+ }
+ edit_controller_->AcceptAddOrEdit(name, keyword, url);
+}
diff --git a/chrome/browser/ui/webui/options2/search_engine_manager_handler.h b/chrome/browser/ui/webui/options2/search_engine_manager_handler.h
new file mode 100644
index 0000000..0d71764
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/search_engine_manager_handler.h
@@ -0,0 +1,79 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_SEARCH_ENGINE_MANAGER_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_SEARCH_ENGINE_MANAGER_HANDLER_H_
+
+#include "chrome/browser/ui/search_engines/edit_search_engine_controller.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+#include "ui/base/models/table_model_observer.h"
+
+class Extension;
+class KeywordEditorController;
+
+class SearchEngineManagerHandler : public OptionsPage2UIHandler,
+ public ui::TableModelObserver,
+ public EditSearchEngineControllerDelegate {
+ public:
+ SearchEngineManagerHandler();
+ virtual ~SearchEngineManagerHandler();
+
+ virtual void Initialize() OVERRIDE;
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // ui::TableModelObserver implementation.
+ virtual void OnModelChanged() OVERRIDE;
+ virtual void OnItemsChanged(int start, int length) OVERRIDE;
+ virtual void OnItemsAdded(int start, int length) OVERRIDE;
+ virtual void OnItemsRemoved(int start, int length) OVERRIDE;
+
+ // EditSearchEngineControllerDelegate implementation.
+ virtual void OnEditedKeyword(const TemplateURL* template_url,
+ const string16& title,
+ const string16& keyword,
+ const std::string& url) OVERRIDE;
+
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ scoped_ptr<KeywordEditorController> list_controller_;
+ scoped_ptr<EditSearchEngineController> edit_controller_;
+
+ // Removes the search engine at the given index. Called from WebUI.
+ void RemoveSearchEngine(const base::ListValue* args);
+
+ // Sets the search engine at the given index to be default. Called from WebUI.
+ void SetDefaultSearchEngine(const base::ListValue* args);
+
+ // Starts an edit session for the search engine at the given index. If the
+ // index is -1, starts editing a new search engine instead of an existing one.
+ // Called from WebUI.
+ void EditSearchEngine(const base::ListValue* args);
+
+ // Validates the given search engine values, and reports the results back
+ // to WebUI. Called from WebUI.
+ void CheckSearchEngineInfoValidity(const base::ListValue* args);
+
+ // Called when an edit is cancelled.
+ // Called from WebUI.
+ void EditCancelled(const base::ListValue* args);
+
+ // Called when an edit is finished and should be saved.
+ // Called from WebUI.
+ void EditCompleted(const base::ListValue* args);
+
+ // Returns a dictionary to pass to WebUI representing the given search engine.
+ base::DictionaryValue* CreateDictionaryForEngine(int index, bool is_default);
+
+ // Returns a dictionary to pass to WebUI representing the extension.
+ base::DictionaryValue* CreateDictionaryForExtension(
+ const Extension& extension);
+
+ DISALLOW_COPY_AND_ASSIGN(SearchEngineManagerHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_SEARCH_ENGINE_MANAGER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/stop_syncing_handler.cc b/chrome/browser/ui/webui/options2/stop_syncing_handler.cc
new file mode 100644
index 0000000..550cc4c
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/stop_syncing_handler.cc
@@ -0,0 +1,54 @@
+// 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/options2/stop_syncing_handler.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+StopSyncingHandler::StopSyncingHandler() {
+}
+
+StopSyncingHandler::~StopSyncingHandler() {
+}
+
+void StopSyncingHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+ localized_strings->SetString("stopSyncingExplanation",
+ l10n_util::GetStringFUTF16(
+ IDS_SYNC_STOP_SYNCING_EXPLANATION_LABEL,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
+ ASCIIToUTF16(google_util::StringAppendGoogleLocaleParam(
+ chrome::kSyncGoogleDashboardURL))));
+ localized_strings->SetString("stopSyncingTitle",
+ l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_DIALOG_TITLE));
+ localized_strings->SetString("stopSyncingConfirm",
+ l10n_util::GetStringUTF16(IDS_SYNC_STOP_SYNCING_CONFIRM_BUTTON_LABEL));
+}
+
+void StopSyncingHandler::RegisterMessages() {
+ DCHECK(web_ui_);
+ web_ui_->RegisterMessageCallback("stopSyncing",
+ base::Bind(&StopSyncingHandler::StopSyncing, base::Unretained(this)));
+}
+
+void StopSyncingHandler::StopSyncing(const ListValue* args){
+ ProfileSyncService* service =
+ Profile::FromWebUI(web_ui_)->GetProfileSyncService();
+ if (service != NULL && ProfileSyncService::IsSyncEnabled()) {
+ service->DisableForUser();
+ ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
+ }
+}
diff --git a/chrome/browser/ui/webui/options2/stop_syncing_handler.h b/chrome/browser/ui/webui/options2/stop_syncing_handler.h
new file mode 100644
index 0000000..b9c3ad5
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/stop_syncing_handler.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_STOP_SYNCING_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_STOP_SYNCING_HANDLER_H_
+
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+// Chrome personal stuff stop syncing overlay UI handler.
+class StopSyncingHandler : public OptionsPage2UIHandler {
+ public:
+ StopSyncingHandler();
+ virtual ~StopSyncingHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ void StopSyncing(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(StopSyncingHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_STOP_SYNCING_HANDLER_H_
diff --git a/chrome/browser/ui/webui/options2/web_intents_settings_handler.cc b/chrome/browser/ui/webui/options2/web_intents_settings_handler.cc
new file mode 100644
index 0000000..874cf834
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/web_intents_settings_handler.cc
@@ -0,0 +1,160 @@
+// 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/options2/web_intents_settings_handler.h"
+
+#include "base/bind.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data_file_system_helper.h"
+#include "chrome/browser/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "chrome/browser/intents/web_intents_registry.h"
+#include "chrome/browser/intents/web_intents_registry_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/webdata/web_data_service.h"
+#include "content/browser/webui/web_ui.h"
+#include "grit/generated_resources.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "ui/base/l10n/l10n_util.h"
+
+WebIntentsSettingsHandler::WebIntentsSettingsHandler()
+ : web_intents_registry_(NULL),
+ batch_update_(false) {
+}
+
+WebIntentsSettingsHandler::~WebIntentsSettingsHandler() {
+}
+
+void WebIntentsSettingsHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ static OptionsStringResource resources[] = {
+ { "intentsDomain", IDS_INTENTS_DOMAIN_COLUMN_HEADER },
+ { "intentsServiceData", IDS_INTENTS_SERVICE_DATA_COLUMN_HEADER },
+ { "manageIntents", IDS_INTENTS_MANAGE_BUTTON },
+ { "removeIntent", IDS_INTENTS_REMOVE_INTENT_BUTTON },
+ };
+
+ RegisterStrings(localized_strings, resources, arraysize(resources));
+ RegisterTitle(localized_strings, "intentsViewPage",
+ IDS_INTENTS_MANAGER_WINDOW_TITLE);
+}
+
+void WebIntentsSettingsHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("removeIntent",
+ base::Bind(&WebIntentsSettingsHandler::RemoveIntent,
+ base::Unretained(this)));
+ web_ui_->RegisterMessageCallback("loadIntents",
+ base::Bind(&WebIntentsSettingsHandler::LoadChildren,
+ base::Unretained(this)));
+}
+
+void WebIntentsSettingsHandler::TreeNodesAdded(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) {
+ SendChildren(intents_tree_model_->GetRoot());
+}
+
+void WebIntentsSettingsHandler::TreeNodesRemoved(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) {
+ SendChildren(intents_tree_model_->GetRoot());
+}
+
+void WebIntentsSettingsHandler::TreeModelBeginBatch(WebIntentsModel* model) {
+ batch_update_ = true;
+}
+
+void WebIntentsSettingsHandler::TreeModelEndBatch(WebIntentsModel* model) {
+ batch_update_ = false;
+
+ SendChildren(intents_tree_model_->GetRoot());
+}
+
+void WebIntentsSettingsHandler::EnsureWebIntentsModelCreated() {
+ if (intents_tree_model_.get()) return;
+
+ Profile* profile = Profile::FromWebUI(web_ui_);
+ web_intents_registry_ = WebIntentsRegistryFactory::GetForProfile(profile);
+ intents_tree_model_.reset(new WebIntentsModel(web_intents_registry_));
+ intents_tree_model_->AddWebIntentsTreeObserver(this);
+}
+
+void WebIntentsSettingsHandler::RemoveIntent(const base::ListValue* args) {
+ std::string node_path;
+ if (!args->GetString(0, &node_path)) {
+ return;
+ }
+
+ EnsureWebIntentsModelCreated();
+
+ WebIntentsTreeNode* node = intents_tree_model_->GetTreeNode(node_path);
+ if (node->Type() == WebIntentsTreeNode::TYPE_ORIGIN) {
+ RemoveOrigin(node);
+ } else if (node->Type() == WebIntentsTreeNode::TYPE_SERVICE) {
+ ServiceTreeNode* snode = static_cast<ServiceTreeNode*>(node);
+ RemoveService(snode);
+ }
+}
+
+void WebIntentsSettingsHandler::RemoveOrigin(WebIntentsTreeNode* node) {
+ // TODO(gbillock): This is a known batch update. Worth optimizing?
+ while (!node->empty()) {
+ WebIntentsTreeNode* cnode = node->GetChild(0);
+ CHECK(cnode->Type() == WebIntentsTreeNode::TYPE_SERVICE);
+ ServiceTreeNode* snode = static_cast<ServiceTreeNode*>(cnode);
+ RemoveService(snode);
+ }
+ delete intents_tree_model_->Remove(node->parent(), node);
+}
+
+void WebIntentsSettingsHandler::RemoveService(ServiceTreeNode* snode) {
+ webkit_glue::WebIntentServiceData service;
+ service.service_url = GURL(snode->ServiceUrl());
+ service.action = snode->Action();
+ string16 stype;
+ if (snode->Types().GetString(0, &stype)) {
+ service.type = stype; // Really need to iterate here.
+ }
+ service.title = snode->ServiceName();
+ web_intents_registry_->UnregisterIntentProvider(service);
+ delete intents_tree_model_->Remove(snode->parent(), snode);
+}
+
+void WebIntentsSettingsHandler::LoadChildren(const base::ListValue* args) {
+ EnsureWebIntentsModelCreated();
+
+ std::string node_path;
+ if (!args->GetString(0, &node_path)) {
+ SendChildren(intents_tree_model_->GetRoot());
+ return;
+ }
+
+ WebIntentsTreeNode* node = intents_tree_model_->GetTreeNode(node_path);
+ SendChildren(node);
+}
+
+void WebIntentsSettingsHandler::SendChildren(WebIntentsTreeNode* parent) {
+ // Early bailout during batch updates. We'll get one after the batch concludes
+ // with batch_update_ set false.
+ if (batch_update_) return;
+
+ ListValue* children = new ListValue;
+ intents_tree_model_->GetChildNodeList(parent, 0, parent->child_count(),
+ children);
+
+ ListValue args;
+ args.Append(parent == intents_tree_model_->GetRoot() ?
+ Value::CreateNullValue() :
+ Value::CreateStringValue(intents_tree_model_->GetTreeNodeId(parent)));
+ args.Append(children);
+
+ web_ui_->CallJavascriptFunction("IntentsView.loadChildren", args);
+}
diff --git a/chrome/browser/ui/webui/options2/web_intents_settings_handler.h b/chrome/browser/ui/webui/options2/web_intents_settings_handler.h
new file mode 100644
index 0000000..6a8edf2
--- /dev/null
+++ b/chrome/browser/ui/webui/options2/web_intents_settings_handler.h
@@ -0,0 +1,77 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS2_WEB_INTENTS_SETTINGS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS2_WEB_INTENTS_SETTINGS_HANDLER_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/intents/web_intents_model.h"
+#include "chrome/browser/ui/webui/options2/options_ui.h"
+
+class WebIntentsRegistry;
+
+// Manage setting up the backing data for the web intents options page.
+class WebIntentsSettingsHandler : public OptionsPage2UIHandler,
+ public WebIntentsModel::Observer {
+ public:
+ WebIntentsSettingsHandler();
+ virtual ~WebIntentsSettingsHandler();
+
+ // OptionsPage2UIHandler implementation.
+ virtual void GetLocalizedValues(
+ base::DictionaryValue* localized_strings) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ // WebIntentsModel::Observer implementation.
+ virtual void TreeNodesAdded(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) OVERRIDE;
+ virtual void TreeNodesRemoved(ui::TreeModel* model,
+ ui::TreeModelNode* parent,
+ int start,
+ int count) OVERRIDE;
+ virtual void TreeNodeChanged(ui::TreeModel* model,
+ ui::TreeModelNode* node) OVERRIDE {}
+ virtual void TreeModelBeginBatch(WebIntentsModel* model) OVERRIDE;
+ virtual void TreeModelEndBatch(WebIntentsModel* model) OVERRIDE;
+
+ private:
+ // Creates the WebIntentsModel if neccessary.
+ void EnsureWebIntentsModelCreated();
+
+ // Updates search filter for cookies tree model.
+ void UpdateSearchResults(const base::ListValue* args);
+
+ // Remove all sites data.
+ void RemoveAll(const base::ListValue* args);
+
+ // Remove selected sites data.
+ void RemoveIntent(const base::ListValue* args);
+
+ // Helper functions for removals.
+ void RemoveOrigin(WebIntentsTreeNode* node);
+ void RemoveService(ServiceTreeNode* snode);
+
+ // Trigger for SendChildren to load the JS model.
+ void LoadChildren(const base::ListValue* args);
+
+ // Get children nodes data and pass it to 'IntentsView.loadChildren' to
+ // update the WebUI.
+ void SendChildren(WebIntentsTreeNode* parent);
+
+ WebIntentsRegistry* web_intents_registry_; // Weak pointer.
+
+ // Backing data model for the intents list.
+ scoped_ptr<WebIntentsModel> intents_tree_model_;
+
+ // Flag to indicate whether there is a batch update in progress.
+ bool batch_update_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebIntentsSettingsHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS2_WEB_INTENTS_SETTINGS_HANDLER_H_