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 #ifndef CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_
7 
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "base/macros.h"
13 #include "base/memory/singleton.h"
14 #include "base/scoped_observer.h"
15 #include "base/values.h"
16 #include "build/build_config.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/input_method/input_method_engine_base.h"
19 #include "chrome/common/extensions/api/input_ime.h"
20 #include "components/keyed_service/core/keyed_service.h"
21 #include "extensions/browser/browser_context_keyed_api_factory.h"
22 #include "extensions/browser/event_router.h"
23 #include "extensions/browser/event_router_factory.h"
24 #include "extensions/browser/extension_function.h"
25 #include "extensions/browser/extension_registry_factory.h"
26 #include "extensions/browser/extension_registry_observer.h"
27 #include "extensions/common/extension.h"
28 #include "ui/base/ime/ime_bridge_observer.h"
29 #include "ui/base/ime/ime_engine_handler_interface.h"
30 #include "ui/base/ime/text_input_flags.h"
31 
32 #if defined(OS_CHROMEOS)
33 #include "chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h"
34 #elif defined(OS_LINUX) || defined(OS_WIN) || defined(OS_BSD)
35 #include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
36 #endif  // defined(OS_CHROMEOS)
37 
38 class Profile;
39 
40 namespace ui {
41 class IMEEngineHandlerInterface;
42 
43 class ImeObserver : public input_method::InputMethodEngineBase::Observer {
44  public:
45   ImeObserver(const std::string& extension_id, Profile* profile);
46 
47   ~ImeObserver() override = default;
48 
49   // input_method::InputMethodEngineBase::Observer overrides.
50   void OnActivate(const std::string& component_id) override;
51   void OnFocus(const IMEEngineHandlerInterface::InputContext& context) override;
52   void OnBlur(int context_id) override;
53   void OnKeyEvent(
54       const std::string& component_id,
55       const input_method::InputMethodEngineBase::KeyboardEvent& event,
56       IMEEngineHandlerInterface::KeyEventDoneCallback key_data) override;
57   void OnReset(const std::string& component_id) override;
58   void OnDeactivated(const std::string& component_id) override;
59   void OnCompositionBoundsChanged(
60       const std::vector<gfx::Rect>& bounds) override;
61   void OnSurroundingTextChanged(const std::string& component_id,
62                                 const base::string16& text,
63                                 int cursor_pos,
64                                 int anchor_pos,
65                                 int offset_pos) override;
66 
67  protected:
68   // Helper function used to forward the given event to the |profile_|'s event
69   // router, which dipatches the event the extension with |extension_id_|.
70   virtual void DispatchEventToExtension(
71       extensions::events::HistogramValue histogram_value,
72       const std::string& event_name,
73       std::unique_ptr<base::ListValue> args) = 0;
74 
75   // Returns the type of the current screen.
76   virtual std::string GetCurrentScreenType() = 0;
77 
78   // Returns true if the extension is ready to accept key event, otherwise
79   // returns false.
80   bool ShouldForwardKeyEvent() const;
81 
82   // Returns true if there are any listeners on the given event.
83   // TODO(https://crbug.com/835699): Merge this with |ExtensionHasListener|.
84   bool HasListener(const std::string& event_name) const;
85 
86   // Returns true if the extension has any listeners on the given event.
87   bool ExtensionHasListener(const std::string& event_name) const;
88 
89   // Functions used to convert InputContext struct to string
90   std::string ConvertInputContextType(
91       IMEEngineHandlerInterface::InputContext input_context);
92   virtual bool ConvertInputContextAutoCorrect(
93       IMEEngineHandlerInterface::InputContext input_context);
94   virtual bool ConvertInputContextAutoComplete(
95       IMEEngineHandlerInterface::InputContext input_context);
96   virtual bool ConvertInputContextSpellCheck(
97       IMEEngineHandlerInterface::InputContext input_context);
98 
99   std::string extension_id_;
100   Profile* profile_;
101 
102  private:
103   extensions::api::input_ime::AutoCapitalizeType
104   ConvertInputContextAutoCapitalize(
105       IMEEngineHandlerInterface::InputContext input_context);
106 
107   DISALLOW_COPY_AND_ASSIGN(ImeObserver);
108 };
109 
110 }  // namespace ui
111 
112 namespace extensions {
113 class InputImeEventRouter;
114 class ExtensionRegistry;
115 
116 class InputImeEventRouterFactory {
117  public:
118   static InputImeEventRouterFactory* GetInstance();
119   InputImeEventRouter* GetRouter(Profile* profile);
120   void RemoveProfile(Profile* profile);
121 
122  private:
123   friend struct base::DefaultSingletonTraits<InputImeEventRouterFactory>;
124   InputImeEventRouterFactory();
125   ~InputImeEventRouterFactory();
126 
127   std::map<Profile*, InputImeEventRouter*, ProfileCompare> router_map_;
128 
129   DISALLOW_COPY_AND_ASSIGN(InputImeEventRouterFactory);
130 };
131 
132 class InputImeKeyEventHandledFunction : public ExtensionFunction {
133  public:
134   DECLARE_EXTENSION_FUNCTION("input.ime.keyEventHandled",
135                              INPUT_IME_KEYEVENTHANDLED)
136 
137  protected:
138   ~InputImeKeyEventHandledFunction() override = default;
139 
140   // ExtensionFunction:
141   ResponseAction Run() override;
142 };
143 
144 class InputImeSetCompositionFunction : public ExtensionFunction {
145  public:
146   DECLARE_EXTENSION_FUNCTION("input.ime.setComposition",
147                              INPUT_IME_SETCOMPOSITION)
148 
149  protected:
150   ~InputImeSetCompositionFunction() override = default;
151 
152   // ExtensionFunction:
153   ResponseAction Run() override;
154 };
155 
156 class InputImeCommitTextFunction : public ExtensionFunction {
157  public:
158   DECLARE_EXTENSION_FUNCTION("input.ime.commitText", INPUT_IME_COMMITTEXT)
159 
160  protected:
161   ~InputImeCommitTextFunction() override = default;
162 
163   // ExtensionFunction:
164   ResponseAction Run() override;
165 };
166 
167 class InputImeSendKeyEventsFunction : public ExtensionFunction {
168  public:
169   DECLARE_EXTENSION_FUNCTION("input.ime.sendKeyEvents", INPUT_IME_SENDKEYEVENTS)
170 
171  protected:
172   ~InputImeSendKeyEventsFunction() override = default;
173 
174   // ExtensionFunction:
175   ResponseAction Run() override;
176 };
177 
178 class InputImeAPI : public BrowserContextKeyedAPI,
179                     public ExtensionRegistryObserver,
180                     public EventRouter::Observer {
181  public:
182   explicit InputImeAPI(content::BrowserContext* context);
183   ~InputImeAPI() override;
184 
185   static BrowserContextKeyedAPIFactory<InputImeAPI>* GetFactoryInstance();
186 
187   // BrowserContextKeyedAPI implementation.
188   void Shutdown() override;
189 
190   // ExtensionRegistryObserver implementation.
191   void OnExtensionLoaded(content::BrowserContext* browser_context,
192                          const Extension* extension) override;
193   void OnExtensionUnloaded(content::BrowserContext* browser_context,
194                            const Extension* extension,
195                            UnloadedExtensionReason reason) override;
196 
197   // EventRouter::Observer implementation.
198   void OnListenerAdded(const EventListenerInfo& details) override;
199 
200  private:
201   friend class BrowserContextKeyedAPIFactory<InputImeAPI>;
202   InputImeEventRouter* input_ime_event_router();
203 
204   // BrowserContextKeyedAPI implementation.
205   static const char* service_name() {
206     return "InputImeAPI";
207   }
208   static const bool kServiceIsNULLWhileTesting = true;
209 
210   content::BrowserContext* const browser_context_;
211 
212   // Listen to extension load, unloaded notifications.
213   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
214       extension_registry_observer_{this};
215 
216   std::unique_ptr<ui::IMEBridgeObserver> observer_;
217 };
218 
219 template <>
220 struct BrowserContextFactoryDependencies<InputImeAPI> {
221   static void DeclareFactoryDependencies(
222       BrowserContextKeyedAPIFactory<InputImeAPI>* factory) {
223     factory->DependsOn(EventRouterFactory::GetInstance());
224     factory->DependsOn(ExtensionRegistryFactory::GetInstance());
225   }
226 };
227 
228 InputImeEventRouter* GetInputImeEventRouter(Profile* profile);
229 
230 // Append the extension function name to the error message so that we know where
231 // the error is from during debugging.
232 std::string InformativeError(const std::string& error,
233                              const char* function_name);
234 }  // namespace extensions
235 
236 #endif  // CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_H_
237