input_method_api.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/input_method_api.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/input_method_event_router.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_util.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/api/input_ime/input_ime_api.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chromeos/ime/extension_ime_util.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chromeos/ime/input_method_descriptor.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/ime/input_method_manager.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_registry.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "extensions/common/value_builder.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Prefix, which is used by XKB. 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kXkbPrefix[] = "xkb:"; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ExtensionFunction::ResponseAction GetCurrentInputMethodFunction::Run() { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_CHROMEOS) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(false); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::input_method::InputMethodManager* manager = 33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) chromeos::input_method::InputMethodManager::Get(); 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return RespondNow(OneArgument(new base::StringValue( 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) manager->GetActiveIMEState()->GetCurrentInputMethod().id()))); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ExtensionFunction::ResponseAction SetCurrentInputMethodFunction::Run() { 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_CHROMEOS) 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(false); 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string new_input_method; 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &new_input_method)); 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state = 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::input_method::InputMethodManager::Get()->GetActiveIMEState(); 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<std::string>& input_methods = 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ime_state->GetActiveInputMethodIds(); 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < input_methods.size(); ++i) { 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& input_method = input_methods[i]; 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (input_method == new_input_method) { 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ime_state->ChangeInputMethod(new_input_method, false /* show_message */); 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RespondNow(NoArguments()); 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RespondNow(Error("Invalid input method id.")); 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ExtensionFunction::ResponseAction GetInputMethodsFunction::Run() { 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if !defined(OS_CHROMEOS) 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(false); 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ListValue* output = new base::ListValue(); 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) chromeos::input_method::InputMethodManager* manager = 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) chromeos::input_method::InputMethodManager::Get(); 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) chromeos::input_method::InputMethodUtil* util = manager->GetInputMethodUtil(); 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state = 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) manager->GetActiveIMEState(); 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<chromeos::input_method::InputMethodDescriptors> input_methods = 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ime_state->GetActiveInputMethods(); 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < input_methods->size(); ++i) { 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const chromeos::input_method::InputMethodDescriptor& input_method = 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*input_methods)[i]; 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::DictionaryValue* val = new base::DictionaryValue(); 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) val->SetString("id", input_method.id()); 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) val->SetString("name", util->GetInputMethodLongName(input_method)); 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) val->SetString("indicator", util->GetInputMethodShortName(input_method)); 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) output->Append(val); 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RespondNow(OneArgument(output)); 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char InputMethodAPI::kOnInputMethodChanged[] = 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "inputMethodPrivate.onChanged"; 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)InputMethodAPI::InputMethodAPI(content::BrowserContext* context) 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : context_(context) { 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(context_)->RegisterObserver(this, kOnInputMethodChanged); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionFunctionRegistry* registry = 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionFunctionRegistry::GetInstance(); 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registry->RegisterFunction<GetCurrentInputMethodFunction>(); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registry->RegisterFunction<SetCurrentInputMethodFunction>(); 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registry->RegisterFunction<GetInputMethodsFunction>(); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InputMethodAPI::~InputMethodAPI() { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) { 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string xkb_prefix = 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) chromeos::extension_ime_util::GetInputMethodIDByEngineID(kXkbPrefix); 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t prefix_length = xkb_prefix.length(); 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return xkb_id.substr(prefix_length); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InputMethodAPI::Shutdown() { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // UnregisterObserver may have already been called in OnListenerAdded, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // but it is safe to call it more than once. 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(context_)->UnregisterObserver(this); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InputMethodAPI::OnListenerAdded( 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::EventListenerInfo& details) { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!input_method_event_router_.get()); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_method_event_router_.reset( 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new chromeos::ExtensionInputMethodEventRouter(context_)); 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(context_)->UnregisterObserver(this); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> > 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<InputMethodAPI>* 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)InputMethodAPI::GetFactoryInstance() { 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 135