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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
|
// Copyright 2017 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_TETHER_TETHER_SERVICE_H_
#define CHROME_BROWSER_ASH_TETHER_TETHER_SERVICE_H_
#include <memory>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"
#include "chromeos/ash/components/tether/tether_component.h"
#include "chromeos/ash/components/tether/tether_host_fetcher.h"
#include "chromeos/ash/services/device_sync/public/cpp/device_sync_client.h"
#include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/keyed_service/core/keyed_service.h"
#include "device/bluetooth/bluetooth_adapter.h"
class Profile;
namespace session_manager {
class SessionManager;
} // namespace session_manager
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
namespace ash {
namespace secure_channel {
class SecureChannelClient;
} // namespace secure_channel
namespace tether {
class GmsCoreNotificationsStateTracker;
class GmsCoreNotificationsStateTrackerImpl;
class NotificationPresenter;
// Service providing access to the Instant Tethering component. Provides an
// interface to start up the component as well as to retrieve metadata about
// ongoing Tether connections.
//
// This service starts up when the user logs in (or recovers from a crash) and
// is shut down when the user logs out.
class TetherService
: public KeyedService,
public chromeos::PowerManagerClient::Observer,
public TetherHostFetcher::Observer,
public device::BluetoothAdapter::Observer,
public NetworkStateHandlerObserver,
public TetherComponent::Observer,
public device_sync::DeviceSyncClient::Observer,
public multidevice_setup::MultiDeviceSetupClient::Observer {
public:
TetherService(
Profile* profile,
chromeos::PowerManagerClient* power_manager_client,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client,
multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
session_manager::SessionManager* session_manager);
TetherService(const TetherService&) = delete;
TetherService& operator=(const TetherService&) = delete;
~TetherService() override;
// Gets TetherService instance.
static TetherService* Get(Profile* profile);
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Attempt to start the Tether module. Only succeeds if all conditions to
// reach NetworkStateHandler::TechnologyState::ENABLED are reached.
// Should only be called once a user is logged in.
virtual void StartTetherIfPossible();
virtual GmsCoreNotificationsStateTracker*
GetGmsCoreNotificationsStateTracker();
protected:
// KeyedService:
void Shutdown() override;
// chromeos::PowerManagerClient::Observer:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void SuspendDone(base::TimeDelta sleep_duration) override;
// TetherHostFetcher::Observer
void OnTetherHostUpdated() override;
// device::BluetoothAdapter::Observer:
void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) override;
// NetworkStateHandlerObserver:
void DeviceListChanged() override;
void DevicePropertiesUpdated(const DeviceState* device) override;
// Helper method called from NetworkStateHandlerObserver methods.
void UpdateEnabledState();
// TetherComponent::Observer:
void OnShutdownComplete() override;
// ash::device_sync::DeviceSyncClient::Observer:
void OnReady() override;
// ash::multidevice_setup::MultiDeviceSetupClient::Observer:
void OnFeatureStatesChanged(
const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) override;
// Stop the Tether module if it is currently enabled; if it was not enabled,
// this function is a no-op.
virtual void StopTetherIfNecessary();
// Whether Tether hosts are available.
virtual bool HasSyncedTetherHosts() const;
virtual void UpdateTetherTechnologyState();
NetworkStateHandler::TechnologyState GetTetherTechnologyState();
NetworkStateHandler* network_state_handler() {
return network_state_handler_;
}
private:
friend class TetherServiceTest;
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestSuspend);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestDeviceSyncClientNotReady);
FRIEND_TEST_ALL_PREFIXES(
TetherServiceTest,
TestMultiDeviceSetupClientInitiallyHasNoVerifiedHost);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestMultiDeviceSetupClientLosesVerifiedHost);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestBetterTogetherSuiteInitiallyDisabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestBetterTogetherSuiteBecomesDisabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestGet_PrimaryUser_FeatureFlagEnabled);
FRIEND_TEST_ALL_PREFIXES(
TetherServiceTest,
TestGet_PrimaryUser_FeatureFlagEnabled_MultiDeviceApiFlagEnabled);
FRIEND_TEST_ALL_PREFIXES(
TetherServiceTest,
TestGet_PrimaryUser_FeatureFlagEnabled_MultiDeviceApiAndMultiDeviceSetupFlagsEnabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestNoTetherHosts);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestProhibitedByPolicy);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestIsBluetoothPowered);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestCellularIsUnavailable);
FRIEND_TEST_ALL_PREFIXES(
TetherServiceTest,
TestCellularIsAvailable_InstantHotspotRebrandDisabled);
FRIEND_TEST_ALL_PREFIXES(
TetherServiceTest,
TestCellularIsAvailable_InstantHotspotRebrandEnabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestDisabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestEnabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestUserPrefChangesViaFeatureStateChange);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestUserPrefChangesViaTechnologyStateChange);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotification);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotPresent);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestMetricsFalsePositives);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestWifiNotPresent);
// Reflects InstantTethering_FeatureState enum in enums.xml. Do not rearrange.
enum TetherFeatureState {
// Note: Value 0 was previously OTHER_OR_UNKNOWN, but this was a vague
// description.
SHUT_DOWN = 0,
// Note: Value 1 was previously BLE_ADVERTISING_NOT_SUPPORTED, but this
// value is obsolete and should no longer be used.
// Note: Value 2 was previously SCREEN_LOCKED, but this value is obsolete
// and should no longer be used.
NO_AVAILABLE_HOSTS = 3,
CELLULAR_DISABLED = 4,
PROHIBITED = 5,
BLUETOOTH_DISABLED = 6,
USER_PREFERENCE_DISABLED = 7,
ENABLED = 8,
BLE_NOT_PRESENT = 9,
WIFI_NOT_PRESENT = 10,
SUSPENDED = 11,
BETTER_TOGETHER_SUITE_DISABLED = 12,
TETHER_FEATURE_STATE_MAX
};
// For debug logs.
static std::string TetherFeatureStateToString(
const TetherFeatureState& state);
void GetBluetoothAdapter();
void OnBluetoothAdapterFetched(
scoped_refptr<device::BluetoothAdapter> adapter);
bool IsBluetoothPresent() const;
bool IsBluetoothPowered() const;
bool IsWifiPresent() const;
bool IsCellularAvailableButNotEnabled() const;
// Whether Tether is allowed to be used. If the controlling preference
// is set (from policy), this returns the preference value. Otherwise, it is
// permitted if the flag is enabled.
bool IsAllowedByPolicy() const;
// Whether Tether is enabled.
bool IsEnabledByPreference() const;
TetherFeatureState GetTetherFeatureState();
// Record to UMA Tether's current feature state.
void RecordTetherFeatureState();
// Attempt to record the current Tether FeatureState.
void RecordTetherFeatureStateIfPossible();
// Handles potential false positive metric states which may occur normally
// during startup. In the normal case (i.e., when Tether is enabled), the
// state transitions from OTHER_OR_UNKNOWN -> BLE_NOT_PRESENT ->
// NO_AVAILABLE_HOSTS -> ENABLED, but we do not wish to log metrics for the
// intermediate states (BLE_NOT_PRESENT or NO_AVAILABLE_HOSTS), since these
// are ephemeral. Returns whether a false positive case was handled.
bool HandleFeatureStateMetricIfUninitialized();
void LogUserPreferenceChanged(bool is_now_enabled);
void SetTestDoubles(
std::unique_ptr<NotificationPresenter> notification_presenter,
std::unique_ptr<base::OneShotTimer> timer);
// Whether the service has been shut down.
bool shut_down_ = false;
// Whether the device and service have been suspended (e.g. the laptop lid
// was closed).
bool suspended_ = false;
bool is_adapter_being_fetched_ = false;
multidevice_setup::mojom::HostStatus host_status_ =
multidevice_setup::mojom::HostStatus::kNoEligibleHosts;
// The first report of TetherFeatureState::BLE_NOT_PRESENT is usually
// incorrect and hence is a false positive. This property tracks if the first
// report has been hit yet.
bool ble_not_present_false_positive_encountered_ = false;
// The first report of TetherFeatureState::NO_AVAILABLE_HOSTS may be incorrect
// and hence a false positive. This property tracks if the first report has
// been hit yet.
bool no_available_hosts_false_positive_encountered_ = false;
// The TetherFeatureState obtained the last time that
// GetTetherTechnologyState() was called. Used only for logging purposes.
TetherFeatureState previous_feature_state_ =
TetherFeatureState::TETHER_FEATURE_STATE_MAX;
raw_ptr<Profile> profile_;
raw_ptr<chromeos::PowerManagerClient> power_manager_client_;
raw_ptr<device_sync::DeviceSyncClient, DanglingUntriaged> device_sync_client_;
raw_ptr<secure_channel::SecureChannelClient> secure_channel_client_;
raw_ptr<multidevice_setup::MultiDeviceSetupClient, DanglingUntriaged>
multidevice_setup_client_;
raw_ptr<NetworkStateHandler> network_state_handler_;
base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver>
network_state_handler_observer_{this};
raw_ptr<session_manager::SessionManager> session_manager_;
std::unique_ptr<NotificationPresenter> notification_presenter_;
std::unique_ptr<GmsCoreNotificationsStateTrackerImpl>
gms_core_notifications_state_tracker_;
std::unique_ptr<TetherHostFetcher> tether_host_fetcher_;
std::unique_ptr<TetherComponent> tether_component_;
scoped_refptr<device::BluetoothAdapter> adapter_;
std::unique_ptr<base::OneShotTimer> timer_;
base::WeakPtrFactory<TetherService> weak_ptr_factory_{this};
};
} // namespace tether
} // namespace ash
#endif // CHROME_BROWSER_ASH_TETHER_TETHER_SERVICE_H_
|