1 // Copyright 2018 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_ARC_INPUT_METHOD_MANAGER_ARC_INPUT_METHOD_MANAGER_SERVICE_H_
6 #define CHROME_BROWSER_CHROMEOS_ARC_INPUT_METHOD_MANAGER_ARC_INPUT_METHOD_MANAGER_SERVICE_H_
7 
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include "base/macros.h"
14 #include "base/observer_list_types.h"
15 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
16 #include "chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_bridge.h"
17 #include "chrome/browser/chromeos/arc/input_method_manager/arc_input_method_state.h"
18 #include "chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.h"
19 #include "chrome/browser/chromeos/input_method/input_method_engine.h"
20 #include "components/arc/mojom/input_method_manager.mojom-forward.h"
21 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
22 #include "components/keyed_service/core/keyed_service.h"
23 #include "ui/base/ime/chromeos/ime_bridge_observer.h"
24 #include "ui/base/ime/chromeos/input_method_manager.h"
25 
26 namespace content {
27 class BrowserContext;
28 }  // namespace content
29 
30 namespace arc {
31 
32 class ArcBridgeService;
33 
34 class ArcInputMethodManagerService
35     : public KeyedService,
36       public ArcInputMethodManagerBridge::Delegate,
37       public chromeos::input_method::InputMethodManager::ImeMenuObserver,
38       public chromeos::input_method::InputMethodManager::Observer,
39       public ui::IMEBridgeObserver {
40  public:
41   class Observer : public base::CheckedObserver {
42    public:
43     virtual void OnAndroidVirtualKeyboardVisibilityChanged(bool visible) = 0;
44   };
45 
46   // Returns the instance for the given BrowserContext, or nullptr if the
47   // browser |context| is not allowed to use ARC.
48   static ArcInputMethodManagerService* GetForBrowserContext(
49       content::BrowserContext* context);
50   // Does the same as GetForBrowserContext() but for testing. Please refer to
51   // ArcBrowserContextKeyedServiceFactoryBase for the difference between them.
52   static ArcInputMethodManagerService* GetForBrowserContextForTesting(
53       content::BrowserContext* context);
54 
55   static BrowserContextKeyedServiceFactory* GetFactory();
56 
57   ArcInputMethodManagerService(content::BrowserContext* context,
58                                ArcBridgeService* bridge_service);
59   ~ArcInputMethodManagerService() override;
60 
61   void SetInputMethodManagerBridgeForTesting(
62       std::unique_ptr<ArcInputMethodManagerBridge> test_bridge);
63 
64   void AddObserver(Observer* observer);
65   void RemoveObserver(Observer* observer);
66 
67   // KeyedService overrides:
68   void Shutdown() override;
69 
70   // ArcInputMethodManagerBridge::Delegate overrides:
71   void OnActiveImeChanged(const std::string& ime_id) override;
72   void OnImeDisabled(const std::string& ime_id) override;
73   void OnImeInfoChanged(std::vector<mojom::ImeInfoPtr> ime_info_array) override;
74   void OnConnectionClosed() override;
75 
76   // chromeos::input_method::InputMethodManager::ImeMenuObserver overrides:
77   void ImeMenuListChanged() override;
ImeMenuActivationChanged(bool is_active)78   void ImeMenuActivationChanged(bool is_active) override {}
ImeMenuItemsChanged(const std::string & engine_id,const std::vector<chromeos::input_method::InputMethodManager::MenuItem> & items)79   void ImeMenuItemsChanged(
80       const std::string& engine_id,
81       const std::vector<chromeos::input_method::InputMethodManager::MenuItem>&
82           items) override {}
83 
84   // chromeos::input_method::InputMethodManager::Observer overrides:
85   void InputMethodChanged(chromeos::input_method::InputMethodManager* manager,
86                           Profile* profile,
87                           bool show_message) override;
88 
89   // ui::IMEBridgeObserver overrides:
OnRequestSwitchEngine()90   void OnRequestSwitchEngine() override {}
91   void OnInputContextHandlerChanged() override;
92 
93   // Called when a11y keyboard option changed and disables ARC IME while a11y
94   // keyboard option is enabled.
95   void OnAccessibilityStatusChanged(
96       const chromeos::AccessibilityStatusEventDetails& event_details);
97 
98   void OnArcInputMethodBoundsChanged(const gfx::Rect& bounds);
99 
100   InputConnectionImpl* GetInputConnectionForTesting();
101 
102  private:
103   class ArcInputMethodBoundsObserver;
104   class InputMethodEngineObserver;
105   class InputMethodObserver;
106   class TabletModeObserver;
107 
108   void EnableIme(const std::string& ime_id, bool enable);
109   void SwitchImeTo(const std::string& ime_id);
110   chromeos::input_method::InputMethodDescriptor BuildInputMethodDescriptor(
111       const mojom::ImeInfo* info);
112   void Focus(int input_context_id);
113   void Blur();
114   void UpdateTextInputState();
115   mojom::TextInputStatePtr GetTextInputState(
116       bool is_input_state_update_requested);
117 
118   // Removes ARC IME from IME related prefs that are current active IME pref,
119   // previous active IME pref, enabled IME list pref and preloading IME list
120   // pref.
121   void RemoveArcIMEFromPrefs();
122   void RemoveArcIMEFromPref(const char* pref_name);
123 
124   void OnTabletModeToggled(bool enabled);
125 
126   // Update the descriptors in IMM and the prefs according to
127   // |arc_ime_state_|.
128   void UpdateInputMethodEntryWithImeInfo();
129 
130   // Notifies InputMethodManager's observers of possible ARC IME state changes.
131   void NotifyInputMethodManagerObservers(bool is_tablet_mode);
132 
133   bool IsVirtualKeyboardShown() const;
134   void SendShowVirtualKeyboard();
135   void SendHideVirtualKeyboard();
136   void NotifyVirtualKeyboardVisibilityChange(bool visible);
137 
138   Profile* const profile_;
139 
140   std::unique_ptr<ArcInputMethodManagerBridge> imm_bridge_;
141   std::set<std::string> active_arc_ime_ids_;
142   std::unique_ptr<ArcInputMethodState::Delegate> arc_ime_state_delegate_;
143   ArcInputMethodState arc_ime_state_;
144   bool is_virtual_keyboard_shown_;
145   // This flag is set to true while updating ARC IMEs entries in IMM to avoid
146   // exposing incomplete state.
147   bool is_updating_imm_entry_;
148 
149   // ArcInputMethodManager installs a proxy IME to redirect IME related events
150   // from/to ARC IMEs in the container. The below two variables are for the
151   // proxy IME.
152   const std::string proxy_ime_extension_id_;
153   std::unique_ptr<chromeos::InputMethodEngine> proxy_ime_engine_;
154 
155   // The currently active input method, observed for
156   // OnShowVirtualKeyboardIfEnabled.
157   ui::InputMethod* input_method_ = nullptr;
158   bool is_arc_ime_active_ = false;
159 
160   std::unique_ptr<InputConnectionImpl> active_connection_;
161 
162   std::unique_ptr<TabletModeObserver> tablet_mode_observer_;
163 
164   std::unique_ptr<InputMethodObserver> input_method_observer_;
165 
166   std::unique_ptr<ArcInputMethodBoundsObserver> input_method_bounds_observer_;
167 
168   std::unique_ptr<chromeos::AccessibilityStatusSubscription>
169       accessibility_status_subscription_;
170 
171   base::ObserverList<Observer> observers_;
172 
173   DISALLOW_COPY_AND_ASSIGN(ArcInputMethodManagerService);
174 };
175 
176 }  // namespace arc
177 
178 #endif  // CHROME_BROWSER_CHROMEOS_ARC_INPUT_METHOD_MANAGER_ARC_INPUT_METHOD_MANAGER_SERVICE_H_
179