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( 35 new base::StringValue(manager->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 chromeos::input_method::InputMethodManager* manager = 46 chromeos::input_method::InputMethodManager::Get(); 47 const std::vector<std::string>& input_methods = 48 manager->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 manager->ChangeInputMethod(new_input_method); 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_ptr<chromeos::input_method::InputMethodDescriptors> input_methods = 69 manager->GetActiveInputMethods(); 70 for (size_t i = 0; i < input_methods->size(); ++i) { 71 const chromeos::input_method::InputMethodDescriptor& input_method = 72 (*input_methods)[i]; 73 base::DictionaryValue* val = new base::DictionaryValue(); 74 val->SetString("id", input_method.id()); 75 val->SetString("name", util->GetInputMethodLongName(input_method)); 76 val->SetString("indicator", util->GetInputMethodShortName(input_method)); 77 output->Append(val); 78 } 79 return RespondNow(OneArgument(output)); 80 #endif 81 } 82 83 // static 84 const char InputMethodAPI::kOnInputMethodChanged[] = 85 "inputMethodPrivate.onChanged"; 86 87 InputMethodAPI::InputMethodAPI(content::BrowserContext* context) 88 : context_(context) { 89 EventRouter::Get(context_)->RegisterObserver(this, kOnInputMethodChanged); 90 ExtensionFunctionRegistry* registry = 91 ExtensionFunctionRegistry::GetInstance(); 92 registry->RegisterFunction<GetCurrentInputMethodFunction>(); 93 registry->RegisterFunction<SetCurrentInputMethodFunction>(); 94 registry->RegisterFunction<GetInputMethodsFunction>(); 95 } 96 97 InputMethodAPI::~InputMethodAPI() { 98 } 99 100 // static 101 std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) { 102 std::string xkb_prefix = 103 chromeos::extension_ime_util::GetInputMethodIDByEngineID(kXkbPrefix); 104 size_t prefix_length = xkb_prefix.length(); 105 DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix); 106 return xkb_id.substr(prefix_length); 107 } 108 109 void InputMethodAPI::Shutdown() { 110 // UnregisterObserver may have already been called in OnListenerAdded, 111 // but it is safe to call it more than once. 112 EventRouter::Get(context_)->UnregisterObserver(this); 113 } 114 115 void InputMethodAPI::OnListenerAdded( 116 const extensions::EventListenerInfo& details) { 117 DCHECK(!input_method_event_router_.get()); 118 input_method_event_router_.reset( 119 new chromeos::ExtensionInputMethodEventRouter(context_)); 120 EventRouter::Get(context_)->UnregisterObserver(this); 121 } 122 123 static base::LazyInstance<BrowserContextKeyedAPIFactory<InputMethodAPI> > 124 g_factory = LAZY_INSTANCE_INITIALIZER; 125 126 // static 127 BrowserContextKeyedAPIFactory<InputMethodAPI>* 128 InputMethodAPI::GetFactoryInstance() { 129 return g_factory.Pointer(); 130 } 131 132 } // namespace extensions 133