Home | History | Annotate | Download | only in input_ime
      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