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 "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" 17 18 namespace extensions { 19 20 namespace keys = manifest_keys; 21 namespace errors = manifest_errors; 22 23 InputComponentInfo::InputComponentInfo() 24 : type(INPUT_COMPONENT_TYPE_NONE), 25 shortcut_alt(false), 26 shortcut_ctrl(false), 27 shortcut_shift(false) { 28 } 29 30 InputComponentInfo::~InputComponentInfo() {} 31 32 InputComponents::InputComponents() {} 33 InputComponents::~InputComponents() {} 34 35 // static 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 43 InputComponentsHandler::InputComponentsHandler() { 44 } 45 46 InputComponentsHandler::~InputComponentsHandler() { 47 } 48 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::OptionsPageInfo::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> 234 InputComponentsHandler::PrerequisiteKeys() const { 235 return SingleKey(keys::kOptionsPage); 236 } 237 238 const std::vector<std::string> InputComponentsHandler::Keys() const { 239 return SingleKey(keys::kInputComponents); 240 } 241 242 } // namespace extensions 243