ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / input_method_api.cc
blob22e9f44fdb26686786015cdc0ac6c2ed5b4b7ef4
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/browser/chromeos/extensions/input_method_api.h"
7 #include "base/command_line.h"
8 #include "base/lazy_instance.h"
9 #include "base/values.h"
10 #include "chrome/browser/chromeos/extensions/input_method_event_router.h"
11 #include "chrome/browser/chromeos/input_method/input_method_util.h"
12 #include "chrome/browser/extensions/api/input_ime/input_ime_api.h"
13 #include "chrome/browser/spellchecker/spellcheck_factory.h"
14 #include "chrome/browser/spellchecker/spellcheck_service.h"
15 #include "chromeos/chromeos_switches.h"
16 #include "extensions/browser/extension_function_registry.h"
17 #include "extensions/browser/extension_system.h"
18 #include "extensions/common/value_builder.h"
19 #include "ui/base/ime/chromeos/extension_ime_util.h"
20 #include "ui/base/ime/chromeos/input_method_descriptor.h"
21 #include "ui/base/ime/chromeos/input_method_manager.h"
23 namespace {
25 // Prefix, which is used by XKB.
26 const char kXkbPrefix[] = "xkb:";
28 } // namespace
30 namespace extensions {
32 ExtensionFunction::ResponseAction GetInputMethodConfigFunction::Run() {
33 #if !defined(OS_CHROMEOS)
34 EXTENSION_FUNCTION_VALIDATE(false);
35 #else
36 base::DictionaryValue* output = new base::DictionaryValue();
37 output->SetBoolean(
38 "isPhysicalKeyboardAutocorrectEnabled",
39 base::CommandLine::ForCurrentProcess()->HasSwitch(
40 chromeos::switches::kEnablePhysicalKeyboardAutocorrect));
41 output->SetBoolean("isVoiceInputEnabled",
42 !base::CommandLine::ForCurrentProcess()->HasSwitch(
43 chromeos::switches::kDisableVoiceInput));
44 output->SetBoolean("isNewMDInputViewEnabled",
45 base::CommandLine::ForCurrentProcess()->HasSwitch(
46 chromeos::switches::kEnableNewMDInputView));
47 return RespondNow(OneArgument(output));
48 #endif
51 ExtensionFunction::ResponseAction GetCurrentInputMethodFunction::Run() {
52 #if !defined(OS_CHROMEOS)
53 EXTENSION_FUNCTION_VALIDATE(false);
54 #else
55 chromeos::input_method::InputMethodManager* manager =
56 chromeos::input_method::InputMethodManager::Get();
57 return RespondNow(OneArgument(new base::StringValue(
58 manager->GetActiveIMEState()->GetCurrentInputMethod().id())));
59 #endif
62 ExtensionFunction::ResponseAction SetCurrentInputMethodFunction::Run() {
63 #if !defined(OS_CHROMEOS)
64 EXTENSION_FUNCTION_VALIDATE(false);
65 #else
66 std::string new_input_method;
67 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &new_input_method));
68 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
69 chromeos::input_method::InputMethodManager::Get()->GetActiveIMEState();
70 const std::vector<std::string>& input_methods =
71 ime_state->GetActiveInputMethodIds();
72 for (size_t i = 0; i < input_methods.size(); ++i) {
73 const std::string& input_method = input_methods[i];
74 if (input_method == new_input_method) {
75 ime_state->ChangeInputMethod(new_input_method, false /* show_message */);
76 return RespondNow(NoArguments());
79 return RespondNow(Error("Invalid input method id."));
80 #endif
83 ExtensionFunction::ResponseAction GetInputMethodsFunction::Run() {
84 #if !defined(OS_CHROMEOS)
85 EXTENSION_FUNCTION_VALIDATE(false);
86 #else
87 base::ListValue* output = new base::ListValue();
88 chromeos::input_method::InputMethodManager* manager =
89 chromeos::input_method::InputMethodManager::Get();
90 chromeos::input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
91 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
92 manager->GetActiveIMEState();
93 scoped_ptr<chromeos::input_method::InputMethodDescriptors> input_methods =
94 ime_state->GetActiveInputMethods();
95 for (size_t i = 0; i < input_methods->size(); ++i) {
96 const chromeos::input_method::InputMethodDescriptor& input_method =
97 (*input_methods)[i];
98 base::DictionaryValue* val = new base::DictionaryValue();
99 val->SetString("id", input_method.id());
100 val->SetString("name", util->GetInputMethodLongName(input_method));
101 val->SetString("indicator", util->GetInputMethodShortName(input_method));
102 output->Append(val);
104 return RespondNow(OneArgument(output));
105 #endif
108 ExtensionFunction::ResponseAction FetchAllDictionaryWordsFunction::Run() {
109 #if !defined(OS_CHROMEOS)
110 EXTENSION_FUNCTION_VALIDATE(false);
111 #else
112 SpellcheckService* spellcheck = SpellcheckServiceFactory::GetForContext(
113 context_);
114 if (!spellcheck) {
115 return RespondNow(Error("Spellcheck service not available."));
117 SpellcheckCustomDictionary* dictionary = spellcheck->GetCustomDictionary();
118 if (!dictionary->IsLoaded()) {
119 return RespondNow(Error("Custom dictionary not loaded yet."));
122 const chrome::spellcheck_common::WordSet& words = dictionary->GetWords();
123 base::ListValue* output = new base::ListValue();
124 for (auto it = words.begin(); it != words.end(); ++it) {
125 output->AppendString(*it);
127 return RespondNow(OneArgument(output));
128 #endif
131 ExtensionFunction::ResponseAction AddWordToDictionaryFunction::Run() {
132 #if !defined(OS_CHROMEOS)
133 EXTENSION_FUNCTION_VALIDATE(false);
134 #else
135 std::string word;
136 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &word));
137 SpellcheckService* spellcheck = SpellcheckServiceFactory::GetForContext(
138 context_);
139 if (!spellcheck) {
140 return RespondNow(Error("Spellcheck service not available."));
142 SpellcheckCustomDictionary* dictionary = spellcheck->GetCustomDictionary();
143 if (!dictionary->IsLoaded()) {
144 return RespondNow(Error("Custom dictionary not loaded yet."));
147 if (dictionary->AddWord(word))
148 return RespondNow(NoArguments());
149 // Invalid words:
150 // - Already in the dictionary.
151 // - Not a UTF8 string.
152 // - Longer than 99 bytes (MAX_CUSTOM_DICTIONARY_WORD_BYTES).
153 // - Leading/trailing whitespace.
154 // - Empty.
155 return RespondNow(Error("Unable to add invalid word to dictionary."));
156 #endif
159 // static
160 const char InputMethodAPI::kOnInputMethodChanged[] =
161 "inputMethodPrivate.onChanged";
163 InputMethodAPI::InputMethodAPI(content::BrowserContext* context)
164 : context_(context) {
165 EventRouter::Get(context_)->RegisterObserver(this, kOnInputMethodChanged);
166 ExtensionFunctionRegistry* registry =
167 ExtensionFunctionRegistry::GetInstance();
168 registry->RegisterFunction<GetInputMethodConfigFunction>();
169 registry->RegisterFunction<GetCurrentInputMethodFunction>();
170 registry->RegisterFunction<SetCurrentInputMethodFunction>();
171 registry->RegisterFunction<GetInputMethodsFunction>();
172 registry->RegisterFunction<FetchAllDictionaryWordsFunction>();
173 registry->RegisterFunction<AddWordToDictionaryFunction>();
176 InputMethodAPI::~InputMethodAPI() {
179 // static
180 std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) {
181 std::string xkb_prefix =
182 chromeos::extension_ime_util::GetInputMethodIDByEngineID(kXkbPrefix);
183 size_t prefix_length = xkb_prefix.length();
184 DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix);
185 return xkb_id.substr(prefix_length);
188 void InputMethodAPI::Shutdown() {
189 // UnregisterObserver may have already been called in OnListenerAdded,
190 // but it is safe to call it more than once.
191 EventRouter::Get(context_)->UnregisterObserver(this);
194 void InputMethodAPI::OnListenerAdded(
195 const extensions::EventListenerInfo& details) {
196 DCHECK(!input_method_event_router_.get());
197 input_method_event_router_.reset(
198 new chromeos::ExtensionInputMethodEventRouter(context_));
199 EventRouter::Get(context_)->UnregisterObserver(this);
202 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> >
203 g_factory = LAZY_INSTANCE_INITIALIZER;
205 // static
206 BrowserContextKeyedAPIFactory<InputMethodAPI>*
207 InputMethodAPI::GetFactoryInstance() {
208 return g_factory.Pointer();
211 } // namespace extensions