• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/common/extensions/api/input_ime/input_components_handler.h"
6 
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 "chrome/common/extensions/manifest_url_handler.h"
13 #include "extensions/common/error_utils.h"
14 #include "extensions/common/extension.h"
15 #include "extensions/common/manifest.h"
16 #include "extensions/common/manifest_constants.h"
17 
18 namespace extensions {
19 
20 namespace keys = manifest_keys;
21 namespace errors = manifest_errors;
22 
InputComponentInfo()23 InputComponentInfo::InputComponentInfo()
24     : type(INPUT_COMPONENT_TYPE_NONE),
25       shortcut_alt(false),
26       shortcut_ctrl(false),
27       shortcut_shift(false) {
28 }
29 
~InputComponentInfo()30 InputComponentInfo::~InputComponentInfo() {}
31 
InputComponents()32 InputComponents::InputComponents() {}
~InputComponents()33 InputComponents::~InputComponents() {}
34 
35 // static
GetInputComponents(const Extension * extension)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;
41 }
42 
InputComponentsHandler()43 InputComponentsHandler::InputComponentsHandler() {
44 }
45 
~InputComponentsHandler()46 InputComponentsHandler::~InputComponentsHandler() {
47 }
48 
Parse(Extension * extension,base::string16 * error)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);
55     return false;
56   }
57   for (size_t i = 0; i < list_value->GetSize(); ++i) {
58     const base::DictionaryValue* module_value = NULL;
59     std::string name_str;
60     InputComponentType type;
61     std::string id_str;
62     std::string description_str;
63     std::set<std::string> languages;
64     std::set<std::string> layouts;
65     std::string shortcut_keycode_str;
66     GURL input_view_url;
67     GURL options_page_url;
68     bool shortcut_alt = false;
69     bool shortcut_ctrl = false;
70     bool shortcut_shift = false;
71 
72     if (!list_value->GetDictionary(i, &module_value)) {
73       *error = base::ASCIIToUTF16(errors::kInvalidInputComponents);
74       return false;
75     }
76 
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));
82       return false;
83     }
84 
85     // Get input_components[i].type.
86     std::string type_str;
87     if (module_value->GetString(keys::kType, &type_str)) {
88       if (type_str == "ime") {
89         type = INPUT_COMPONENT_TYPE_IME;
90       } else {
91         *error = ErrorUtils::FormatErrorMessageUTF16(
92             errors::kInvalidInputComponentType,
93             base::IntToString(i));
94         return false;
95       }
96     } else {
97       *error = ErrorUtils::FormatErrorMessageUTF16(
98           errors::kInvalidInputComponentType,
99           base::IntToString(i));
100       return false;
101     }
102 
103     // Get input_components[i].id.
104     if (!module_value->GetString(keys::kId, &id_str)) {
105       id_str = "";
106     }
107 
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));
113       return false;
114     }
115 
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);
132         }
133       }
134     }
135 
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));
145           return false;
146         }
147         layouts.insert(layout_name_str);
148       }
149     }
150 
151     if (module_value->HasKey(keys::kShortcutKey)) {
152       const base::DictionaryValue* shortcut_value = NULL;
153       if (!module_value->GetDictionary(keys::kShortcutKey,
154           &shortcut_value)) {
155         *error = ErrorUtils::FormatErrorMessageUTF16(
156             errors::kInvalidInputComponentShortcutKey,
157             base::IntToString(i));
158         return false;
159       }
160 
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));
166         return false;
167       }
168 
169       // Get input_components[i].shortcut_alt.
170       if (!shortcut_value->GetBoolean(keys::kAltKey, &shortcut_alt)) {
171         shortcut_alt = false;
172       }
173 
174       // Get input_components[i].shortcut_ctrl.
175       if (!shortcut_value->GetBoolean(keys::kCtrlKey, &shortcut_ctrl)) {
176         shortcut_ctrl = false;
177       }
178 
179       // Get input_components[i].shortcut_shift.
180       if (!shortcut_value->GetBoolean(keys::kShiftKey, &shortcut_shift)) {
181         shortcut_shift = false;
182       }
183     }
184 
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));
194         return false;
195       }
196     }
197 
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));
207         return false;
208       }
209     } else {
210       // Fall back to extension's options page for backward compatibility.
211       options_page_url = extensions::ManifestURL::GetOptionsPage(extension);
212     }
213 
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(),
221         layouts.end());
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;
228   }
229   extension->SetManifestData(keys::kInputComponents, info.release());
230   return true;
231 }
232 
233 const std::vector<std::string>
PrerequisiteKeys() const234 InputComponentsHandler::PrerequisiteKeys() const {
235   return SingleKey(keys::kOptionsPage);
236 }
237 
Keys() const238 const std::vector<std::string> InputComponentsHandler::Keys() const {
239   return SingleKey(keys::kInputComponents);
240 }
241 
242 }  // namespace extensions
243