1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/extensions/api/input_ime/input_components_handler.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "extensions/common/error_utils.h"
13 #include "extensions/common/extension.h"
14 #include "extensions/common/manifest.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "extensions/common/manifest_handlers/options_page_info.h"
18 namespace extensions
{
20 namespace keys
= manifest_keys
;
21 namespace errors
= manifest_errors
;
23 InputComponentInfo::InputComponentInfo()
24 : type(INPUT_COMPONENT_TYPE_NONE
),
27 shortcut_shift(false) {
30 InputComponentInfo::~InputComponentInfo() {}
32 InputComponents::InputComponents() {}
33 InputComponents::~InputComponents() {}
36 const std::vector
<InputComponentInfo
>* InputComponents::GetInputComponents(
37 const Extension
* extension
) {
38 InputComponents
* info
= static_cast<InputComponents
*>(
39 extension
->GetManifestData(keys::kInputComponents
));
40 return info
? &info
->input_components
: NULL
;
43 InputComponentsHandler::InputComponentsHandler() {
46 InputComponentsHandler::~InputComponentsHandler() {
49 bool InputComponentsHandler::Parse(Extension
* extension
,
50 base::string16
* error
) {
51 scoped_ptr
<InputComponents
> info(new InputComponents
);
52 const base::ListValue
* list_value
= NULL
;
53 if (!extension
->manifest()->GetList(keys::kInputComponents
, &list_value
)) {
54 *error
= base::ASCIIToUTF16(errors::kInvalidInputComponents
);
57 for (size_t i
= 0; i
< list_value
->GetSize(); ++i
) {
58 const base::DictionaryValue
* module_value
= NULL
;
60 InputComponentType type
;
62 std::string description_str
;
63 std::set
<std::string
> languages
;
64 std::set
<std::string
> layouts
;
65 std::string shortcut_keycode_str
;
67 GURL options_page_url
;
68 bool shortcut_alt
= false;
69 bool shortcut_ctrl
= false;
70 bool shortcut_shift
= false;
72 if (!list_value
->GetDictionary(i
, &module_value
)) {
73 *error
= base::ASCIIToUTF16(errors::kInvalidInputComponents
);
77 // Get input_components[i].name.
78 if (!module_value
->GetString(keys::kName
, &name_str
)) {
79 *error
= ErrorUtils::FormatErrorMessageUTF16(
80 errors::kInvalidInputComponentName
,
81 base::IntToString(i
));
85 // Get input_components[i].type.
87 if (module_value
->GetString(keys::kType
, &type_str
)) {
88 if (type_str
== "ime") {
89 type
= INPUT_COMPONENT_TYPE_IME
;
91 *error
= ErrorUtils::FormatErrorMessageUTF16(
92 errors::kInvalidInputComponentType
,
93 base::IntToString(i
));
97 *error
= ErrorUtils::FormatErrorMessageUTF16(
98 errors::kInvalidInputComponentType
,
99 base::IntToString(i
));
103 // Get input_components[i].id.
104 if (!module_value
->GetString(keys::kId
, &id_str
)) {
108 // Get input_components[i].description.
109 if (!module_value
->GetString(keys::kDescription
, &description_str
)) {
110 *error
= ErrorUtils::FormatErrorMessageUTF16(
111 errors::kInvalidInputComponentDescription
,
112 base::IntToString(i
));
116 // Get input_components[i].language.
117 // Both string and list of string are allowed to be compatibile with old
118 // input_ime manifest specification.
119 const base::Value
* language_value
= NULL
;
120 if (module_value
->Get(keys::kLanguage
, &language_value
)) {
121 if (language_value
->GetType() == base::Value::TYPE_STRING
) {
122 std::string language_str
;
123 language_value
->GetAsString(&language_str
);
124 languages
.insert(language_str
);
125 } else if (language_value
->GetType() == base::Value::TYPE_LIST
) {
126 const base::ListValue
* language_list
= NULL
;
127 language_value
->GetAsList(&language_list
);
128 for (size_t j
= 0; j
< language_list
->GetSize(); ++j
) {
129 std::string language_str
;
130 if (language_list
->GetString(j
, &language_str
))
131 languages
.insert(language_str
);
136 // Get input_components[i].layouts.
137 const base::ListValue
* layouts_value
= NULL
;
138 if (module_value
->GetList(keys::kLayouts
, &layouts_value
)) {
139 for (size_t j
= 0; j
< layouts_value
->GetSize(); ++j
) {
140 std::string layout_name_str
;
141 if (!layouts_value
->GetString(j
, &layout_name_str
)) {
142 *error
= ErrorUtils::FormatErrorMessageUTF16(
143 errors::kInvalidInputComponentLayoutName
,
144 base::IntToString(i
), base::IntToString(j
));
147 layouts
.insert(layout_name_str
);
151 if (module_value
->HasKey(keys::kShortcutKey
)) {
152 const base::DictionaryValue
* shortcut_value
= NULL
;
153 if (!module_value
->GetDictionary(keys::kShortcutKey
,
155 *error
= ErrorUtils::FormatErrorMessageUTF16(
156 errors::kInvalidInputComponentShortcutKey
,
157 base::IntToString(i
));
161 // Get input_components[i].shortcut_keycode.
162 if (!shortcut_value
->GetString(keys::kKeycode
, &shortcut_keycode_str
)) {
163 *error
= ErrorUtils::FormatErrorMessageUTF16(
164 errors::kInvalidInputComponentShortcutKeycode
,
165 base::IntToString(i
));
169 // Get input_components[i].shortcut_alt.
170 if (!shortcut_value
->GetBoolean(keys::kAltKey
, &shortcut_alt
)) {
171 shortcut_alt
= false;
174 // Get input_components[i].shortcut_ctrl.
175 if (!shortcut_value
->GetBoolean(keys::kCtrlKey
, &shortcut_ctrl
)) {
176 shortcut_ctrl
= false;
179 // Get input_components[i].shortcut_shift.
180 if (!shortcut_value
->GetBoolean(keys::kShiftKey
, &shortcut_shift
)) {
181 shortcut_shift
= false;
185 // Get input_components[i].input_view_url.
186 // Note: 'input_view' is optional in manifest.
187 std::string input_view_str
;
188 if (module_value
->GetString(keys::kInputView
, &input_view_str
)) {
189 input_view_url
= extension
->GetResourceURL(input_view_str
);
190 if (!input_view_url
.is_valid()) {
191 *error
= ErrorUtils::FormatErrorMessageUTF16(
192 errors::kInvalidInputView
,
193 base::IntToString(i
));
198 // Get input_components[i].options_page_url.
199 // Note: 'options_page' is optional in manifest.
200 std::string options_page_str
;
201 if (module_value
->GetString(keys::kImeOptionsPage
, &options_page_str
)) {
202 options_page_url
= extension
->GetResourceURL(options_page_str
);
203 if (!options_page_url
.is_valid()) {
204 *error
= ErrorUtils::FormatErrorMessageUTF16(
205 errors::kInvalidOptionsPage
,
206 base::IntToString(i
));
210 // Fall back to extension's options page for backward compatibility.
211 options_page_url
= extensions::OptionsPageInfo::GetOptionsPage(extension
);
214 info
->input_components
.push_back(InputComponentInfo());
215 info
->input_components
.back().name
= name_str
;
216 info
->input_components
.back().type
= type
;
217 info
->input_components
.back().id
= id_str
;
218 info
->input_components
.back().description
= description_str
;
219 info
->input_components
.back().languages
= languages
;
220 info
->input_components
.back().layouts
.insert(layouts
.begin(),
222 info
->input_components
.back().shortcut_keycode
= shortcut_keycode_str
;
223 info
->input_components
.back().shortcut_alt
= shortcut_alt
;
224 info
->input_components
.back().shortcut_ctrl
= shortcut_ctrl
;
225 info
->input_components
.back().shortcut_shift
= shortcut_shift
;
226 info
->input_components
.back().options_page_url
= options_page_url
;
227 info
->input_components
.back().input_view_url
= input_view_url
;
229 extension
->SetManifestData(keys::kInputComponents
, info
.release());
233 const std::vector
<std::string
>
234 InputComponentsHandler::PrerequisiteKeys() const {
235 return SingleKey(keys::kOptionsPage
);
238 const std::vector
<std::string
> InputComponentsHandler::Keys() const {
239 return SingleKey(keys::kInputComponents
);
242 } // namespace extensions