1 // Copyright 2020 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 "chrome/browser/nearby_sharing/nearby_process_manager.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/barrier_closure.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/callback_helpers.h"
14 #include "base/files/file_path.h"
15 #include "build/build_config.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chromeos/nearby/nearby_process_manager_factory.h"
18 #include "chrome/browser/chromeos/nearby/nearby_process_manager_impl.h"
19 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
20 #include "chrome/browser/nearby_sharing/logging/logging.h"
21 #include "chrome/browser/nearby_sharing/webrtc_signaling_messenger.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_attributes_entry.h"
24 #include "chrome/browser/profiles/profile_attributes_storage.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/sharing/webrtc/ice_config_fetcher.h"
27 #include "chrome/browser/sharing/webrtc/sharing_mojo_service.h"
28 #include "chrome/browser/signin/identity_manager_factory.h"
29 #include "chromeos/services/nearby/public/mojom/nearby_connections.mojom.h"
30 #include "components/prefs/pref_service.h"
31 #include "components/signin/public/identity_manager/identity_manager.h"
32 #include "content/public/browser/network_context_client_base.h"
33 #include "content/public/browser/network_service_instance.h"
34 #include "content/public/browser/service_process_host.h"
35 #include "content/public/browser/storage_partition.h"
36 #include "device/bluetooth/adapter.h"
37 #include "device/bluetooth/bluetooth_adapter_factory.h"
38 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
39 #include "services/network/public/mojom/network_context.mojom.h"
40 #include "services/network/public/mojom/network_service.mojom.h"
41 #include "services/network/public/mojom/p2p.mojom.h"
42 #include "services/network/public/mojom/p2p_trusted.mojom.h"
43 
44 namespace {
45 
GetStoredNearbyProfile()46 ProfileAttributesEntry* GetStoredNearbyProfile() {
47   PrefService* local_state = g_browser_process->local_state();
48   if (!local_state)
49     return nullptr;
50 
51   base::FilePath advertising_profile_path =
52       local_state->GetFilePath(::prefs::kNearbySharingActiveProfilePrefName);
53   if (advertising_profile_path.empty())
54     return nullptr;
55 
56   ProfileManager* profile_manager = g_browser_process->profile_manager();
57   if (!profile_manager)
58     return nullptr;
59 
60   ProfileAttributesStorage& storage =
61       profile_manager->GetProfileAttributesStorage();
62 
63   ProfileAttributesEntry* entry;
64   if (!storage.GetProfileAttributesWithPath(advertising_profile_path, &entry)) {
65     // Stored profile path is invalid so remove it.
66     local_state->ClearPref(::prefs::kNearbySharingActiveProfilePrefName);
67     return nullptr;
68   }
69   return entry;
70 }
71 
SetStoredNearbyProfile(Profile * profile)72 void SetStoredNearbyProfile(Profile* profile) {
73   PrefService* local_state = g_browser_process->local_state();
74   if (!local_state)
75     return;
76 
77   if (profile) {
78     local_state->SetFilePath(::prefs::kNearbySharingActiveProfilePrefName,
79                              profile->GetPath());
80   } else {
81     local_state->ClearPref(::prefs::kNearbySharingActiveProfilePrefName);
82   }
83 }
84 
IsStoredNearbyProfile(Profile * profile)85 bool IsStoredNearbyProfile(Profile* profile) {
86   ProfileAttributesEntry* entry = GetStoredNearbyProfile();
87   if (!entry)
88     return profile == nullptr;
89   return profile && entry->GetPath() == profile->GetPath();
90 }
91 
92 }  // namespace
93 
94 // static
GetInstance()95 NearbyProcessManager& NearbyProcessManager::GetInstance() {
96   static base::NoDestructor<NearbyProcessManager> instance;
97   return *instance;
98 }
99 
AddObserver(Observer * observer)100 void NearbyProcessManager::AddObserver(Observer* observer) {
101   observers_.AddObserver(observer);
102 }
103 
RemoveObserver(Observer * observer)104 void NearbyProcessManager::RemoveObserver(Observer* observer) {
105   observers_.RemoveObserver(observer);
106 }
107 
GetActiveProfile() const108 ProfileAttributesEntry* NearbyProcessManager::GetActiveProfile() const {
109   return GetStoredNearbyProfile();
110 }
111 
IsActiveProfile(Profile * profile) const112 bool NearbyProcessManager::IsActiveProfile(Profile* profile) const {
113   // If the active profile is not loaded yet, try looking in prefs.
114   if (!active_profile_)
115     return IsStoredNearbyProfile(profile);
116 
117   return active_profile_ == profile;
118 }
119 
IsAnyProfileActive() const120 bool NearbyProcessManager::IsAnyProfileActive() const {
121   return !IsActiveProfile(/*profile=*/nullptr);
122 }
123 
SetActiveProfile(Profile * profile)124 void NearbyProcessManager::SetActiveProfile(Profile* profile) {
125   if (IsActiveProfile(profile))
126     return;
127 
128   active_profile_ = profile;
129   SetStoredNearbyProfile(active_profile_);
130   StopProcess(active_profile_);
131 
132   for (auto& observer : observers_)
133     observer.OnNearbyProfileChanged(profile);
134 }
135 
ClearActiveProfile()136 void NearbyProcessManager::ClearActiveProfile() {
137   SetActiveProfile(/*profile=*/nullptr);
138 }
139 
140 location::nearby::connections::mojom::NearbyConnections*
GetOrStartNearbyConnections(Profile * profile)141 NearbyProcessManager::GetOrStartNearbyConnections(Profile* profile) {
142   if (!IsActiveProfile(profile))
143     return nullptr;
144 
145   EnsureProcessIsRunning();
146   return reference_->GetNearbyConnections().get();
147 }
148 
149 sharing::mojom::NearbySharingDecoder*
GetOrStartNearbySharingDecoder(Profile * profile)150 NearbyProcessManager::GetOrStartNearbySharingDecoder(Profile* profile) {
151   if (!IsActiveProfile(profile))
152     return nullptr;
153 
154   EnsureProcessIsRunning();
155   return reference_->GetNearbySharingDecoder().get();
156 }
157 
StopProcess(Profile * profile)158 void NearbyProcessManager::StopProcess(Profile* profile) {
159   if (!IsActiveProfile(profile))
160     return;
161 
162   EnsureNearbyProcessReferenceReleased();
163 }
164 
OnProfileAdded(Profile * profile)165 void NearbyProcessManager::OnProfileAdded(Profile* profile) {
166   // Cache active |profile| once it loads so we don't have to check prefs.
167   if (IsActiveProfile(profile))
168     active_profile_ = profile;
169 }
170 
OnProfileMarkedForPermanentDeletion(Profile * profile)171 void NearbyProcessManager::OnProfileMarkedForPermanentDeletion(
172     Profile* profile) {
173   if (IsActiveProfile(profile))
174     SetActiveProfile(nullptr);
175 }
176 
NearbyProcessManager()177 NearbyProcessManager::NearbyProcessManager() {
178   // profile_manager() might be null in tests or during shutdown.
179   if (auto* manager = g_browser_process->profile_manager())
180     manager->AddObserver(this);
181 }
182 
~NearbyProcessManager()183 NearbyProcessManager::~NearbyProcessManager() {
184   if (auto* manager = g_browser_process->profile_manager())
185     manager->RemoveObserver(this);
186 }
187 
EnsureProcessIsRunning()188 void NearbyProcessManager::EnsureProcessIsRunning() {
189   DCHECK(IsAnyProfileActive());
190 
191   // A reference already exists; the process is active.
192   if (reference_)
193     return;
194 
195   chromeos::nearby::NearbyProcessManager* process_manager =
196       chromeos::nearby::NearbyProcessManagerFactory::GetForProfile(
197           active_profile_);
198   DCHECK(process_manager);
199 
200   NS_LOG(INFO) << "Initializing Nearby Share process reference.";
201 
202   // Note: base::Unretained(this) is used because this is a singleton.
203   reference_ = process_manager->GetNearbyProcessReference(base::BindOnce(
204       &NearbyProcessManager::OnNearbyProcessStopped, base::Unretained(this)));
205   DCHECK(reference_);
206 
207   for (auto& observer : observers_)
208     observer.OnNearbyProcessStarted();
209 }
210 
OnNearbyProcessStopped()211 void NearbyProcessManager::OnNearbyProcessStopped() {
212   NS_LOG(INFO) << "Nearby process has stopped.";
213   EnsureNearbyProcessReferenceReleased();
214 }
215 
EnsureNearbyProcessReferenceReleased()216 void NearbyProcessManager::EnsureNearbyProcessReferenceReleased() {
217   if (!reference_)
218     return;
219 
220   NS_LOG(INFO) << "Releasing Nearby Share process reference.";
221   reference_.reset();
222 
223   for (auto& observer : observers_)
224     observer.OnNearbyProcessStopped();
225 }
226