File: arc_input_overlay_manager.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (188 lines) | stat: -rw-r--r-- 8,155 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_ARC_INPUT_OVERLAY_MANAGER_H_
#define CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_ARC_INPUT_OVERLAY_MANAGER_H_

#include "ash/constants/ash_features.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/ash/arc/input_overlay/db/data_controller.h"
#include "chrome/browser/ash/arc/input_overlay/db/proto/app_data.pb.h"
#include "chrome/browser/ash/arc/input_overlay/key_event_source_rewriter.h"
#include "chrome/browser/ash/arc/input_overlay/touch_injector.h"
#include "chromeos/ash/experiences/arc/mojom/app.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/env.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/display/display_observer.h"

class ArcAppListPrefs;

namespace arc {
class ArcBridgeService;
}  // namespace arc

namespace content {
class BrowserContext;
}  // namespace content

namespace display {
enum class TabletState;
}  // namespace display

namespace ui {
class InputMethod;
}  // namespace ui

namespace arc::input_overlay {

// Manager for ARC input overlay feature which improves input compatibility
// for touch-only apps.
class ArcInputOverlayManager : public KeyedService,
                               public aura::EnvObserver,
                               public aura::WindowObserver,
                               public aura::client::FocusChangeObserver,
                               public display::DisplayObserver {
 public:
  // Returns singleton instance for the given BrowserContext,
  // or nullptr if the browser `context` is not allowed to use ARC.
  static ArcInputOverlayManager* GetForBrowserContext(
      content::BrowserContext* context);
  ArcInputOverlayManager(content::BrowserContext* browser_context,
                         ::arc::ArcBridgeService* arc_bridge_service);
  ArcInputOverlayManager(const ArcInputOverlayManager&) = delete;
  ArcInputOverlayManager& operator=(const ArcInputOverlayManager&) = delete;
  ~ArcInputOverlayManager() override;

  static void EnsureFactoryBuilt();

  // aura::EnvObserver:
  void OnWindowInitialized(aura::Window* new_window) override;

  // aura::WindowObserver:
  void OnWindowPropertyChanged(aura::Window* window,
                               const void* key,
                               intptr_t old) override;
  void OnWindowDestroying(aura::Window* window) override;
  void OnWindowAddedToRootWindow(aura::Window* window) override;
  void OnWindowRemovingFromRootWindow(aura::Window* window,
                                      aura::Window* new_root) override;
  void OnWindowParentChanged(aura::Window* window,
                             aura::Window* parent) override;

  // KeyedService:
  void Shutdown() override;

  // aura::client::FocusChangeObserver:
  void OnWindowFocused(aura::Window* gained_focus,
                       aura::Window* lost_focus) override;

  // display::DisplayObserver:
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t metrics) override;
  void OnDisplayTabletStateChanged(display::TabletState state) override;

 private:
  friend class ArcInputOverlayManagerTest;
  friend class GameControlsTestBase;
  friend class TestArcInputOverlayManager;

  class InputMethodObserver;

  // Remove `window` from observation list.
  void RemoveWindowObservation(aura::Window* window);
  void UnregisterAndRemoveObservation(aura::Window* window);
  // Read default data.
  static std::unique_ptr<TouchInjector> ReadDefaultData(
      std::unique_ptr<TouchInjector> touch_injector);
  // Called when finishing reading default data.
  void OnFinishReadDefaultData(std::unique_ptr<TouchInjector> touch_injector);
  // Apply the customized proto data.
  void OnProtoDataAvailable(std::unique_ptr<TouchInjector> touch_injector,
                            std::unique_ptr<AppDataProto> proto);
  // Callback function triggered by Save button.
  void OnSaveProtoFile(std::unique_ptr<AppDataProto> proto,
                       std::string package_name);

  // Returns true if the app has Game Controls opt-out metadata set to true.
  bool IsGameControlsOptOut(const std::string& package_name);
  // Checks app category.
  void CheckAppCategory(std::unique_ptr<TouchInjector> touch_injector);
  // Called after getting app category.
  void OnDidCheckAppCategory(std::unique_ptr<TouchInjector> touch_injector,
                             arc::mojom::AppCategory app_category);
  // Checks if it is O4C app.
  void CheckO4C(std::unique_ptr<TouchInjector> touch_injector);

  void NotifyTextInputState();
  void AddObserverToInputMethod();
  void RemoveObserverFromInputMethod();
  // Only top level window will be registered/unregistered successfully.
  void RegisterWindow(aura::Window* window);
  void UnRegisterWindow(aura::Window* window);
  void RegisterFocusedWindow();
  // Add display overlay controller related to `touch_injector`. Virtual for
  // test.
  virtual void AddDisplayOverlayController(TouchInjector* touch_injector);
  void RemoveDisplayOverlayController();
  // Reset for removing pending `touch_injector` because of no GIO data or
  // window destroying.
  void ResetForPendingTouchInjector(
      std::unique_ptr<TouchInjector> touch_injector);
  // Called when data loading finished from files or mojom calls for
  // `touch_injector`. `is_o4c` is true if the game is optimized for ChromeOS.
  void OnLoadingFinished(std::unique_ptr<TouchInjector> touch_injector,
                         bool is_o4c = false);
  // Once there is an error when checking Android side, reset `TouchInjector` if
  // it has empty actions. Otherwise, finish data loading. This is called for
  // mojom connection error. Once the mojom connection failed, it considers GIO
  // is available if there is mapping data.
  void MayKeepTouchInjectorAfterError(
      std::unique_ptr<TouchInjector> touch_injector);

  ArcAppListPrefs* GetArcAppListPrefs();

  // Returns `window`'s anchor window if `window` is a game dashboard main menu
  // dialog window or `ash::AnchoredNudge` or a transient window, or returns
  // `window` itself if `window` is none of above windows. For Alpha/AlphaV2
  // version, it still returns `window` itself.
  aura::Window* GetAnchorWindow(aura::Window* window);

  base::ScopedObservation<aura::Env, aura::EnvObserver> env_observation_{this};
  base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
      window_observations_{this};
  base::flat_map<aura::Window*, std::unique_ptr<TouchInjector>>
      input_overlay_enabled_windows_;
  display::ScopedDisplayObserver display_observer_{this};

  // To avoid UAF issue reported in crbug.com/1363030. Save the windows which
  // prepare or start loading the GIO default key mapping data. Once window is
  // destroying or the GIO data reading is finished, window is removed from this
  // set.
  base::flat_set<raw_ptr<aura::Window, CtnExperimental>> loading_data_windows_;
  bool is_text_input_active_ = false;
  raw_ptr<ui::InputMethod> input_method_ = nullptr;
  std::unique_ptr<InputMethodObserver> input_method_observer_;
  // Only one window is registered since there is only one window can be focused
  // each time.
  raw_ptr<aura::Window> registered_top_level_window_ = nullptr;
  std::unique_ptr<KeyEventSourceRewriter> key_event_source_rewriter_;
  std::unique_ptr<DisplayOverlayController> display_overlay_controller_;
  std::unique_ptr<DataController> data_controller_;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;

  base::WeakPtrFactory<ArcInputOverlayManager> weak_ptr_factory_{this};
};

}  // namespace arc::input_overlay

#endif  // CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_ARC_INPUT_OVERLAY_MANAGER_H_