Commit 7a53a30e authored by kevers@chromium.org's avatar kevers@chromium.org

Add confirmation dialog when enabling a 3rd party IME.

Based on patch 290083004. Third party IMEs provide a privacy risk as they can monitor everything you type. The patch provides an additional measure of security by prompting the user for confirmation with a warning of the potential risks.

BUG=367861

Review URL: https://codereview.chromium.org/325633003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276535 0039d316-1c4b-4281-b951-d872f2087c98
parent 87f8e3c4
...@@ -3240,6 +3240,14 @@ Press any key to continue exploring. ...@@ -3240,6 +3240,14 @@ Press any key to continue exploring.
desc="The label for languages with no Input Methods"> desc="The label for languages with no Input Methods">
This language doesn't have any input methods This language doesn't have any input methods
</message> </message>
<message name="IDS_OPTIONS_SETTINGS_LANGUAGES_THIRD_PARTY_WARNING_TITLE"
desc="The title showing in the warning dialog when enabling a 3rd party Input Method">
Third party input method
</message>
<message name="IDS_OPTIONS_SETTINGS_LANGUAGES_THIRD_PARTY_WARNING_MESSAGE"
desc="The description showing in the warning dialog when enabling a 3rd party Input Method">
This input method may be able to collect all the text you type, including personal data like passwords and credit card numbers. It comes from the extension &quot;<ph name="EXTENSION_NAME">$1<ex>Google Input Tools extension</ex></ph>&quot;. Use this input method?
</message>
<message name="IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON" <message name="IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON"
desc="The label for the sign out button for changing UI language"> desc="The label for the sign out button for changing UI language">
Sign out Sign out
......
/* Copyright 2014 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.
*/
#third-party-ime-confirm-overlay {
width: 500px;
}
<div id="third-party-ime-confirm-overlay" class="page" hidden>
<div class="close-button"></div>
<h1 i18n-content="thirdPartyImeConfirmOverlay"></h1>
<div class="content-area">
<span id="third-party-ime-confirm-text"
i18n-content="thirdPartyImeConfirmMessage">
</span>
</div>
<div class="action-area">
<div class="action-area-right">
<div class="button-strip">
<button id="third-party-ime-confirm-cancel"
i18n-content="thirdPartyImeConfirmDisable">
</button>
<button id="third-party-ime-confirm-ok" class="default-button"
i18n-content="thirdPartyImeConfirmEnable">
</button>
</div>
</div>
</div>
</div>
// Copyright 2014 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.
cr.define('options', function() {
/** @const */ var OptionsPage = options.OptionsPage;
/** @const */ var SettingsDialog = options.SettingsDialog;
/**
* HomePageOverlay class
* Dialog that allows users to set the home page.
* @extends {SettingsDialog}
*/
function ThirdPartyImeConfirmOverlay() {
SettingsDialog.call(
this, 'thirdPartyImeConfirm',
loadTimeData.getString('thirdPartyImeConfirmOverlayTabTitle'),
'third-party-ime-confirm-overlay',
$('third-party-ime-confirm-ok'),
$('third-party-ime-confirm-cancel'));
}
cr.addSingletonGetter(ThirdPartyImeConfirmOverlay);
ThirdPartyImeConfirmOverlay.prototype = {
__proto__: SettingsDialog.prototype,
/**
* Callback to authorize use of an input method.
* @type {Function}
* @private
*/
confirmationCallback_: null,
/**
* Callback to cancel enabling an input method.
* @type {Function}
* @private
*/
cancellationCallback_: null,
/**
* Confirms enabling of a third party IME.
*/
handleConfirm: function() {
SettingsDialog.prototype.handleConfirm.call(this);
this.confirmationCallback_();
},
/**
* Resets state of the checkobx.
*/
handleCancel: function() {
SettingsDialog.prototype.handleCancel.call(this);
this.cancellationCallback_();
},
/**
* Displays a confirmation dialog indicating the risk fo enabling
* a third party IME.
* @param {{extension: string, confirm: Function, cancel: Function}} data
* Options for the confirmation dialog.
* @private
*/
showConfirmationDialog_: function(data) {
this.confirmationCallback_ = data.confirm;
this.cancellationCallback_ = data.cancel;
var message = loadTimeData.getStringF('thirdPartyImeConfirmMessage',
data.extension);
$('third-party-ime-confirm-text').textContent = message;
OptionsPage.showPageByName(this.name, false);
},
};
/**
* Displays a confirmation dialog indicating the risk fo enabling
* a third party IME.
* @param {{extension: string, confirm: Function, cancel: Function}} data
* Options for the confirmation dialog.
*/
ThirdPartyImeConfirmOverlay.showConfirmationDialog = function(data) {
ThirdPartyImeConfirmOverlay.getInstance().showConfirmationDialog_(data);
};
// Export
return {
ThirdPartyImeConfirmOverlay: ThirdPartyImeConfirmOverlay
};
});
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
cr.define('options', function() { cr.define('options', function() {
/** @const */ var OptionsPage = options.OptionsPage; /** @const */ var OptionsPage = options.OptionsPage;
/** @const */ var LanguageList = options.LanguageList; /** @const */ var LanguageList = options.LanguageList;
/** @const */ var ThirdPartyImeConfirmOverlay =
options.ThirdPartyImeConfirmOverlay;
/** /**
* Spell check dictionary download status. * Spell check dictionary download status.
...@@ -318,6 +320,7 @@ cr.define('options', function() { ...@@ -318,6 +320,7 @@ cr.define('options', function() {
var input = element.querySelector('input'); var input = element.querySelector('input');
input.inputMethodId = inputMethod.id; input.inputMethodId = inputMethod.id;
input.imeProvider = inputMethod.extensionName;
var span = element.querySelector('span'); var span = element.querySelector('span');
span.textContent = inputMethod.displayName; span.textContent = inputMethod.displayName;
...@@ -823,6 +826,31 @@ cr.define('options', function() { ...@@ -823,6 +826,31 @@ cr.define('options', function() {
handleCheckboxClick_: function(e) { handleCheckboxClick_: function(e) {
var checkbox = e.target; var checkbox = e.target;
// Third party IMEs require additional confirmation prior to enabling due
// to privacy risk.
if (/^_ext_ime_/.test(checkbox.inputMethodId) && checkbox.checked) {
var confirmationCallback = this.handleCheckboxUpdate_.bind(this,
checkbox);
var cancellationCallback = function() {
checkbox.checked = false;
};
ThirdPartyImeConfirmOverlay.showConfirmationDialog({
extension: checkbox.imeProvider,
confirm: confirmationCallback,
cancel: cancellationCallback
});
} else {
this.handleCheckboxUpdate_(checkbox);
}
},
/**
* Updates active IMEs based on change in state of a checkbox for an input
* method.
* @param {!Element} checkbox Updated checkbox element.
* @private
*/
handleCheckboxUpdate_: function(checkbox) {
if (checkbox.inputMethodId.match(/^_ext_ime_/)) { if (checkbox.inputMethodId.match(/^_ext_ime_/)) {
this.updateEnabledExtensionsFromCheckboxes_(); this.updateEnabledExtensionsFromCheckboxes_();
this.saveEnabledExtensionPref_(); this.saveEnabledExtensionPref_();
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
<link rel="stylesheet" href="startup_overlay.css"> <link rel="stylesheet" href="startup_overlay.css">
<link rel="stylesheet" href="../sync_setup_overlay.css"> <link rel="stylesheet" href="../sync_setup_overlay.css">
<if expr="chromeos"> <if expr="chromeos">
<link rel="stylesheet" href="chromeos/third_party_ime_confirm_overlay.css">
<link rel="stylesheet" href="chromeos/accounts_options_page.css"> <link rel="stylesheet" href="chromeos/accounts_options_page.css">
<link rel="stylesheet" href="chromeos/bluetooth.css"> <link rel="stylesheet" href="chromeos/bluetooth.css">
<link rel="stylesheet" href="chromeos/change_picture_options.css"> <link rel="stylesheet" href="chromeos/change_picture_options.css">
...@@ -151,6 +152,7 @@ ...@@ -151,6 +152,7 @@
<include src="chromeos/display_overscan.html"> <include src="chromeos/display_overscan.html">
<include src="chromeos/internet_detail.html"> <include src="chromeos/internet_detail.html">
<include src="chromeos/preferred_networks.html"> <include src="chromeos/preferred_networks.html">
<include src="chromeos/third_party_ime_confirm_overlay.html">
</if> </if>
<if expr="not is_win and not is_macosx"> <if expr="not is_win and not is_macosx">
<include src="certificate_restore_overlay.html"> <include src="certificate_restore_overlay.html">
......
...@@ -41,6 +41,7 @@ var SearchEngineManager = options.SearchEngineManager; ...@@ -41,6 +41,7 @@ var SearchEngineManager = options.SearchEngineManager;
var SearchPage = options.SearchPage; var SearchPage = options.SearchPage;
var StartupOverlay = options.StartupOverlay; var StartupOverlay = options.StartupOverlay;
var SyncSetupOverlay = options.SyncSetupOverlay; var SyncSetupOverlay = options.SyncSetupOverlay;
var ThirdPartyImeConfirmOverlay = options.ThirdPartyImeConfirmOverlay;
/** /**
* DOMContentLoaded handler, sets up the page. * DOMContentLoaded handler, sets up the page.
...@@ -201,6 +202,8 @@ function load() { ...@@ -201,6 +202,8 @@ function load() {
[$('pointer-settings-button')]); [$('pointer-settings-button')]);
OptionsPage.registerOverlay(PreferredNetworks.getInstance(), OptionsPage.registerOverlay(PreferredNetworks.getInstance(),
BrowserOptions.getInstance()); BrowserOptions.getInstance());
OptionsPage.registerOverlay(ThirdPartyImeConfirmOverlay.getInstance(),
LanguageOptions.getInstance());
} }
if (!cr.isWindows && !cr.isMac) { if (!cr.isWindows && !cr.isMac) {
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
<include src="chromeos/display_overscan.js"></include> <include src="chromeos/display_overscan.js"></include>
<include src="chromeos/keyboard_overlay.js"></include> <include src="chromeos/keyboard_overlay.js"></include>
<include src="chromeos/pointer_overlay.js"></include> <include src="chromeos/pointer_overlay.js"></include>
<include src="chromeos/third_party_ime_confirm_overlay.js"></include>
var AccountsOptions = options.AccountsOptions; var AccountsOptions = options.AccountsOptions;
var ChangePictureOptions = options.ChangePictureOptions; var ChangePictureOptions = options.ChangePictureOptions;
var DetailsInternetPage = options.internet.DetailsInternetPage; var DetailsInternetPage = options.internet.DetailsInternetPage;
......
...@@ -414,6 +414,10 @@ void BrowserOptionsHandler::GetLocalizedValues(base::DictionaryValue* values) { ...@@ -414,6 +414,10 @@ void BrowserOptionsHandler::GetLocalizedValues(base::DictionaryValue* values) {
{ "securityTitle", IDS_OPTIONS_SECURITY_SECTION_TITLE }, { "securityTitle", IDS_OPTIONS_SECURITY_SECTION_TITLE },
{ "syncOverview", IDS_SYNC_OVERVIEW }, { "syncOverview", IDS_SYNC_OVERVIEW },
{ "syncButtonTextStart", IDS_SYNC_SETUP_BUTTON_LABEL }, { "syncButtonTextStart", IDS_SYNC_SETUP_BUTTON_LABEL },
{ "thirdPartyImeConfirmEnable", IDS_OK },
{ "thirdPartyImeConfirmDisable", IDS_CANCEL },
{ "thirdPartyImeConfirmMessage",
IDS_OPTIONS_SETTINGS_LANGUAGES_THIRD_PARTY_WARNING_MESSAGE },
{ "timezone", IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION }, { "timezone", IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION },
{ "use24HourClock", IDS_OPTIONS_SETTINGS_USE_24HOUR_CLOCK_DESCRIPTION }, { "use24HourClock", IDS_OPTIONS_SETTINGS_USE_24HOUR_CLOCK_DESCRIPTION },
#else #else
...@@ -603,6 +607,9 @@ void BrowserOptionsHandler::GetLocalizedValues(base::DictionaryValue* values) { ...@@ -603,6 +607,9 @@ void BrowserOptionsHandler::GetLocalizedValues(base::DictionaryValue* values) {
"consumerManagementEnabled", "consumerManagementEnabled",
CommandLine::ForCurrentProcess()->HasSwitch( CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kEnableConsumerManagement)); chromeos::switches::kEnableConsumerManagement));
RegisterTitle(values, "thirdPartyImeConfirmOverlay",
IDS_OPTIONS_SETTINGS_LANGUAGES_THIRD_PARTY_WARNING_TITLE);
#endif #endif
} }
......
...@@ -119,9 +119,11 @@ void CrosLanguageOptionsHandler::GetLocalizedValues( ...@@ -119,9 +119,11 @@ void CrosLanguageOptionsHandler::GetLocalizedValues(
input_method::InputMethodDescriptors ext_ime_descriptors; input_method::InputMethodDescriptors ext_ime_descriptors;
manager->GetInputMethodExtensions(&ext_ime_descriptors); manager->GetInputMethodExtensions(&ext_ime_descriptors);
localized_strings->Set("extensionImeList",
ConvertInputMethodDescriptosToIMEList( base::ListValue* ext_ime_list = ConvertInputMethodDescriptorsToIMEList(
ext_ime_descriptors)); ext_ime_descriptors);
AddImeProvider(ext_ime_list);
localized_strings->Set("extensionImeList", ext_ime_list);
ComponentExtensionIMEManager* component_extension_manager = ComponentExtensionIMEManager* component_extension_manager =
input_method::InputMethodManager::Get() input_method::InputMethodManager::Get()
...@@ -129,7 +131,7 @@ void CrosLanguageOptionsHandler::GetLocalizedValues( ...@@ -129,7 +131,7 @@ void CrosLanguageOptionsHandler::GetLocalizedValues(
if (component_extension_manager->IsInitialized()) { if (component_extension_manager->IsInitialized()) {
localized_strings->Set( localized_strings->Set(
"componentExtensionImeList", "componentExtensionImeList",
ConvertInputMethodDescriptosToIMEList( ConvertInputMethodDescriptorsToIMEList(
component_extension_manager->GetAllIMEAsInputMethodDescriptor())); component_extension_manager->GetAllIMEAsInputMethodDescriptor()));
composition_extension_appended_ = true; composition_extension_appended_ = true;
} else { } else {
...@@ -157,6 +159,7 @@ void CrosLanguageOptionsHandler::RegisterMessages() { ...@@ -157,6 +159,7 @@ void CrosLanguageOptionsHandler::RegisterMessages() {
base::Unretained(this))); base::Unretained(this)));
} }
// static
base::ListValue* CrosLanguageOptionsHandler::GetInputMethodList( base::ListValue* CrosLanguageOptionsHandler::GetInputMethodList(
const input_method::InputMethodDescriptors& descriptors) { const input_method::InputMethodDescriptors& descriptors) {
input_method::InputMethodManager* manager = input_method::InputMethodManager* manager =
...@@ -418,7 +421,7 @@ base::ListValue* CrosLanguageOptionsHandler::GetUILanguageList( ...@@ -418,7 +421,7 @@ base::ListValue* CrosLanguageOptionsHandler::GetUILanguageList(
} }
base::ListValue* base::ListValue*
CrosLanguageOptionsHandler::ConvertInputMethodDescriptosToIMEList( CrosLanguageOptionsHandler::ConvertInputMethodDescriptorsToIMEList(
const input_method::InputMethodDescriptors& descriptors) { const input_method::InputMethodDescriptors& descriptors) {
scoped_ptr<base::ListValue> ime_ids_list(new base::ListValue()); scoped_ptr<base::ListValue> ime_ids_list(new base::ListValue());
for (size_t i = 0; i < descriptors.size(); ++i) { for (size_t i = 0; i < descriptors.size(); ++i) {
...@@ -519,7 +522,7 @@ void CrosLanguageOptionsHandler::OnImeComponentExtensionInitialized() { ...@@ -519,7 +522,7 @@ void CrosLanguageOptionsHandler::OnImeComponentExtensionInitialized() {
DCHECK(manager->IsInitialized()); DCHECK(manager->IsInitialized());
scoped_ptr<base::ListValue> ime_list( scoped_ptr<base::ListValue> ime_list(
ConvertInputMethodDescriptosToIMEList( ConvertInputMethodDescriptorsToIMEList(
manager->GetAllIMEAsInputMethodDescriptor())); manager->GetAllIMEAsInputMethodDescriptor()));
web_ui()->CallJavascriptFunction( web_ui()->CallJavascriptFunction(
"options.LanguageOptions.onComponentManagerInitialized", "options.LanguageOptions.onComponentManagerInitialized",
...@@ -542,7 +545,7 @@ void CrosLanguageOptionsHandler::InitializePage() { ...@@ -542,7 +545,7 @@ void CrosLanguageOptionsHandler::InitializePage() {
} }
scoped_ptr<base::ListValue> ime_list( scoped_ptr<base::ListValue> ime_list(
ConvertInputMethodDescriptosToIMEList( ConvertInputMethodDescriptorsToIMEList(
component_extension_manager->GetAllIMEAsInputMethodDescriptor())); component_extension_manager->GetAllIMEAsInputMethodDescriptor()));
web_ui()->CallJavascriptFunction( web_ui()->CallJavascriptFunction(
"options.LanguageOptions.onComponentManagerInitialized", "options.LanguageOptions.onComponentManagerInitialized",
...@@ -550,5 +553,24 @@ void CrosLanguageOptionsHandler::InitializePage() { ...@@ -550,5 +553,24 @@ void CrosLanguageOptionsHandler::InitializePage() {
composition_extension_appended_ = true; composition_extension_appended_ = true;
} }
void CrosLanguageOptionsHandler::AddImeProvider(base::ListValue* list) {
Profile* profile = Profile::FromWebUI(web_ui());
ExtensionService* extension_service = profile->GetExtensionService();
for (size_t i = 0; i < list->GetSize(); i++) {
base::DictionaryValue* entry;
list->GetDictionary(i, &entry);
std::string input_method_id;
entry->GetString("id", &input_method_id);
std::string extension_id =
extension_ime_util::GetExtensionIDFromInputMethodID(input_method_id);
const extensions::Extension* extension =
extension_service->GetExtensionById(extension_id, false);
if (extension)
entry->SetString("extensionName", extension->name());
}
}
} // namespace options } // namespace options
} // namespace chromeos } // namespace chromeos
...@@ -71,7 +71,7 @@ class CrosLanguageOptionsHandler ...@@ -71,7 +71,7 @@ class CrosLanguageOptionsHandler
// The return value will look like: // The return value will look like:
// [{'id': '_ext_ime_nejguenhnsnjnwychcnsdsdjketest', // [{'id': '_ext_ime_nejguenhnsnjnwychcnsdsdjketest',
// 'displayName': 'Sample IME'}, ...] // 'displayName': 'Sample IME'}, ...]
static base::ListValue* ConvertInputMethodDescriptosToIMEList( static base::ListValue* ConvertInputMethodDescriptorsToIMEList(
const input_method::InputMethodDescriptors& descriptors); const input_method::InputMethodDescriptors& descriptors);
private: private:
...@@ -110,6 +110,10 @@ class CrosLanguageOptionsHandler ...@@ -110,6 +110,10 @@ class CrosLanguageOptionsHandler
// OptionsPageUIHandler implementation. // OptionsPageUIHandler implementation.
virtual void InitializePage() OVERRIDE; virtual void InitializePage() OVERRIDE;
// Adds the name of the extension that provides the IME to each entry in the
// |list| of extension IMEs.
void AddImeProvider(base::ListValue* list);
// True if the component extension list was appended into input method list. // True if the component extension list was appended into input method list.
bool composition_extension_appended_; bool composition_extension_appended_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment