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/browser/chromeos/extensions/input_method_api.h" 6 7#include "base/lazy_instance.h" 8#include "base/values.h" 9#include "chrome/browser/chromeos/extensions/input_method_event_router.h" 10#include "chrome/browser/chromeos/input_method/input_method_util.h" 11#include "chrome/browser/extensions/api/input_ime/input_ime_api.h" 12#include "chromeos/ime/extension_ime_util.h" 13#include "chromeos/ime/input_method_descriptor.h" 14#include "chromeos/ime/input_method_manager.h" 15#include "extensions/browser/extension_function_registry.h" 16#include "extensions/browser/extension_system.h" 17#include "extensions/common/value_builder.h" 18 19namespace { 20 21// Prefix, which is used by XKB. 22const char kXkbPrefix[] = "xkb:"; 23 24} // namespace 25 26namespace extensions { 27 28ExtensionFunction::ResponseAction GetCurrentInputMethodFunction::Run() { 29#if !defined(OS_CHROMEOS) 30 EXTENSION_FUNCTION_VALIDATE(false); 31#else 32 chromeos::input_method::InputMethodManager* manager = 33 chromeos::input_method::InputMethodManager::Get(); 34 return RespondNow(OneArgument(new base::StringValue( 35 manager->GetActiveIMEState()->GetCurrentInputMethod().id()))); 36#endif 37} 38 39ExtensionFunction::ResponseAction SetCurrentInputMethodFunction::Run() { 40#if !defined(OS_CHROMEOS) 41 EXTENSION_FUNCTION_VALIDATE(false); 42#else 43 std::string new_input_method; 44 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &new_input_method)); 45 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state = 46 chromeos::input_method::InputMethodManager::Get()->GetActiveIMEState(); 47 const std::vector<std::string>& input_methods = 48 ime_state->GetActiveInputMethodIds(); 49 for (size_t i = 0; i < input_methods.size(); ++i) { 50 const std::string& input_method = input_methods[i]; 51 if (input_method == new_input_method) { 52 ime_state->ChangeInputMethod(new_input_method, false /* show_message */); 53 return RespondNow(NoArguments()); 54 } 55 } 56 return RespondNow(Error("Invalid input method id.")); 57#endif 58} 59 60ExtensionFunction::ResponseAction GetInputMethodsFunction::Run() { 61#if !defined(OS_CHROMEOS) 62 EXTENSION_FUNCTION_VALIDATE(false); 63#else 64 base::ListValue* output = new base::ListValue(); 65 chromeos::input_method::InputMethodManager* manager = 66 chromeos::input_method::InputMethodManager::Get(); 67 chromeos::input_method::InputMethodUtil* util = manager->GetInputMethodUtil(); 68 scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state = 69 manager->GetActiveIMEState(); 70 scoped_ptr<chromeos::input_method::InputMethodDescriptors> input_methods = 71 ime_state->GetActiveInputMethods(); 72 for (size_t i = 0; i < input_methods->size(); ++i) { 73 const chromeos::input_method::InputMethodDescriptor& input_method = 74 (*input_methods)[i]; 75 base::DictionaryValue* val = new base::DictionaryValue(); 76 val->SetString("id", input_method.id()); 77 val->SetString("name", util->GetInputMethodLongName(input_method)); 78 val->SetString("indicator", util->GetInputMethodShortName(input_method)); 79 output->Append(val); 80 } 81 return RespondNow(OneArgument(output)); 82#endif 83} 84 85// static 86const char InputMethodAPI::kOnInputMethodChanged[] = 87 "inputMethodPrivate.onChanged"; 88 89InputMethodAPI::InputMethodAPI(content::BrowserContext* context) 90 : context_(context) { 91 EventRouter::Get(context_)->RegisterObserver(this, kOnInputMethodChanged); 92 ExtensionFunctionRegistry* registry = 93 ExtensionFunctionRegistry::GetInstance(); 94 registry->RegisterFunction<GetCurrentInputMethodFunction>(); 95 registry->RegisterFunction<SetCurrentInputMethodFunction>(); 96 registry->RegisterFunction<GetInputMethodsFunction>(); 97} 98 99InputMethodAPI::~InputMethodAPI() { 100} 101 102// static 103std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) { 104 std::string xkb_prefix = 105 chromeos::extension_ime_util::GetInputMethodIDByEngineID(kXkbPrefix); 106 size_t prefix_length = xkb_prefix.length(); 107 DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix); 108 return xkb_id.substr(prefix_length); 109} 110 111void InputMethodAPI::Shutdown() { 112 // UnregisterObserver may have already been called in OnListenerAdded, 113 // but it is safe to call it more than once. 114 EventRouter::Get(context_)->UnregisterObserver(this); 115} 116 117void InputMethodAPI::OnListenerAdded( 118 const extensions::EventListenerInfo& details) { 119 DCHECK(!input_method_event_router_.get()); 120 input_method_event_router_.reset( 121 new chromeos::ExtensionInputMethodEventRouter(context_)); 122 EventRouter::Get(context_)->UnregisterObserver(this); 123} 124 125static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> > 126 g_factory = LAZY_INSTANCE_INITIALIZER; 127 128// static 129BrowserContextKeyedAPIFactory<InputMethodAPI>* 130InputMethodAPI::GetFactoryInstance() { 131 return g_factory.Pointer(); 132} 133 134} // namespace extensions 135