1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/components/tether/tether_component_impl.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/memory/ptr_util.h"
12 #include "chromeos/components/multidevice/logging/logging.h"
13 #include "chromeos/components/tether/active_host.h"
14 #include "chromeos/components/tether/asynchronous_shutdown_object_container_impl.h"
15 #include "chromeos/components/tether/crash_recovery_manager_impl.h"
16 #include "chromeos/components/tether/host_scan_scheduler.h"
17 #include "chromeos/components/tether/persistent_host_scan_cache_impl.h"
18 #include "chromeos/components/tether/synchronous_shutdown_object_container_impl.h"
19 #include "chromeos/components/tether/tether_disconnector.h"
20 #include "chromeos/components/tether/tether_host_response_recorder.h"
21 #include "chromeos/components/tether/tether_session_completion_logger.h"
22 #include "chromeos/components/tether/wifi_hotspot_disconnector_impl.h"
23 #include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
24 #include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client.h"
25 #include "components/pref_registry/pref_registry_syncable.h"
26 
27 namespace chromeos {
28 
29 namespace tether {
30 
31 namespace {
32 
OnDisconnectErrorDuringShutdown(const std::string & error_name)33 void OnDisconnectErrorDuringShutdown(const std::string& error_name) {
34   PA_LOG(WARNING) << "Error disconnecting from Tether network during shutdown; "
35                   << "Error name: " << error_name;
36 }
37 
38 TetherSessionCompletionLogger::SessionCompletionReason
GetSessionCompletionReasonFromShutdownReason(TetherComponent::ShutdownReason shutdown_reason)39 GetSessionCompletionReasonFromShutdownReason(
40     TetherComponent::ShutdownReason shutdown_reason) {
41   switch (shutdown_reason) {
42     case TetherComponent::ShutdownReason::OTHER:
43       return TetherSessionCompletionLogger::SessionCompletionReason::OTHER;
44     case TetherComponent::ShutdownReason::USER_LOGGED_OUT:
45       return TetherSessionCompletionLogger::SessionCompletionReason::
46           USER_LOGGED_OUT;
47     case TetherComponent::ShutdownReason::USER_CLOSED_LID:
48       return TetherSessionCompletionLogger::SessionCompletionReason::
49           USER_CLOSED_LID;
50     case TetherComponent::ShutdownReason::PREF_DISABLED:
51       return TetherSessionCompletionLogger::SessionCompletionReason::
52           PREF_DISABLED;
53     case TetherComponent::ShutdownReason::BLUETOOTH_DISABLED:
54       return TetherSessionCompletionLogger::SessionCompletionReason::
55           BLUETOOTH_DISABLED;
56     case TetherComponent::ShutdownReason::CELLULAR_DISABLED:
57       return TetherSessionCompletionLogger::SessionCompletionReason::
58           CELLULAR_DISABLED;
59     case TetherComponent::ShutdownReason::MULTIDEVICE_HOST_UNVERIFIED:
60       return TetherSessionCompletionLogger::SessionCompletionReason::
61           MULTIDEVICE_HOST_UNVERIFIED;
62     case TetherComponent::ShutdownReason::BETTER_TOGETHER_SUITE_DISABLED:
63       return TetherSessionCompletionLogger::SessionCompletionReason::
64           BETTER_TOGETHER_SUITE_DISABLED;
65     default:
66       break;
67   }
68 
69   return TetherSessionCompletionLogger::SessionCompletionReason::OTHER;
70 }
71 
72 }  // namespace
73 
74 // static
75 TetherComponentImpl::Factory* TetherComponentImpl::Factory::factory_instance_ =
76     nullptr;
77 
78 // static
Create(device_sync::DeviceSyncClient * device_sync_client,secure_channel::SecureChannelClient * secure_channel_client,TetherHostFetcher * tether_host_fetcher,NotificationPresenter * notification_presenter,GmsCoreNotificationsStateTrackerImpl * gms_core_notifications_state_tracker,PrefService * pref_service,NetworkStateHandler * network_state_handler,ManagedNetworkConfigurationHandler * managed_network_configuration_handler,NetworkConnect * network_connect,NetworkConnectionHandler * network_connection_handler,scoped_refptr<device::BluetoothAdapter> adapter,session_manager::SessionManager * session_manager)79 std::unique_ptr<TetherComponent> TetherComponentImpl::Factory::Create(
80     device_sync::DeviceSyncClient* device_sync_client,
81     secure_channel::SecureChannelClient* secure_channel_client,
82     TetherHostFetcher* tether_host_fetcher,
83     NotificationPresenter* notification_presenter,
84     GmsCoreNotificationsStateTrackerImpl* gms_core_notifications_state_tracker,
85     PrefService* pref_service,
86     NetworkStateHandler* network_state_handler,
87     ManagedNetworkConfigurationHandler* managed_network_configuration_handler,
88     NetworkConnect* network_connect,
89     NetworkConnectionHandler* network_connection_handler,
90     scoped_refptr<device::BluetoothAdapter> adapter,
91     session_manager::SessionManager* session_manager) {
92   if (factory_instance_) {
93     return factory_instance_->CreateInstance(
94         device_sync_client, secure_channel_client, tether_host_fetcher,
95         notification_presenter, gms_core_notifications_state_tracker,
96         pref_service, network_state_handler,
97         managed_network_configuration_handler, network_connect,
98         network_connection_handler, adapter, session_manager);
99   }
100 
101   return base::WrapUnique(new TetherComponentImpl(
102       device_sync_client, secure_channel_client, tether_host_fetcher,
103       notification_presenter, gms_core_notifications_state_tracker,
104       pref_service, network_state_handler,
105       managed_network_configuration_handler, network_connect,
106       network_connection_handler, adapter, session_manager));
107 }
108 
109 // static
SetFactoryForTesting(Factory * factory)110 void TetherComponentImpl::Factory::SetFactoryForTesting(Factory* factory) {
111   factory_instance_ = factory;
112 }
113 
114 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)115 void TetherComponentImpl::RegisterProfilePrefs(
116     user_prefs::PrefRegistrySyncable* registry) {
117   ActiveHost::RegisterPrefs(registry);
118   PersistentHostScanCacheImpl::RegisterPrefs(registry);
119   TetherHostResponseRecorder::RegisterPrefs(registry);
120   WifiHotspotDisconnectorImpl::RegisterPrefs(registry);
121 }
122 
TetherComponentImpl(device_sync::DeviceSyncClient * device_sync_client,secure_channel::SecureChannelClient * secure_channel_client,TetherHostFetcher * tether_host_fetcher,NotificationPresenter * notification_presenter,GmsCoreNotificationsStateTrackerImpl * gms_core_notifications_state_tracker,PrefService * pref_service,NetworkStateHandler * network_state_handler,ManagedNetworkConfigurationHandler * managed_network_configuration_handler,NetworkConnect * network_connect,NetworkConnectionHandler * network_connection_handler,scoped_refptr<device::BluetoothAdapter> adapter,session_manager::SessionManager * session_manager)123 TetherComponentImpl::TetherComponentImpl(
124     device_sync::DeviceSyncClient* device_sync_client,
125     secure_channel::SecureChannelClient* secure_channel_client,
126     TetherHostFetcher* tether_host_fetcher,
127     NotificationPresenter* notification_presenter,
128     GmsCoreNotificationsStateTrackerImpl* gms_core_notifications_state_tracker,
129     PrefService* pref_service,
130     NetworkStateHandler* network_state_handler,
131     ManagedNetworkConfigurationHandler* managed_network_configuration_handler,
132     NetworkConnect* network_connect,
133     NetworkConnectionHandler* network_connection_handler,
134     scoped_refptr<device::BluetoothAdapter> adapter,
135     session_manager::SessionManager* session_manager)
136     : asynchronous_shutdown_object_container_(
137           AsynchronousShutdownObjectContainerImpl::Factory::Create(
138               device_sync_client,
139               secure_channel_client,
140               tether_host_fetcher,
141               network_state_handler,
142               managed_network_configuration_handler,
143               network_connection_handler,
144               pref_service)),
145       synchronous_shutdown_object_container_(
146           SynchronousShutdownObjectContainerImpl::Factory::Create(
147               asynchronous_shutdown_object_container_.get(),
148               notification_presenter,
149               gms_core_notifications_state_tracker,
150               pref_service,
151               network_state_handler,
152               network_connect,
153               network_connection_handler,
154               session_manager,
155               device_sync_client,
156               secure_channel_client)),
157       crash_recovery_manager_(CrashRecoveryManagerImpl::Factory::Create(
158           network_state_handler,
159           synchronous_shutdown_object_container_->active_host(),
160           synchronous_shutdown_object_container_->host_scan_cache())) {
161   crash_recovery_manager_->RestorePreCrashStateIfNecessary(
162       base::Bind(&TetherComponentImpl::OnPreCrashStateRestored,
163                  weak_ptr_factory_.GetWeakPtr()));
164 }
165 
166 TetherComponentImpl::~TetherComponentImpl() = default;
167 
RequestShutdown(const ShutdownReason & shutdown_reason)168 void TetherComponentImpl::RequestShutdown(
169     const ShutdownReason& shutdown_reason) {
170   has_shutdown_been_requested_ = true;
171 
172   // If shutdown has already happened, there is nothing else to do.
173   if (status() != TetherComponent::Status::ACTIVE)
174     return;
175 
176   shutdown_reason_ = shutdown_reason;
177 
178   // If crash recovery has not yet completed, wait for it to complete before
179   // continuing.
180   if (crash_recovery_manager_)
181     return;
182 
183   InitiateShutdown();
184 }
185 
OnPreCrashStateRestored()186 void TetherComponentImpl::OnPreCrashStateRestored() {
187   // |crash_recovery_manager_| is no longer needed since it has completed.
188   crash_recovery_manager_.reset();
189 
190   if (has_shutdown_been_requested_) {
191     InitiateShutdown();
192     return;
193   }
194 
195   // Start a scan now that the Tether module has started up.
196   synchronous_shutdown_object_container_->host_scan_scheduler()
197       ->AttemptScanIfOffline();
198 }
199 
InitiateShutdown()200 void TetherComponentImpl::InitiateShutdown() {
201   DCHECK(has_shutdown_been_requested_);
202   DCHECK(!crash_recovery_manager_);
203   DCHECK(status() == TetherComponent::Status::ACTIVE);
204 
205   ActiveHost* active_host =
206       synchronous_shutdown_object_container_->active_host();
207   TetherDisconnector* tether_disconnector =
208       synchronous_shutdown_object_container_->tether_disconnector();
209 
210   // If there is an active connection, it needs to be disconnected before the
211   // Tether component is shut down.
212   if (active_host->GetActiveHostStatus() !=
213       ActiveHost::ActiveHostStatus::DISCONNECTED) {
214     PA_LOG(VERBOSE) << "There was an active connection during Tether shutdown. "
215                     << "Initiating disconnection from device ID \""
216                     << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
217                            active_host->GetActiveHostDeviceId())
218                     << "\".";
219     tether_disconnector->DisconnectFromNetwork(
220         active_host->GetTetherNetworkGuid(), base::DoNothing(),
221         base::Bind(&OnDisconnectErrorDuringShutdown),
222         GetSessionCompletionReasonFromShutdownReason(shutdown_reason_));
223   }
224 
225   TransitionToStatus(TetherComponent::Status::SHUTTING_DOWN);
226 
227   // Delete objects which can shutdown synchronously immediately.
228   synchronous_shutdown_object_container_.reset();
229 
230   // Start the shutdown process for objects which shutdown asynchronously.
231   asynchronous_shutdown_object_container_->Shutdown(
232       base::Bind(&TetherComponentImpl::OnShutdownComplete,
233                  weak_ptr_factory_.GetWeakPtr()));
234 }
235 
OnShutdownComplete()236 void TetherComponentImpl::OnShutdownComplete() {
237   DCHECK(status() == TetherComponent::Status::SHUTTING_DOWN);
238 
239   // Shutdown has completed. The asynchronous objects can now be deleted as
240   // well.
241   asynchronous_shutdown_object_container_.reset();
242 
243   TransitionToStatus(TetherComponent::Status::SHUT_DOWN);
244 }
245 
246 }  // namespace tether
247 
248 }  // namespace chromeos
249