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 19 namespace { 20 21 // Prefix, which is used by XKB. 22 const char kXkbPrefix[] = "xkb:"; 23 24 } // namespace 25 26 namespace extensions { 27 28 ExtensionFunction::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 39 ExtensionFunction::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 60 ExtensionFunction::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 86 const char InputMethodAPI::kOnInputMethodChanged[] = 87 "inputMethodPrivate.onChanged"; 88 89 InputMethodAPI::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 99 InputMethodAPI::~InputMethodAPI() { 100 } 101 102 // static 103 std::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 111 void 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 117 void 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 125 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> > 126 g_factory = LAZY_INSTANCE_INITIALIZER; 127 128 // static 129 BrowserContextKeyedAPIFactory<InputMethodAPI>* 130 InputMethodAPI::GetFactoryInstance() { 131 return g_factory.Pointer(); 132 } 133 134 } // namespace extensions 135