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

ash / system / human_presence / snooping_protection_controller.h [blame]

// 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 ASH_SYSTEM_HUMAN_PRESENCE_SNOOPING_PROTECTION_CONTROLLER_H_
#define ASH_SYSTEM_HUMAN_PRESENCE_SNOOPING_PROTECTION_CONTROLLER_H_

#include <memory>
#include <optional>

#include "ash/ash_export.h"
#include "ash/public/cpp/session/session_controller.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/system/human_presence/human_presence_orientation_controller.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/dbus/hps/hps_service.pb.h"
#include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
#include "components/session_manager/session_manager_types.h"

class PrefChangeRegistrar;
class PrefRegistrySimple;

namespace ash {

class SnoopingProtectionNotificationBlocker;

// Pushes status changes to the snooping protection icon and notification
// blocker based on DBus state, preferences and session type.
class ASH_EXPORT SnoopingProtectionController
    : public SessionObserver,
      public HumanPresenceOrientationController::Observer,
      public HumanPresenceDBusClient::Observer {
 public:
  class Observer : public base::CheckedObserver {
   public:
    ~Observer() override = default;

    // Called when an observer should show or hide itself because the snooping
    // status has changed. Argument is true if a snooper has now been detected.
    virtual void OnSnoopingStatusChanged(bool snooper) = 0;

    // Used to coordinate observers that might outlive the controller.
    virtual void OnSnoopingProtectionControllerDestroyed() = 0;
  };

  SnoopingProtectionController();
  SnoopingProtectionController(const SnoopingProtectionController&) = delete;
  SnoopingProtectionController& operator=(const SnoopingProtectionController&) =
      delete;
  ~SnoopingProtectionController() override;

  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  // SessionObserver:
  void OnSessionStateChanged(session_manager::SessionState state) override;
  void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;

  // HumanPresenceOrientationObserver:
  void OnOrientationChanged(bool suitable_for_human_presence) override;

  // HumanPresenceDBusClient::Observer:
  void OnHpsSenseChanged(const hps::HpsResultProto&) override;
  void OnHpsNotifyChanged(const hps::HpsResultProto&) override;
  void OnRestart() override;
  void OnShutdown() override;

  // Add/remove views that are listening for snooper presence.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // The current snooper status.
  bool SnooperPresent() const;

 private:
  // Used to track whether a signal should actually trigger a visibility change.
  struct State {
    // Whether a snooper is present, as last reported by the service.
    bool present = false;

    // Whether there is an active user session ongoing.
    bool session_active = false;

    // Whether the user has enabled the feature via preferences.
    bool pref_enabled = false;

    // Whether the daemon is available for communication.
    bool service_available = false;

    // Whether the daemon has been successfully configured.
    bool service_configured = false;

    // Whether the device is in physical orientation where our models are
    // accurate.
    bool orientation_suitable = false;

    // Whether we are within the minimum time window for which to report a
    // positive result.
    bool within_pos_window = false;
  };

  // Updates snooper state as appropriate given the signal, session,
  // preference and device orientation state. If changed, notifies observers.
  void UpdateSnooperStatus(const State& new_state);

  // Requests the start or stop of the snooping signal, so that the daemon need
  // not be running snooping logic while the user has the feature disabled.
  // Also updates the new state of service availability.
  void ReconfigureService(State* new_state);

  // Configures the daemon, polls its initial state and opts into its signals.
  void StartServiceObservation(bool service_is_available);

  // Performs the state update from the daemon response.
  void UpdateServiceState(std::optional<hps::HpsResultProto> result);

  // A callback to update visibility when the user enables or disables the
  // feature.
  void UpdatePrefState();

  // A callback that fires once a positive signal has been emitted for the
  // minimum allowed time. Sends out any delayed updates to observers.
  void OnMinWindowExpired();

  // Logs the amount of time a snooper was present / absent.
  // An initial call just caches the current time (and doesn't log anything).
  // Subsequent calls update the cache and log time elapsed if snooping status
  // has changed.
  // The cache can be cleared by resetting `last_presence_report_time_`.
  void LogPresenceWindow(bool is_present);

  // The state of all signals relevant to snooping status.
  State state_;

  // Used to enforce a minimum window of positive results.
  base::RetainingOneShotTimer pos_window_timer_;

  base::ScopedObservation<SessionController, SessionObserver>
      session_observation_{this};
  base::ScopedObservation<HumanPresenceOrientationController,
                          HumanPresenceOrientationController::Observer>
      orientation_observation_{this};
  base::ScopedObservation<HumanPresenceDBusClient,
                          HumanPresenceDBusClient::Observer>
      human_presence_dbus_observation_{this};

  // Used to notify ourselves of changes to the pref that enables / disables
  // this feature.
  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;

  // Clients listening for snooping status changes.
  base::ObserverList<Observer> observers_;

  // Controls popup hiding and our info notification.
  const std::unique_ptr<SnoopingProtectionNotificationBlocker>
      notification_blocker_;

  // The minimum amount of time between emitting an initial positive signal and
  // then a subsequent negative one.
  const base::TimeDelta pos_window_;

  // Last time the snooper became present or absent.
  base::TimeTicks last_presence_report_time_;

  // Must be last.
  base::WeakPtrFactory<SnoopingProtectionController> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // ASH_SYSTEM_HUMAN_PRESENCE_SNOOPING_PROTECTION_CONTROLLER_H_