// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_ #include <map> #include <string> #include <vector> #include "base/macros.h" #include "base/memory/singleton.h" #include "base/scoped_observer.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/input_method/input_method_engine_base.h" #include "components/keyed_service/core/keyed_service.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_function.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/common/extension.h" #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/text_input_flags.h" #if defined(OS_CHROMEOS) #include "chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h" #elif defined(OS_LINUX) || defined(OS_WIN) #include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h" #endif // defined(OS_CHROMEOS) class Profile; namespace ui { class IMEEngineHandlerInterface; class ImeObserver : public input_method::InputMethodEngineBase::Observer { public: ImeObserver(const std::string& extension_id, Profile* profile); ~ImeObserver() override {} // input_method::InputMethodEngineBase::Observer overrides. void OnActivate(const std::string& component_id) override; void OnFocus(const IMEEngineHandlerInterface::InputContext& context) override; void OnBlur(int context_id) override; void OnKeyEvent( const std::string& component_id, const input_method::InputMethodEngineBase::KeyboardEvent& event, IMEEngineHandlerInterface::KeyEventDoneCallback& key_data) override; void OnReset(const std::string& component_id) override; void OnDeactivated(const std::string& component_id) override; void OnCompositionBoundsChanged( const std::vector<gfx::Rect>& bounds) override; bool IsInterestedInKeyEvent() const override; void OnSurroundingTextChanged(const std::string& component_id, const std::string& text, int cursor_pos, int anchor_pos, int offset_pos) override; protected: // Helper function used to forward the given event to the |profile_|'s event // router, which dipatches the event the extension with |extension_id_|. virtual void DispatchEventToExtension( extensions::events::HistogramValue histogram_value, const std::string& event_name, scoped_ptr<base::ListValue> args) = 0; // Returns the type of the current screen. virtual std::string GetCurrentScreenType() = 0; // Returns true if the extension is ready to accept key event, otherwise // returns false. bool ShouldForwardKeyEvent() const; // Returns true if there are any listeners on the given event. bool HasListener(const std::string& event_name) const; // Functions used to convert InputContext struct to string std::string ConvertInputContextType( IMEEngineHandlerInterface::InputContext input_context); bool ConvertInputContextAutoCorrect( IMEEngineHandlerInterface::InputContext input_context); bool ConvertInputContextAutoComplete( IMEEngineHandlerInterface::InputContext input_context); bool ConvertInputContextSpellCheck( IMEEngineHandlerInterface::InputContext input_context); std::string extension_id_; Profile* profile_; DISALLOW_COPY_AND_ASSIGN(ImeObserver); }; } // namespace ui namespace extensions { class InputImeEventRouter; class ExtensionRegistry; class InputImeEventRouterFactory { public: static InputImeEventRouterFactory* GetInstance(); InputImeEventRouter* GetRouter(Profile* profile); private: friend struct base::DefaultSingletonTraits<InputImeEventRouterFactory>; InputImeEventRouterFactory(); ~InputImeEventRouterFactory(); std::map<Profile*, InputImeEventRouter*, ProfileCompare> router_map_; DISALLOW_COPY_AND_ASSIGN(InputImeEventRouterFactory); }; class InputImeKeyEventHandledFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("input.ime.keyEventHandled", INPUT_IME_KEYEVENTHANDLED) protected: ~InputImeKeyEventHandledFunction() override {} // UIThreadExtensionFunction: ResponseAction Run() override; }; class InputImeSetCompositionFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("input.ime.setComposition", INPUT_IME_SETCOMPOSITION) protected: ~InputImeSetCompositionFunction() override {} // UIThreadExtensionFunction: ResponseAction Run() override; }; class InputImeCommitTextFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("input.ime.commitText", INPUT_IME_COMMITTEXT) protected: ~InputImeCommitTextFunction() override {} // UIThreadExtensionFunction: ResponseAction Run() override; }; class InputImeSendKeyEventsFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("input.ime.sendKeyEvents", INPUT_IME_SENDKEYEVENTS) protected: ~InputImeSendKeyEventsFunction() override {} // UIThreadExtensionFunction: ResponseAction Run() override; }; class InputImeAPI : public BrowserContextKeyedAPI, public ExtensionRegistryObserver, public EventRouter::Observer { public: explicit InputImeAPI(content::BrowserContext* context); ~InputImeAPI() override; // BrowserContextKeyedAPI implementation. static BrowserContextKeyedAPIFactory<InputImeAPI>* GetFactoryInstance(); // ExtensionRegistryObserver implementation. void OnExtensionLoaded(content::BrowserContext* browser_context, const Extension* extension) override; void OnExtensionUnloaded(content::BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) override; // EventRouter::Observer implementation. void OnListenerAdded(const EventListenerInfo& details) override; private: friend class BrowserContextKeyedAPIFactory<InputImeAPI>; InputImeEventRouter* input_ime_event_router(); // BrowserContextKeyedAPI implementation. static const char* service_name() { return "InputImeAPI"; } static const bool kServiceIsNULLWhileTesting = true; content::BrowserContext* const browser_context_; // Listen to extension load, unloaded notifications. ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observer_; }; InputImeEventRouter* GetInputImeEventRouter(Profile* profile); } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_