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_
|