1 // Copyright 2013 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/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
9 #include "base/files/file_util.h"
10 #include "base/json/json_string_value_serializer.h"
11 #include "base/logging.h"
12 #include "base/path_service.h"
13 #include "base/strings/string_util.h"
14 #include "base/sys_info.h"
15 #include "chrome/browser/extensions/component_loader.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/extensions/extension_file_util.h"
22 #include "chrome/grit/browser_resources.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "chromeos/ime/extension_ime_util.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/extension_l10n_util.h"
29 #include "extensions/common/file_util.h"
30 #include "extensions/common/manifest_constants.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
38 struct WhitelistedComponentExtensionIME
{
40 int manifest_resource_id
;
41 } whitelisted_component_extension
[] = {
42 {// ChromeOS Hangul Input.
43 extension_ime_util::kHangulExtensionId
, IDR_HANGUL_MANIFEST
,
45 #if defined(GOOGLE_CHROME_BUILD)
46 {// Official Google XKB Input.
47 extension_ime_util::kXkbExtensionId
, IDR_GOOGLE_XKB_MANIFEST
,
49 {// Google input tools.
50 extension_ime_util::kT13nExtensionId
, IDR_GOOGLE_INPUT_TOOLS_MANIFEST
,
53 {// Open-sourced ChromeOS xkb extension.
54 extension_ime_util::kXkbExtensionId
, IDR_XKB_MANIFEST
,
56 {// Open-sourced ChromeOS Keyboards extension.
57 extension_ime_util::kM17nExtensionId
, IDR_M17N_MANIFEST
,
59 {// Open-sourced Pinyin Chinese Input Method.
60 extension_ime_util::kChinesePinyinExtensionId
, IDR_PINYIN_MANIFEST
,
62 {// Open-sourced Zhuyin Chinese Input Method.
63 extension_ime_util::kChineseZhuyinExtensionId
, IDR_ZHUYIN_MANIFEST
,
65 {// Open-sourced Cangjie Chinese Input Method.
66 extension_ime_util::kChineseCangjieExtensionId
, IDR_CANGJIE_MANIFEST
,
68 {// Japanese Mozc Input.
69 extension_ime_util::kMozcExtensionId
, IDR_MOZC_MANIFEST
,
72 {// Braille hardware keyboard IME that works together with ChromeVox.
73 extension_misc::kBrailleImeExtensionId
, IDR_BRAILLE_MANIFEST
,
77 const struct InputMethodNameMap
{
78 const char* message_name
;
80 bool operator<(const InputMethodNameMap
& other
) const {
81 return strcmp(message_name
, other
.message_name
) < 0;
83 } kInputMethodNameMap
[] = {
84 {"__MSG_INPUTMETHOD_ARRAY__", IDS_IME_NAME_INPUTMETHOD_ARRAY
},
85 {"__MSG_INPUTMETHOD_CANGJIE__", IDS_IME_NAME_INPUTMETHOD_CANGJIE
},
86 {"__MSG_INPUTMETHOD_DAYI__", IDS_IME_NAME_INPUTMETHOD_DAYI
},
87 {"__MSG_INPUTMETHOD_HANGUL_2_SET__",
88 IDS_IME_NAME_INPUTMETHOD_HANGUL_2_SET
},
89 {"__MSG_INPUTMETHOD_HANGUL_3_SET_390__",
90 IDS_IME_NAME_INPUTMETHOD_HANGUL_3_SET_390
},
91 {"__MSG_INPUTMETHOD_HANGUL_3_SET_FINAL__",
92 IDS_IME_NAME_INPUTMETHOD_HANGUL_3_SET_FINAL
},
93 {"__MSG_INPUTMETHOD_HANGUL_3_SET_NO_SHIFT__",
94 IDS_IME_NAME_INPUTMETHOD_HANGUL_3_SET_NO_SHIFT
},
95 {"__MSG_INPUTMETHOD_HANGUL_AHNMATAE__",
96 IDS_IME_NAME_INPUTMETHOD_HANGUL_AHNMATAE
},
97 {"__MSG_INPUTMETHOD_HANGUL_ROMAJA__",
98 IDS_IME_NAME_INPUTMETHOD_HANGUL_ROMAJA
},
99 {"__MSG_INPUTMETHOD_MOZC_JP__", IDS_IME_NAME_INPUTMETHOD_MOZC_JP
},
100 {"__MSG_INPUTMETHOD_MOZC_US__", IDS_IME_NAME_INPUTMETHOD_MOZC_US
},
101 {"__MSG_INPUTMETHOD_PINYIN__", IDS_IME_NAME_INPUTMETHOD_PINYIN
},
102 {"__MSG_INPUTMETHOD_QUICK__", IDS_IME_NAME_INPUTMETHOD_QUICK
},
103 {"__MSG_INPUTMETHOD_TRADITIONAL_PINYIN__",
104 IDS_IME_NAME_INPUTMETHOD_TRADITIONAL_PINYIN
},
105 {"__MSG_INPUTMETHOD_WUBI__", IDS_IME_NAME_INPUTMETHOD_WUBI
},
106 {"__MSG_INPUTMETHOD_ZHUYIN__", IDS_IME_NAME_INPUTMETHOD_ZHUYIN
},
107 {"__MSG_KEYBOARD_ARABIC__", IDS_IME_NAME_KEYBOARD_ARABIC
},
108 {"__MSG_KEYBOARD_ARMENIAN_PHONETIC__",
109 IDS_IME_NAME_KEYBOARD_ARMENIAN_PHONETIC
},
110 {"__MSG_KEYBOARD_BELARUSIAN__", IDS_IME_NAME_KEYBOARD_BELARUSIAN
},
111 {"__MSG_KEYBOARD_BELGIAN__", IDS_IME_NAME_KEYBOARD_BELGIAN
},
112 {"__MSG_KEYBOARD_BENGALI_PHONETIC__",
113 IDS_IME_NAME_KEYBOARD_BENGALI_PHONETIC
},
114 {"__MSG_KEYBOARD_BRAZILIAN__", IDS_IME_NAME_KEYBOARD_BRAZILIAN
},
115 {"__MSG_KEYBOARD_BULGARIAN_PHONETIC__",
116 IDS_IME_NAME_KEYBOARD_BULGARIAN_PHONETIC
},
117 {"__MSG_KEYBOARD_BULGARIAN__", IDS_IME_NAME_KEYBOARD_BULGARIAN
},
118 {"__MSG_KEYBOARD_CANADIAN_ENGLISH__",
119 IDS_IME_NAME_KEYBOARD_CANADIAN_ENGLISH
},
120 {"__MSG_KEYBOARD_CANADIAN_FRENCH__",
121 IDS_IME_NAME_KEYBOARD_CANADIAN_FRENCH
},
122 {"__MSG_KEYBOARD_CANADIAN_MULTILINGUAL__",
123 IDS_IME_NAME_KEYBOARD_CANADIAN_MULTILINGUAL
},
124 {"__MSG_KEYBOARD_CATALAN__", IDS_IME_NAME_KEYBOARD_CATALAN
},
125 {"__MSG_KEYBOARD_CROATIAN__", IDS_IME_NAME_KEYBOARD_CROATIAN
},
126 {"__MSG_KEYBOARD_CZECH_QWERTY__", IDS_IME_NAME_KEYBOARD_CZECH_QWERTY
},
127 {"__MSG_KEYBOARD_CZECH__", IDS_IME_NAME_KEYBOARD_CZECH
},
128 {"__MSG_KEYBOARD_DANISH__", IDS_IME_NAME_KEYBOARD_DANISH
},
129 {"__MSG_KEYBOARD_DEVANAGARI_PHONETIC__",
130 IDS_IME_NAME_KEYBOARD_DEVANAGARI_PHONETIC
},
131 {"__MSG_KEYBOARD_ESTONIAN__", IDS_IME_NAME_KEYBOARD_ESTONIAN
},
132 {"__MSG_KEYBOARD_ETHIOPIC__", IDS_IME_NAME_KEYBOARD_ETHIOPIC
},
133 {"__MSG_KEYBOARD_FINNISH__", IDS_IME_NAME_KEYBOARD_FINNISH
},
134 {"__MSG_KEYBOARD_FRENCH__", IDS_IME_NAME_KEYBOARD_FRENCH
},
135 {"__MSG_KEYBOARD_GEORGIAN__", IDS_IME_NAME_KEYBOARD_GEORGIAN
},
136 {"__MSG_KEYBOARD_GERMAN_NEO_2__", IDS_IME_NAME_KEYBOARD_GERMAN_NEO_2
},
137 {"__MSG_KEYBOARD_GERMAN__", IDS_IME_NAME_KEYBOARD_GERMAN
},
138 {"__MSG_KEYBOARD_GREEK__", IDS_IME_NAME_KEYBOARD_GREEK
},
139 {"__MSG_KEYBOARD_GUJARATI_PHONETIC__",
140 IDS_IME_NAME_KEYBOARD_GUJARATI_PHONETIC
},
141 {"__MSG_KEYBOARD_HEBREW__", IDS_IME_NAME_KEYBOARD_HEBREW
},
142 {"__MSG_KEYBOARD_HUNGARIAN__", IDS_IME_NAME_KEYBOARD_HUNGARIAN
},
143 {"__MSG_KEYBOARD_ICELANDIC__", IDS_IME_NAME_KEYBOARD_ICELANDIC
},
144 {"__MSG_KEYBOARD_IRISH__", IDS_IME_NAME_KEYBOARD_IRISH
},
145 {"__MSG_KEYBOARD_ITALIAN__", IDS_IME_NAME_KEYBOARD_ITALIAN
},
146 {"__MSG_KEYBOARD_JAPANESE__", IDS_IME_NAME_KEYBOARD_JAPANESE
},
147 {"__MSG_KEYBOARD_KANNADA_PHONETIC__",
148 IDS_IME_NAME_KEYBOARD_KANNADA_PHONETIC
},
149 {"__MSG_KEYBOARD_KHMER__", IDS_IME_NAME_KEYBOARD_KHMER
},
150 {"__MSG_KEYBOARD_LAO__", IDS_IME_NAME_KEYBOARD_LAO
},
151 {"__MSG_KEYBOARD_LATIN_AMERICAN__", IDS_IME_NAME_KEYBOARD_LATIN_AMERICAN
},
152 {"__MSG_KEYBOARD_LATVIAN__", IDS_IME_NAME_KEYBOARD_LATVIAN
},
153 {"__MSG_KEYBOARD_LITHUANIAN__", IDS_IME_NAME_KEYBOARD_LITHUANIAN
},
154 {"__MSG_KEYBOARD_MALAYALAM_PHONETIC__",
155 IDS_IME_NAME_KEYBOARD_MALAYALAM_PHONETIC
},
156 {"__MSG_KEYBOARD_MALTESE__", IDS_IME_NAME_KEYBOARD_MALTESE
},
157 {"__MSG_KEYBOARD_MONGOLIAN__", IDS_IME_NAME_KEYBOARD_MONGOLIAN
},
158 {"__MSG_KEYBOARD_MYANMAR_MYANSAN__",
159 IDS_IME_NAME_KEYBOARD_MYANMAR_MYANSAN
},
160 {"__MSG_KEYBOARD_MYANMAR__", IDS_IME_NAME_KEYBOARD_MYANMAR
},
161 {"__MSG_KEYBOARD_NEPALI_INSCRIPT__",
162 IDS_IME_NAME_KEYBOARD_NEPALI_INSCRIPT
},
163 {"__MSG_KEYBOARD_NEPALI_PHONETIC__",
164 IDS_IME_NAME_KEYBOARD_NEPALI_PHONETIC
},
165 {"__MSG_KEYBOARD_NORWEGIAN__", IDS_IME_NAME_KEYBOARD_NORWEGIAN
},
166 {"__MSG_KEYBOARD_PERSIAN__", IDS_IME_NAME_KEYBOARD_PERSIAN
},
167 {"__MSG_KEYBOARD_POLISH__", IDS_IME_NAME_KEYBOARD_POLISH
},
168 {"__MSG_KEYBOARD_PORTUGUESE__", IDS_IME_NAME_KEYBOARD_PORTUGUESE
},
169 {"__MSG_KEYBOARD_ROMANIAN__", IDS_IME_NAME_KEYBOARD_ROMANIAN
},
170 {"__MSG_KEYBOARD_RUSSIAN_PHONETIC_AATSEEL__",
171 IDS_IME_NAME_KEYBOARD_RUSSIAN_PHONETIC_AATSEEL
},
172 {"__MSG_KEYBOARD_RUSSIAN_PHONETIC_YAZHERT__",
173 IDS_IME_NAME_KEYBOARD_RUSSIAN_PHONETIC_YAZHERT
},
174 {"__MSG_KEYBOARD_RUSSIAN_PHONETIC__",
175 IDS_IME_NAME_KEYBOARD_RUSSIAN_PHONETIC
},
176 {"__MSG_KEYBOARD_RUSSIAN__", IDS_IME_NAME_KEYBOARD_RUSSIAN
},
177 {"__MSG_KEYBOARD_SERBIAN__", IDS_IME_NAME_KEYBOARD_SERBIAN
},
178 {"__MSG_KEYBOARD_SINHALA__", IDS_IME_NAME_KEYBOARD_SINHALA
},
179 {"__MSG_KEYBOARD_SLOVAKIAN__", IDS_IME_NAME_KEYBOARD_SLOVAKIAN
},
180 {"__MSG_KEYBOARD_SLOVENIAN__", IDS_IME_NAME_KEYBOARD_SLOVENIAN
},
181 {"__MSG_KEYBOARD_SORANIKURDISH_AR__",
182 IDS_IME_NAME_KEYBOARD_SORANIKURDISH_AR
},
183 {"__MSG_KEYBOARD_SORANIKURDISH_EN__",
184 IDS_IME_NAME_KEYBOARD_SORANIKURDISH_EN
},
185 {"__MSG_KEYBOARD_SPANISH__", IDS_IME_NAME_KEYBOARD_SPANISH
},
186 {"__MSG_KEYBOARD_SWEDISH__", IDS_IME_NAME_KEYBOARD_SWEDISH
},
187 {"__MSG_KEYBOARD_SWISS_FRENCH__", IDS_IME_NAME_KEYBOARD_SWISS_FRENCH
},
188 {"__MSG_KEYBOARD_SWISS__", IDS_IME_NAME_KEYBOARD_SWISS
},
189 {"__MSG_KEYBOARD_TAMIL_INSCRIPT__", IDS_IME_NAME_KEYBOARD_TAMIL_INSCRIPT
},
190 {"__MSG_KEYBOARD_TAMIL_ITRANS__", IDS_IME_NAME_KEYBOARD_TAMIL_ITRANS
},
191 {"__MSG_KEYBOARD_TAMIL_PHONETIC__", IDS_IME_NAME_KEYBOARD_TAMIL_PHONETIC
},
192 {"__MSG_KEYBOARD_TAMIL_TAMIL99__", IDS_IME_NAME_KEYBOARD_TAMIL_TAMIL99
},
193 {"__MSG_KEYBOARD_TAMIL_TYPEWRITER__",
194 IDS_IME_NAME_KEYBOARD_TAMIL_TYPEWRITER
},
195 {"__MSG_KEYBOARD_TELUGU_PHONETIC__",
196 IDS_IME_NAME_KEYBOARD_TELUGU_PHONETIC
},
197 {"__MSG_KEYBOARD_THAI_KEDMANEE__", IDS_IME_NAME_KEYBOARD_THAI_KEDMANEE
},
198 {"__MSG_KEYBOARD_THAI_PATTACHOTE__",
199 IDS_IME_NAME_KEYBOARD_THAI_PATTACHOTE
},
200 {"__MSG_KEYBOARD_THAI_TIS__", IDS_IME_NAME_KEYBOARD_THAI_TIS
},
201 {"__MSG_KEYBOARD_TURKISH__", IDS_IME_NAME_KEYBOARD_TURKISH
},
202 {"__MSG_KEYBOARD_UKRAINIAN__", IDS_IME_NAME_KEYBOARD_UKRAINIAN
},
203 {"__MSG_KEYBOARD_UK_DVORAK__", IDS_IME_NAME_KEYBOARD_UK_DVORAK
},
204 {"__MSG_KEYBOARD_UK__", IDS_IME_NAME_KEYBOARD_UK
},
205 {"__MSG_KEYBOARD_US_COLEMAK__", IDS_IME_NAME_KEYBOARD_US_COLEMAK
},
206 {"__MSG_KEYBOARD_US_DVORAK__", IDS_IME_NAME_KEYBOARD_US_DVORAK
},
207 {"__MSG_KEYBOARD_US_EXTENDED__", IDS_IME_NAME_KEYBOARD_US_EXTENDED
},
208 {"__MSG_KEYBOARD_US_INTERNATIONAL__",
209 IDS_IME_NAME_KEYBOARD_US_INTERNATIONAL
},
210 {"__MSG_KEYBOARD_US__", IDS_IME_NAME_KEYBOARD_US
},
211 {"__MSG_KEYBOARD_VIETNAMESE_TCVN__",
212 IDS_IME_NAME_KEYBOARD_VIETNAMESE_TCVN
},
213 {"__MSG_KEYBOARD_VIETNAMESE_TELEX__",
214 IDS_IME_NAME_KEYBOARD_VIETNAMESE_TELEX
},
215 {"__MSG_KEYBOARD_VIETNAMESE_VIQR__",
216 IDS_IME_NAME_KEYBOARD_VIETNAMESE_VIQR
},
217 {"__MSG_KEYBOARD_VIETNAMESE_VNI__", IDS_IME_NAME_KEYBOARD_VIETNAMESE_VNI
},
218 {"__MSG_TRANSLITERATION_AM__", IDS_IME_NAME_TRANSLITERATION_AM
},
219 {"__MSG_TRANSLITERATION_AR__", IDS_IME_NAME_TRANSLITERATION_AR
},
220 {"__MSG_TRANSLITERATION_BN__", IDS_IME_NAME_TRANSLITERATION_BN
},
221 {"__MSG_TRANSLITERATION_EL__", IDS_IME_NAME_TRANSLITERATION_EL
},
222 {"__MSG_TRANSLITERATION_FA__", IDS_IME_NAME_TRANSLITERATION_FA
},
223 {"__MSG_TRANSLITERATION_GU__", IDS_IME_NAME_TRANSLITERATION_GU
},
224 {"__MSG_TRANSLITERATION_HE__", IDS_IME_NAME_TRANSLITERATION_HE
},
225 {"__MSG_TRANSLITERATION_HI__", IDS_IME_NAME_TRANSLITERATION_HI
},
226 {"__MSG_TRANSLITERATION_KN__", IDS_IME_NAME_TRANSLITERATION_KN
},
227 {"__MSG_TRANSLITERATION_ML__", IDS_IME_NAME_TRANSLITERATION_ML
},
228 {"__MSG_TRANSLITERATION_MR__", IDS_IME_NAME_TRANSLITERATION_MR
},
229 {"__MSG_TRANSLITERATION_NE__", IDS_IME_NAME_TRANSLITERATION_NE
},
230 {"__MSG_TRANSLITERATION_OR__", IDS_IME_NAME_TRANSLITERATION_OR
},
231 {"__MSG_TRANSLITERATION_PA__", IDS_IME_NAME_TRANSLITERATION_PA
},
232 {"__MSG_TRANSLITERATION_SA__", IDS_IME_NAME_TRANSLITERATION_SA
},
233 {"__MSG_TRANSLITERATION_SR__", IDS_IME_NAME_TRANSLITERATION_SR
},
234 {"__MSG_TRANSLITERATION_TA__", IDS_IME_NAME_TRANSLITERATION_TA
},
235 {"__MSG_TRANSLITERATION_TE__", IDS_IME_NAME_TRANSLITERATION_TE
},
236 {"__MSG_TRANSLITERATION_TI__", IDS_IME_NAME_TRANSLITERATION_TI
},
237 {"__MSG_TRANSLITERATION_UR__", IDS_IME_NAME_TRANSLITERATION_UR
},
240 const char kImePathKeyName
[] = "ime_path";
242 extensions::ComponentLoader
* GetComponentLoader(Profile
* profile
) {
243 extensions::ExtensionSystem
* extension_system
=
244 extensions::ExtensionSystem::Get(profile
);
245 ExtensionService
* extension_service
= extension_system
->extension_service();
246 return extension_service
->component_loader();
249 void DoLoadExtension(Profile
* profile
,
250 const std::string
& extension_id
,
251 const std::string
& manifest
,
252 const base::FilePath
& file_path
) {
253 extensions::ExtensionSystem
* extension_system
=
254 extensions::ExtensionSystem::Get(profile
);
255 ExtensionService
* extension_service
= extension_system
->extension_service();
256 if (extension_service
->GetExtensionById(extension_id
, false))
258 const std::string loaded_extension_id
=
259 GetComponentLoader(profile
)->Add(manifest
, file_path
);
260 DCHECK_EQ(loaded_extension_id
, extension_id
);
263 bool CheckFilePath(const base::FilePath
* file_path
) {
264 return base::PathExists(*file_path
);
267 void OnFilePathChecked(Profile
* profile
,
268 const std::string
* extension_id
,
269 const std::string
* manifest
,
270 const base::FilePath
* file_path
,
273 DoLoadExtension(profile
, *extension_id
, *manifest
, *file_path
);
275 LOG(ERROR
) << "IME extension file path not exists: " << file_path
->value();
280 ComponentExtensionIMEManagerImpl::ComponentExtensionIMEManagerImpl() {
281 ReadComponentExtensionsInfo(&component_extension_list_
);
284 ComponentExtensionIMEManagerImpl::~ComponentExtensionIMEManagerImpl() {
287 std::vector
<ComponentExtensionIME
> ComponentExtensionIMEManagerImpl::ListIME() {
288 return component_extension_list_
;
291 void ComponentExtensionIMEManagerImpl::Load(Profile
* profile
,
292 const std::string
& extension_id
,
293 const std::string
& manifest
,
294 const base::FilePath
& file_path
) {
295 if (base::SysInfo::IsRunningOnChromeOS()) {
296 // In the case of real Chrome OS device, the no need to check the file path
297 // for preinstalled files existence.
298 DoLoadExtension(profile
, extension_id
, manifest
, file_path
);
301 // If current environment is linux_chromeos, check the existence of file path
302 // to avoid unnecessary extension loading and InputMethodEngine creation, so
303 // that the virtual keyboard web content url won't be override by IME
304 // component extensions.
305 base::FilePath
* copied_file_path
= new base::FilePath(file_path
);
306 content::BrowserThread::PostTaskAndReplyWithResult(
307 content::BrowserThread::FILE,
309 base::Bind(&CheckFilePath
,
310 base::Unretained(copied_file_path
)),
311 base::Bind(&OnFilePathChecked
,
312 base::Unretained(profile
),
313 base::Owned(new std::string(extension_id
)),
314 base::Owned(new std::string(manifest
)),
315 base::Owned(copied_file_path
)));
318 void ComponentExtensionIMEManagerImpl::Unload(Profile
* profile
,
319 const std::string
& extension_id
,
320 const base::FilePath
& file_path
) {
321 // Remove(extension_id) does nothing when the extension has already been
322 // removed or not been registered.
323 GetComponentLoader(profile
)->Remove(extension_id
);
326 scoped_ptr
<base::DictionaryValue
> ComponentExtensionIMEManagerImpl::GetManifest(
327 const std::string
& manifest_string
) {
329 JSONStringValueSerializer
serializer(manifest_string
);
330 scoped_ptr
<base::Value
> manifest(serializer
.Deserialize(NULL
, &error
));
332 LOG(ERROR
) << "Failed at getting manifest";
334 return scoped_ptr
<base::DictionaryValue
>(
335 static_cast<base::DictionaryValue
*>(manifest
.release())).Pass();
339 bool ComponentExtensionIMEManagerImpl::ReadEngineComponent(
340 const ComponentExtensionIME
& component_extension
,
341 const base::DictionaryValue
& dict
,
342 ComponentExtensionEngine
* out
) {
345 if (!dict
.GetString(extensions::manifest_keys::kType
, &type
))
349 if (!dict
.GetString(extensions::manifest_keys::kId
, &out
->engine_id
))
351 if (!dict
.GetString(extensions::manifest_keys::kName
, &out
->display_name
))
353 if (!dict
.GetString(extensions::manifest_keys::kIndicator
, &out
->indicator
))
356 // Localizes the input method name.
357 if (out
->display_name
.find("__MSG_") == 0) {
358 const InputMethodNameMap
* map
= kInputMethodNameMap
;
359 size_t map_size
= arraysize(kInputMethodNameMap
);
360 std::string name
= StringToUpperASCII(out
->display_name
);
361 const InputMethodNameMap map_key
= {name
.c_str(), 0};
362 const InputMethodNameMap
* p
=
363 std::lower_bound(map
, map
+ map_size
, map_key
);
364 if (p
!= map
+ map_size
&& name
== p
->message_name
)
365 out
->display_name
= l10n_util::GetStringUTF8(p
->resource_id
);
367 DCHECK(out
->display_name
.find("__MSG_") == std::string::npos
);
369 std::set
<std::string
> languages
;
370 const base::Value
* language_value
= NULL
;
371 if (dict
.Get(extensions::manifest_keys::kLanguage
, &language_value
)) {
372 if (language_value
->GetType() == base::Value::TYPE_STRING
) {
373 std::string language_str
;
374 language_value
->GetAsString(&language_str
);
375 languages
.insert(language_str
);
376 } else if (language_value
->GetType() == base::Value::TYPE_LIST
) {
377 const base::ListValue
* language_list
= NULL
;
378 language_value
->GetAsList(&language_list
);
379 for (size_t j
= 0; j
< language_list
->GetSize(); ++j
) {
380 std::string language_str
;
381 if (language_list
->GetString(j
, &language_str
))
382 languages
.insert(language_str
);
386 DCHECK(!languages
.empty());
387 out
->language_codes
.assign(languages
.begin(), languages
.end());
389 const base::ListValue
* layouts
= NULL
;
390 if (!dict
.GetList(extensions::manifest_keys::kLayouts
, &layouts
))
393 for (size_t i
= 0; i
< layouts
->GetSize(); ++i
) {
395 if (layouts
->GetString(i
, &buffer
))
396 out
->layouts
.push_back(buffer
);
399 std::string url_string
;
400 if (dict
.GetString(extensions::manifest_keys::kInputView
,
402 GURL url
= extensions::Extension::GetResourceURL(
403 extensions::Extension::GetBaseURLFromExtensionId(
404 component_extension
.id
),
408 out
->input_view_url
= url
;
411 if (dict
.GetString(extensions::manifest_keys::kOptionsPage
,
413 GURL url
= extensions::Extension::GetResourceURL(
414 extensions::Extension::GetBaseURLFromExtensionId(
415 component_extension
.id
),
419 out
->options_page_url
= url
;
421 // Fallback to extension level options page.
422 out
->options_page_url
= component_extension
.options_page_url
;
429 bool ComponentExtensionIMEManagerImpl::ReadExtensionInfo(
430 const base::DictionaryValue
& manifest
,
431 const std::string
& extension_id
,
432 ComponentExtensionIME
* out
) {
433 if (!manifest
.GetString(extensions::manifest_keys::kDescription
,
437 if (manifest
.GetString(kImePathKeyName
, &path
))
438 out
->path
= base::FilePath(path
);
439 std::string url_string
;
440 if (manifest
.GetString(extensions::manifest_keys::kOptionsPage
,
442 GURL url
= extensions::Extension::GetResourceURL(
443 extensions::Extension::GetBaseURLFromExtensionId(extension_id
),
447 out
->options_page_url
= url
;
449 // It's okay to return true on no option page and/or input view page case.
454 void ComponentExtensionIMEManagerImpl::ReadComponentExtensionsInfo(
455 std::vector
<ComponentExtensionIME
>* out_imes
) {
457 for (size_t i
= 0; i
< arraysize(whitelisted_component_extension
); ++i
) {
458 ComponentExtensionIME component_ime
;
459 ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
460 component_ime
.manifest
=
461 rb
.GetRawDataResource(
462 whitelisted_component_extension
[i
].manifest_resource_id
)
464 if (component_ime
.manifest
.empty())
467 scoped_ptr
<base::DictionaryValue
> manifest
=
468 GetManifest(component_ime
.manifest
);
472 if (!ReadExtensionInfo(*manifest
.get(),
473 whitelisted_component_extension
[i
].id
,
476 component_ime
.id
= whitelisted_component_extension
[i
].id
;
478 if (!component_ime
.path
.IsAbsolute()) {
479 base::FilePath resources_path
;
480 if (!PathService::Get(chrome::DIR_RESOURCES
, &resources_path
))
482 component_ime
.path
= resources_path
.Append(component_ime
.path
);
485 const base::ListValue
* component_list
;
486 if (!manifest
->GetList(extensions::manifest_keys::kInputComponents
,
490 for (size_t i
= 0; i
< component_list
->GetSize(); ++i
) {
491 const base::DictionaryValue
* dictionary
;
492 if (!component_list
->GetDictionary(i
, &dictionary
))
495 ComponentExtensionEngine engine
;
496 ReadEngineComponent(component_ime
, *dictionary
, &engine
);
497 component_ime
.engines
.push_back(engine
);
499 out_imes
->push_back(component_ime
);
503 } // namespace chromeos