Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / input_method_api.cc
blobcd315a250887ca6f347727efb3b29463f3a5cb03
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 <set>
8 #include <string>
10 #include "base/command_line.h"
11 #include "base/lazy_instance.h"
12 #include "base/values.h"
13 #include "chrome/browser/chromeos/extensions/dictionary_event_router.h"
14 #include "chrome/browser/chromeos/extensions/input_method_event_router.h"
15 #include "chrome/browser/chromeos/input_method/input_method_util.h"
16 #include "chrome/browser/extensions/api/input_ime/input_ime_api.h"
17 #include "chrome/browser/spellchecker/spellcheck_factory.h"
18 #include "chrome/browser/spellchecker/spellcheck_service.h"
19 #include "chrome/browser/sync/profile_sync_service.h"
20 #include "chrome/browser/sync/profile_sync_service_factory.h"
21 #include "chromeos/chromeos_switches.h"
22 #include "extensions/browser/extension_function_registry.h"
23 #include "extensions/browser/extension_system.h"
24 #include "ui/base/ime/chromeos/extension_ime_util.h"
25 #include "ui/base/ime/chromeos/input_method_descriptor.h"
26 #include "ui/base/ime/chromeos/input_method_manager.h"
27 #include "ui/keyboard/keyboard_util.h"
29 namespace {
31 // Prefix, which is used by XKB.
32 const char kXkbPrefix[] = "xkb:";
34 } // namespace
36 namespace extensions {
38 ExtensionFunction::ResponseAction GetInputMethodConfigFunction::Run() {
39 #if !defined(OS_CHROMEOS)
40 EXTENSION_FUNCTION_VALIDATE(false);
41 #else
42 base::DictionaryValue* output = new base::DictionaryValue();
43 output->SetBoolean(
44 "isPhysicalKeyboardAutocorrectEnabled",
45 !base::CommandLine::ForCurrentProcess()->HasSwitch(
46 chromeos::switches::kDisablePhysicalKeyboardAutocorrect));
47 // TODO(rsadam): Delete these two flags once callers have been updated.
48 output->SetBoolean("isVoiceInputEnabled", keyboard::IsVoiceInputEnabled());
49 output->SetBoolean("isNewMDInputViewEnabled",
50 keyboard::IsMaterialDesignEnabled());
51 return RespondNow(OneArgument(output));
52 #endif
55 ExtensionFunction::ResponseAction GetCurrentInputMethodFunction::Run() {
56 #if !defined(OS_CHROMEOS)
57 EXTENSION_FUNCTION_VALIDATE(false);
58 #else
59 chromeos::input_method::InputMethodManager* manager =
60 chromeos::input_method::InputMethodManager::Get();
61 return RespondNow(OneArgument(new base::StringValue(
62 manager->GetActiveIMEState()->GetCurrentInputMethod().id())));
63 #endif
66 ExtensionFunction::ResponseAction SetCurrentInputMethodFunction::Run() {
67 #if !defined(OS_CHROMEOS)
68 EXTENSION_FUNCTION_VALIDATE(false);
69 #else
70 std::string new_input_method;
71 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &new_input_method));
72 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
73 chromeos::input_method::InputMethodManager::Get()->GetActiveIMEState();
74 const std::vector<std::string>& input_methods =
75 ime_state->GetActiveInputMethodIds();
76 for (size_t i = 0; i < input_methods.size(); ++i) {
77 const std::string& input_method = input_methods[i];
78 if (input_method == new_input_method) {
79 ime_state->ChangeInputMethod(new_input_method, false /* show_message */);
80 return RespondNow(NoArguments());
83 return RespondNow(Error("Invalid input method id."));
84 #endif
87 ExtensionFunction::ResponseAction GetInputMethodsFunction::Run() {
88 #if !defined(OS_CHROMEOS)
89 EXTENSION_FUNCTION_VALIDATE(false);
90 #else
91 base::ListValue* output = new base::ListValue();
92 chromeos::input_method::InputMethodManager* manager =
93 chromeos::input_method::InputMethodManager::Get();
94 chromeos::input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
95 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
96 manager->GetActiveIMEState();
97 scoped_ptr<chromeos::input_method::InputMethodDescriptors> input_methods =
98 ime_state->GetActiveInputMethods();
99 for (size_t i = 0; i < input_methods->size(); ++i) {
100 const chromeos::input_method::InputMethodDescriptor& input_method =
101 (*input_methods)[i];
102 base::DictionaryValue* val = new base::DictionaryValue();
103 val->SetString("id", input_method.id());
104 val->SetString("name", util->GetInputMethodLongName(input_method));
105 val->SetString("indicator", util->GetInputMethodShortName(input_method));
106 output->Append(val);
108 return RespondNow(OneArgument(output));
109 #endif
112 ExtensionFunction::ResponseAction FetchAllDictionaryWordsFunction::Run() {
113 #if !defined(OS_CHROMEOS)
114 EXTENSION_FUNCTION_VALIDATE(false);
115 #else
116 SpellcheckService* spellcheck = SpellcheckServiceFactory::GetForContext(
117 context_);
118 if (!spellcheck) {
119 return RespondNow(Error("Spellcheck service not available."));
121 SpellcheckCustomDictionary* dictionary = spellcheck->GetCustomDictionary();
122 if (!dictionary->IsLoaded()) {
123 return RespondNow(Error("Custom dictionary not loaded yet."));
126 const std::set<std::string>& words = dictionary->GetWords();
127 base::ListValue* output = new base::ListValue();
128 for (auto it = words.begin(); it != words.end(); ++it) {
129 output->AppendString(*it);
131 return RespondNow(OneArgument(output));
132 #endif
135 ExtensionFunction::ResponseAction AddWordToDictionaryFunction::Run() {
136 #if !defined(OS_CHROMEOS)
137 EXTENSION_FUNCTION_VALIDATE(false);
138 #else
139 std::string word;
140 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &word));
141 SpellcheckService* spellcheck = SpellcheckServiceFactory::GetForContext(
142 context_);
143 if (!spellcheck) {
144 return RespondNow(Error("Spellcheck service not available."));
146 SpellcheckCustomDictionary* dictionary = spellcheck->GetCustomDictionary();
147 if (!dictionary->IsLoaded()) {
148 return RespondNow(Error("Custom dictionary not loaded yet."));
151 if (dictionary->AddWord(word))
152 return RespondNow(NoArguments());
153 // Invalid words:
154 // - Already in the dictionary.
155 // - Not a UTF8 string.
156 // - Longer than 99 bytes (MAX_CUSTOM_DICTIONARY_WORD_BYTES).
157 // - Leading/trailing whitespace.
158 // - Empty.
159 return RespondNow(Error("Unable to add invalid word to dictionary."));
160 #endif
163 ExtensionFunction::ResponseAction GetEncryptSyncEnabledFunction::Run() {
164 #if !defined(OS_CHROMEOS)
165 EXTENSION_FUNCTION_VALIDATE(false);
166 #else
167 ProfileSyncService* profile_sync_service =
168 ProfileSyncServiceFactory::GetForProfile(
169 Profile::FromBrowserContext(browser_context()));
170 if (!profile_sync_service)
171 return RespondNow(Error("Sync service is not ready for current profile."));
172 scoped_ptr<base::Value> ret(new base::FundamentalValue(
173 profile_sync_service->EncryptEverythingEnabled()));
174 return RespondNow(OneArgument(ret.Pass()));
175 #endif
178 // static
179 const char InputMethodAPI::kOnDictionaryChanged[] =
180 "inputMethodPrivate.onDictionaryChanged";
182 // static
183 const char InputMethodAPI::kOnDictionaryLoaded[] =
184 "inputMethodPrivate.onDictionaryLoaded";
186 // static
187 const char InputMethodAPI::kOnInputMethodChanged[] =
188 "inputMethodPrivate.onChanged";
190 InputMethodAPI::InputMethodAPI(content::BrowserContext* context)
191 : context_(context) {
192 EventRouter::Get(context_)->RegisterObserver(this, kOnInputMethodChanged);
193 EventRouter::Get(context_)->RegisterObserver(this, kOnDictionaryChanged);
194 EventRouter::Get(context_)->RegisterObserver(this, kOnDictionaryLoaded);
195 ExtensionFunctionRegistry* registry =
196 ExtensionFunctionRegistry::GetInstance();
197 registry->RegisterFunction<GetInputMethodConfigFunction>();
198 registry->RegisterFunction<GetCurrentInputMethodFunction>();
199 registry->RegisterFunction<SetCurrentInputMethodFunction>();
200 registry->RegisterFunction<GetInputMethodsFunction>();
201 registry->RegisterFunction<FetchAllDictionaryWordsFunction>();
202 registry->RegisterFunction<AddWordToDictionaryFunction>();
203 registry->RegisterFunction<GetEncryptSyncEnabledFunction>();
206 InputMethodAPI::~InputMethodAPI() {
209 // static
210 std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) {
211 std::string xkb_prefix =
212 chromeos::extension_ime_util::GetInputMethodIDByEngineID(kXkbPrefix);
213 size_t prefix_length = xkb_prefix.length();
214 DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix);
215 return xkb_id.substr(prefix_length);
218 void InputMethodAPI::Shutdown() {
219 EventRouter::Get(context_)->UnregisterObserver(this);
222 void InputMethodAPI::OnListenerAdded(
223 const extensions::EventListenerInfo& details) {
224 if (details.event_name == kOnInputMethodChanged) {
225 if (!input_method_event_router_.get()) {
226 input_method_event_router_.reset(
227 new chromeos::ExtensionInputMethodEventRouter(context_));
229 } else if (details.event_name == kOnDictionaryChanged ||
230 details.event_name == kOnDictionaryLoaded) {
231 if (!dictionary_event_router_.get()) {
232 dictionary_event_router_.reset(
233 new chromeos::ExtensionDictionaryEventRouter(context_));
235 if (details.event_name == kOnDictionaryLoaded) {
236 dictionary_event_router_->DispatchLoadedEventIfLoaded();
241 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> >
242 g_factory = LAZY_INSTANCE_INITIALIZER;
244 // static
245 BrowserContextKeyedAPIFactory<InputMethodAPI>*
246 InputMethodAPI::GetFactoryInstance() {
247 return g_factory.Pointer();
250 } // namespace extensions