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_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_H_
6 #define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_H_
7 
8 #include <stddef.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "base/macros.h"
16 #include "base/observer_list.h"
17 #include "base/threading/thread_checker.h"
18 #include "chrome/browser/chromeos/input_method/assistive_window_controller.h"
19 #include "chrome/browser/chromeos/input_method/assistive_window_controller_delegate.h"
20 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
21 #include "chrome/browser/chromeos/input_method/ime_service_connector.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "ui/base/ime/chromeos/ime_engine_handler_interface.h"
26 #include "ui/base/ime/chromeos/input_method_manager.h"
27 #include "ui/base/ime/chromeos/input_method_util.h"
28 
29 namespace ui {
30 class IMEEngineHandlerInterface;
31 }  // namespace ui
32 
33 namespace chromeos {
34 class ComponentExtensionIMEManager;
35 class ComponentExtensionIMEManagerDelegate;
36 namespace input_method {
37 class InputMethodDelegate;
38 class ImeKeyboard;
39 
40 // The implementation of InputMethodManager.
41 class InputMethodManagerImpl : public InputMethodManager,
42                                public CandidateWindowController::Observer,
43                                public AssistiveWindowControllerDelegate,
44                                public content::NotificationObserver {
45  public:
46   class StateImpl : public InputMethodManager::State {
47    public:
48     StateImpl(InputMethodManagerImpl* manager, Profile* profile);
49 
50     // Init new state as a copy of other.
51     void InitFrom(const StateImpl& other);
52 
53     // Returns true if (manager_->state_ == this).
54     bool IsActive() const;
55 
56     // Returns human-readable dump (for debug).
57     std::string Dump() const;
58 
59     // Adds new input method to given list if possible
60     bool EnableInputMethodImpl(
61         const std::string& input_method_id,
62         std::vector<std::string>* new_active_input_method_ids) const;
63 
64     // Returns true if |input_method_id| is in |active_input_method_ids|.
65     bool InputMethodIsActivated(const std::string& input_method_id) const;
66 
67     // If |current_input_methodid_| is not in |input_method_ids|, switch to
68     // input_method_ids[0]. If the ID is equal to input_method_ids[N], switch to
69     // input_method_ids[N+1].
70     void SwitchToNextInputMethodInternal(
71         const std::vector<std::string>& input_method_ids,
72         const std::string& current_input_methodid);
73 
74     // Returns true if given input method requires pending extension.
75     bool MethodAwaitsExtensionLoad(const std::string& input_method_id) const;
76 
77     // Returns whether the input method (or keyboard layout) can be switched
78     // to the next or previous one. Returns false if only one input method is
79     // enabled.
80     bool CanCycleInputMethod() const;
81 
82     // InputMethodManager::State overrides.
83     scoped_refptr<InputMethodManager::State> Clone() const override;
84     void AddInputMethodExtension(
85         const std::string& extension_id,
86         const InputMethodDescriptors& descriptors,
87         ui::IMEEngineHandlerInterface* instance) override;
88     void RemoveInputMethodExtension(const std::string& extension_id) override;
89     void ChangeInputMethod(const std::string& input_method_id,
90                            bool show_message) override;
91     void ChangeInputMethodToJpKeyboard() override;
92     void ChangeInputMethodToJpIme() override;
93     void ToggleInputMethodForJpIme() override;
94     bool EnableInputMethod(
95         const std::string& new_active_input_method_id) override;
96     void EnableLoginLayouts(
97         const std::string& language_code,
98         const std::vector<std::string>& initial_layouts) override;
99     void EnableLockScreenLayouts() override;
100     void GetInputMethodExtensions(InputMethodDescriptors* result) override;
101     std::unique_ptr<InputMethodDescriptors> GetActiveInputMethods()
102         const override;
103     const std::vector<std::string>& GetActiveInputMethodIds() const override;
104     const InputMethodDescriptor* GetInputMethodFromId(
105         const std::string& input_method_id) const override;
106     size_t GetNumActiveInputMethods() const override;
107     void SetEnabledExtensionImes(std::vector<std::string>* ids) override;
108     void SetInputMethodLoginDefault() override;
109     void SetInputMethodLoginDefaultFromVPD(const std::string& locale,
110                                            const std::string& layout) override;
111     void SwitchToNextInputMethod() override;
112     void SwitchToLastUsedInputMethod() override;
113     InputMethodDescriptor GetCurrentInputMethod() const override;
114     bool ReplaceEnabledInputMethods(
115         const std::vector<std::string>& new_active_input_method_ids) override;
116     bool SetAllowedInputMethods(
117         const std::vector<std::string>& new_allowed_input_method_ids,
118         bool enable_allowed_input_methods) override;
119     const std::vector<std::string>& GetAllowedInputMethods() override;
120     void EnableInputView() override;
121     void DisableInputView() override;
122     const GURL& GetInputViewUrl() const override;
123     InputMethodManager::UIStyle GetUIStyle() const override;
124     void SetUIStyle(InputMethodManager::UIStyle ui_style) override;
125 
126     // Override the input view URL used to explicitly display some keyset.
127     void OverrideInputViewUrl(const GURL& url);
128 
129     // Reset the input view URL to the default url of the current input method.
130     void ResetInputViewUrl();
131 
132     // Connect to an InputEngineManager instance in an IME Mojo service.
133     void ConnectMojoManager(
134         mojo::PendingReceiver<chromeos::ime::mojom::InputEngineManager>
135             receiver);
136 
137     // ------------------------- Data members.
138     Profile* const profile;
139 
140     // The input method which was/is selected.
141     InputMethodDescriptor last_used_input_method;
142     InputMethodDescriptor current_input_method;
143 
144     // The active input method ids cache.
145     std::vector<std::string> active_input_method_ids;
146 
147     // The allowed keyboard layout input methods (e.g. by policy).
148     std::vector<std::string> allowed_keyboard_layout_input_method_ids;
149 
150     // The pending input method id for delayed 3rd party IME enabling.
151     std::string pending_input_method_id;
152 
153     // The list of enabled extension IMEs.
154     std::vector<std::string> enabled_extension_imes;
155 
156     // Extra input methods that have been explicitly added to the menu, such as
157     // those created by extension.
158     std::map<std::string, InputMethodDescriptor> extra_input_methods;
159 
160     InputMethodManagerImpl* const manager_;
161 
162     // True if the opt-in IME menu is activated.
163     bool menu_activated = false;
164 
165    protected:
166     friend base::RefCounted<chromeos::input_method::InputMethodManager::State>;
167     ~StateImpl() override;
168 
169    private:
170     // Returns true if the passed input method is allowed. By default, all input
171     // methods are allowed. After SetAllowedKeyboardLayoutInputMethods was
172     // called, the passed keyboard layout input methods are allowed and all
173     // non-keyboard input methods remain to be allowed.
174     bool IsInputMethodAllowed(const std::string& input_method_id) const;
175 
176     // Returns the first hardware input method that is allowed or the first
177     // allowed input method, if no hardware input method is allowed.
178     std::string GetAllowedFallBackKeyboardLayout() const;
179 
180     // The URL of the input view of the active ime with parameters (e.g. layout,
181     // keyset).
182     GURL input_view_url;
183 
184     // Whether the input view URL has been forcibly overridden e.g. to show a
185     // specific keyset.
186     bool input_view_url_overridden = false;
187 
188     InputMethodManager::UIStyle ui_style_ =
189         InputMethodManager::UIStyle::kNormal;
190 
191     std::unique_ptr<ImeServiceConnector> ime_service_connector_;
192 
193     // Do not forget to update StateImpl::InitFrom(const StateImpl& other) and
194     // StateImpl::Dump() when adding new data members!!!
195   };
196 
197   // Constructs an InputMethodManager instance. The client is responsible for
198   // calling |SetUISessionState| in response to relevant changes in browser
199   // state.
200   InputMethodManagerImpl(std::unique_ptr<InputMethodDelegate> delegate,
201                          bool enable_extension_loading);
202   ~InputMethodManagerImpl() override;
203 
204   // InputMethodManager override:
205   void AddObserver(InputMethodManager::Observer* observer) override;
206   void AddCandidateWindowObserver(
207       InputMethodManager::CandidateWindowObserver* observer) override;
208   void AddImeMenuObserver(
209       InputMethodManager::ImeMenuObserver* observer) override;
210   void RemoveObserver(InputMethodManager::Observer* observer) override;
211   void RemoveCandidateWindowObserver(
212       InputMethodManager::CandidateWindowObserver* observer) override;
213   void RemoveImeMenuObserver(
214       InputMethodManager::ImeMenuObserver* observer) override;
215   std::unique_ptr<InputMethodDescriptors> GetSupportedInputMethods()
216       const override;
217   void ActivateInputMethodMenuItem(const std::string& key) override;
218   void ConnectInputEngineManager(
219       mojo::PendingReceiver<chromeos::ime::mojom::InputEngineManager> receiver)
220       override;
221   bool IsISOLevel5ShiftUsedByCurrentInputMethod() const override;
222   bool IsAltGrUsedByCurrentInputMethod() const override;
223   void NotifyImeMenuItemsChanged(
224       const std::string& engine_id,
225       const std::vector<InputMethodManager::MenuItem>& items) override;
226   void MaybeNotifyImeMenuActivationChanged() override;
227   void OverrideKeyboardKeyset(
228       chromeos::input_method::ImeKeyset keyset) override;
229   void SetImeMenuFeatureEnabled(ImeMenuFeature feature, bool enabled) override;
230   bool GetImeMenuFeatureEnabled(ImeMenuFeature feature) const override;
231   void NotifyObserversImeExtraInputStateChange() override;
232   ui::InputMethodKeyboardController* GetInputMethodKeyboardController()
233       override;
234   void NotifyInputMethodExtensionAdded(
235       const std::string& extension_id) override;
236   void NotifyInputMethodExtensionRemoved(
237       const std::string& extension_id) override;
238 
239   ImeKeyboard* GetImeKeyboard() override;
240   InputMethodUtil* GetInputMethodUtil() override;
241   ComponentExtensionIMEManager* GetComponentExtensionIMEManager() override;
242   bool IsLoginKeyboard(const std::string& layout) const override;
243 
244   bool MigrateInputMethods(std::vector<std::string>* input_method_ids) override;
245 
246   scoped_refptr<InputMethodManager::State> CreateNewState(
247       Profile* profile) override;
248 
249   scoped_refptr<InputMethodManager::State> GetActiveIMEState() override;
250   void SetState(scoped_refptr<InputMethodManager::State> state) override;
251 
252   void ImeMenuActivationChanged(bool is_active) override;
253 
254   // Sets |candidate_window_controller_|.
255   void SetCandidateWindowControllerForTesting(
256       CandidateWindowController* candidate_window_controller);
257   // Sets |keyboard_|.
258   void SetImeKeyboardForTesting(ImeKeyboard* keyboard);
259   // Initialize |component_extension_manager_|.
260   void InitializeComponentExtensionForTesting(
261       std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate);
262 
263   // content::NotificationObserver overrides:
264   void Observe(int type,
265                const content::NotificationSource& source,
266                const content::NotificationDetails& details) override;
267 
268  private:
269   friend class InputMethodManagerImplTest;
270 
271   // CandidateWindowController::Observer overrides:
272   void CandidateClicked(int index) override;
273   void CandidateWindowOpened() override;
274   void CandidateWindowClosed() override;
275 
276   // AssistiveWindowControllerDelegate overrides:
277   void AssistiveWindowButtonClicked(
278       const ui::ime::AssistiveWindowButton& button) const override;
279 
280   // Creates and initializes |candidate_window_controller_| if it hasn't been
281   // done.
282   void MaybeInitializeCandidateWindowController();
283   // Creates and initializes |assistive_window_controller_| if it hasn't been
284   // done.
285   void MaybeInitializeAssistiveWindowController();
286 
287   // Returns Input Method that best matches given id.
288   const InputMethodDescriptor* LookupInputMethod(
289       const std::string& input_method_id,
290       StateImpl* state);
291 
292   // Change system input method to the one specified in the active state.
293   void ChangeInputMethodInternalFromActiveState(bool show_message,
294                                                 bool notify_menu);
295 
296   // Loads necessary component extensions.
297   // TODO(nona): Support dynamical unloading.
298   void LoadNecessaryComponentExtensions(StateImpl* state);
299 
300   // Starts or stops the system input method framework as needed.
301   // (after list of enabled input methods has been updated).
302   // If state is active, active input method is updated.
303   void ReconfigureIMFramework(StateImpl* state);
304 
305   // Record input method usage histograms.
306   void RecordInputMethodUsage(const std::string& input_method_id);
307 
308   // Notifies the current input method or the list of active input method IDs
309   // changed.
310   void NotifyImeMenuListChanged();
311 
312   // Request that the virtual keyboard be reloaded.
313   void ReloadKeyboard();
314 
315   std::unique_ptr<InputMethodDelegate> delegate_;
316 
317   // A list of objects that monitor the manager.
318   base::ObserverList<InputMethodManager::Observer>::Unchecked observers_;
319   base::ObserverList<CandidateWindowObserver>::Unchecked
320       candidate_window_observers_;
321   base::ObserverList<ImeMenuObserver>::Unchecked ime_menu_observers_;
322 
323   scoped_refptr<StateImpl> state_;
324 
325   // The candidate window.  This will be deleted when the APP_TERMINATING
326   // message is sent.
327   std::unique_ptr<CandidateWindowController> candidate_window_controller_;
328   // The assistive window.  This will be deleted when the APP_TERMINATING
329   // message is sent.
330   std::unique_ptr<AssistiveWindowController> assistive_window_controller_;
331 
332   // An object which provides miscellaneous input method utility functions. Note
333   // that |util_| is required to initialize |keyboard_|.
334   InputMethodUtil util_;
335 
336   // An object which provides component extension ime management functions.
337   std::unique_ptr<ComponentExtensionIMEManager>
338       component_extension_ime_manager_;
339 
340   // An object for switching XKB layouts and keyboard status like caps lock and
341   // auto-repeat interval.
342   std::unique_ptr<ImeKeyboard> keyboard_;
343 
344   // Whether load IME extensions.
345   bool enable_extension_loading_;
346 
347   // Whether the expanded IME menu is activated.
348   bool is_ime_menu_activated_ = false;
349 
350   // The enabled state of keyboard features.
351   uint32_t features_enabled_state_;
352 
353   // The engine map from extension_id to an engine.
354   typedef std::map<std::string, ui::IMEEngineHandlerInterface*> EngineMap;
355   typedef std::map<Profile*, EngineMap, ProfileCompare> ProfileEngineMap;
356   ProfileEngineMap engine_map_;
357 
358   content::NotificationRegistrar notification_registrar_;
359 
360   DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
361 };
362 
363 }  // namespace input_method
364 }  // namespace chromeos
365 
366 #endif  // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_H_
367