blob: 2ac0a295a918edae91b0adbaa2a77c75912613b0 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include "ash/public/interfaces/tray_action.mojom.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/lock_screen_apps/app_manager.h"
#include "chrome/browser/chromeos/lock_screen_apps/state_observer.h"
#include "chromeos/dbus/power_manager_client.h"
#include "components/session_manager/core/session_manager_observer.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/common/api/app_runtime.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/aura/window.h"
#include "ui/events/devices/input_device_event_observer.h"
class PrefRegistrySimple;
class Profile;
namespace aura {
class Window;
namespace base {
class TickClock;
namespace content {
class BrowserContext;
namespace extensions {
class AppDelegate;
class AppWindow;
class Extension;
namespace lock_screen_data {
class LockScreenItemStorage;
} // namespace extensions
namespace session_manager {
class SessionManager;
namespace ui {
class InputDeviceManager;
namespace lock_screen_apps {
class AppWindowMetricsTracker;
class FocusCyclerDelegate;
class LockScreenProfileCreator;
class StateObserver;
class FirstAppRunToastManager;
// Manages state of lock screen action handler apps, and notifies
// interested parties as the state changes.
// Currently assumes single supported action - NEW_NOTE.
class StateController : public ash::mojom::TrayActionClient,
public session_manager::SessionManagerObserver,
public aura::WindowObserver,
public extensions::AppWindowRegistry::Observer,
public ui::InputDeviceEventObserver,
public chromeos::PowerManagerClient::Observer {
// Returns the global StateController instance.
static StateController* Get();
static void RegisterProfilePrefs(PrefRegistrySimple* pref_registry);
// Note that only one StateController is allowed per process. Creating a
// StateController will set global instance ptr that can be accessed using
// |Get|. This pointer will be reset when the StateController is destroyed.
~StateController() override;
// Sets the tray action that should be used by |StateController|.
// Has to be called before |Initialize|.
void SetTrayActionPtrForTesting(ash::mojom::TrayActionPtr tray_action_ptr);
void FlushTrayActionForTesting();
// Sets the callback that will be run when the state controller is fully
// initialized and ready for action.
void SetReadyCallbackForTesting(const base::Closure& ready_callback);
// Sets the tick clock to be used in tests.
void SetTickClockForTesting(const base::TickClock* clock);
// Sets test AppManager implementation. Should be called before
// |SetPrimaryProfile|
void SetAppManagerForTesting(std::unique_ptr<AppManager> app_manager);
// Sets test LockScreenProfileCreator implementation. Should be called before
// |SetPrimaryProfile|
void SetLockScreenLockScreenProfileCreatorForTesting(
std::unique_ptr<LockScreenProfileCreator> profile_creator);
// Initializes mojo bindings for the StateController - it creates binding to
// ash's tray action interface and sets this object as the interface's client.
void Initialize();
void SetPrimaryProfile(Profile* profile);
// Shuts down the state controller, reseting all dependencies on profiles.
// Should be called on global instance before profile destruction starts.
// TODO(tbarzic): Consider removing this after lock screen implementation
// moves to ash - the main reason the method is needed is to enable
// SigninScreenHandler to safely remove itself as an observer on its
// destruction (which might happen after state controller has to be
// shutdown). When this is not the case anymore StateController::Shutdown
// usage can be replaced with destructing the StateController instance.
void Shutdown();
void AddObserver(StateObserver* observer);
void RemoveObserver(StateObserver* observer);
// Sets the focus cycler delegate the state controller should use to pass on
// from and give focus to the active lock screen app window.
void SetFocusCyclerDelegate(FocusCyclerDelegate* delegate);
// Gets current state assiciated with the lock screen note action.
ash::mojom::TrayActionState GetLockScreenNoteState() const;
// ash::mojom::TrayActionClient:
void RequestNewLockScreenNote(
ash::mojom::LockScreenNoteOrigin origin) override;
void CloseLockScreenNote(
ash::mojom::CloseLockScreenNoteReason reason) override;
// session_manager::SessionManagerObserver:
void OnSessionStateChanged() override;
// aura::WindowObserver:
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
void OnWindowDestroying(aura::Window* window) override;
// extensions::AppWindowRegistry::Observer:
void OnAppWindowAdded(extensions::AppWindow* app_window) override;
void OnAppWindowRemoved(extensions::AppWindow* app_window) override;
// ui::InputDeviceEventObserver:
void OnInputDeviceConfigurationChanged(uint8_t input_device_types) override;
// chromeos::PowerManagerClient::Observer
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
// Creates and registers an app window as action handler for the action on
// Chrome OS lock screen. The ownership of the returned app window is passed
// to the caller.
// If the app is not allowed to create an app window for handling the action
// on lock screen (e.g. if the action has not been requested), it will return
// nullptr.
extensions::AppWindow* CreateAppWindowForLockScreenAction(
content::BrowserContext* context,
const extensions::Extension* extension,
extensions::api::app_runtime::ActionType action,
std::unique_ptr<extensions::AppDelegate> app_delegate);
// Should be called when the active app window is tabbed through. If needed,
// the method will take focus from the app window and pass it on using
// |focus_cycler_delegate_|.
// Returns whether the focus has been taken from the app window.
bool HandleTakeFocus(content::WebContents* web_contents, bool reverse);
FirstAppRunToastManager* first_app_run_toast_manager() {
return first_app_run_toast_manager_.get();
// Gets the encryption key that should be used to encrypt user data created on
// the lock screen. If a key hadn't previously been created and saved to
// user prefs, a new key is created and saved.
// |crypto_key| - the found/created key.
// Returns whether |crypto_key| was successfully retrieved.
bool GetUserCryptoKey(Profile* profile, std::string* crypto_key);
// Continues lock screen apps initialization with primary user profile and
// associated encryption key to be used for encrypting user data created in
// lock screen context.
void InitializeWithCryptoKey(Profile* profile, const std::string& crypto_key);
// Continues lock screen apps initialization. Should be called when stylus
// input has been detected.
void InitializeWithStylusInputPresent();
// Called when app manager reports that note taking availability has changed.
void OnNoteTakingAvailabilityChanged();
// If there is an app window registered as a handler for note taking action
// on lock screen, unregisters the window, and closes is if |close_window| is
// set. It changes the current state to kAvailable or kNotAvailable, depending
// on whether lock screen note taking action can still be handled.
void ResetNoteTakingWindowAndMoveToNextState(
bool close_window,
ash::mojom::CloseLockScreenNoteReason reason);
// Requests lock screen note action state change to |state|.
// Returns whether the action state has changed.
bool UpdateLockScreenNoteState(ash::mojom::TrayActionState state);
// Notifies observers that the lock screen note action state changed.
void NotifyLockScreenNoteStateChanged();
// Passed as a focus handler to |focus_cycler_delegate_| when the assiciated
// app window is visible (active or in background).
// It focuses the app window.
void FocusAppWindow(bool reverse);
// Lock screen note action state.
ash::mojom::TrayActionState lock_screen_note_state_ =
base::ObserverList<StateObserver>::Unchecked observers_;
mojo::Binding<ash::mojom::TrayActionClient> binding_;
ash::mojom::TrayActionPtr tray_action_ptr_;
std::unique_ptr<LockScreenProfileCreator> lock_screen_profile_creator_;
// Whether lock screen apps initialization was stopped due to stylus input
// missing (or stylus not being otherwise enabled). If stylus availability
// changes due to stylus input being detected, initialization will continue.
bool stylus_input_missing_ = false;
std::unique_ptr<AppManager> app_manager_;
FocusCyclerDelegate* focus_cycler_delegate_ = nullptr;
extensions::AppWindow* note_app_window_ = nullptr;
// Used to track metrics for app window launches - it is set when the user
// session is locked (and reset on unlock). Note that a single instance
// should not be reused for different lock sessions - it tracks number of app
// launches per lock screen.
std::unique_ptr<AppWindowMetricsTracker> note_app_window_metrics_;
// Used to show first lock screen app run (toast) dialog when an app window
// is first launched for an app.
// NOTE: The manager can be used for every app launch - before showing the
// toast dialog, the manager will bail out if it determines that the toast
// for the associated app has been previosly seen (and closed) by the user.
std::unique_ptr<FirstAppRunToastManager> first_app_run_toast_manager_;
ScopedObserver<aura::Window, aura::WindowObserver> note_window_observer_;
ScopedObserver<ui::InputDeviceManager, ui::InputDeviceEventObserver>
// If set, this callback will be run when the state controller is fully
// initialized. It can be used to throttle tests until state controller
// is ready for action - i.e. until the state controller starts reacting
// to session / app manager changes.
base::Closure ready_callback_;
// The clock used to keep track of time, for example to report app window
// lifetime metrics.
const base::TickClock* tick_clock_ = nullptr;
base::WeakPtrFactory<StateController> weak_ptr_factory_;
} // namespace lock_screen_apps