blob: 277849f60ccb5a7d5ad543e0739f9238a75a182f [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FBPREPROCESSOR_SESSION_STATE_MANAGER_H_
#define FBPREPROCESSOR_SESSION_STATE_MANAGER_H_
#include <memory>
#include <string>
#include <utility>
#include <base/files/file_path.h>
#include <base/memory/weak_ptr.h>
#include <base/observer_list.h>
#include <debugd/dbus-proxies.h>
#include <login_manager/proto_bindings/policy_descriptor.pb.h>
#include <session_manager/dbus-proxies.h>
#include "fbpreprocessor/firmware_dump.h"
#include "fbpreprocessor/manager.h"
#include "fbpreprocessor/platform_features_client.h"
namespace fbpreprocessor {
class SessionStateManagerInterface {
public:
// Interface for observing session state changes. Objects that want to be
// notified when the user logs in/out can add themselves to the list of
// observers.
class Observer {
public:
// Called when user was logged in. |user_dir| argument contains the path
// to the daemon store where files can be read/written.
virtual void OnUserLoggedIn(const std::string& user_dir) = 0;
// Called when user was logged out.
virtual void OnUserLoggedOut() = 0;
virtual ~Observer() = default;
};
// Adds and removes the observer.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
virtual ~SessionStateManagerInterface() = default;
};
class SessionStateManager : public SessionStateManagerInterface,
public PlatformFeaturesClientInterface::Observer {
public:
explicit SessionStateManager(
Manager* manager,
org::chromium::SessionManagerInterfaceProxyInterface*
session_manager_proxy,
org::chromium::debugdProxyInterface* debugd_proxy);
SessionStateManager(const SessionStateManager&) = delete;
SessionStateManager& operator=(const SessionStateManager&) = delete;
~SessionStateManager() override;
void AddObserver(SessionStateManagerInterface::Observer* observer) override;
void RemoveObserver(
SessionStateManagerInterface::Observer* observer) override;
bool RefreshPrimaryUser();
// Called by |PlatformFeaturesClientInterface| after fetching Finch.
void OnFeatureChanged(bool allowed) override;
// Returns true if the user is allowed to include firmware dumps in feedback
// reports, false otherwise.
bool FirmwareDumpsAllowedByPolicy(FirmwareDump::Type type) const;
void set_base_dir_for_test(const base::FilePath& base_dir) {
base_dir_ = base_dir;
}
private:
void OnSessionStateChanged(const std::string& state);
// Performs tasks for user login, including clearing debug buffer and then
// notifying all observers the user login event. If the debug buffer clearing
// task is successful, fetch the policy for the current user session.
void HandleUserLogin();
// Performs tasks for user logout, including clearing debug buffer and
// notifying all observers the user logout event. Unlike |HandleUserLogin|,
// the debug buffer clearing task is best-effort and other tasks do not
// depend on it.
void HandleUserLogout();
// Handler for the response of the asynchronous D-Bus method call to
// |org.chromium.debugd.ClearFirmwareDumpBuffer| that clears debug buffer.
// |is_login| indicates if this function is invoked during user login.
// |success| is the D-Bus method return indicating if the low-level execution
// is successful.
void OnClearFirmwareDumpBufferResponse(bool is_login, bool success);
// Handler for the error return of the asynchronous D-Bus method call to
// |org.chromium.debugd.ClearFirmwareDumpBuffer| that clears debug buffer.
void OnClearFirmwareDumpBufferError(brillo::Error* error);
// Notify all observers the user login and logout events
void NotifyObserversOnUserLogin();
void NotifyObserversOnUserLogout();
void EmitFeatureAllowedMetric();
// Query session manager for the current primary user. Returns std::nullopt
// when there was an error while getting primary user.
// If successful, the first member of the pair is the username and the second
// member is the sanitized username which is used for the home directory.
std::optional<std::pair<std::string, std::string>> RetrievePrimaryUser();
// Updates primary user internally.
bool UpdatePrimaryUser();
// Query session manager to know all the sessions that are currently active.
// We keep track of the number of active sessions to ensure that only the
// primary user is logged in.
bool UpdateActiveSessions();
// Fetch the policy from login_manager and see if
// |UserFeedbackWithLowLevelDebugDataAllowed| is set to allow firmware dumps.
// Returns true if fetching and parsing the policy was successful.
bool RetrieveAndParsePolicy(
org::chromium::SessionManagerInterfaceProxyInterface* proxy,
const login_manager::PolicyDescriptor& descriptor);
// Retrieve the value of the UserFeedbackWithLowLevelDebugDataAllowed policy.
bool UpdatePolicy();
// Extract the value of the UserFeedbackWithLowLevelDebugDataAllowed policy
// when there's an update to the policy.
void OnPolicyUpdated();
// Utility method that resets the relevant members that hold the state of
// logged in users/sessions when the state changes, for example when users log
// out.
void ResetPrimaryUser();
// Create directories in the daemon-store where the input and output files
// will live.
bool CreateUserDirectories() const;
void OnSignalConnected(const std::string& interface_name,
const std::string& signal_name,
bool success) const;
// Returns true if the primary user is in the allowlist of domains or users
// who are allowed to include firmware dumps in feedback reports.
bool PrimaryUserInAllowlist() const;
// Proxy for dbus communication with session manager / login.
org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy_;
// Proxy for dbus communication with debugd.
org::chromium::debugdProxyInterface* debugd_proxy_;
// Base directory to the root of the daemon-store where the firmware dumps are
// stored, typically /run/daemon-store/fbpreprocessord/. Unit tests can
// replace this directory with local temporary directories.
base::FilePath base_dir_;
// Username of the primary user. Empty if no primary user present.
std::string primary_user_;
// Sanitized username of the primary user. Daemon store folders are under
// /run/daemon-store/fbpreprocessord/${primary_user_hash_}.
// Empty if no primary user present.
std::string primary_user_hash_;
// Number of concurrently active sessions. Includes incognito sessions. If
// more than 1 session is active, do not allow adding firmware dumps to
// feedback reports.
int active_sessions_num_;
// When the user logs in, we retrieve the policy and use this field to track
// if the UserFeedbackWithLowLevelDebugDataAllowed policy allows us to
// process firmware dumps.
bool wifi_fw_dumps_allowed_by_policy_;
bool bluetooth_fw_dumps_allowed_by_policy_;
// When the user logs in, it takes a little time to fetch the policy. This
// boolean is flipped to true once we've retrieved all the necessary policy
// information.
bool fw_dumps_policy_loaded_;
// Set to true if we have already retrieved the Finch setting.
bool finch_loaded_;
// List of SessionStateManager observers
base::ObserverList<SessionStateManagerInterface::Observer>::Unchecked
observers_;
// Pointer to the Manager class that instantiates all the main modules.
Manager* manager_;
base::WeakPtrFactory<SessionStateManager> weak_factory_{this};
};
} // namespace fbpreprocessor
#endif // FBPREPROCESSOR_SESSION_STATE_MANAGER_H_