1 // Copyright 2016 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_CHROMEOS_INPUT_METHOD_INPUT_METHOD_ENGINE_BASE_H_
6 #define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_ENGINE_BASE_H_
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "base/scoped_observer.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_observer.h"
18 #include "components/prefs/pref_change_registrar.h"
19 #include "ui/base/ime/chromeos/ime_engine_handler_interface.h"
20 #include "ui/base/ime/chromeos/input_method_descriptor.h"
21 #include "ui/base/ime/composition_text.h"
22 #include "url/gurl.h"
23 
24 namespace ui {
25 struct CompositionText;
26 class IMEEngineHandlerInterface;
27 class KeyEvent;
28 
29 namespace ime {
30 struct AssistiveWindowButton;
31 }  // namespace ime
32 }  // namespace ui
33 
34 namespace chromeos {
35 
36 class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface,
37                               public ProfileObserver {
38  public:
39   struct KeyboardEvent {
40     KeyboardEvent();
41     KeyboardEvent(const KeyboardEvent& other);
42     virtual ~KeyboardEvent();
43 
44     std::string type;
45     std::string key;
46     std::string code;
47     int key_code;  // only used by on-screen keyboards.
48     std::string extension_id;
49     bool alt_key = false;
50     bool altgr_key = false;
51     bool ctrl_key = false;
52     bool shift_key = false;
53     bool caps_lock = false;
54   };
55 
56   enum SegmentStyle {
57     SEGMENT_STYLE_UNDERLINE,
58     SEGMENT_STYLE_DOUBLE_UNDERLINE,
59     SEGMENT_STYLE_NO_UNDERLINE,
60   };
61 
62   struct SegmentInfo {
63     int start;
64     int end;
65     SegmentStyle style;
66   };
67 
68   enum MouseButtonEvent {
69     MOUSE_BUTTON_LEFT,
70     MOUSE_BUTTON_RIGHT,
71     MOUSE_BUTTON_MIDDLE,
72   };
73 
74   class Observer {
75    public:
~Observer()76     virtual ~Observer() {}
77 
78     // Called when the IME becomes the active IME.
79     virtual void OnActivate(const std::string& engine_id) = 0;
80 
81     // Called when a text field gains focus, and will be sending key events.
82     virtual void OnFocus(
83         const IMEEngineHandlerInterface::InputContext& context) = 0;
84 
85     // Called when a text field loses focus, and will no longer generate events.
86     virtual void OnBlur(int context_id) = 0;
87 
88     // Called when the user pressed a key with a text field focused.
89     virtual void OnKeyEvent(
90         const std::string& engine_id,
91         const InputMethodEngineBase::KeyboardEvent& event,
92         ui::IMEEngineHandlerInterface::KeyEventDoneCallback key_data) = 0;
93 
94     // Called when Chrome terminates on-going text input session.
95     virtual void OnReset(const std::string& engine_id) = 0;
96 
97     // Called when the IME is no longer active.
98     virtual void OnDeactivated(const std::string& engine_id) = 0;
99 
100     // Called when composition bounds are changed.
101     virtual void OnCompositionBoundsChanged(
102         const std::vector<gfx::Rect>& bounds) = 0;
103 
104     // Called when a surrounding text is changed.
105     virtual void OnSurroundingTextChanged(const std::string& engine_id,
106                                           const base::string16& text,
107                                           int cursor_pos,
108                                           int anchor_pos,
109                                           int offset_pos) = 0;
110 
111     // Called when an InputContext's properties change while it is focused.
112     virtual void OnInputContextUpdate(
113         const IMEEngineHandlerInterface::InputContext& context) = 0;
114 
115     // Called when the user clicks on an item in the candidate list.
116     virtual void OnCandidateClicked(
117         const std::string& component_id,
118         int candidate_id,
119         InputMethodEngineBase::MouseButtonEvent button) = 0;
120 
121     // Called when the user clicks on a button in assistive window.
OnAssistiveWindowButtonClicked(const ui::ime::AssistiveWindowButton & button)122     virtual void OnAssistiveWindowButtonClicked(
123         const ui::ime::AssistiveWindowButton& button) {}
124 
125     // Called when a menu item for this IME is interacted with.
126     virtual void OnMenuItemActivated(const std::string& component_id,
127                                      const std::string& menu_id) = 0;
128 
129     virtual void OnScreenProjectionChanged(bool is_projected) = 0;
130 
131     // Called when the suggestions to display have changed.
132     virtual void OnSuggestionsChanged(
133         const std::vector<std::string>& suggestions) = 0;
134 
135     // Called when the input method options are updated.
136     virtual void OnInputMethodOptionsChanged(const std::string& engine_id) = 0;
137   };
138 
139   InputMethodEngineBase();
140 
141   ~InputMethodEngineBase() override;
142 
143   virtual void Initialize(
144       std::unique_ptr<InputMethodEngineBase::Observer> observer,
145       const char* extension_id,
146       Profile* profile);
147 
148   // IMEEngineHandlerInterface overrides.
149   void FocusIn(const ui::IMEEngineHandlerInterface::InputContext& input_context)
150       override;
151   void FocusOut() override;
152   void Enable(const std::string& component_id) override;
153   void Disable() override;
154   void Reset() override;
155   void ProcessKeyEvent(const ui::KeyEvent& key_event,
156                        KeyEventDoneCallback callback) override;
157   void SetSurroundingText(const base::string16& text,
158                           uint32_t cursor_pos,
159                           uint32_t anchor_pos,
160                           uint32_t offset_pos) override;
161   void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) override;
162   ui::InputMethodKeyboardController* GetInputMethodKeyboardController()
163       const override;
164 
165   // Returns the current active input_component id.
166   const std::string& GetActiveComponentId() const;
167 
168   // Clear the current composition.
169   bool ClearComposition(int context_id, std::string* error);
170 
171   // Commit the specified text to the specified context.  Fails if the context
172   // is not focused.
173   bool CommitText(int context_id, const char* text, std::string* error);
174 
175   // Notifies InputContextHandler to commit any composition text.
176   // Set |reset_engine| to false if the event was from the extension.
177   void ConfirmCompositionText(bool reset_engine, bool keep_selection);
178 
179   // Deletes |number_of_chars| unicode characters as the basis of |offset| from
180   // the surrounding text. The |offset| is relative position based on current
181   // caret.
182   // NOTE: Currently we are falling back to backspace forwarding workaround,
183   // because delete_surrounding_text is not supported in Chrome. So this
184   // function is restricted for only preceding text.
185   // TODO(nona): Support full spec delete surrounding text.
186   bool DeleteSurroundingText(int context_id,
187                              int offset,
188                              size_t number_of_chars,
189                              std::string* error);
190 
191   // Commit the text currently being composed to the composition.
192   // Fails if the context is not focused.
193   bool FinishComposingText(int context_id, std::string* error);
194 
195   // Send the sequence of key events.
196   bool SendKeyEvents(int context_id,
197                      const std::vector<KeyboardEvent>& events,
198                      std::string* error);
199 
200   // Set the current composition and associated properties.
201   bool SetComposition(int context_id,
202                       const char* text,
203                       int selection_start,
204                       int selection_end,
205                       int cursor,
206                       const std::vector<SegmentInfo>& segments,
207                       std::string* error);
208 
209   // Set the current composition range around the current cursor.
210   // This function is deprecated. Use |SetComposingRange| instead.
211   bool SetCompositionRange(int context_id,
212                            int selection_before,
213                            int selection_after,
214                            const std::vector<SegmentInfo>& segments,
215                            std::string* error);
216 
217   // Set the current composition range.
218   bool SetComposingRange(int context_id,
219                          int start,
220                          int end,
221                          const std::vector<SegmentInfo>& segments,
222                          std::string* error);
223 
224   gfx::Range GetAutocorrectRange(int context_id, std::string* error);
225 
226   gfx::Rect GetAutocorrectCharacterBounds(int context_id, std::string* error);
227 
228   bool SetAutocorrectRange(int context_id,
229                            const base::string16& autocorrect_text,
230                            int start,
231                            int end,
232                            std::string* error);
233 
234   // Set the current selection range.
235   bool SetSelectionRange(int context_id,
236                          int start,
237                          int end,
238                          std::string* error);
239 
240   // Called when a key event is handled.
241   void KeyEventHandled(const std::string& extension_id,
242                        const std::string& request_id,
243                        bool handled);
244 
245   // Returns the request ID for this key event.
246   std::string AddPendingKeyEvent(
247       const std::string& component_id,
248       ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback);
249 
250   void OnInputMethodOptionsChanged();
251 
GetContextIdForTesting()252   int GetContextIdForTesting() const { return context_id_; }
253 
GetPrefChangeRegistrarForTesting()254   PrefChangeRegistrar* GetPrefChangeRegistrarForTesting() const {
255     return pref_change_registrar_.get();
256   }
257 
258   // Get the composition bounds.
composition_bounds()259   const std::vector<gfx::Rect>& composition_bounds() const {
260     return composition_bounds_;
261   }
262 
263   // ProfileObserver:
264   void OnProfileWillBeDestroyed(Profile* profile) override;
265 
266  protected:
267   struct PendingKeyEvent {
268     PendingKeyEvent(
269         const std::string& component_id,
270         ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback);
271     PendingKeyEvent(PendingKeyEvent&& other);
272     ~PendingKeyEvent();
273 
274     std::string component_id;
275     KeyboardEvent key_event;
276     ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback;
277 
278    private:
279     DISALLOW_COPY_AND_ASSIGN(PendingKeyEvent);
280   };
281 
282   // Returns true if this IME is active, false if not.
283   virtual bool IsActive() const = 0;
284 
285   // Notifies InputContextHandler that the composition is changed.
286   virtual void UpdateComposition(const ui::CompositionText& composition_text,
287                                  uint32_t cursor_pos,
288                                  bool is_visible) = 0;
289 
290   // Notifies InputContextHandler to change the composition range.
291   virtual bool SetCompositionRange(
292       uint32_t before,
293       uint32_t after,
294       const std::vector<ui::ImeTextSpan>& text_spans) = 0;
295 
296   virtual bool SetComposingRange(
297       uint32_t start,
298       uint32_t end,
299       const std::vector<ui::ImeTextSpan>& text_spans) = 0;
300 
301   virtual gfx::Range GetAutocorrectRange() = 0;
302 
303   virtual gfx::Rect GetAutocorrectCharacterBounds() = 0;
304 
305   // Notifies the InputContextHandler that the autocorrect range should
306   // be updated and the autocorrect text has updated.
307   virtual bool SetAutocorrectRange(const base::string16& autocorrect_text,
308                                    uint32_t start,
309                                    uint32_t end) = 0;
310 
311   // Notifies the InputContextHandler to change the selection range.
312   virtual bool SetSelectionRange(uint32_t start, uint32_t end) = 0;
313 
314   // Notifies InputContextHanlder to commit |text|.
315   virtual void CommitTextToInputContext(int context_id,
316                                         const std::string& text) = 0;
317 
318   // Notifies InputContextHandler to delete surrounding text.
319   void DeleteSurroundingTextToInputContext(int offset, size_t number_of_chars);
320 
321   // Sends the key event to the window tree host.
322   virtual bool SendKeyEvent(ui::KeyEvent* ui_event,
323                             const std::string& code,
324                             std::string* error) = 0;
325 
326   // Used to verify that a key event is valid before precessing it in the
327   // current context.
328   virtual bool IsValidKeyEvent(const ui::KeyEvent* ui_event) = 0;
329 
330   ui::TextInputType current_input_type_;
331 
332   // ID that is used for the current input context.  False if there is no focus.
333   int context_id_;
334 
335   // Next id that will be assigned to a context.
336   int next_context_id_;
337 
338   // The input_component ID in IME extension's manifest.
339   std::string active_component_id_;
340 
341   // The IME extension ID.
342   std::string extension_id_;
343 
344   // The observer object recieving events for this IME.
345   std::unique_ptr<InputMethodEngineBase::Observer> observer_;
346 
347   Profile* profile_;
348 
349   unsigned int next_request_id_ = 1;
350   std::map<std::string, PendingKeyEvent> pending_key_events_;
351 
352   // The composition text to be set from calling input.ime.setComposition API.
353   ui::CompositionText composition_;
354   bool composition_changed_;
355 
356   // The composition bounds returned by inputMethodPrivate.getCompositionBounds
357   // API.
358   std::vector<gfx::Rect> composition_bounds_;
359 
360   // The text to be committed from calling input.ime.commitText API.
361   std::string text_;
362   bool commit_text_changed_;
363 
364   // Indicates whether the IME extension is currently handling a physical key
365   // event. This is used in CommitText/UpdateCompositionText/etc.
366   bool handling_key_event_;
367 
368  private:
369   ui::KeyEvent ConvertKeyboardEventToUIKeyEvent(const KeyboardEvent& event);
370 
371   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
372 
373   base::Value input_method_settings_snapshot_;
374 
375   ScopedObserver<Profile, ProfileObserver> profile_observer_{this};
376 };
377 
378 }  // namespace chromeos
379 
380 #endif  // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_ENGINE_BASE_H_
381