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_sharing_service_impl.h"
6 
7 #include <utility>
8 
9 #include "ash/public/cpp/session/session_controller.h"
10 #include "base/barrier_closure.h"
11 #include "base/bind.h"
12 #include "base/files/file.h"
13 #include "base/logging.h"
14 #include "base/numerics/checked_math.h"
15 #include "base/rand_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/system/sys_info.h"
18 #include "base/task/post_task.h"
19 #include "base/task_runner_util.h"
20 #include "base/threading/sequenced_task_runner_handle.h"
21 #include "chrome/browser/download/download_prefs.h"
22 #include "chrome/browser/nearby_sharing/certificates/common.h"
23 #include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.h"
24 #include "chrome/browser/nearby_sharing/certificates/nearby_share_encrypted_metadata_key.h"
25 #include "chrome/browser/nearby_sharing/client/nearby_share_client_impl.h"
26 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
27 #include "chrome/browser/nearby_sharing/constants.h"
28 #include "chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl.h"
29 #include "chrome/browser/nearby_sharing/fast_initiation_manager.h"
30 #include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl.h"
31 #include "chrome/browser/nearby_sharing/logging/logging.h"
32 #include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
33 #include "chrome/browser/nearby_sharing/nearby_share_default_device_name.h"
34 #include "chrome/browser/nearby_sharing/nearby_share_metrics_logger.h"
35 #include "chrome/browser/nearby_sharing/paired_key_verification_runner.h"
36 #include "chrome/browser/nearby_sharing/transfer_metadata.h"
37 #include "chrome/browser/nearby_sharing/transfer_metadata_builder.h"
38 #include "chrome/browser/profiles/profile.h"
39 #include "chrome/browser/signin/identity_manager_factory.h"
40 #include "chrome/services/sharing/public/cpp/advertisement.h"
41 #include "chrome/services/sharing/public/cpp/conversions.h"
42 #include "chromeos/services/nearby/public/mojom/nearby_connections_types.mojom.h"
43 #include "chromeos/services/nearby/public/mojom/nearby_share_target_types.mojom.h"
44 #include "components/prefs/pref_service.h"
45 #include "content/public/browser/download_manager.h"
46 #include "content/public/browser/storage_partition.h"
47 #include "crypto/random.h"
48 #include "device/bluetooth/bluetooth_adapter_factory.h"
49 #include "services/network/public/cpp/shared_url_loader_factory.h"
50 #include "url/gurl.h"
51 
52 namespace {
53 
54 constexpr base::TimeDelta kBackgroundAdvertisementRotationDelayMin =
55     base::TimeDelta::FromMinutes(12);
56 constexpr base::TimeDelta kBackgroundAdvertisementRotationDelayMax =
57     base::TimeDelta::FromMinutes(15);
58 constexpr base::TimeDelta kInvalidateSurfaceStateDelayAfterTransferDone =
59     base::TimeDelta::FromMilliseconds(3000);
60 
61 // Used to hash a token into a 4 digit string.
62 constexpr int kHashModulo = 9973;
63 constexpr int kHashBaseMultiplier = 31;
64 
ReceiveSurfaceStateToString(NearbySharingService::ReceiveSurfaceState state)65 std::string ReceiveSurfaceStateToString(
66     NearbySharingService::ReceiveSurfaceState state) {
67   switch (state) {
68     case NearbySharingService::ReceiveSurfaceState::kForeground:
69       return "FOREGROUND";
70     case NearbySharingService::ReceiveSurfaceState::kBackground:
71       return "BACKGROUND";
72     case NearbySharingService::ReceiveSurfaceState::kUnknown:
73       return "UNKNOWN";
74   }
75 }
76 
SendSurfaceStateToString(NearbySharingService::SendSurfaceState state)77 std::string SendSurfaceStateToString(
78     NearbySharingService::SendSurfaceState state) {
79   switch (state) {
80     case NearbySharingService::SendSurfaceState::kForeground:
81       return "FOREGROUND";
82     case NearbySharingService::SendSurfaceState::kBackground:
83       return "BACKGROUND";
84     case NearbySharingService::SendSurfaceState::kUnknown:
85       return "UNKNOWN";
86   }
87 }
88 
PowerLevelToString(PowerLevel level)89 std::string PowerLevelToString(PowerLevel level) {
90   switch (level) {
91     case PowerLevel::kLowPower:
92       return "LOW_POWER";
93     case PowerLevel::kMediumPower:
94       return "MEDIUM_POWER";
95     case PowerLevel::kHighPower:
96       return "HIGH_POWER";
97     case PowerLevel::kUnknown:
98       return "UNKNOWN";
99   }
100 }
101 
GetDeviceName(const sharing::mojom::AdvertisementPtr & advertisement,const base::Optional<NearbyShareDecryptedPublicCertificate> & certificate)102 base::Optional<std::string> GetDeviceName(
103     const sharing::mojom::AdvertisementPtr& advertisement,
104     const base::Optional<NearbyShareDecryptedPublicCertificate>& certificate) {
105   DCHECK(advertisement);
106 
107   // Device name is always included when visible to everyone.
108   if (advertisement->device_name)
109     return *(advertisement->device_name);
110 
111   // For contacts only advertisements, we can't do anything without the
112   // certificate.
113   if (!certificate || !certificate->unencrypted_metadata().has_device_name())
114     return base::nullopt;
115 
116   return certificate->unencrypted_metadata().device_name();
117 }
118 
GetDeviceId(const std::string & endpoint_id,const base::Optional<NearbyShareDecryptedPublicCertificate> & certificate)119 std::string GetDeviceId(
120     const std::string& endpoint_id,
121     const base::Optional<NearbyShareDecryptedPublicCertificate>& certificate) {
122   if (!certificate || certificate->id().empty())
123     return endpoint_id;
124 
125   return std::string(certificate->id().begin(), certificate->id().end());
126 }
127 
ToFourDigitString(const base::Optional<std::vector<uint8_t>> & bytes)128 base::Optional<std::string> ToFourDigitString(
129     const base::Optional<std::vector<uint8_t>>& bytes) {
130   if (!bytes)
131     return base::nullopt;
132 
133   int hash = 0;
134   int multiplier = 1;
135   for (uint8_t byte : *bytes) {
136     // Java bytes are signed two's complement so cast to use the correct sign.
137     hash = (hash + static_cast<int8_t>(byte) * multiplier) % kHashModulo;
138     multiplier = (multiplier * kHashBaseMultiplier) % kHashModulo;
139   }
140 
141   return base::StringPrintf("%04d", std::abs(hash));
142 }
143 
IsOutOfStorage(base::FilePath file_path,int64_t storage_required,base::Optional<int64_t> free_disk_space_for_testing)144 bool IsOutOfStorage(base::FilePath file_path,
145                     int64_t storage_required,
146                     base::Optional<int64_t> free_disk_space_for_testing) {
147   int64_t free_space = free_disk_space_for_testing.value_or(
148       base::SysInfo::AmountOfFreeDiskSpace(file_path));
149   return free_space < storage_required;
150 }
151 
DoAttachmentsExceedThreshold(const ShareTarget & share_target,int64_t threshold)152 bool DoAttachmentsExceedThreshold(const ShareTarget& share_target,
153                                   int64_t threshold) {
154   for (const auto& attachment : share_target.text_attachments) {
155     if (attachment.size() > threshold)
156       return false;
157 
158     threshold -= attachment.size();
159   }
160 
161   for (const auto& attachment : share_target.file_attachments) {
162     if (attachment.size() > threshold)
163       return false;
164 
165     threshold -= attachment.size();
166   }
167 
168   return true;
169 }
170 
CheckFileSizeForDataUsagePreference(DataUsage client_preference,const ShareTarget & share_target)171 DataUsage CheckFileSizeForDataUsagePreference(DataUsage client_preference,
172                                               const ShareTarget& share_target) {
173   if (client_preference == DataUsage::kOffline)
174     return client_preference;
175 
176   if (DoAttachmentsExceedThreshold(share_target, kOnlineFileSizeLimitBytes))
177     return DataUsage::kOffline;
178 
179   return client_preference;
180 }
181 
GeneratePayloadId()182 int64_t GeneratePayloadId() {
183   int64_t payload_id = 0;
184   crypto::RandBytes(&payload_id, sizeof(payload_id));
185   return payload_id;
186 }
187 
188 // Wraps a call to OnTransferUpdate() to filter any updates after receiving a
189 // final status.
190 class TransferUpdateDecorator : public TransferUpdateCallback {
191  public:
192   using Callback = base::RepeatingCallback<void(const ShareTarget&,
193                                                 const TransferMetadata&)>;
194 
TransferUpdateDecorator(Callback callback)195   explicit TransferUpdateDecorator(Callback callback)
196       : callback_(std::move(callback)) {}
197   TransferUpdateDecorator(const TransferUpdateDecorator&) = delete;
198   TransferUpdateDecorator& operator=(const TransferUpdateDecorator&) = delete;
199   ~TransferUpdateDecorator() override = default;
200 
OnTransferUpdate(const ShareTarget & share_target,const TransferMetadata & transfer_metadata)201   void OnTransferUpdate(const ShareTarget& share_target,
202                         const TransferMetadata& transfer_metadata) override {
203     NS_LOG(VERBOSE) << __func__ << ": Transfer update decorator: "
204                     << "Transfer update for share target with ID "
205                     << share_target.id << ": "
206                     << TransferMetadata::StatusToString(
207                            transfer_metadata.status());
208     if (got_final_status_) {
209       // If we already got a final status, we can ignore any subsequent final
210       // statuses caused by race conditions.
211       return;
212     }
213     got_final_status_ = transfer_metadata.is_final_status();
214     callback_.Run(share_target, transfer_metadata);
215   }
216 
217  private:
218   bool got_final_status_ = false;
219   Callback callback_;
220 };
221 
222 }  // namespace
223 
NearbySharingServiceImpl(PrefService * prefs,NotificationDisplayService * notification_display_service,Profile * profile,std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager,NearbyProcessManager * process_manager,std::unique_ptr<PowerClient> power_client)224 NearbySharingServiceImpl::NearbySharingServiceImpl(
225     PrefService* prefs,
226     NotificationDisplayService* notification_display_service,
227     Profile* profile,
228     std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager,
229     NearbyProcessManager* process_manager,
230     std::unique_ptr<PowerClient> power_client)
231     : profile_(profile),
232       nearby_connections_manager_(std::move(nearby_connections_manager)),
233       process_manager_(process_manager),
234       power_client_(std::move(power_client)),
235       http_client_factory_(std::make_unique<NearbyShareClientFactoryImpl>(
236           IdentityManagerFactory::GetForProfile(profile),
237           profile->GetURLLoaderFactory(),
238           &nearby_share_http_notifier_)),
239       local_device_data_manager_(
240           NearbyShareLocalDeviceDataManagerImpl::Factory::Create(
241               prefs,
242               http_client_factory_.get(),
243               GetNearbyShareDefaultDeviceName(profile_))),
244       contact_manager_(NearbyShareContactManagerImpl::Factory::Create(
245           prefs,
246           http_client_factory_.get(),
247           local_device_data_manager_.get(),
248           profile->GetProfileUserName())),
249       certificate_manager_(NearbyShareCertificateManagerImpl::Factory::Create(
250           local_device_data_manager_.get(),
251           contact_manager_.get(),
252           prefs,
253           content::BrowserContext::GetDefaultStoragePartition(profile)
254               ->GetProtoDatabaseProvider(),
255           profile->GetPath(),
256           http_client_factory_.get())),
257       settings_(prefs, local_device_data_manager_.get()) {
258   DCHECK(profile_);
259   DCHECK(nearby_connections_manager_);
260   DCHECK(power_client_);
261 
262   RecordNearbyShareEnabledMetric(prefs);
263 
264 #if defined(OS_CHROMEOS)
265   auto* session_controller = ash::SessionController::Get();
266   if (session_controller) {
267     is_screen_locked_ = session_controller->IsScreenLocked();
268     session_controller->AddObserver(this);
269   }
270 #endif  // OS_CHROMEOS
271 
272   nearby_process_observer_.Add(process_manager_);
273   power_client_->AddObserver(this);
274   certificate_manager_->AddObserver(this);
275 
276   settings_.AddSettingsObserver(settings_receiver_.BindNewPipeAndPassRemote());
277 
278   GetBluetoothAdapter();
279 
280   nearby_notification_manager_ = std::make_unique<NearbyNotificationManager>(
281       notification_display_service, this, prefs, profile_);
282 
283   if (settings_.GetEnabled()) {
284     local_device_data_manager_->Start();
285     contact_manager_->Start();
286     certificate_manager_->Start();
287   }
288 }
289 
~NearbySharingServiceImpl()290 NearbySharingServiceImpl::~NearbySharingServiceImpl() {
291   // Make sure the service has been shut down properly before.
292   DCHECK(!nearby_notification_manager_);
293   DCHECK(!bluetooth_adapter_ || !bluetooth_adapter_->HasObserver(this));
294 }
295 
Shutdown()296 void NearbySharingServiceImpl::Shutdown() {
297   // Before we clean up, lets give observers a heads up we are shutting down.
298   for (auto& observer : observers_) {
299     observer.OnShutdown();
300   }
301   observers_.Clear();
302 
303   // Clear in-progress transfers.
304   ClearOutgoingShareTargetInfoMap();
305   incoming_share_target_info_map_.clear();
306 
307   StopAdvertising();
308   StopFastInitiationAdvertising();
309   StopScanning();
310   nearby_connections_manager_->Shutdown();
311 
312   // Destroy NearbyNotificationManager as its profile has been shut down.
313   nearby_notification_manager_.reset();
314 
315   // Stop listening to NearbyProcessManager events and stop the utility process.
316   nearby_process_observer_.Remove(process_manager_);
317   if (process_manager_->IsActiveProfile(profile_))
318     process_manager_->StopProcess(profile_);
319 
320   power_client_->RemoveObserver(this);
321   certificate_manager_->RemoveObserver(this);
322 
323   // TODO(crbug/1147652): The call to update the advertising interval is
324   // removed to prevent a Bluez crash. We need to either reduce the global
325   // advertising interval asynchronously and wait for the result or use the
326   // updated API referenced in the bug which allows setting a per-advertisement
327   // interval.
328 
329   if (bluetooth_adapter_)
330     bluetooth_adapter_->RemoveObserver(this);
331 
332 #if defined(OS_CHROMEOS)
333   auto* session_controller = ash::SessionController::Get();
334   if (session_controller)
335     session_controller->RemoveObserver(this);
336 #endif  // OS_CHROMEOS
337 
338   foreground_receive_callbacks_.Clear();
339   background_receive_callbacks_.Clear();
340   foreground_send_transfer_callbacks_.Clear();
341   foreground_send_discovery_callbacks_.Clear();
342   background_send_transfer_callbacks_.Clear();
343   background_send_discovery_callbacks_.Clear();
344 
345   last_incoming_metadata_.reset();
346   last_outgoing_metadata_.reset();
347   attachment_info_map_.clear();
348   mutual_acceptance_timeout_alarm_.Cancel();
349   disconnection_timeout_alarms_.clear();
350 
351   is_transferring_ = false;
352   is_receiving_files_ = false;
353   is_sending_files_ = false;
354   is_connecting_ = false;
355 
356   settings_receiver_.reset();
357 
358   if (settings_.GetEnabled()) {
359     local_device_data_manager_->Stop();
360     contact_manager_->Stop();
361     certificate_manager_->Stop();
362   }
363 
364   process_shutdown_pending_timer_.Stop();
365   rotate_background_advertisement_timer_.Stop();
366 
367   // |profile_| has now been shut down so we shouldn't use it anymore.
368   profile_ = nullptr;
369 }
370 
AddObserver(NearbySharingService::Observer * observer)371 void NearbySharingServiceImpl::AddObserver(
372     NearbySharingService::Observer* observer) {
373   observers_.AddObserver(observer);
374 }
375 
RemoveObserver(NearbySharingService::Observer * observer)376 void NearbySharingServiceImpl::RemoveObserver(
377     NearbySharingService::Observer* observer) {
378   observers_.RemoveObserver(observer);
379 }
380 
HasObserver(NearbySharingService::Observer * observer)381 bool NearbySharingServiceImpl::HasObserver(
382     NearbySharingService::Observer* observer) {
383   return observers_.HasObserver(observer);
384 }
385 
RegisterSendSurface(TransferUpdateCallback * transfer_callback,ShareTargetDiscoveredCallback * discovery_callback,SendSurfaceState state)386 NearbySharingService::StatusCodes NearbySharingServiceImpl::RegisterSendSurface(
387     TransferUpdateCallback* transfer_callback,
388     ShareTargetDiscoveredCallback* discovery_callback,
389     SendSurfaceState state) {
390   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
391   DCHECK(transfer_callback);
392   DCHECK(discovery_callback);
393   DCHECK_NE(state, SendSurfaceState::kUnknown);
394 
395   if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback) ||
396       background_send_transfer_callbacks_.HasObserver(transfer_callback)) {
397     NS_LOG(VERBOSE) << __func__
398                     << ": RegisterSendSurface failed. Already registered for a "
399                        "different state.";
400     return StatusCodes::kError;
401   }
402 
403   if (state == SendSurfaceState::kForeground) {
404     foreground_send_transfer_callbacks_.AddObserver(transfer_callback);
405     foreground_send_discovery_callbacks_.AddObserver(discovery_callback);
406   } else {
407     background_send_transfer_callbacks_.AddObserver(transfer_callback);
408     background_send_discovery_callbacks_.AddObserver(discovery_callback);
409   }
410 
411   if (is_receiving_files_) {
412     UnregisterSendSurface(transfer_callback, discovery_callback);
413     NS_LOG(VERBOSE)
414         << __func__
415         << ": Ignore registering (and unregistering if registered) send "
416            "surface because we're currently receiving files.";
417     return StatusCodes::kTransferAlreadyInProgress;
418   }
419 
420   // If the share sheet to be registered is a foreground surface, let it catch
421   // up with most recent transfer metadata immediately.
422   if (state == SendSurfaceState::kForeground && last_outgoing_metadata_) {
423     // When a new share sheet is registered, we want to immediately show the
424     // in-progress bar.
425     discovery_callback->OnShareTargetDiscovered(last_outgoing_metadata_->first);
426     transfer_callback->OnTransferUpdate(last_outgoing_metadata_->first,
427                                         last_outgoing_metadata_->second);
428   }
429 
430   // Sync down data from Nearby server when the sending flow starts, making our
431   // best effort to have fresh contact and certificate data. There is no need to
432   // wait for these calls to finish. The periodic server requests will typically
433   // be sufficient, but we don't want the user to be blocked for hours waiting
434   // for a periodic sync.
435   if (state == SendSurfaceState::kForeground && !last_outgoing_metadata_) {
436     NS_LOG(VERBOSE)
437         << __func__
438         << ": Downloading local device data, contacts, and certificates from "
439         << "Nearby server at start of sending flow.";
440     local_device_data_manager_->DownloadDeviceData();
441     contact_manager_->DownloadContacts();
442     certificate_manager_->DownloadPublicCertificates();
443   }
444 
445   // Let newly registered send surface catch up with discovered share targets
446   // from current scanning session.
447   for (const std::pair<std::string, ShareTarget>& item :
448        outgoing_share_target_map_) {
449     discovery_callback->OnShareTargetDiscovered(item.second);
450   }
451 
452   NS_LOG(VERBOSE) << __func__
453                   << ": A SendSurface has been registered for state: "
454                   << SendSurfaceStateToString(state);
455   InvalidateSendSurfaceState();
456   return StatusCodes::kOk;
457 }
458 
459 NearbySharingService::StatusCodes
UnregisterSendSurface(TransferUpdateCallback * transfer_callback,ShareTargetDiscoveredCallback * discovery_callback)460 NearbySharingServiceImpl::UnregisterSendSurface(
461     TransferUpdateCallback* transfer_callback,
462     ShareTargetDiscoveredCallback* discovery_callback) {
463   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
464   DCHECK(transfer_callback);
465   DCHECK(discovery_callback);
466   if (!foreground_send_transfer_callbacks_.HasObserver(transfer_callback) &&
467       !background_send_transfer_callbacks_.HasObserver(transfer_callback)) {
468     NS_LOG(VERBOSE)
469         << __func__
470         << ": unregisterSendSurface failed. Unknown TransferUpdateCallback";
471     return StatusCodes::kError;
472   }
473 
474   if (foreground_send_transfer_callbacks_.might_have_observers() &&
475       last_outgoing_metadata_ &&
476       last_outgoing_metadata_->second.is_final_status()) {
477     // We already saw the final status in the foreground
478     // Nullify it so the next time the user opens sharing, it starts the UI from
479     // the beginning
480     last_outgoing_metadata_.reset();
481   }
482 
483   SendSurfaceState state = SendSurfaceState::kUnknown;
484   if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback)) {
485     foreground_send_transfer_callbacks_.RemoveObserver(transfer_callback);
486     foreground_send_discovery_callbacks_.RemoveObserver(discovery_callback);
487     state = SendSurfaceState::kForeground;
488   } else {
489     background_send_transfer_callbacks_.RemoveObserver(transfer_callback);
490     background_send_discovery_callbacks_.RemoveObserver(discovery_callback);
491     state = SendSurfaceState::kBackground;
492   }
493 
494   // Displays the most recent payload status processed by foreground surfaces on
495   // background surfaces.
496   if (!foreground_send_transfer_callbacks_.might_have_observers() &&
497       last_outgoing_metadata_) {
498     for (TransferUpdateCallback& background_transfer_callback :
499          background_send_transfer_callbacks_) {
500       background_transfer_callback.OnTransferUpdate(
501           last_outgoing_metadata_->first, last_outgoing_metadata_->second);
502     }
503   }
504 
505   NS_LOG(VERBOSE) << __func__ << ": A SendSurface has been unregistered: "
506                   << SendSurfaceStateToString(state);
507   InvalidateSurfaceState();
508   return StatusCodes::kOk;
509 }
510 
511 NearbySharingService::StatusCodes
RegisterReceiveSurface(TransferUpdateCallback * transfer_callback,ReceiveSurfaceState state)512 NearbySharingServiceImpl::RegisterReceiveSurface(
513     TransferUpdateCallback* transfer_callback,
514     ReceiveSurfaceState state) {
515   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
516   DCHECK(transfer_callback);
517   DCHECK_NE(state, ReceiveSurfaceState::kUnknown);
518 
519   if (is_sending_files_) {
520     UnregisterReceiveSurface(transfer_callback);
521     NS_LOG(VERBOSE)
522         << __func__
523         << ": Ignore registering (and unregistering if registered) receive "
524            "surface, because we're currently sending files.";
525     return StatusCodes::kTransferAlreadyInProgress;
526   }
527 
528   // We specifically allow re-registring with out error so it is clear to caller
529   // that the transfer_callback is currently registered.
530   if (GetReceiveCallbacksFromState(state).HasObserver(transfer_callback)) {
531     NS_LOG(VERBOSE) << __func__
532                     << ": transfer callback already registered, ignoring";
533     return StatusCodes::kOk;
534   } else if (foreground_receive_callbacks_.HasObserver(transfer_callback) ||
535              background_receive_callbacks_.HasObserver(transfer_callback)) {
536     NS_LOG(ERROR)
537         << __func__
538         << ":  transfer callback already registered but for a different state.";
539     return StatusCodes::kError;
540   }
541 
542   // If the receive surface to be registered is a foreground surface, let it
543   // catch up with most recent transfer metadata immediately.
544   if (state == ReceiveSurfaceState::kForeground && last_incoming_metadata_) {
545     transfer_callback->OnTransferUpdate(last_incoming_metadata_->first,
546                                         last_incoming_metadata_->second);
547   }
548 
549   GetReceiveCallbacksFromState(state).AddObserver(transfer_callback);
550 
551   NS_LOG(VERBOSE) << __func__ << ": A ReceiveSurface("
552                   << ReceiveSurfaceStateToString(state)
553                   << ") has been registered";
554   InvalidateReceiveSurfaceState();
555   return StatusCodes::kOk;
556 }
557 
558 NearbySharingService::StatusCodes
UnregisterReceiveSurface(TransferUpdateCallback * transfer_callback)559 NearbySharingServiceImpl::UnregisterReceiveSurface(
560     TransferUpdateCallback* transfer_callback) {
561   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
562   DCHECK(transfer_callback);
563   bool is_foreground =
564       foreground_receive_callbacks_.HasObserver(transfer_callback);
565   bool is_background =
566       background_receive_callbacks_.HasObserver(transfer_callback);
567   if (!is_foreground && !is_background) {
568     NS_LOG(VERBOSE)
569         << __func__
570         << ": Unknown transfer callback was un-registered, ignoring.";
571     // We intentionally allow this be successful so the caller can be sure
572     // they are not registered anymore.
573     return StatusCodes::kOk;
574   }
575 
576   if (foreground_receive_callbacks_.might_have_observers() &&
577       last_incoming_metadata_ &&
578       last_incoming_metadata_->second.is_final_status()) {
579     // We already saw the final status in the foreground.
580     // Nullify it so the next time the user opens sharing, it starts the UI from
581     // the beginning
582     last_incoming_metadata_.reset();
583   }
584 
585   if (is_foreground) {
586     foreground_receive_callbacks_.RemoveObserver(transfer_callback);
587   } else {
588     background_receive_callbacks_.RemoveObserver(transfer_callback);
589   }
590 
591   // Displays the most recent payload status processed by foreground surfaces on
592   // background surface.
593   if (!foreground_receive_callbacks_.might_have_observers() &&
594       last_incoming_metadata_) {
595     for (TransferUpdateCallback& background_callback :
596          background_receive_callbacks_) {
597       background_callback.OnTransferUpdate(last_incoming_metadata_->first,
598                                            last_incoming_metadata_->second);
599     }
600   }
601 
602   NS_LOG(VERBOSE) << __func__ << ": A ReceiveSurface("
603                   << (is_foreground ? "foreground" : "background")
604                   << ") has been unregistered";
605   InvalidateSurfaceState();
606   return StatusCodes::kOk;
607 }
608 
609 NearbySharingService::StatusCodes
ClearForegroundReceiveSurfaces()610 NearbySharingServiceImpl::ClearForegroundReceiveSurfaces() {
611   std::vector<TransferUpdateCallback*> fg_receivers;
612   for (auto& callback : foreground_receive_callbacks_)
613     fg_receivers.push_back(&callback);
614 
615   StatusCodes status = StatusCodes::kOk;
616   for (TransferUpdateCallback* callback : fg_receivers) {
617     if (UnregisterReceiveSurface(callback) != StatusCodes::kOk)
618       status = StatusCodes::kError;
619   }
620   return status;
621 }
622 
IsInHighVisibility()623 bool NearbySharingServiceImpl::IsInHighVisibility() {
624   return in_high_visibility;
625 }
626 
SendAttachments(const ShareTarget & share_target,std::vector<std::unique_ptr<Attachment>> attachments)627 NearbySharingService::StatusCodes NearbySharingServiceImpl::SendAttachments(
628     const ShareTarget& share_target,
629     std::vector<std::unique_ptr<Attachment>> attachments) {
630   if (!is_scanning_) {
631     NS_LOG(WARNING) << __func__
632                     << ": Failed to send attachments. Not scanning.";
633     return StatusCodes::kError;
634   }
635 
636   // |is_scanning_| means at least one send transfer callback.
637   DCHECK(foreground_send_transfer_callbacks_.might_have_observers() ||
638          background_send_transfer_callbacks_.might_have_observers());
639   // |is_scanning_| and |is_transferring_| are mutually exclusive.
640   DCHECK(!is_transferring_);
641 
642   ShareTargetInfo* info = GetShareTargetInfo(share_target);
643   if (!info || !info->endpoint_id()) {
644     // TODO(crbug.com/1119276): Support scanning for unknown share targets.
645     NS_LOG(WARNING) << __func__
646                     << ": Failed to send attachments. Unknown ShareTarget.";
647     return StatusCodes::kError;
648   }
649 
650   ShareTarget share_target_copy = share_target;
651   for (std::unique_ptr<Attachment>& attachment : attachments) {
652     DCHECK(attachment);
653     attachment->MoveToShareTarget(share_target_copy);
654   }
655 
656   if (!share_target_copy.has_attachments()) {
657     NS_LOG(WARNING) << __func__ << ": No attachments to send.";
658     return StatusCodes::kError;
659   }
660 
661   // For sending advertisement from scanner, the request advertisement should
662   // always be visible to everyone.
663   base::Optional<std::vector<uint8_t>> endpoint_info =
664       CreateEndpointInfo(local_device_data_manager_->GetDeviceName());
665   if (!endpoint_info) {
666     NS_LOG(WARNING) << __func__ << ": Could not create local endpoint info.";
667     return StatusCodes::kError;
668   }
669 
670   info->set_transfer_update_callback(std::make_unique<TransferUpdateDecorator>(
671       base::BindRepeating(&NearbySharingServiceImpl::OnOutgoingTransferUpdate,
672                           weak_ptr_factory_.GetWeakPtr())));
673 
674   OnTransferStarted(/*is_incoming=*/false);
675   is_connecting_ = true;
676   InvalidateSendSurfaceState();
677 
678   // Send process initialized successfully, from now on status updated will be
679   // sent out via OnOutgoingTransferUpdate().
680   info->transfer_update_callback()->OnTransferUpdate(
681       share_target_copy, TransferMetadataBuilder()
682                              .set_status(TransferMetadata::Status::kConnecting)
683                              .build());
684 
685   CreatePayloads(std::move(share_target_copy),
686                  base::BindOnce(&NearbySharingServiceImpl::OnCreatePayloads,
687                                 weak_ptr_factory_.GetWeakPtr(),
688                                 std::move(*endpoint_info)));
689 
690   return StatusCodes::kOk;
691 }
692 
Accept(const ShareTarget & share_target,StatusCodesCallback status_codes_callback)693 void NearbySharingServiceImpl::Accept(
694     const ShareTarget& share_target,
695     StatusCodesCallback status_codes_callback) {
696   ShareTargetInfo* info = GetShareTargetInfo(share_target);
697   if (!info || !info->connection()) {
698     NS_LOG(WARNING) << __func__ << ": Accept invoked for unknown share target";
699     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
700     return;
701   }
702 
703   base::Optional<std::pair<ShareTarget, TransferMetadata>> metadata =
704       share_target.is_incoming ? last_incoming_metadata_
705                                : last_outgoing_metadata_;
706   if (!metadata || metadata->second.status() !=
707                        TransferMetadata::Status::kAwaitingLocalConfirmation) {
708     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
709     return;
710   }
711 
712   if (share_target.is_incoming) {
713     ReceivePayloads(share_target, std::move(status_codes_callback));
714     return;
715   }
716 
717   std::move(status_codes_callback).Run(SendPayloads(share_target));
718 }
719 
Reject(const ShareTarget & share_target,StatusCodesCallback status_codes_callback)720 void NearbySharingServiceImpl::Reject(
721     const ShareTarget& share_target,
722     StatusCodesCallback status_codes_callback) {
723   ShareTargetInfo* info = GetShareTargetInfo(share_target);
724   if (!info || !info->connection()) {
725     NS_LOG(WARNING) << __func__ << ": Reject invoked for unknown share target";
726     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
727     return;
728   }
729   NearbyConnection* connection = info->connection();
730 
731   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
732       FROM_HERE,
733       base::BindOnce(&NearbySharingServiceImpl::CloseConnection,
734                      weak_ptr_factory_.GetWeakPtr(), share_target),
735       kIncomingRejectionDelay);
736 
737   connection->SetDisconnectionListener(
738       base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
739                      weak_ptr_factory_.GetWeakPtr(), share_target));
740 
741   WriteResponse(*connection, sharing::nearby::ConnectionResponseFrame::REJECT);
742   NS_LOG(VERBOSE) << __func__
743                   << ": Successfully wrote a rejection response frame";
744 
745   if (info->transfer_update_callback()) {
746     info->transfer_update_callback()->OnTransferUpdate(
747         share_target, TransferMetadataBuilder()
748                           .set_status(TransferMetadata::Status::kRejected)
749                           .build());
750   }
751 
752   std::move(status_codes_callback).Run(StatusCodes::kOk);
753 }
754 
Cancel(const ShareTarget & share_target,StatusCodesCallback status_codes_callback)755 void NearbySharingServiceImpl::Cancel(
756     const ShareTarget& share_target,
757     StatusCodesCallback status_codes_callback) {
758   NS_LOG(INFO) << __func__ << ": User canceled transfer";
759   DoCancel(share_target, std::move(status_codes_callback),
760            /*write_cancel_frame=*/true);
761 }
762 
DoCancel(ShareTarget share_target,StatusCodesCallback status_codes_callback,bool write_cancel_frame)763 void NearbySharingServiceImpl::DoCancel(
764     ShareTarget share_target,
765     StatusCodesCallback status_codes_callback,
766     bool write_cancel_frame) {
767   ShareTargetInfo* info = GetShareTargetInfo(share_target);
768   if (!info || !info->endpoint_id()) {
769     NS_LOG(ERROR) << __func__
770                   << ": Cancel invoked for unknown share target, returning "
771                      "kOutOfOrderApiCall";
772     // Make sure to clean up files just in case.
773     RemoveIncomingPayloads(share_target);
774     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
775     return;
776   }
777 
778   // Cancel all ongoing payload transfers before invoking the transfer update
779   // callback. Invoking the transfer update callback first could result in
780   // payload cleanup before we have a chance to cancel the payload via Nearby
781   // Connections, and the payload tracker might not receive the expected
782   // cancellation signals. Also, note that there might not be any ongoing
783   // payload transfer, for example, if a connection has not been established
784   // yet.
785   for (int64_t attachment_id : share_target.GetAttachmentIds()) {
786     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id);
787     if (payload_id) {
788       nearby_connections_manager_->Cancel(*payload_id);
789     }
790   }
791 
792   // Inform the user that the transfer has been cancelled before disconnecting
793   // because subsequent disconnections might be interpreted as failure. The
794   // TransferUpdateDecorator will ignore subsequent statuses in favor of this
795   // cancelled status. Note that the transfer update callback might have already
796   // been invoked as a result of the payload cancellations above, but again,
797   // superfluous status updates are handled gracefully by the
798   // TransferUpdateDecorator.
799   if (info->transfer_update_callback()) {
800     info->transfer_update_callback()->OnTransferUpdate(
801         share_target, TransferMetadataBuilder()
802                           .set_status(TransferMetadata::Status::kCancelled)
803                           .build());
804   }
805 
806   // If a connection exists, close the connection after a short delay that
807   // allows for final processing by the other device. Otherwise, disconnect from
808   // endpoint id directly. Note: A share attempt can be cancelled by the user
809   // before a connection is fully established, in which case, info->connection()
810   // will be null.
811   if (info->connection()) {
812     info->connection()->SetDisconnectionListener(
813         base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
814                        weak_ptr_factory_.GetWeakPtr(), share_target));
815     base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
816         FROM_HERE,
817         base::BindOnce(&NearbySharingServiceImpl::CloseConnection,
818                        weak_ptr_factory_.GetWeakPtr(), share_target),
819         kIncomingCancelDelay);
820 
821     if (write_cancel_frame) {
822       WriteCancel(*info->connection());
823     }
824   } else {
825     nearby_connections_manager_->Disconnect(*info->endpoint_id());
826     UnregisterShareTarget(share_target);
827   }
828 
829   std::move(status_codes_callback).Run(StatusCodes::kOk);
830 }
831 
Open(const ShareTarget & share_target,StatusCodesCallback status_codes_callback)832 void NearbySharingServiceImpl::Open(const ShareTarget& share_target,
833                                     StatusCodesCallback status_codes_callback) {
834   std::move(status_codes_callback).Run(StatusCodes::kOk);
835 }
836 
GetNotificationDelegate(const std::string & notification_id)837 NearbyNotificationDelegate* NearbySharingServiceImpl::GetNotificationDelegate(
838     const std::string& notification_id) {
839   if (!nearby_notification_manager_)
840     return nullptr;
841 
842   return nearby_notification_manager_->GetNotificationDelegate(notification_id);
843 }
844 
GetSettings()845 NearbyShareSettings* NearbySharingServiceImpl::GetSettings() {
846   return &settings_;
847 }
848 
GetHttpNotifier()849 NearbyShareHttpNotifier* NearbySharingServiceImpl::GetHttpNotifier() {
850   return &nearby_share_http_notifier_;
851 }
852 
853 NearbyShareLocalDeviceDataManager*
GetLocalDeviceDataManager()854 NearbySharingServiceImpl::GetLocalDeviceDataManager() {
855   return local_device_data_manager_.get();
856 }
857 
GetContactManager()858 NearbyShareContactManager* NearbySharingServiceImpl::GetContactManager() {
859   return contact_manager_.get();
860 }
861 
862 NearbyShareCertificateManager*
GetCertificateManager()863 NearbySharingServiceImpl::GetCertificateManager() {
864   return certificate_manager_.get();
865 }
866 
OnNearbyProfileChanged(Profile * profile)867 void NearbySharingServiceImpl::OnNearbyProfileChanged(Profile* profile) {
868   // TODO(crbug.com/1084576): Notify UI about the new active profile.
869   if (profile) {
870     NS_LOG(VERBOSE) << __func__ << ": Active Nearby profile changed to: "
871                     << profile->GetProfileUserName();
872   } else {
873     NS_LOG(VERBOSE) << __func__ << ": Active Nearby profile cleared";
874   }
875   InvalidateSurfaceState();
876 }
877 
OnNearbyProcessStarted()878 void NearbySharingServiceImpl::OnNearbyProcessStarted() {
879   DCHECK(profile_);
880   if (process_manager_->IsActiveProfile(profile_)) {
881     NS_LOG(VERBOSE) << __func__ << ": Nearby process started for profile: "
882                     << profile_->GetProfileUserName();
883   }
884 }
885 
OnNearbyProcessStopped()886 void NearbySharingServiceImpl::OnNearbyProcessStopped() {
887   DCHECK(profile_);
888   InvalidateSurfaceState();
889   if (process_manager_->IsActiveProfile(profile_)) {
890     NS_LOG(VERBOSE) << __func__ << ": Nearby process stopped for profile: "
891                     << profile_->GetProfileUserName();
892   }
893 }
894 
OnIncomingConnection(const std::string & endpoint_id,const std::vector<uint8_t> & endpoint_info,NearbyConnection * connection)895 void NearbySharingServiceImpl::OnIncomingConnection(
896     const std::string& endpoint_id,
897     const std::vector<uint8_t>& endpoint_info,
898     NearbyConnection* connection) {
899   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
900   DCHECK(connection);
901   DCHECK(profile_);
902 
903   // Sync down data from Nearby server when the receiving flow starts, making
904   // our best effort to have fresh contact and certificate data. There is no
905   // need to wait for these calls to finish. The periodic server requests will
906   // typically be sufficient, but we don't want the user to be blocked for hours
907   // waiting for a periodic sync.
908   NS_LOG(VERBOSE)
909       << __func__
910       << ": Downloading local device data, contacts, and certificates from "
911       << "Nearby server at start of receiving flow.";
912   local_device_data_manager_->DownloadDeviceData();
913   contact_manager_->DownloadContacts();
914   certificate_manager_->DownloadPublicCertificates();
915 
916   ShareTarget placeholder_share_target;
917   placeholder_share_target.is_incoming = true;
918   ShareTargetInfo& share_target_info =
919       GetOrCreateShareTargetInfo(placeholder_share_target, endpoint_id);
920   share_target_info.set_connection(connection);
921 
922   connection->SetDisconnectionListener(
923       base::BindOnce(&NearbySharingServiceImpl::RefreshUIOnDisconnection,
924                      weak_ptr_factory_.GetWeakPtr(), placeholder_share_target));
925 
926   process_manager_->GetOrStartNearbySharingDecoder(profile_)
927       ->DecodeAdvertisement(
928           endpoint_info,
929           base::BindOnce(
930               &NearbySharingServiceImpl::OnIncomingAdvertisementDecoded,
931               weak_ptr_factory_.GetWeakPtr(), endpoint_id,
932               std::move(placeholder_share_target)));
933 }
934 
FlushMojoForTesting()935 void NearbySharingServiceImpl::FlushMojoForTesting() {
936   settings_receiver_.FlushForTesting();
937 }
938 
OnEnabledChanged(bool enabled)939 void NearbySharingServiceImpl::OnEnabledChanged(bool enabled) {
940   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
941   if (enabled) {
942     NS_LOG(VERBOSE) << __func__ << ": Nearby sharing enabled!";
943     local_device_data_manager_->Start();
944     contact_manager_->Start();
945     certificate_manager_->Start();
946   } else {
947     NS_LOG(VERBOSE) << __func__ << ": Nearby sharing disabled!";
948     StopAdvertising();
949     StopScanning();
950     nearby_connections_manager_->Shutdown();
951     local_device_data_manager_->Stop();
952     contact_manager_->Stop();
953     certificate_manager_->Stop();
954   }
955   InvalidateSurfaceState();
956 }
957 
OnDeviceNameChanged(const std::string & device_name)958 void NearbySharingServiceImpl::OnDeviceNameChanged(
959     const std::string& device_name) {
960   NS_LOG(VERBOSE) << __func__ << ": Nearby sharing device name changed to "
961                   << device_name;
962   // TODO(vecore): handle device name change
963 }
964 
OnDataUsageChanged(DataUsage data_usage)965 void NearbySharingServiceImpl::OnDataUsageChanged(DataUsage data_usage) {
966   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
967   NS_LOG(VERBOSE) << __func__ << ": Nearby sharing data usage changed to "
968                   << data_usage;
969 
970   if (advertising_power_level_ != PowerLevel::kUnknown)
971     StopAdvertising();
972 
973   InvalidateSurfaceState();
974 }
975 
OnVisibilityChanged(Visibility new_visibility)976 void NearbySharingServiceImpl::OnVisibilityChanged(Visibility new_visibility) {
977   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
978   NS_LOG(VERBOSE) << __func__ << ": Nearby sharing visibility changed to "
979                   << new_visibility;
980   if (advertising_power_level_ != PowerLevel::kUnknown)
981     StopAdvertising();
982 
983   InvalidateSurfaceState();
984 }
985 
OnAllowedContactsChanged(const std::vector<std::string> & allowed_contacts)986 void NearbySharingServiceImpl::OnAllowedContactsChanged(
987     const std::vector<std::string>& allowed_contacts) {
988   NS_LOG(VERBOSE) << __func__ << ": Nearby sharing visible contacts changed";
989   // TODO(vecore): handle visible contacts change
990 }
991 
OnPublicCertificatesDownloaded()992 void NearbySharingServiceImpl::OnPublicCertificatesDownloaded() {
993   // TODO(https://crbug.com/1152158): Possibly restart scanning after public
994   // certificates are downloaded.
995 }
996 
OnPrivateCertificatesChanged()997 void NearbySharingServiceImpl::OnPrivateCertificatesChanged() {
998   // If we are currently advertising, restart advertising using the updated
999   // private certificates.
1000   if (rotate_background_advertisement_timer_.IsRunning()) {
1001     NS_LOG(VERBOSE)
1002         << __func__
1003         << ": Private certificates changed; rotating background advertisement.";
1004     rotate_background_advertisement_timer_.FireNow();
1005   }
1006 }
1007 
OnEndpointDiscovered(const std::string & endpoint_id,const std::vector<uint8_t> & endpoint_info)1008 void NearbySharingServiceImpl::OnEndpointDiscovered(
1009     const std::string& endpoint_id,
1010     const std::vector<uint8_t>& endpoint_info) {
1011   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1012   DCHECK(profile_);
1013   if (!is_scanning_) {
1014     NS_LOG(VERBOSE)
1015         << __func__
1016         << ": Ignoring discovered endpoint because we're no longer scanning";
1017     return;
1018   }
1019 
1020   process_manager_->GetOrStartNearbySharingDecoder(profile_)
1021       ->DecodeAdvertisement(
1022           endpoint_info,
1023           base::BindOnce(
1024               &NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded,
1025               weak_ptr_factory_.GetWeakPtr(), endpoint_id));
1026 }
1027 
OnEndpointLost(const std::string & endpoint_id)1028 void NearbySharingServiceImpl::OnEndpointLost(const std::string& endpoint_id) {
1029   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1030   if (!is_scanning_) {
1031     NS_LOG(VERBOSE)
1032         << __func__
1033         << ": Ignoring lost endpoint because we're no longer scanning";
1034     return;
1035   }
1036 
1037   RemoveOutgoingShareTargetWithEndpointId(endpoint_id);
1038 }
1039 
OnLockStateChanged(bool locked)1040 void NearbySharingServiceImpl::OnLockStateChanged(bool locked) {
1041   NS_LOG(VERBOSE) << __func__ << ": Screen lock state changed. (" << locked
1042                   << ")";
1043   is_screen_locked_ = locked;
1044   InvalidateSurfaceState();
1045 }
1046 
AdapterPresentChanged(device::BluetoothAdapter * adapter,bool present)1047 void NearbySharingServiceImpl::AdapterPresentChanged(
1048     device::BluetoothAdapter* adapter,
1049     bool present) {
1050   NS_LOG(VERBOSE) << "Bluetooth present changed: " << present;
1051   InvalidateSurfaceState();
1052 }
1053 
AdapterPoweredChanged(device::BluetoothAdapter * adapter,bool powered)1054 void NearbySharingServiceImpl::AdapterPoweredChanged(
1055     device::BluetoothAdapter* adapter,
1056     bool powered) {
1057   NS_LOG(VERBOSE) << "Bluetooth powered changed: " << powered;
1058   InvalidateSurfaceState();
1059 }
1060 
SuspendImminent()1061 void NearbySharingServiceImpl::SuspendImminent() {
1062   NS_LOG(VERBOSE) << __func__ << ": Suspend imminent.";
1063   InvalidateSurfaceState();
1064 }
1065 
SuspendDone()1066 void NearbySharingServiceImpl::SuspendDone() {
1067   NS_LOG(VERBOSE) << __func__ << ": Suspend done.";
1068   InvalidateSurfaceState();
1069 }
1070 
1071 base::ObserverList<TransferUpdateCallback>&
GetReceiveCallbacksFromState(ReceiveSurfaceState state)1072 NearbySharingServiceImpl::GetReceiveCallbacksFromState(
1073     ReceiveSurfaceState state) {
1074   switch (state) {
1075     case ReceiveSurfaceState::kForeground:
1076       return foreground_receive_callbacks_;
1077     case ReceiveSurfaceState::kBackground:
1078       return background_receive_callbacks_;
1079     case ReceiveSurfaceState::kUnknown:
1080       NOTREACHED();
1081       return foreground_receive_callbacks_;
1082   }
1083 }
1084 
IsVisibleInBackground(Visibility visibility)1085 bool NearbySharingServiceImpl::IsVisibleInBackground(Visibility visibility) {
1086   return visibility == Visibility::kAllContacts ||
1087          visibility == Visibility::kSelectedContacts;
1088 }
1089 
1090 const base::Optional<std::vector<uint8_t>>
CreateEndpointInfo(const base::Optional<std::string> & device_name)1091 NearbySharingServiceImpl::CreateEndpointInfo(
1092     const base::Optional<std::string>& device_name) {
1093   std::vector<uint8_t> salt;
1094   std::vector<uint8_t> encrypted_key;
1095 
1096   nearby_share::mojom::Visibility visibility = settings_.GetVisibility();
1097   if (visibility == Visibility::kAllContacts ||
1098       visibility == Visibility::kSelectedContacts) {
1099     base::Optional<NearbyShareEncryptedMetadataKey> encrypted_metadata_key =
1100         certificate_manager_->EncryptPrivateCertificateMetadataKey(visibility);
1101     if (encrypted_metadata_key) {
1102       salt = encrypted_metadata_key->salt();
1103       encrypted_key = encrypted_metadata_key->encrypted_key();
1104     } else {
1105       NS_LOG(WARNING) << __func__
1106                       << ": Failed to encrypt private certificate metadata key "
1107                       << "for advertisement.";
1108     }
1109   }
1110 
1111   if (salt.empty() || encrypted_key.empty()) {
1112     // Generate random metadata key.
1113     salt = GenerateRandomBytes(sharing::Advertisement::kSaltSize);
1114     encrypted_key = GenerateRandomBytes(
1115         sharing::Advertisement::kMetadataEncryptionKeyHashByteSize);
1116   }
1117 
1118   nearby_share::mojom::ShareTargetType device_type =
1119       nearby_share::mojom::ShareTargetType::kLaptop;
1120 
1121   std::unique_ptr<sharing::Advertisement> advertisement =
1122       sharing::Advertisement::NewInstance(
1123           std::move(salt), std::move(encrypted_key), device_type, device_name);
1124   if (advertisement) {
1125     return advertisement->ToEndpointInfo();
1126   } else {
1127     return base::nullopt;
1128   }
1129 }
1130 
GetBluetoothAdapter()1131 void NearbySharingServiceImpl::GetBluetoothAdapter() {
1132   auto* adapter_factory = device::BluetoothAdapterFactory::Get();
1133   if (!adapter_factory->IsBluetoothSupported())
1134     return;
1135 
1136   // Because this will be called from the constructor, GetAdapter() may call
1137   // OnGetBluetoothAdapter() immediately which can cause problems during tests
1138   // since the class is not fully constructed yet.
1139   base::SequencedTaskRunnerHandle::Get()->PostTask(
1140       FROM_HERE,
1141       base::BindOnce(
1142           &device::BluetoothAdapterFactory::GetAdapter,
1143           base::Unretained(adapter_factory),
1144           base::BindOnce(&NearbySharingServiceImpl::OnGetBluetoothAdapter,
1145                          weak_ptr_factory_.GetWeakPtr())));
1146 }
1147 
OnGetBluetoothAdapter(scoped_refptr<device::BluetoothAdapter> adapter)1148 void NearbySharingServiceImpl::OnGetBluetoothAdapter(
1149     scoped_refptr<device::BluetoothAdapter> adapter) {
1150   bluetooth_adapter_ = adapter;
1151   bluetooth_adapter_->AddObserver(this);
1152 
1153   // TODO(crbug/1147652): The call to update the advertising interval is
1154   // removed to prevent a Bluez crash. We need to either reduce the global
1155   // advertising interval asynchronously and wait for the result or use the
1156   // updated API referenced in the bug which allows setting a per-advertisement
1157   // interval.
1158 
1159   // TODO(crbug.com/1132469): This was added to fix an issue where advertising
1160   // was not starting on sign-in. Add a unit test to cover this case.
1161   InvalidateSurfaceState();
1162 }
1163 
StartFastInitiationAdvertising()1164 void NearbySharingServiceImpl::StartFastInitiationAdvertising() {
1165   NS_LOG(VERBOSE) << __func__ << ": Starting fast initiation advertising.";
1166 
1167   fast_initiation_manager_ =
1168       FastInitiationManager::Factory::Create(bluetooth_adapter_);
1169 
1170   // TODO(crbug/1147652): The call to update the advertising interval is
1171   // removed to prevent a Bluez crash. We need to either reduce the global
1172   // advertising interval asynchronously and wait for the result or use the
1173   // updated API referenced in the bug which allows setting a per-advertisement
1174   // interval.
1175 
1176   // TODO(crbug.com/1100686): Determine whether to call StartAdvertising() with
1177   // kNotify or kSilent.
1178   fast_initiation_manager_->StartAdvertising(
1179       FastInitiationManager::FastInitType::kNotify,
1180       base::BindOnce(
1181           &NearbySharingServiceImpl::OnStartFastInitiationAdvertising,
1182           weak_ptr_factory_.GetWeakPtr()),
1183       base::BindOnce(
1184           &NearbySharingServiceImpl::OnStartFastInitiationAdvertisingError,
1185           weak_ptr_factory_.GetWeakPtr()));
1186 }
1187 
OnStartFastInitiationAdvertising()1188 void NearbySharingServiceImpl::OnStartFastInitiationAdvertising() {
1189   // TODO(hansenmichael): Do not invoke
1190   // |register_send_surface_callback_| until Nearby Connections
1191   // scanning is kicked off.
1192   NS_LOG(VERBOSE) << "Started advertising FastInitiation.";
1193 }
1194 
OnStartFastInitiationAdvertisingError()1195 void NearbySharingServiceImpl::OnStartFastInitiationAdvertisingError() {
1196   fast_initiation_manager_.reset();
1197   NS_LOG(ERROR) << "Failed to start FastInitiation advertising.";
1198 }
1199 
StopFastInitiationAdvertising()1200 void NearbySharingServiceImpl::StopFastInitiationAdvertising() {
1201   if (!fast_initiation_manager_) {
1202     NS_LOG(VERBOSE)
1203         << "Can't stop advertising FastInitiation. Not advertising.";
1204     return;
1205   }
1206 
1207   fast_initiation_manager_->StopAdvertising(
1208       base::BindOnce(&NearbySharingServiceImpl::OnStopFastInitiationAdvertising,
1209                      weak_ptr_factory_.GetWeakPtr()));
1210 }
1211 
OnStopFastInitiationAdvertising()1212 void NearbySharingServiceImpl::OnStopFastInitiationAdvertising() {
1213   fast_initiation_manager_.reset();
1214   NS_LOG(VERBOSE) << "Stopped advertising FastInitiation";
1215 
1216   // TODO(crbug/1147652): The call to update the advertising interval is
1217   // removed to prevent a Bluez crash. We need to either reduce the global
1218   // advertising interval asynchronously and wait for the result or use the
1219   // updated API referenced in the bug which allows setting a per-advertisement
1220   // interval.
1221 }
1222 
OnOutgoingAdvertisementDecoded(const std::string & endpoint_id,sharing::mojom::AdvertisementPtr advertisement)1223 void NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded(
1224     const std::string& endpoint_id,
1225     sharing::mojom::AdvertisementPtr advertisement) {
1226   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1227   if (!advertisement) {
1228     NS_LOG(VERBOSE) << __func__
1229                     << ": Failed to parse discovered advertisement.";
1230     return;
1231   }
1232 
1233   // Now we will report endpoints met before in NearbyConnectionsManager.
1234   // Check outgoingShareTargetInfoMap first and pass the same shareTarget if we
1235   // found one.
1236 
1237   // Looking for the ShareTarget based on endpoint id.
1238   if (outgoing_share_target_map_.find(endpoint_id) !=
1239       outgoing_share_target_map_.end()) {
1240     return;
1241   }
1242 
1243   // Once we get the advertisement, the first thing to do is decrypt the
1244   // certificate.
1245   NearbyShareEncryptedMetadataKey encrypted_metadata_key(
1246       advertisement->salt, advertisement->encrypted_metadata_key);
1247   GetCertificateManager()->GetDecryptedPublicCertificate(
1248       std::move(encrypted_metadata_key),
1249       base::BindOnce(&NearbySharingServiceImpl::OnOutgoingDecryptedCertificate,
1250                      weak_ptr_factory_.GetWeakPtr(), endpoint_id,
1251                      std::move(advertisement)));
1252 }
1253 
OnOutgoingDecryptedCertificate(const std::string & endpoint_id,sharing::mojom::AdvertisementPtr advertisement,base::Optional<NearbyShareDecryptedPublicCertificate> certificate)1254 void NearbySharingServiceImpl::OnOutgoingDecryptedCertificate(
1255     const std::string& endpoint_id,
1256     sharing::mojom::AdvertisementPtr advertisement,
1257     base::Optional<NearbyShareDecryptedPublicCertificate> certificate) {
1258   // Check again for this endpoint id, to avoid race conditions.
1259   if (outgoing_share_target_map_.find(endpoint_id) !=
1260       outgoing_share_target_map_.end()) {
1261     return;
1262   }
1263 
1264   // The certificate provides the device name, in order to create a ShareTarget
1265   // to represent this remote device.
1266   base::Optional<ShareTarget> share_target = CreateShareTarget(
1267       endpoint_id, std::move(advertisement), std::move(certificate),
1268       /*is_incoming=*/false);
1269   if (!share_target) {
1270     NS_LOG(VERBOSE) << __func__
1271                     << ": Failed to convert advertisement to share target from "
1272                        "discovered advertisement. Ignoring endpoint.";
1273     return;
1274   }
1275 
1276   // Update the endpoint id for the share target.
1277   NS_LOG(VERBOSE) << __func__
1278                   << ": An endpoint has been discovered, with an advertisement "
1279                      "containing a valid share target.";
1280 
1281   // Notifies the user that we discovered a device.
1282   for (ShareTargetDiscoveredCallback& discovery_callback :
1283        foreground_send_discovery_callbacks_) {
1284     discovery_callback.OnShareTargetDiscovered(*share_target);
1285   }
1286   for (ShareTargetDiscoveredCallback& discovery_callback :
1287        background_send_discovery_callbacks_) {
1288     discovery_callback.OnShareTargetDiscovered(*share_target);
1289   }
1290 
1291   NS_LOG(VERBOSE) << __func__ << ": Reported OnShareTargetDiscovered "
1292                   << (base::Time::Now() - scanning_start_timestamp_);
1293 
1294   // TODO(crbug/1108348) CachingManager should cache known and non-external
1295   // share targets.
1296 }
1297 
IsBluetoothPresent() const1298 bool NearbySharingServiceImpl::IsBluetoothPresent() const {
1299   return bluetooth_adapter_.get() && bluetooth_adapter_->IsPresent();
1300 }
1301 
IsBluetoothPowered() const1302 bool NearbySharingServiceImpl::IsBluetoothPowered() const {
1303   return IsBluetoothPresent() && bluetooth_adapter_->IsPowered();
1304 }
1305 
HasAvailableConnectionMediums()1306 bool NearbySharingServiceImpl::HasAvailableConnectionMediums() {
1307   // Check if Wifi or Ethernet LAN is off.  Advertisements won't work, so
1308   // disable them, unless bluetooth is known to be enabled. Not all platforms
1309   // have bluetooth, so wifi LAN is a platform-agnostic check.
1310   net::NetworkChangeNotifier::ConnectionType connection_type =
1311       net::NetworkChangeNotifier::GetConnectionType();
1312   bool hasNetworkConnection =
1313       connection_type ==
1314           net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI ||
1315       connection_type ==
1316           net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET;
1317   return IsBluetoothPowered() || (kIsWifiLanSupported && hasNetworkConnection);
1318 }
1319 
InvalidateSurfaceState()1320 void NearbySharingServiceImpl::InvalidateSurfaceState() {
1321   InvalidateSendSurfaceState();
1322   InvalidateReceiveSurfaceState();
1323   if (ShouldStopNearbyProcess()) {
1324     // We need to debounce the call to shut down the process in case this state
1325     // is temporary (we don't want to the thrash the process). Any advertisment,
1326     // scanning or transfering will stop this timer from triggering.
1327     NS_LOG(INFO) << __func__
1328                  << ": Scheduling process shutdown if not needed in 15 seconds";
1329     // NOTE: Using base::Unretained is safe because if shutdown_pending_timer_
1330     // goes out of scope the timer will be canceled.
1331     process_shutdown_pending_timer_.Start(
1332         FROM_HERE, base::TimeDelta::FromSeconds(15),
1333         base::BindOnce(&NearbySharingServiceImpl::OnProcessShutdownTimerFired,
1334                        base::Unretained(this)));
1335   } else {
1336     process_shutdown_pending_timer_.Stop();
1337   }
1338 }
1339 
ShouldStopNearbyProcess()1340 bool NearbySharingServiceImpl::ShouldStopNearbyProcess() {
1341   // Nothing to do if we're shutting down the profile.
1342   if (!profile_)
1343     return false;
1344 
1345   // Cannot stop process without being the active profile.
1346   if (!process_manager_->IsActiveProfile(profile_))
1347     return false;
1348 
1349   // We're currently advertising.
1350   if (advertising_power_level_ != PowerLevel::kUnknown)
1351     return false;
1352 
1353   // We're currently discovering.
1354   if (is_scanning_)
1355     return false;
1356 
1357   // We're currently attempting to connect to a remote device.
1358   if (is_connecting_)
1359     return false;
1360 
1361   // We're currently sending or receiving a file.
1362   if (is_transferring_)
1363     return false;
1364 
1365   // We're not using NearbyConnections, should stop the process.
1366   return true;
1367 }
1368 
OnProcessShutdownTimerFired()1369 void NearbySharingServiceImpl::OnProcessShutdownTimerFired() {
1370   if (ShouldStopNearbyProcess()) {
1371     NS_LOG(INFO) << __func__
1372                  << ": Shutdown Process timer fired, shutting down process";
1373     process_manager_->StopProcess(profile_);
1374   }
1375 }
1376 
InvalidateSendSurfaceState()1377 void NearbySharingServiceImpl::InvalidateSendSurfaceState() {
1378   InvalidateScanningState();
1379   InvalidateFastInitiationAdvertising();
1380 }
1381 
InvalidateScanningState()1382 void NearbySharingServiceImpl::InvalidateScanningState() {
1383   // Nothing to do if we're shutting down the profile.
1384   if (!profile_)
1385     return;
1386 
1387   if (power_client_->IsSuspended()) {
1388     StopScanning();
1389     NS_LOG(VERBOSE) << __func__
1390                     << ": Stopping discovery because the system is suspended.";
1391     return;
1392   }
1393 
1394   if (!process_manager_->IsActiveProfile(profile_)) {
1395     NS_LOG(VERBOSE) << __func__
1396                     << ": Stopping discovery because profile was not active: "
1397                     << profile_->GetProfileUserName();
1398     StopScanning();
1399     return;
1400   }
1401 
1402   // Screen is off. Do no work.
1403   if (is_screen_locked_) {
1404     StopScanning();
1405     NS_LOG(VERBOSE) << __func__
1406                     << ": Stopping discovery because the screen is locked.";
1407     return;
1408   }
1409 
1410   if (!HasAvailableConnectionMediums()) {
1411     StopScanning();
1412     NS_LOG(VERBOSE)
1413         << __func__
1414         << ": Stopping scanning because both bluetooth and wifi LAN are "
1415            "disabled.";
1416     return;
1417   }
1418 
1419   // Nearby Sharing is disabled. Don't advertise.
1420   if (!settings_.GetEnabled()) {
1421     StopScanning();
1422     NS_LOG(VERBOSE)
1423         << __func__
1424         << ": Stopping discovery because Nearby Sharing is disabled.";
1425     return;
1426   }
1427 
1428   if (is_transferring_ || is_connecting_) {
1429     StopScanning();
1430     NS_LOG(VERBOSE)
1431         << __func__
1432         << ": Stopping discovery because we're currently in the midst of a "
1433            "transfer.";
1434     return;
1435   }
1436 
1437   if (!foreground_send_transfer_callbacks_.might_have_observers()) {
1438     StopScanning();
1439     NS_LOG(VERBOSE)
1440         << __func__
1441         << ": Stopping discovery because no scanning surface has been "
1442            "registered.";
1443     return;
1444   }
1445 
1446   process_shutdown_pending_timer_.Stop();
1447   // Screen is on, Bluetooth is enabled, and Nearby Sharing is enabled! Start
1448   // discovery.
1449   StartScanning();
1450 }
1451 
InvalidateFastInitiationAdvertising()1452 void NearbySharingServiceImpl::InvalidateFastInitiationAdvertising() {
1453   // Nothing to do if we're shutting down the profile.
1454   if (!profile_)
1455     return;
1456 
1457   if (power_client_->IsSuspended()) {
1458     StopFastInitiationAdvertising();
1459     NS_LOG(VERBOSE)
1460         << __func__
1461         << ": Stopping fast init advertising because the system is suspended.";
1462     return;
1463   }
1464 
1465   if (!process_manager_->IsActiveProfile(profile_)) {
1466     StopFastInitiationAdvertising();
1467     NS_LOG(VERBOSE)
1468         << __func__
1469         << ": Stopping fast init advertising because profile was not active: "
1470         << profile_->GetProfileUserName();
1471     return;
1472   }
1473 
1474   // Screen is off. Do no work.
1475   if (is_screen_locked_) {
1476     StopFastInitiationAdvertising();
1477     NS_LOG(VERBOSE)
1478         << __func__
1479         << ": Stopping fast init advertising because the screen is locked.";
1480     return;
1481   }
1482 
1483   if (!IsBluetoothPowered()) {
1484     StopFastInitiationAdvertising();
1485     NS_LOG(VERBOSE) << __func__
1486                     << ": Stopping fast init advertising because both "
1487                        "bluetooth is disabled.";
1488     return;
1489   }
1490 
1491   // Nearby Sharing is disabled. Don't fast init advertise.
1492   if (!settings_.GetEnabled()) {
1493     StopFastInitiationAdvertising();
1494     NS_LOG(VERBOSE) << __func__
1495                     << ": Stopping fast init advertising because Nearby "
1496                        "Sharing is disabled.";
1497     return;
1498   }
1499 
1500   if (!foreground_send_transfer_callbacks_.might_have_observers()) {
1501     StopFastInitiationAdvertising();
1502     NS_LOG(VERBOSE) << __func__
1503                     << ": Stopping fast init advertising because no send "
1504                        "surface is registered.";
1505     return;
1506   }
1507 
1508   if (fast_initiation_manager_) {
1509     NS_LOG(VERBOSE)
1510         << "Failed to advertise FastInitiation. Already advertising.";
1511     return;
1512   }
1513 
1514   process_shutdown_pending_timer_.Stop();
1515 
1516   StartFastInitiationAdvertising();
1517 }
1518 
InvalidateReceiveSurfaceState()1519 void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
1520   InvalidateAdvertisingState();
1521   // TODO(b/161889067) InvalidateFastInitScan();
1522 }
1523 
InvalidateAdvertisingState()1524 void NearbySharingServiceImpl::InvalidateAdvertisingState() {
1525   // Nothing to do if we're shutting down the profile.
1526   if (!profile_)
1527     return;
1528 
1529   if (power_client_->IsSuspended()) {
1530     StopAdvertising();
1531     NS_LOG(VERBOSE)
1532         << __func__
1533         << ": Stopping advertising because the system is suspended.";
1534     return;
1535   }
1536 
1537   if (!process_manager_->IsActiveProfile(profile_)) {
1538     NS_LOG(VERBOSE) << __func__
1539                     << ": Stopping advertising because profile was not active: "
1540                     << profile_->GetProfileUserName();
1541     StopAdvertising();
1542     return;
1543   }
1544 
1545   // Screen is off. Do no work.
1546   if (is_screen_locked_) {
1547     StopAdvertising();
1548     NS_LOG(VERBOSE) << __func__
1549                     << ": Stopping advertising because the screen is locked.";
1550     return;
1551   }
1552 
1553   if (!HasAvailableConnectionMediums()) {
1554     StopAdvertising();
1555     NS_LOG(VERBOSE)
1556         << __func__
1557         << ": Stopping advertising because both bluetooth and wifi LAN are "
1558            "disabled.";
1559     return;
1560   }
1561 
1562   // Nearby Sharing is disabled. Don't advertise.
1563   if (!settings_.GetEnabled()) {
1564     StopAdvertising();
1565     NS_LOG(VERBOSE)
1566         << __func__
1567         << ": Stopping advertising because Nearby Sharing is disabled.";
1568     return;
1569   }
1570 
1571   // We're scanning for other nearby devices. Don't advertise.
1572   if (is_scanning_) {
1573     StopAdvertising();
1574     NS_LOG(VERBOSE)
1575         << __func__
1576         << ": Stopping advertising because we're scanning for other devices.";
1577     return;
1578   }
1579 
1580   if (is_transferring_) {
1581     StopAdvertising();
1582     NS_LOG(VERBOSE)
1583         << __func__
1584         << ": Stopping advertising because we're currently in the midst of "
1585            "a transfer.";
1586     return;
1587   }
1588 
1589   if (!foreground_receive_callbacks_.might_have_observers() &&
1590       !background_receive_callbacks_.might_have_observers()) {
1591     StopAdvertising();
1592     NS_LOG(VERBOSE)
1593         << __func__
1594         << ": Stopping advertising because no receive surface is registered.";
1595     return;
1596   }
1597 
1598   if (!IsVisibleInBackground(settings_.GetVisibility()) &&
1599       !foreground_receive_callbacks_.might_have_observers()) {
1600     StopAdvertising();
1601     NS_LOG(VERBOSE)
1602         << __func__
1603         << ": Stopping advertising because no high power receive surface "
1604            "is registered and device is visible to NO_ONE.";
1605     return;
1606   }
1607 
1608   process_shutdown_pending_timer_.Stop();
1609 
1610   PowerLevel power_level;
1611   if (foreground_receive_callbacks_.might_have_observers()) {
1612     power_level = PowerLevel::kHighPower;
1613     // TODO(crbug/1100367) handle fast init
1614     // } else if (isFastInitDeviceNearby) {
1615     //   power_level = PowerLevel::kMediumPower;
1616   } else {
1617     power_level = PowerLevel::kLowPower;
1618   }
1619 
1620   DataUsage data_usage = settings_.GetDataUsage();
1621   if (advertising_power_level_ != PowerLevel::kUnknown) {
1622     if (power_level == advertising_power_level_) {
1623       NS_LOG(VERBOSE)
1624           << __func__
1625           << ": Failed to advertise because we're already advertising with "
1626              "power level "
1627           << PowerLevelToString(advertising_power_level_)
1628           << " and data usage preference " << data_usage;
1629       return;
1630     }
1631 
1632     StopAdvertising();
1633     NS_LOG(VERBOSE) << __func__ << ": Restart advertising with power level "
1634                     << PowerLevelToString(power_level)
1635                     << " and data usage preference " << data_usage;
1636   }
1637 
1638   base::Optional<std::string> device_name;
1639   if (foreground_receive_callbacks_.might_have_observers())
1640     device_name = local_device_data_manager_->GetDeviceName();
1641 
1642   // Starts advertising through Nearby Connections. Caller is expected to ensure
1643   // |listener| remains valid until StopAdvertising is called.
1644   base::Optional<std::vector<uint8_t>> endpoint_info =
1645       CreateEndpointInfo(device_name);
1646   if (!endpoint_info) {
1647     NS_LOG(VERBOSE) << __func__
1648                     << ": Unable to advertise since could not parse the "
1649                        "endpoint info from the advertisement.";
1650     return;
1651   }
1652 
1653   // TODO(crbug/1147652): The call to update the advertising interval is
1654   // removed to prevent a Bluez crash. We need to either reduce the global
1655   // advertising interval asynchronously and wait for the result or use the
1656   // updated API referenced in the bug which allows setting a per-advertisement
1657   // interval.
1658 
1659   nearby_connections_manager_->StartAdvertising(
1660       *endpoint_info,
1661       /*listener=*/this, power_level, data_usage,
1662       base::BindOnce(&NearbySharingServiceImpl::OnStartAdvertisingResult,
1663                      weak_ptr_factory_.GetWeakPtr(), device_name.has_value()));
1664 
1665   advertising_power_level_ = power_level;
1666   NS_LOG(VERBOSE) << __func__
1667                   << ": StartAdvertising requested over Nearby Connections: "
1668                   << " power level: " << PowerLevelToString(power_level)
1669                   << " visibility: " << settings_.GetVisibility()
1670                   << " data usage: " << data_usage << " device name: "
1671                   << device_name.value_or("** no device name **");
1672 
1673   ScheduleRotateBackgroundAdvertisementTimer();
1674 }
1675 
StopAdvertising()1676 void NearbySharingServiceImpl::StopAdvertising() {
1677   SetInHighVisibility(false);
1678   if (advertising_power_level_ == PowerLevel::kUnknown) {
1679     NS_LOG(VERBOSE)
1680         << __func__
1681         << ": Failed to stop advertising because we weren't advertising";
1682     return;
1683   }
1684 
1685   nearby_connections_manager_->StopAdvertising();
1686   advertising_power_level_ = PowerLevel::kUnknown;
1687 
1688   // TODO(crbug/1147652): The call to update the advertising interval is
1689   // removed to prevent a Bluez crash. We need to either reduce the global
1690   // advertising interval asynchronously and wait for the result or use the
1691   // updated API referenced in the bug which allows setting a per-advertisement
1692   // interval.
1693 
1694   NS_LOG(VERBOSE) << __func__ << ": Advertising has stopped";
1695 }
1696 
StartScanning()1697 void NearbySharingServiceImpl::StartScanning() {
1698   DCHECK(profile_);
1699   DCHECK(!power_client_->IsSuspended());
1700   DCHECK(settings_.GetEnabled());
1701   DCHECK(!is_screen_locked_);
1702   DCHECK(HasAvailableConnectionMediums());
1703   DCHECK(foreground_send_transfer_callbacks_.might_have_observers());
1704 
1705   if (is_scanning_) {
1706     NS_LOG(VERBOSE) << __func__
1707                     << ": Failed to scan because we're currently scanning.";
1708     return;
1709   }
1710 
1711   scanning_start_timestamp_ = base::Time::Now();
1712   is_scanning_ = true;
1713   InvalidateReceiveSurfaceState();
1714 
1715   ClearOutgoingShareTargetInfoMap();
1716 
1717   nearby_connections_manager_->StartDiscovery(
1718       /*listener=*/this, settings_.GetDataUsage(),
1719       base::BindOnce([](NearbyConnectionsManager::ConnectionsStatus status) {
1720         NS_LOG(VERBOSE) << __func__
1721                         << ": Scanning start attempted over Nearby Connections "
1722                            "with result "
1723                         << status;
1724       }));
1725 
1726   InvalidateSendSurfaceState();
1727   NS_LOG(VERBOSE) << __func__ << ": Scanning has started";
1728 }
1729 
StopScanning()1730 NearbySharingService::StatusCodes NearbySharingServiceImpl::StopScanning() {
1731   if (!is_scanning_) {
1732     NS_LOG(VERBOSE) << __func__
1733                     << ": Failed to stop scanning because weren't scanning.";
1734     return StatusCodes::kStatusAlreadyStopped;
1735   }
1736 
1737   nearby_connections_manager_->StopDiscovery();
1738   is_scanning_ = false;
1739 
1740   // Note: We don't know if we stopped scanning in preparation to send a file,
1741   // or we stopped because the user left the page. We'll invalidate after a
1742   // short delay.
1743   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
1744       FROM_HERE,
1745       base::BindOnce(&NearbySharingServiceImpl::InvalidateSurfaceState,
1746                      weak_ptr_factory_.GetWeakPtr()),
1747       kInvalidateDelay);
1748 
1749   NS_LOG(VERBOSE) << __func__ << ": Scanning has stopped.";
1750   return StatusCodes::kOk;
1751 }
1752 
ScheduleRotateBackgroundAdvertisementTimer()1753 void NearbySharingServiceImpl::ScheduleRotateBackgroundAdvertisementTimer() {
1754   uint64_t delayRangeMilliseconds = base::checked_cast<uint64_t>(
1755       kBackgroundAdvertisementRotationDelayMax.InMilliseconds() -
1756       kBackgroundAdvertisementRotationDelayMin.InMilliseconds());
1757   uint64_t delayMilliseconds =
1758       base::RandGenerator(delayRangeMilliseconds) +
1759       base::checked_cast<uint64_t>(
1760           kBackgroundAdvertisementRotationDelayMin.InMilliseconds());
1761   rotate_background_advertisement_timer_.Start(
1762       FROM_HERE,
1763       base::TimeDelta::FromMilliseconds(
1764           base::checked_cast<uint64_t>(delayMilliseconds)),
1765       base::BindOnce(
1766           &NearbySharingServiceImpl::OnRotateBackgroundAdvertisementTimerFired,
1767           weak_ptr_factory_.GetWeakPtr()));
1768 }
1769 
OnRotateBackgroundAdvertisementTimerFired()1770 void NearbySharingServiceImpl::OnRotateBackgroundAdvertisementTimerFired() {
1771   if (foreground_receive_callbacks_.might_have_observers()) {
1772     ScheduleRotateBackgroundAdvertisementTimer();
1773   } else {
1774     StopAdvertising();
1775     InvalidateSurfaceState();
1776   }
1777 }
1778 
RemoveOutgoingShareTargetWithEndpointId(const std::string & endpoint_id)1779 void NearbySharingServiceImpl::RemoveOutgoingShareTargetWithEndpointId(
1780     const std::string& endpoint_id) {
1781   auto it = outgoing_share_target_map_.find(endpoint_id);
1782   if (it == outgoing_share_target_map_.end())
1783     return;
1784 
1785   NS_LOG(VERBOSE) << __func__ << ": Removing (endpoint_id=" << it->first
1786                   << ", share_target.id=" << it->second.id
1787                   << ") from outgoing share target map";
1788   ShareTarget share_target = std::move(it->second);
1789   outgoing_share_target_map_.erase(it);
1790 
1791   auto info_it = outgoing_share_target_info_map_.find(share_target.id);
1792   if (info_it != outgoing_share_target_info_map_.end()) {
1793     file_handler_.ReleaseFilePayloads(info_it->second.ExtractFilePayloads());
1794     outgoing_share_target_info_map_.erase(info_it);
1795   }
1796 
1797   for (ShareTargetDiscoveredCallback& discovery_callback :
1798        foreground_send_discovery_callbacks_) {
1799     discovery_callback.OnShareTargetLost(share_target);
1800   }
1801   for (ShareTargetDiscoveredCallback& discovery_callback :
1802        background_send_discovery_callbacks_) {
1803     discovery_callback.OnShareTargetLost(share_target);
1804   }
1805 
1806   NS_LOG(VERBOSE) << __func__ << ": Reported OnShareTargetLost";
1807 }
1808 
OnTransferComplete()1809 void NearbySharingServiceImpl::OnTransferComplete() {
1810   bool was_sending_files = is_sending_files_;
1811   is_receiving_files_ = false;
1812   is_transferring_ = false;
1813   is_sending_files_ = false;
1814 
1815   NS_LOG(VERBOSE) << __func__
1816                   << ": NearbySharing state change transfer finished";
1817   // Files transfer is done! Receivers can immediately cancel, but senders
1818   // should add a short delay to ensure the final in-flight packet(s) make
1819   // it to the remote device.
1820   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
1821       FROM_HERE,
1822       base::BindOnce(&NearbySharingServiceImpl::InvalidateSurfaceState,
1823                      weak_ptr_factory_.GetWeakPtr()),
1824       was_sending_files ? kInvalidateSurfaceStateDelayAfterTransferDone
1825                         : base::TimeDelta());
1826 }
1827 
OnTransferStarted(bool is_incoming)1828 void NearbySharingServiceImpl::OnTransferStarted(bool is_incoming) {
1829   is_transferring_ = true;
1830   if (is_incoming) {
1831     is_receiving_files_ = true;
1832   } else {
1833     is_sending_files_ = true;
1834   }
1835   InvalidateSurfaceState();
1836 }
1837 
ReceivePayloads(ShareTarget share_target,StatusCodesCallback status_codes_callback)1838 void NearbySharingServiceImpl::ReceivePayloads(
1839     ShareTarget share_target,
1840     StatusCodesCallback status_codes_callback) {
1841   DCHECK(profile_);
1842   mutual_acceptance_timeout_alarm_.Cancel();
1843 
1844   base::FilePath download_path =
1845       DownloadPrefs::FromDownloadManager(
1846           content::BrowserContext::GetDownloadManager(profile_))
1847           ->DownloadPath();
1848 
1849   // Register payload path for all valid file payloads.
1850   base::flat_map<int64_t, base::FilePath> valid_file_payloads;
1851   for (auto& file : share_target.file_attachments) {
1852     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(file.id());
1853     if (!payload_id) {
1854       NS_LOG(WARNING)
1855           << __func__
1856           << ": Failed to register payload path for attachment id - "
1857           << file.id();
1858       continue;
1859     }
1860 
1861     base::FilePath file_path = download_path.AppendASCII(file.file_name());
1862     valid_file_payloads.emplace(file.id(), std::move(file_path));
1863   }
1864 
1865   auto aggregated_success = std::make_unique<bool>(true);
1866   bool* aggregated_success_ptr = aggregated_success.get();
1867 
1868   if (valid_file_payloads.empty()) {
1869     OnPayloadPathsRegistered(share_target, std::move(aggregated_success),
1870                              std::move(status_codes_callback));
1871     return;
1872   }
1873 
1874   auto all_paths_registered_callback = base::BarrierClosure(
1875       valid_file_payloads.size(),
1876       base::BindOnce(&NearbySharingServiceImpl::OnPayloadPathsRegistered,
1877                      weak_ptr_factory_.GetWeakPtr(), share_target,
1878                      std::move(aggregated_success),
1879                      std::move(status_codes_callback)));
1880 
1881   for (const auto& payload : valid_file_payloads) {
1882     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(payload.first);
1883     DCHECK(payload_id);
1884 
1885     file_handler_.GetUniquePath(
1886         payload.second,
1887         base::BindOnce(
1888             &NearbySharingServiceImpl::OnUniquePathFetched,
1889             weak_ptr_factory_.GetWeakPtr(), payload.first, *payload_id,
1890             base::BindOnce(
1891                 &NearbySharingServiceImpl::OnPayloadPathRegistered,
1892                 weak_ptr_factory_.GetWeakPtr(),
1893                 base::ScopedClosureRunner(all_paths_registered_callback),
1894                 aggregated_success_ptr)));
1895   }
1896 }
1897 
SendPayloads(const ShareTarget & share_target)1898 NearbySharingService::StatusCodes NearbySharingServiceImpl::SendPayloads(
1899     const ShareTarget& share_target) {
1900   NS_LOG(VERBOSE) << __func__ << ": Preparing to send payloads to "
1901                   << share_target.device_name;
1902   ShareTargetInfo* info = GetShareTargetInfo(share_target);
1903   if (!info || !info->connection()) {
1904     NS_LOG(WARNING) << "Failed to send payload due to missing connection.";
1905     return StatusCodes::kOutOfOrderApiCall;
1906   }
1907   if (!info->transfer_update_callback()) {
1908     NS_LOG(WARNING) << "Failed to send payload due to missing transfer update "
1909                        "callback. Disconnecting.";
1910     info->connection()->Close();
1911     return StatusCodes::kOutOfOrderApiCall;
1912   }
1913 
1914   info->transfer_update_callback()->OnTransferUpdate(
1915       share_target,
1916       TransferMetadataBuilder()
1917           .set_token(info->token())
1918           .set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
1919           .build());
1920 
1921   if (!info->endpoint_id()) {
1922     info->transfer_update_callback()->OnTransferUpdate(
1923         share_target, TransferMetadataBuilder()
1924                           .set_status(TransferMetadata::Status::kFailed)
1925                           .build());
1926     info->connection()->Close();
1927     NS_LOG(WARNING) << "Failed to send payload due to missing endpoint id.";
1928     return StatusCodes::kOutOfOrderApiCall;
1929   }
1930 
1931   ReceiveConnectionResponse(share_target);
1932   return StatusCodes::kOk;
1933 }
1934 
OnUniquePathFetched(int64_t attachment_id,int64_t payload_id,base::OnceCallback<void (location::nearby::connections::mojom::Status)> callback,base::FilePath path)1935 void NearbySharingServiceImpl::OnUniquePathFetched(
1936     int64_t attachment_id,
1937     int64_t payload_id,
1938     base::OnceCallback<void(location::nearby::connections::mojom::Status)>
1939         callback,
1940     base::FilePath path) {
1941   attachment_info_map_[attachment_id].file_path = path;
1942   nearby_connections_manager_->RegisterPayloadPath(payload_id, path,
1943                                                    std::move(callback));
1944 }
1945 
OnPayloadPathRegistered(base::ScopedClosureRunner closure_runner,bool * aggregated_success,location::nearby::connections::mojom::Status status)1946 void NearbySharingServiceImpl::OnPayloadPathRegistered(
1947     base::ScopedClosureRunner closure_runner,
1948     bool* aggregated_success,
1949     location::nearby::connections::mojom::Status status) {
1950   if (status != location::nearby::connections::mojom::Status::kSuccess)
1951     *aggregated_success = false;
1952 }
1953 
OnPayloadPathsRegistered(const ShareTarget & share_target,std::unique_ptr<bool> aggregated_success,StatusCodesCallback status_codes_callback)1954 void NearbySharingServiceImpl::OnPayloadPathsRegistered(
1955     const ShareTarget& share_target,
1956     std::unique_ptr<bool> aggregated_success,
1957     StatusCodesCallback status_codes_callback) {
1958   DCHECK(aggregated_success);
1959   if (!*aggregated_success) {
1960     NS_LOG(WARNING)
1961         << __func__
1962         << ": Not all payload paths could be registered successfully.";
1963     std::move(status_codes_callback).Run(StatusCodes::kError);
1964     return;
1965   }
1966 
1967   ShareTargetInfo* info = GetShareTargetInfo(share_target);
1968   if (!info || !info->connection()) {
1969     NS_LOG(WARNING) << __func__ << ": Accept invoked for unknown share target";
1970     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
1971     return;
1972   }
1973   NearbyConnection* connection = info->connection();
1974 
1975   if (!info->transfer_update_callback()) {
1976     NS_LOG(WARNING) << __func__
1977                     << ": Accept invoked for share target without transfer "
1978                        "update callback. Disconnecting.";
1979     connection->Close();
1980     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
1981     return;
1982   }
1983 
1984   info->set_payload_tracker(std::make_unique<PayloadTracker>(
1985       share_target, attachment_info_map_,
1986       base::BindRepeating(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
1987                           weak_ptr_factory_.GetWeakPtr())));
1988 
1989   // Register status listener for all payloads.
1990   for (int64_t attachment_id : share_target.GetAttachmentIds()) {
1991     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id);
1992     if (!payload_id) {
1993       NS_LOG(WARNING) << __func__
1994                       << ": Failed to retrieve payload for attachment id - "
1995                       << attachment_id;
1996       continue;
1997     }
1998 
1999     NS_LOG(VERBOSE) << __func__
2000                     << ": Started listening for progress on payload - "
2001                     << *payload_id;
2002 
2003     nearby_connections_manager_->RegisterPayloadStatusListener(
2004         *payload_id, info->payload_tracker());
2005 
2006     NS_LOG(VERBOSE) << __func__
2007                     << ": Accepted incoming files from share target - "
2008                     << share_target.device_name;
2009   }
2010 
2011   WriteResponse(*connection, sharing::nearby::ConnectionResponseFrame::ACCEPT);
2012   NS_LOG(VERBOSE) << __func__ << ": Successfully wrote response frame";
2013 
2014   info->transfer_update_callback()->OnTransferUpdate(
2015       share_target,
2016       TransferMetadataBuilder()
2017           .set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
2018           .set_token(info->token())
2019           .build());
2020 
2021   base::Optional<std::string> endpoint_id = info->endpoint_id();
2022   if (endpoint_id) {
2023     nearby_connections_manager_->UpgradeBandwidth(*endpoint_id);
2024   } else {
2025     NS_LOG(WARNING) << __func__
2026                     << ": Failed to initiate bandwidth upgrade. No endpoint_id "
2027                        "found for target - "
2028                     << share_target.device_name;
2029     std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
2030     return;
2031   }
2032 
2033   std::move(status_codes_callback).Run(StatusCodes::kOk);
2034 }
2035 
OnOutgoingConnection(const ShareTarget & share_target,NearbyConnection * connection)2036 void NearbySharingServiceImpl::OnOutgoingConnection(
2037     const ShareTarget& share_target,
2038     NearbyConnection* connection) {
2039   OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target);
2040   if (!info || !info->endpoint_id() || !connection) {
2041     NS_LOG(WARNING) << __func__
2042                     << ": Failed to initate connection to share target "
2043                     << share_target.device_name;
2044     if (info->transfer_update_callback()) {
2045       info->transfer_update_callback()->OnTransferUpdate(
2046           share_target, TransferMetadataBuilder()
2047                             .set_status(TransferMetadata::Status::kFailed)
2048                             .build());
2049     }
2050     return;
2051   }
2052 
2053   info->set_connection(connection);
2054 
2055   connection->SetDisconnectionListener(base::BindOnce(
2056       &NearbySharingServiceImpl::OnOutgoingConnectionDisconnected,
2057       weak_ptr_factory_.GetWeakPtr(), share_target));
2058 
2059   base::Optional<std::string> four_digit_token =
2060       ToFourDigitString(nearby_connections_manager_->GetRawAuthenticationToken(
2061           *info->endpoint_id()));
2062 
2063   RunPairedKeyVerification(
2064       share_target, *info->endpoint_id(),
2065       base::BindOnce(
2066           &NearbySharingServiceImpl::OnOutgoingConnectionKeyVerificationDone,
2067           weak_ptr_factory_.GetWeakPtr(), share_target,
2068           std::move(four_digit_token)));
2069 }
2070 
SendIntroduction(const ShareTarget & share_target,base::Optional<std::string> four_digit_token)2071 void NearbySharingServiceImpl::SendIntroduction(
2072     const ShareTarget& share_target,
2073     base::Optional<std::string> four_digit_token) {
2074   // We successfully connected! Now lets build up Payloads for all the files we
2075   // want to send them. We won't send any just yet, but we'll send the Payload
2076   // IDs in our our introduction frame so that they know what to expect if they
2077   // accept.
2078   NS_LOG(VERBOSE) << __func__ << ": Preparing to send introduction to "
2079                   << share_target.device_name;
2080 
2081   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2082   if (!info || !info->connection()) {
2083     NS_LOG(WARNING) << __func__ << ": No NearbyConnection tied to "
2084                     << share_target.device_name;
2085     return;
2086   }
2087   NearbyConnection* connection = info->connection();
2088 
2089   if (!info->transfer_update_callback()) {
2090     connection->Close();
2091     NS_LOG(WARNING) << __func__
2092                     << ": No transfer update callback, disconnecting.";
2093     return;
2094   }
2095 
2096   if (!foreground_send_transfer_callbacks_.might_have_observers() &&
2097       !background_send_transfer_callbacks_.might_have_observers()) {
2098     connection->Close();
2099     NS_LOG(WARNING) << __func__ << ": No transfer callbacks, disconnecting.";
2100     return;
2101   }
2102 
2103   // Build the introduction.
2104   auto introduction = std::make_unique<sharing::nearby::IntroductionFrame>();
2105   NS_LOG(VERBOSE) << __func__ << ": Sending attachments to "
2106                   << share_target.device_name;
2107 
2108   // Write introduction of file payloads.
2109   for (const auto& file : share_target.file_attachments) {
2110     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(file.id());
2111     if (!payload_id) {
2112       NS_LOG(VERBOSE) << __func__ << ": Skipping unknown file attachment";
2113       continue;
2114     }
2115     auto* file_metadata = introduction->add_file_metadata();
2116     file_metadata->set_id(file.id());
2117     file_metadata->set_name(file.file_name());
2118     file_metadata->set_payload_id(*payload_id);
2119     file_metadata->set_type(sharing::ConvertFileMetadataType(file.type()));
2120     file_metadata->set_mime_type(file.mime_type());
2121     file_metadata->set_size(file.size());
2122   }
2123 
2124   // Write introduction of text payloads.
2125   for (const auto& text : share_target.text_attachments) {
2126     base::Optional<int64_t> payload_id = GetAttachmentPayloadId(text.id());
2127     if (!payload_id) {
2128       NS_LOG(VERBOSE) << __func__ << ": Skipping unknown text attachment";
2129       continue;
2130     }
2131     auto* text_metadata = introduction->add_text_metadata();
2132     text_metadata->set_id(text.id());
2133     text_metadata->set_text_title(text.text_title());
2134     text_metadata->set_type(sharing::ConvertTextMetadataType(text.type()));
2135     text_metadata->set_size(text.size());
2136     text_metadata->set_payload_id(*payload_id);
2137   }
2138 
2139   if (introduction->file_metadata_size() == 0 &&
2140       introduction->text_metadata_size() == 0) {
2141     NS_LOG(WARNING) << __func__
2142                     << ": No payloads tied to transfer, disconnecting.";
2143     info->transfer_update_callback()->OnTransferUpdate(
2144         share_target, TransferMetadataBuilder()
2145                           .set_status(TransferMetadata::Status::kFailed)
2146                           .build());
2147     connection->Close();
2148     return;
2149   }
2150 
2151   // Write the introduction to the remote device.
2152   sharing::nearby::Frame frame;
2153   frame.set_version(sharing::nearby::Frame::V1);
2154   sharing::nearby::V1Frame* v1_frame = frame.mutable_v1();
2155   v1_frame->set_type(sharing::nearby::V1Frame::INTRODUCTION);
2156   v1_frame->set_allocated_introduction(introduction.release());
2157 
2158   std::vector<uint8_t> data(frame.ByteSize());
2159   frame.SerializeToArray(data.data(), frame.ByteSize());
2160   connection->Write(std::move(data));
2161 
2162   // We've successfully written the introduction, so we now have to wait for the
2163   // remote side to accept.
2164   NS_LOG(VERBOSE) << __func__ << ": Successfully wrote the introduction frame";
2165 
2166   mutual_acceptance_timeout_alarm_.Reset(base::BindOnce(
2167       &NearbySharingServiceImpl::OnOutgoingMutualAcceptanceTimeout,
2168       weak_ptr_factory_.GetWeakPtr(), share_target));
2169 
2170   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
2171       FROM_HERE, base::BindOnce(mutual_acceptance_timeout_alarm_.callback()),
2172       kReadResponseFrameTimeout);
2173 
2174   info->transfer_update_callback()->OnTransferUpdate(
2175       share_target,
2176       TransferMetadataBuilder()
2177           .set_status(TransferMetadata::Status::kAwaitingLocalConfirmation)
2178           .set_token(four_digit_token)
2179           .build());
2180 }
2181 
CreatePayloads(ShareTarget share_target,base::OnceCallback<void (ShareTarget,bool)> callback)2182 void NearbySharingServiceImpl::CreatePayloads(
2183     ShareTarget share_target,
2184     base::OnceCallback<void(ShareTarget, bool)> callback) {
2185   OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target);
2186   if (!info || !share_target.has_attachments()) {
2187     std::move(callback).Run(std::move(share_target), /*success=*/false);
2188     return;
2189   }
2190 
2191   if (!info->file_payloads().empty() || !info->text_payloads().empty()) {
2192     // We may have already created the payloads in the case of retry, so we can
2193     // skip this step.
2194     std::move(callback).Run(std::move(share_target), /*success=*/false);
2195     return;
2196   }
2197 
2198   info->set_text_payloads(CreateTextPayloads(share_target.text_attachments));
2199   if (share_target.file_attachments.empty()) {
2200     std::move(callback).Run(std::move(share_target), /*success=*/true);
2201     return;
2202   }
2203 
2204   std::vector<base::FilePath> file_paths;
2205   for (const FileAttachment& attachment : share_target.file_attachments) {
2206     if (!attachment.file_path()) {
2207       NS_LOG(WARNING) << __func__ << ": Got file attachment without path";
2208       std::move(callback).Run(std::move(share_target), /*success=*/false);
2209       return;
2210     }
2211     file_paths.push_back(*attachment.file_path());
2212   }
2213 
2214   file_handler_.OpenFiles(
2215       std::move(file_paths),
2216       base::BindOnce(&NearbySharingServiceImpl::OnOpenFiles,
2217                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target),
2218                      std::move(callback)));
2219 }
2220 
OnCreatePayloads(std::vector<uint8_t> endpoint_info,ShareTarget share_target,bool success)2221 void NearbySharingServiceImpl::OnCreatePayloads(
2222     std::vector<uint8_t> endpoint_info,
2223     ShareTarget share_target,
2224     bool success) {
2225   OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target);
2226   bool has_payloads = info && (!info->text_payloads().empty() ||
2227                                !info->file_payloads().empty());
2228   if (!success || !has_payloads || !info->endpoint_id()) {
2229     NS_LOG(WARNING) << __func__
2230                     << ": Failed to send file to remote ShareTarget. Failed to "
2231                        "create payloads.";
2232     if (info && info->transfer_update_callback()) {
2233       info->transfer_update_callback()->OnTransferUpdate(
2234           share_target,
2235           TransferMetadataBuilder()
2236               .set_status(TransferMetadata::Status::kMediaUnavailable)
2237               .build());
2238     }
2239     return;
2240   }
2241 
2242   base::Optional<std::vector<uint8_t>> bluetooth_mac_address =
2243       GetBluetoothMacAddress(share_target);
2244 
2245   DataUsage adjusted_data_usage = CheckFileSizeForDataUsagePreference(
2246       settings_.GetDataUsage(), share_target);
2247 
2248   // TODO(crbug.com/1111458): Add preferred transfer type.
2249   nearby_connections_manager_->Connect(
2250       std::move(endpoint_info), *info->endpoint_id(),
2251       std::move(bluetooth_mac_address), adjusted_data_usage,
2252       base::BindOnce(&NearbySharingServiceImpl::OnOutgoingConnection,
2253                      weak_ptr_factory_.GetWeakPtr(), share_target));
2254 }
2255 
OnOpenFiles(ShareTarget share_target,base::OnceCallback<void (ShareTarget,bool)> callback,std::vector<NearbyFileHandler::FileInfo> files)2256 void NearbySharingServiceImpl::OnOpenFiles(
2257     ShareTarget share_target,
2258     base::OnceCallback<void(ShareTarget, bool)> callback,
2259     std::vector<NearbyFileHandler::FileInfo> files) {
2260   OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target);
2261   if (!info || files.size() != share_target.file_attachments.size()) {
2262     std::move(callback).Run(std::move(share_target), /*success=*/false);
2263     return;
2264   }
2265 
2266   std::vector<location::nearby::connections::mojom::PayloadPtr> payloads;
2267   payloads.reserve(files.size());
2268 
2269   for (size_t i = 0; i < files.size(); ++i) {
2270     FileAttachment& attachment = share_target.file_attachments[i];
2271     attachment.set_size(files[i].size);
2272     base::File& file = files[i].file;
2273     int64_t payload_id = GeneratePayloadId();
2274     SetAttachmentPayloadId(attachment, payload_id);
2275     payloads.push_back(location::nearby::connections::mojom::Payload::New(
2276         payload_id,
2277         location::nearby::connections::mojom::PayloadContent::NewFile(
2278             location::nearby::connections::mojom::FilePayload::New(
2279                 std::move(file)))));
2280   }
2281 
2282   info->set_file_payloads(std::move(payloads));
2283   std::move(callback).Run(std::move(share_target), /*success=*/true);
2284 }
2285 
2286 std::vector<location::nearby::connections::mojom::PayloadPtr>
CreateTextPayloads(const std::vector<TextAttachment> & attachments)2287 NearbySharingServiceImpl::CreateTextPayloads(
2288     const std::vector<TextAttachment>& attachments) {
2289   std::vector<location::nearby::connections::mojom::PayloadPtr> payloads;
2290   payloads.reserve(attachments.size());
2291   for (const TextAttachment& attachment : attachments) {
2292     const std::string& body = attachment.text_body();
2293     std::vector<uint8_t> bytes(body.begin(), body.end());
2294 
2295     int64_t payload_id = GeneratePayloadId();
2296     SetAttachmentPayloadId(attachment, payload_id);
2297     payloads.push_back(location::nearby::connections::mojom::Payload::New(
2298         payload_id,
2299         location::nearby::connections::mojom::PayloadContent::NewBytes(
2300             location::nearby::connections::mojom::BytesPayload::New(
2301                 std::move(bytes)))));
2302   }
2303   return payloads;
2304 }
2305 
WriteResponse(NearbyConnection & connection,sharing::nearby::ConnectionResponseFrame::Status status)2306 void NearbySharingServiceImpl::WriteResponse(
2307     NearbyConnection& connection,
2308     sharing::nearby::ConnectionResponseFrame::Status status) {
2309   sharing::nearby::Frame frame;
2310   frame.set_version(sharing::nearby::Frame::V1);
2311   sharing::nearby::V1Frame* v1_frame = frame.mutable_v1();
2312   v1_frame->set_type(sharing::nearby::V1Frame::RESPONSE);
2313   v1_frame->mutable_connection_response()->set_status(status);
2314 
2315   std::vector<uint8_t> data(frame.ByteSize());
2316   frame.SerializeToArray(data.data(), frame.ByteSize());
2317 
2318   connection.Write(std::move(data));
2319 }
2320 
WriteCancel(NearbyConnection & connection)2321 void NearbySharingServiceImpl::WriteCancel(NearbyConnection& connection) {
2322   NS_LOG(INFO) << __func__ << ": Writing cancel frame.";
2323 
2324   sharing::nearby::Frame frame;
2325   frame.set_version(sharing::nearby::Frame::V1);
2326   sharing::nearby::V1Frame* v1_frame = frame.mutable_v1();
2327   v1_frame->set_type(sharing::nearby::V1Frame::CANCEL);
2328 
2329   std::vector<uint8_t> data(frame.ByteSize());
2330   frame.SerializeToArray(data.data(), frame.ByteSize());
2331 
2332   connection.Write(std::move(data));
2333 }
2334 
Fail(const ShareTarget & share_target,TransferMetadata::Status status)2335 void NearbySharingServiceImpl::Fail(const ShareTarget& share_target,
2336                                     TransferMetadata::Status status) {
2337   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2338   if (!info || !info->connection()) {
2339     NS_LOG(WARNING) << __func__ << ": Fail invoked for unknown share target.";
2340     return;
2341   }
2342   NearbyConnection* connection = info->connection();
2343 
2344   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
2345       FROM_HERE,
2346       base::BindOnce(&NearbySharingServiceImpl::CloseConnection,
2347                      weak_ptr_factory_.GetWeakPtr(), share_target),
2348       kIncomingRejectionDelay);
2349 
2350   connection->SetDisconnectionListener(
2351       base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
2352                      weak_ptr_factory_.GetWeakPtr(), share_target));
2353 
2354   // Send response to remote device.
2355   sharing::nearby::ConnectionResponseFrame::Status response_status;
2356   switch (status) {
2357     case TransferMetadata::Status::kNotEnoughSpace:
2358       response_status =
2359           sharing::nearby::ConnectionResponseFrame::NOT_ENOUGH_SPACE;
2360       break;
2361 
2362     case TransferMetadata::Status::kUnsupportedAttachmentType:
2363       response_status =
2364           sharing::nearby::ConnectionResponseFrame::UNSUPPORTED_ATTACHMENT_TYPE;
2365       break;
2366 
2367     case TransferMetadata::Status::kTimedOut:
2368       response_status = sharing::nearby::ConnectionResponseFrame::TIMED_OUT;
2369       break;
2370 
2371     default:
2372       response_status = sharing::nearby::ConnectionResponseFrame::UNKNOWN;
2373       break;
2374   }
2375 
2376   WriteResponse(*connection, response_status);
2377 
2378   if (info->transfer_update_callback()) {
2379     info->transfer_update_callback()->OnTransferUpdate(
2380         share_target, TransferMetadataBuilder().set_status(status).build());
2381   }
2382 }
2383 
OnIncomingAdvertisementDecoded(const std::string & endpoint_id,ShareTarget placeholder_share_target,sharing::mojom::AdvertisementPtr advertisement)2384 void NearbySharingServiceImpl::OnIncomingAdvertisementDecoded(
2385     const std::string& endpoint_id,
2386     ShareTarget placeholder_share_target,
2387     sharing::mojom::AdvertisementPtr advertisement) {
2388   NearbyConnection* connection = GetConnection(placeholder_share_target);
2389   if (!connection) {
2390     NS_LOG(VERBOSE) << __func__ << ": Invalid connection for endoint id - "
2391                     << endpoint_id;
2392     return;
2393   }
2394 
2395   if (!advertisement) {
2396     NS_LOG(VERBOSE) << __func__
2397                     << "Failed to parse incoming connection from endpoint - "
2398                     << endpoint_id << ", disconnecting.";
2399     connection->Close();
2400     return;
2401   }
2402 
2403   NearbyShareEncryptedMetadataKey encrypted_metadata_key(
2404       advertisement->salt, advertisement->encrypted_metadata_key);
2405   GetCertificateManager()->GetDecryptedPublicCertificate(
2406       std::move(encrypted_metadata_key),
2407       base::BindOnce(&NearbySharingServiceImpl::OnIncomingDecryptedCertificate,
2408                      weak_ptr_factory_.GetWeakPtr(), endpoint_id,
2409                      std::move(advertisement),
2410                      std::move(placeholder_share_target)));
2411 }
2412 
OnIncomingTransferUpdate(const ShareTarget & share_target,const TransferMetadata & metadata)2413 void NearbySharingServiceImpl::OnIncomingTransferUpdate(
2414     const ShareTarget& share_target,
2415     const TransferMetadata& metadata) {
2416   NS_LOG(VERBOSE) << __func__ << ": Nearby Share service: "
2417                   << "Incoming transfer update for share target with ID "
2418                   << share_target.id << ": "
2419                   << TransferMetadata::StatusToString(metadata.status());
2420   if (metadata.status() != TransferMetadata::Status::kCancelled &&
2421       metadata.status() != TransferMetadata::Status::kRejected) {
2422     last_incoming_metadata_ =
2423         std::make_pair(share_target, TransferMetadataBuilder::Clone(metadata)
2424                                          .set_is_original(false)
2425                                          .build());
2426   } else {
2427     last_incoming_metadata_ = base::nullopt;
2428   }
2429 
2430   if (metadata.is_final_status()) {
2431     RecordNearbyShareTransferCompletionStatusMetric(
2432         /*is_incoming=*/true, share_target.type, metadata.status());
2433     OnTransferComplete();
2434     if (metadata.status() != TransferMetadata::Status::kComplete) {
2435       // For any type of failure, lets make sure any pending files get cleaned
2436       // up.
2437       RemoveIncomingPayloads(share_target);
2438     }
2439   } else if (metadata.status() ==
2440              TransferMetadata::Status::kAwaitingLocalConfirmation) {
2441     OnTransferStarted(/*is_incoming=*/true);
2442   }
2443 
2444   base::ObserverList<TransferUpdateCallback>& transfer_callbacks =
2445       foreground_receive_callbacks_.might_have_observers()
2446           ? foreground_receive_callbacks_
2447           : background_receive_callbacks_;
2448 
2449   for (TransferUpdateCallback& callback : transfer_callbacks) {
2450     callback.OnTransferUpdate(share_target, metadata);
2451   }
2452 }
2453 
OnOutgoingTransferUpdate(const ShareTarget & share_target,const TransferMetadata & metadata)2454 void NearbySharingServiceImpl::OnOutgoingTransferUpdate(
2455     const ShareTarget& share_target,
2456     const TransferMetadata& metadata) {
2457   NS_LOG(VERBOSE) << __func__ << ": Nearby Share service: "
2458                   << "Outgoing transfer update for share target with ID "
2459                   << share_target.id << ": "
2460                   << TransferMetadata::StatusToString(metadata.status());
2461 
2462   if (metadata.is_final_status()) {
2463     is_connecting_ = false;
2464     RecordNearbyShareTransferCompletionStatusMetric(
2465         /*is_incoming=*/false, share_target.type, metadata.status());
2466     OnTransferComplete();
2467   } else if (metadata.status() == TransferMetadata::Status::kMediaDownloading ||
2468              metadata.status() ==
2469                  TransferMetadata::Status::kAwaitingLocalConfirmation) {
2470     is_connecting_ = false;
2471     OnTransferStarted(/*is_incoming=*/false);
2472   }
2473 
2474   bool has_foreground_send_surface =
2475       foreground_send_transfer_callbacks_.might_have_observers();
2476   base::ObserverList<TransferUpdateCallback>& transfer_callbacks =
2477       has_foreground_send_surface ? foreground_send_transfer_callbacks_
2478                                   : background_send_transfer_callbacks_;
2479 
2480   for (TransferUpdateCallback& callback : transfer_callbacks)
2481     callback.OnTransferUpdate(share_target, metadata);
2482 
2483   if (has_foreground_send_surface && metadata.is_final_status()) {
2484     last_outgoing_metadata_ = base::nullopt;
2485   } else {
2486     last_outgoing_metadata_ =
2487         std::make_pair(share_target, TransferMetadataBuilder::Clone(metadata)
2488                                          .set_is_original(false)
2489                                          .build());
2490   }
2491 }
2492 
CloseConnection(const ShareTarget & share_target)2493 void NearbySharingServiceImpl::CloseConnection(
2494     const ShareTarget& share_target) {
2495   NearbyConnection* connection = GetConnection(share_target);
2496   if (!connection) {
2497     NS_LOG(WARNING) << __func__ << ": Invalid connection for target - "
2498                     << share_target.device_name;
2499     return;
2500   }
2501   connection->Close();
2502 }
2503 
OnIncomingDecryptedCertificate(const std::string & endpoint_id,sharing::mojom::AdvertisementPtr advertisement,ShareTarget placeholder_share_target,base::Optional<NearbyShareDecryptedPublicCertificate> certificate)2504 void NearbySharingServiceImpl::OnIncomingDecryptedCertificate(
2505     const std::string& endpoint_id,
2506     sharing::mojom::AdvertisementPtr advertisement,
2507     ShareTarget placeholder_share_target,
2508     base::Optional<NearbyShareDecryptedPublicCertificate> certificate) {
2509   NearbyConnection* connection = GetConnection(placeholder_share_target);
2510   if (!connection) {
2511     NS_LOG(VERBOSE) << __func__ << ": Invalid connection for endpoint id - "
2512                     << endpoint_id;
2513     return;
2514   }
2515 
2516   // Remove placeholder share target since we are creating the actual share
2517   // target below.
2518   incoming_share_target_info_map_.erase(placeholder_share_target.id);
2519 
2520   base::Optional<ShareTarget> share_target = CreateShareTarget(
2521       endpoint_id, advertisement, std::move(certificate), /*is_incoming=*/true);
2522 
2523   if (!share_target) {
2524     NS_LOG(VERBOSE) << __func__
2525                     << "Failed to convert advertisement to share target for "
2526                        "incoming connection, disconnecting";
2527     connection->Close();
2528     return;
2529   }
2530 
2531   NS_LOG(VERBOSE) << __func__ << "Received incoming connection from "
2532                   << share_target->device_name;
2533 
2534   ShareTargetInfo* share_target_info = GetShareTargetInfo(*share_target);
2535   DCHECK(share_target_info);
2536   share_target_info->set_connection(connection);
2537 
2538   share_target_info->set_transfer_update_callback(
2539       std::make_unique<TransferUpdateDecorator>(base::BindRepeating(
2540           &NearbySharingServiceImpl::OnIncomingTransferUpdate,
2541           weak_ptr_factory_.GetWeakPtr())));
2542 
2543   connection->SetDisconnectionListener(
2544       base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
2545                      weak_ptr_factory_.GetWeakPtr(), *share_target));
2546 
2547   base::Optional<std::string> four_digit_token = ToFourDigitString(
2548       nearby_connections_manager_->GetRawAuthenticationToken(endpoint_id));
2549 
2550   RunPairedKeyVerification(
2551       *share_target, endpoint_id,
2552       base::BindOnce(
2553           &NearbySharingServiceImpl::OnIncomingConnectionKeyVerificationDone,
2554           weak_ptr_factory_.GetWeakPtr(), *share_target,
2555           std::move(four_digit_token)));
2556 }
2557 
RunPairedKeyVerification(const ShareTarget & share_target,const std::string & endpoint_id,base::OnceCallback<void (PairedKeyVerificationRunner::PairedKeyVerificationResult)> callback)2558 void NearbySharingServiceImpl::RunPairedKeyVerification(
2559     const ShareTarget& share_target,
2560     const std::string& endpoint_id,
2561     base::OnceCallback<void(
2562         PairedKeyVerificationRunner::PairedKeyVerificationResult)> callback) {
2563   DCHECK(profile_);
2564   base::Optional<std::vector<uint8_t>> token =
2565       nearby_connections_manager_->GetRawAuthenticationToken(endpoint_id);
2566   if (!token) {
2567     NS_LOG(VERBOSE) << __func__
2568                     << ": Failed to read authentication token from endpoint - "
2569                     << endpoint_id;
2570     std::move(callback).Run(
2571         PairedKeyVerificationRunner::PairedKeyVerificationResult::kFail);
2572     return;
2573   }
2574 
2575   ShareTargetInfo* share_target_info = GetShareTargetInfo(share_target);
2576   DCHECK(share_target_info);
2577 
2578   share_target_info->set_frames_reader(std::make_unique<IncomingFramesReader>(
2579       process_manager_, profile_, share_target_info->connection()));
2580 
2581   bool restrict_to_contacts =
2582       share_target.is_incoming &&
2583       advertising_power_level_ != PowerLevel::kHighPower;
2584   share_target_info->set_key_verification_runner(
2585       std::make_unique<PairedKeyVerificationRunner>(
2586           share_target, endpoint_id, *token, share_target_info->connection(),
2587           share_target_info->certificate(), GetCertificateManager(),
2588           settings_.GetVisibility(), restrict_to_contacts,
2589           share_target_info->frames_reader(), kReadFramesTimeout));
2590   share_target_info->key_verification_runner()->Run(std::move(callback));
2591 }
2592 
OnIncomingConnectionKeyVerificationDone(ShareTarget share_target,base::Optional<std::string> four_digit_token,PairedKeyVerificationRunner::PairedKeyVerificationResult result)2593 void NearbySharingServiceImpl::OnIncomingConnectionKeyVerificationDone(
2594     ShareTarget share_target,
2595     base::Optional<std::string> four_digit_token,
2596     PairedKeyVerificationRunner::PairedKeyVerificationResult result) {
2597   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2598   if (!info || !info->connection() || !info->endpoint_id()) {
2599     NS_LOG(VERBOSE) << __func__ << ": Invalid connection or endpoint id";
2600     return;
2601   }
2602 
2603   switch (result) {
2604     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kFail:
2605       NS_LOG(VERBOSE) << __func__ << ": Paired key handshake failed for target "
2606                       << share_target.device_name << ". Disconnecting.";
2607       info->connection()->Close();
2608       return;
2609 
2610     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kSuccess:
2611       NS_LOG(VERBOSE) << __func__
2612                       << ": Paired key handshake succeeded for target - "
2613                       << share_target.device_name;
2614       nearby_connections_manager_->UpgradeBandwidth(*info->endpoint_id());
2615       ReceiveIntroduction(share_target, /*four_digit_token=*/base::nullopt);
2616       break;
2617 
2618     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kUnable:
2619       NS_LOG(VERBOSE) << __func__
2620                       << ": Unable to verify paired key encryption when "
2621                          "receiving connection from target - "
2622                       << share_target.device_name;
2623       if (advertising_power_level_ == PowerLevel::kHighPower)
2624         nearby_connections_manager_->UpgradeBandwidth(*info->endpoint_id());
2625 
2626       if (four_digit_token)
2627         info->set_token(*four_digit_token);
2628 
2629       ReceiveIntroduction(share_target, std::move(four_digit_token));
2630       break;
2631 
2632     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kUnknown:
2633       NS_LOG(VERBOSE) << __func__
2634                       << ": Unknown PairedKeyVerificationResult for target "
2635                       << share_target.device_name << ". Disconnecting.";
2636       info->connection()->Close();
2637       break;
2638   }
2639 }
2640 
OnOutgoingConnectionKeyVerificationDone(const ShareTarget & share_target,base::Optional<std::string> four_digit_token,PairedKeyVerificationRunner::PairedKeyVerificationResult result)2641 void NearbySharingServiceImpl::OnOutgoingConnectionKeyVerificationDone(
2642     const ShareTarget& share_target,
2643     base::Optional<std::string> four_digit_token,
2644     PairedKeyVerificationRunner::PairedKeyVerificationResult result) {
2645   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2646   if (!info || !info->connection())
2647     return;
2648 
2649   if (!info->transfer_update_callback()) {
2650     NS_LOG(VERBOSE) << __func__
2651                     << ": No transfer update callback. Disconnecting.";
2652     info->connection()->Close();
2653     return;
2654   }
2655 
2656   // TODO(crbug.com/1119279): Check if we need to set this to false for
2657   // Advanced Protection users.
2658   bool sender_skips_confirmation = true;
2659 
2660   switch (result) {
2661     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kFail:
2662       NS_LOG(VERBOSE) << __func__ << ": Paired key handshake failed for target "
2663                       << share_target.device_name << ". Disconnecting.";
2664       info->transfer_update_callback()->OnTransferUpdate(
2665           share_target, TransferMetadataBuilder()
2666                             .set_status(TransferMetadata::Status::kFailed)
2667                             .build());
2668       info->connection()->Close();
2669       return;
2670 
2671     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kSuccess:
2672       NS_LOG(VERBOSE) << __func__
2673                       << ": Paired key handshake succeeded for target - "
2674                       << share_target.device_name;
2675       SendIntroduction(share_target, /*four_digit_token=*/base::nullopt);
2676       SendPayloads(share_target);
2677       return;
2678 
2679     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kUnable:
2680       NS_LOG(VERBOSE) << __func__
2681                       << ": Unable to verify paired key encryption when "
2682                          "initating connection to target - "
2683                       << share_target.device_name;
2684 
2685       if (four_digit_token)
2686         info->set_token(*four_digit_token);
2687 
2688       if (sender_skips_confirmation) {
2689         NS_LOG(VERBOSE) << __func__
2690                         << ": Sender-side verification is disabled. Skipping "
2691                            "token comparison with "
2692                         << share_target.device_name;
2693         SendIntroduction(share_target, /*four_digit_token=*/base::nullopt);
2694         SendPayloads(share_target);
2695       } else {
2696         SendIntroduction(share_target, std::move(four_digit_token));
2697       }
2698       return;
2699 
2700     case PairedKeyVerificationRunner::PairedKeyVerificationResult::kUnknown:
2701       NS_LOG(VERBOSE) << __func__
2702                       << ": Unknown PairedKeyVerificationResult for target "
2703                       << share_target.device_name << ". Disconnecting.";
2704       info->connection()->Close();
2705       break;
2706   }
2707 }
2708 
RefreshUIOnDisconnection(ShareTarget share_target)2709 void NearbySharingServiceImpl::RefreshUIOnDisconnection(
2710     ShareTarget share_target) {
2711   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2712   if (info && info->transfer_update_callback()) {
2713     info->transfer_update_callback()->OnTransferUpdate(
2714         share_target,
2715         TransferMetadataBuilder()
2716             .set_status(
2717                 TransferMetadata::Status::kAwaitingRemoteAcceptanceFailed)
2718             .build());
2719   }
2720 
2721   UnregisterShareTarget(share_target);
2722 }
2723 
ReceiveIntroduction(ShareTarget share_target,base::Optional<std::string> four_digit_token)2724 void NearbySharingServiceImpl::ReceiveIntroduction(
2725     ShareTarget share_target,
2726     base::Optional<std::string> four_digit_token) {
2727   NS_LOG(INFO) << __func__ << ": Receiving introduction from "
2728                << share_target.device_name;
2729   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2730   DCHECK(info && info->connection());
2731 
2732   info->frames_reader()->ReadFrame(
2733       sharing::mojom::V1Frame::Tag::INTRODUCTION,
2734       base::BindOnce(&NearbySharingServiceImpl::OnReceivedIntroduction,
2735                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target),
2736                      std::move(four_digit_token)),
2737       kReadFramesTimeout);
2738 }
2739 
OnReceivedIntroduction(ShareTarget share_target,base::Optional<std::string> four_digit_token,base::Optional<sharing::mojom::V1FramePtr> frame)2740 void NearbySharingServiceImpl::OnReceivedIntroduction(
2741     ShareTarget share_target,
2742     base::Optional<std::string> four_digit_token,
2743     base::Optional<sharing::mojom::V1FramePtr> frame) {
2744   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2745   if (!info || !info->connection()) {
2746     NS_LOG(WARNING)
2747         << __func__
2748         << ": Ignore received introduction, due to no connection established.";
2749     return;
2750   }
2751   NearbyConnection* connection = info->connection();
2752   DCHECK(profile_);
2753 
2754   if (!frame) {
2755     connection->Close();
2756     NS_LOG(WARNING) << __func__ << ": Invalid introduction frame";
2757     return;
2758   }
2759 
2760   NS_LOG(INFO) << __func__ << ": Successfully read the introduction frame.";
2761 
2762   base::CheckedNumeric<int64_t> file_size_sum(0);
2763 
2764   sharing::mojom::IntroductionFramePtr introduction_frame =
2765       std::move((*frame)->get_introduction());
2766   for (const auto& file : introduction_frame->file_metadata) {
2767     if (file->size <= 0) {
2768       Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType);
2769       NS_LOG(WARNING)
2770           << __func__
2771           << ": Ignore introduction, due to invalid attachment size";
2772       return;
2773     }
2774 
2775     NS_LOG(VERBOSE) << __func__ << "Found file attachment " << file->name
2776                     << " of type " << file->type << " with mimeType "
2777                     << file->mime_type;
2778     FileAttachment attachment(file->id, file->size, file->name, file->mime_type,
2779                               file->type);
2780     SetAttachmentPayloadId(attachment, file->payload_id);
2781     share_target.file_attachments.push_back(std::move(attachment));
2782 
2783     file_size_sum += file->size;
2784     if (!file_size_sum.IsValid()) {
2785       Fail(share_target, TransferMetadata::Status::kNotEnoughSpace);
2786       NS_LOG(WARNING) << __func__
2787                       << ": Ignoring introduction, total file size overflowed "
2788                          "64 bit integer.";
2789       return;
2790     }
2791   }
2792 
2793   for (const auto& text : introduction_frame->text_metadata) {
2794     if (text->size <= 0) {
2795       Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType);
2796       NS_LOG(WARNING)
2797           << __func__
2798           << ": Ignore introduction, due to invalid attachment size";
2799       return;
2800     }
2801 
2802     NS_LOG(VERBOSE) << __func__ << "Found text attachment " << text->text_title
2803                     << " of type " << text->type;
2804     TextAttachment attachment(text->id, text->type, text->text_title,
2805                               text->size);
2806     SetAttachmentPayloadId(attachment, text->payload_id);
2807     share_target.text_attachments.push_back(std::move(attachment));
2808   }
2809 
2810   if (!share_target.has_attachments()) {
2811     NS_LOG(WARNING) << __func__
2812                     << ": No attachment is found for this share target. It can "
2813                        "be result of unrecognizable attachment type";
2814     Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType);
2815 
2816     NS_LOG(VERBOSE) << __func__
2817                     << ": We don't support the attachments sent by the sender. "
2818                        "We have informed "
2819                     << share_target.device_name;
2820     return;
2821   }
2822 
2823   if (file_size_sum.ValueOrDie() == 0) {
2824     OnStorageCheckCompleted(std::move(share_target),
2825                             std::move(four_digit_token),
2826                             /*is_out_of_storage=*/false);
2827     return;
2828   }
2829 
2830   base::FilePath download_path =
2831       DownloadPrefs::FromDownloadManager(
2832           content::BrowserContext::GetDownloadManager(profile_))
2833           ->DownloadPath();
2834 
2835   base::ThreadPool::PostTaskAndReplyWithResult(
2836       FROM_HERE, {base::MayBlock()},
2837       base::BindOnce(&IsOutOfStorage, std::move(download_path),
2838                      file_size_sum.ValueOrDie(), free_disk_space_for_testing_),
2839       base::BindOnce(&NearbySharingServiceImpl::OnStorageCheckCompleted,
2840                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target),
2841                      std::move(four_digit_token)));
2842 }
2843 
ReceiveConnectionResponse(ShareTarget share_target)2844 void NearbySharingServiceImpl::ReceiveConnectionResponse(
2845     ShareTarget share_target) {
2846   NS_LOG(VERBOSE) << __func__ << ": Receiving response frame from "
2847                   << share_target.device_name;
2848   ShareTargetInfo* info = GetShareTargetInfo(share_target);
2849   DCHECK(info && info->connection());
2850 
2851   info->frames_reader()->ReadFrame(
2852       sharing::mojom::V1Frame::Tag::CONNECTION_RESPONSE,
2853       base::BindOnce(&NearbySharingServiceImpl::OnReceiveConnectionResponse,
2854                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target)),
2855       kReadResponseFrameTimeout);
2856 }
2857 
OnReceiveConnectionResponse(ShareTarget share_target,base::Optional<sharing::mojom::V1FramePtr> frame)2858 void NearbySharingServiceImpl::OnReceiveConnectionResponse(
2859     ShareTarget share_target,
2860     base::Optional<sharing::mojom::V1FramePtr> frame) {
2861   OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target);
2862   if (!info || !info->connection()) {
2863     NS_LOG(WARNING) << __func__
2864                     << ": Ignore received connection response, due to no "
2865                        "connection established.";
2866     return;
2867   }
2868   NearbyConnection* connection = info->connection();
2869 
2870   if (!info->transfer_update_callback()) {
2871     NS_LOG(WARNING) << __func__
2872                     << ": No transfer update callback. Disconnecting.";
2873     connection->Close();
2874     return;
2875   }
2876 
2877   if (!frame) {
2878     NS_LOG(WARNING)
2879         << __func__
2880         << ": Failed to read a response from the remote device. Disconnecting.";
2881     info->transfer_update_callback()->OnTransferUpdate(
2882         share_target, TransferMetadataBuilder()
2883                           .set_status(TransferMetadata::Status::kFailed)
2884                           .build());
2885     connection->Close();
2886     return;
2887   }
2888 
2889   mutual_acceptance_timeout_alarm_.Cancel();
2890 
2891   NS_LOG(VERBOSE) << __func__
2892                   << ": Successfully read the connection response frame.";
2893 
2894   sharing::mojom::ConnectionResponseFramePtr response =
2895       std::move((*frame)->get_connection_response());
2896   switch (response->status) {
2897     case sharing::mojom::ConnectionResponseFrame::Status::kAccept: {
2898       info->frames_reader()->ReadFrame(
2899           base::BindOnce(&NearbySharingServiceImpl::OnFrameRead,
2900                          weak_ptr_factory_.GetWeakPtr(), share_target));
2901 
2902       info->transfer_update_callback()->OnTransferUpdate(
2903           share_target, TransferMetadataBuilder()
2904                             .set_status(TransferMetadata::Status::kInProgress)
2905                             .build());
2906 
2907       info->set_payload_tracker(std::make_unique<PayloadTracker>(
2908           share_target, attachment_info_map_,
2909           base::BindRepeating(
2910               &NearbySharingServiceImpl::OnPayloadTransferUpdate,
2911               weak_ptr_factory_.GetWeakPtr())));
2912 
2913       for (auto& payload : info->ExtractTextPayloads()) {
2914         nearby_connections_manager_->Send(
2915             *info->endpoint_id(), std::move(payload), info->payload_tracker());
2916       }
2917       for (auto& payload : info->ExtractFilePayloads()) {
2918         nearby_connections_manager_->Send(
2919             *info->endpoint_id(), std::move(payload), info->payload_tracker());
2920       }
2921       NS_LOG(VERBOSE)
2922           << __func__
2923           << ": The connection was accepted. Payloads are now being sent.";
2924       break;
2925     }
2926     case sharing::mojom::ConnectionResponseFrame::Status::kReject:
2927       info->transfer_update_callback()->OnTransferUpdate(
2928           share_target, TransferMetadataBuilder()
2929                             .set_status(TransferMetadata::Status::kRejected)
2930                             .build());
2931       connection->Close();
2932       NS_LOG(VERBOSE)
2933           << __func__
2934           << ": The connection was rejected. The connection has been closed.";
2935       break;
2936     case sharing::mojom::ConnectionResponseFrame::Status::kNotEnoughSpace:
2937       info->transfer_update_callback()->OnTransferUpdate(
2938           share_target,
2939           TransferMetadataBuilder()
2940               .set_status(TransferMetadata::Status::kNotEnoughSpace)
2941               .build());
2942       connection->Close();
2943       NS_LOG(VERBOSE)
2944           << __func__
2945           << ": The connection was rejected because the remote device "
2946              "does not have enough space for our attachments. The "
2947              "connection has been closed.";
2948       break;
2949     case sharing::mojom::ConnectionResponseFrame::Status::
2950         kUnsupportedAttachmentType:
2951       info->transfer_update_callback()->OnTransferUpdate(
2952           share_target,
2953           TransferMetadataBuilder()
2954               .set_status(TransferMetadata::Status::kUnsupportedAttachmentType)
2955               .build());
2956       connection->Close();
2957       NS_LOG(VERBOSE)
2958           << __func__
2959           << ": The connection was rejected because the remote device "
2960              "does not support the attachments we were sending. The "
2961              "connection has been closed.";
2962       break;
2963     case sharing::mojom::ConnectionResponseFrame::Status::kTimedOut:
2964       info->transfer_update_callback()->OnTransferUpdate(
2965           share_target, TransferMetadataBuilder()
2966                             .set_status(TransferMetadata::Status::kTimedOut)
2967                             .build());
2968       connection->Close();
2969       NS_LOG(VERBOSE)
2970           << __func__
2971           << ": The connection was rejected because the remote device "
2972              "timed out. The connection has been closed.";
2973       break;
2974     default:
2975       info->transfer_update_callback()->OnTransferUpdate(
2976           share_target, TransferMetadataBuilder()
2977                             .set_status(TransferMetadata::Status::kFailed)
2978                             .build());
2979       connection->Close();
2980       NS_LOG(VERBOSE)
2981           << __func__
2982           << ": The connection failed. The connection has been closed.";
2983       break;
2984   }
2985 }
2986 
OnStorageCheckCompleted(ShareTarget share_target,base::Optional<std::string> four_digit_token,bool is_out_of_storage)2987 void NearbySharingServiceImpl::OnStorageCheckCompleted(
2988     ShareTarget share_target,
2989     base::Optional<std::string> four_digit_token,
2990     bool is_out_of_storage) {
2991   if (is_out_of_storage) {
2992     Fail(share_target, TransferMetadata::Status::kNotEnoughSpace);
2993     NS_LOG(WARNING) << __func__
2994                     << ": Not enough space on the receiver. We have informed "
2995                     << share_target.device_name;
2996     return;
2997   }
2998 
2999   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3000   if (!info || !info->connection()) {
3001     NS_LOG(WARNING) << __func__ << ": Invalid connection for share target - "
3002                     << share_target.device_name;
3003     return;
3004   }
3005   NearbyConnection* connection = info->connection();
3006 
3007   if (!info->transfer_update_callback()) {
3008     connection->Close();
3009     NS_LOG(VERBOSE) << __func__
3010                     << ": No transfer update callback. Disconnecting.";
3011     return;
3012   }
3013 
3014   mutual_acceptance_timeout_alarm_.Reset(base::BindOnce(
3015       &NearbySharingServiceImpl::OnIncomingMutualAcceptanceTimeout,
3016       weak_ptr_factory_.GetWeakPtr(), share_target));
3017 
3018   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
3019       FROM_HERE, base::BindOnce(mutual_acceptance_timeout_alarm_.callback()),
3020       kReadResponseFrameTimeout);
3021 
3022   info->transfer_update_callback()->OnTransferUpdate(
3023       share_target,
3024       TransferMetadataBuilder()
3025           .set_status(TransferMetadata::Status::kAwaitingLocalConfirmation)
3026           .set_token(std::move(four_digit_token))
3027           .build());
3028 
3029   if (!incoming_share_target_info_map_.count(share_target.id)) {
3030     connection->Close();
3031     NS_LOG(VERBOSE) << __func__
3032                     << ": IncomingShareTarget not found, disconnecting "
3033                     << share_target.device_name;
3034     return;
3035   }
3036 
3037   connection->SetDisconnectionListener(base::BindOnce(
3038       &NearbySharingServiceImpl::OnIncomingConnectionDisconnected,
3039       weak_ptr_factory_.GetWeakPtr(), share_target));
3040 
3041   auto* frames_reader = info->frames_reader();
3042   if (!frames_reader) {
3043     NS_LOG(WARNING) << __func__
3044                     << ": Stopped reading further frames, due to no connection "
3045                        "established.";
3046     return;
3047   }
3048 
3049   frames_reader->ReadFrame(
3050       base::BindOnce(&NearbySharingServiceImpl::OnFrameRead,
3051                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target)));
3052 }
3053 
OnFrameRead(ShareTarget share_target,base::Optional<sharing::mojom::V1FramePtr> frame)3054 void NearbySharingServiceImpl::OnFrameRead(
3055     ShareTarget share_target,
3056     base::Optional<sharing::mojom::V1FramePtr> frame) {
3057   if (!frame) {
3058     // This is the case when the connection has been closed since we wait
3059     // indefinitely for incoming frames.
3060     return;
3061   }
3062 
3063   sharing::mojom::V1FramePtr v1_frame = std::move(*frame);
3064   switch (v1_frame->which()) {
3065     case sharing::mojom::V1Frame::Tag::CANCEL_FRAME:
3066       NS_LOG(INFO) << __func__ << ": Read the cancel frame, closing connection";
3067       DoCancel(share_target, base::DoNothing(), /*write_cancel_frame=*/false);
3068       break;
3069 
3070     case sharing::mojom::V1Frame::Tag::CERTIFICATE_INFO:
3071       HandleCertificateInfoFrame(v1_frame->get_certificate_info());
3072       break;
3073 
3074     default:
3075       NS_LOG(VERBOSE) << __func__ << ": Discarding unknown frame of type";
3076       break;
3077   }
3078 
3079   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3080   if (!info || !info->frames_reader()) {
3081     NS_LOG(WARNING) << __func__
3082                     << ": Stopped reading further frames, due to no connection "
3083                        "established.";
3084     return;
3085   }
3086 
3087   info->frames_reader()->ReadFrame(
3088       base::BindOnce(&NearbySharingServiceImpl::OnFrameRead,
3089                      weak_ptr_factory_.GetWeakPtr(), std::move(share_target)));
3090 }
3091 
HandleCertificateInfoFrame(const sharing::mojom::CertificateInfoFramePtr & certificate_frame)3092 void NearbySharingServiceImpl::HandleCertificateInfoFrame(
3093     const sharing::mojom::CertificateInfoFramePtr& certificate_frame) {
3094   DCHECK(certificate_frame);
3095 
3096   // TODO(crbug.com/1113858): Allow saving certificates from remote devices.
3097 }
3098 
OnIncomingConnectionDisconnected(const ShareTarget & share_target)3099 void NearbySharingServiceImpl::OnIncomingConnectionDisconnected(
3100     const ShareTarget& share_target) {
3101   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3102   if (info && info->transfer_update_callback()) {
3103     info->transfer_update_callback()->OnTransferUpdate(
3104         share_target, TransferMetadataBuilder()
3105                           .set_status(TransferMetadata::Status::kFailed)
3106                           .build());
3107   }
3108   UnregisterShareTarget(share_target);
3109 }
3110 
OnOutgoingConnectionDisconnected(const ShareTarget & share_target)3111 void NearbySharingServiceImpl::OnOutgoingConnectionDisconnected(
3112     const ShareTarget& share_target) {
3113   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3114   if (info && info->transfer_update_callback()) {
3115     info->transfer_update_callback()->OnTransferUpdate(
3116         share_target,
3117         TransferMetadataBuilder()
3118             .set_status(
3119                 TransferMetadata::Status::kAwaitingRemoteAcceptanceFailed)
3120             .build());
3121   }
3122   UnregisterShareTarget(share_target);
3123 }
3124 
OnIncomingMutualAcceptanceTimeout(const ShareTarget & share_target)3125 void NearbySharingServiceImpl::OnIncomingMutualAcceptanceTimeout(
3126     const ShareTarget& share_target) {
3127   DCHECK(share_target.is_incoming);
3128 
3129   NS_LOG(VERBOSE)
3130       << __func__
3131       << ": Incoming mutual acceptance timed out, closing connection for "
3132       << share_target.device_name;
3133 
3134   Fail(share_target, TransferMetadata::Status::kTimedOut);
3135 }
3136 
OnOutgoingMutualAcceptanceTimeout(const ShareTarget & share_target)3137 void NearbySharingServiceImpl::OnOutgoingMutualAcceptanceTimeout(
3138     const ShareTarget& share_target) {
3139   DCHECK(!share_target.is_incoming);
3140 
3141   NS_LOG(VERBOSE)
3142       << __func__
3143       << ": Outgoing mutual acceptance timed out, closing connection for "
3144       << share_target.device_name;
3145 
3146   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3147   if (!info)
3148     return;
3149 
3150   if (info->transfer_update_callback()) {
3151     info->transfer_update_callback()->OnTransferUpdate(
3152         share_target, TransferMetadataBuilder()
3153                           .set_status(TransferMetadata::Status::kTimedOut)
3154                           .build());
3155   }
3156 
3157   if (info->connection())
3158     info->connection()->Close();
3159 }
3160 
CreateShareTarget(const std::string & endpoint_id,const sharing::mojom::AdvertisementPtr & advertisement,base::Optional<NearbyShareDecryptedPublicCertificate> certificate,bool is_incoming)3161 base::Optional<ShareTarget> NearbySharingServiceImpl::CreateShareTarget(
3162     const std::string& endpoint_id,
3163     const sharing::mojom::AdvertisementPtr& advertisement,
3164     base::Optional<NearbyShareDecryptedPublicCertificate> certificate,
3165     bool is_incoming) {
3166   DCHECK(advertisement);
3167 
3168   if (!advertisement->device_name && !certificate) {
3169     NS_LOG(VERBOSE) << __func__
3170                     << ": Failed to retrieve public certificate for contact "
3171                        "only advertisement.";
3172     return base::nullopt;
3173   }
3174 
3175   base::Optional<std::string> device_name =
3176       GetDeviceName(advertisement, certificate);
3177   if (!device_name) {
3178     NS_LOG(VERBOSE) << __func__
3179                     << ": Failed to retrieve device name for advertisement.";
3180     return base::nullopt;
3181   }
3182 
3183   ShareTarget target;
3184   target.type = advertisement->device_type;
3185   target.device_name = std::move(*device_name);
3186   target.is_incoming = is_incoming;
3187   target.device_id = GetDeviceId(endpoint_id, certificate);
3188 
3189   ShareTargetInfo& info = GetOrCreateShareTargetInfo(target, endpoint_id);
3190 
3191   if (certificate) {
3192     if (certificate->unencrypted_metadata().has_full_name())
3193       target.full_name = certificate->unencrypted_metadata().full_name();
3194 
3195     if (certificate->unencrypted_metadata().has_icon_url())
3196       target.image_url = GURL(certificate->unencrypted_metadata().icon_url());
3197 
3198     target.is_known = true;
3199     info.set_certificate(std::move(*certificate));
3200   }
3201 
3202   return target;
3203 }
3204 
OnPayloadTransferUpdate(ShareTarget share_target,TransferMetadata metadata)3205 void NearbySharingServiceImpl::OnPayloadTransferUpdate(
3206     ShareTarget share_target,
3207     TransferMetadata metadata) {
3208   NS_LOG(VERBOSE) << __func__ << ": Nearby Share service: "
3209                   << "Payload transfer update for share target with ID "
3210                   << share_target.id << ": "
3211                   << TransferMetadata::StatusToString(metadata.status());
3212 
3213   if (metadata.status() == TransferMetadata::Status::kComplete &&
3214       share_target.is_incoming && !OnIncomingPayloadsComplete(share_target)) {
3215     metadata = TransferMetadataBuilder()
3216                    .set_status(TransferMetadata::Status::kFailed)
3217                    .build();
3218 
3219     // Reset file paths for file attachments.
3220     for (auto& file : share_target.file_attachments)
3221       file.set_file_path(base::nullopt);
3222 
3223     // Reset body of text attachments.
3224     for (auto& text : share_target.text_attachments)
3225       text.set_text_body(std::string());
3226   }
3227 
3228   // Make sure to call this before calling Disconnect or we risk loosing some
3229   // transfer updates in the receive case due to the Disconnect call cleaning up
3230   // share targets.
3231   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3232   if (info && info->transfer_update_callback())
3233     info->transfer_update_callback()->OnTransferUpdate(share_target, metadata);
3234 
3235   // Cancellation has its own disconnection strategy, possibly adding a delay
3236   // before disconnection to provide the other party time to process the
3237   // cancellation.
3238   if (TransferMetadata::IsFinalStatus(metadata.status()) &&
3239       metadata.status() != TransferMetadata::Status::kCancelled) {
3240     Disconnect(share_target, metadata);
3241   }
3242 }
3243 
OnIncomingPayloadsComplete(ShareTarget & share_target)3244 bool NearbySharingServiceImpl::OnIncomingPayloadsComplete(
3245     ShareTarget& share_target) {
3246   DCHECK(share_target.is_incoming);
3247 
3248   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3249   if (!info || !info->connection()) {
3250     NS_LOG(VERBOSE) << __func__ << ": Connection not found for target - "
3251                     << share_target.device_name;
3252 
3253     return false;
3254   }
3255   NearbyConnection* connection = info->connection();
3256 
3257   connection->SetDisconnectionListener(
3258       base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
3259                      weak_ptr_factory_.GetWeakPtr(), share_target));
3260 
3261   for (auto& file : share_target.file_attachments) {
3262     AttachmentInfo& attachment_info = attachment_info_map_[file.id()];
3263     base::Optional<int64_t> payload_id = attachment_info.payload_id;
3264     if (!payload_id) {
3265       NS_LOG(WARNING) << __func__ << ": No payload id found for file - "
3266                       << file.id();
3267       return false;
3268     }
3269 
3270     location::nearby::connections::mojom::Payload* incoming_payload =
3271         nearby_connections_manager_->GetIncomingPayload(*payload_id);
3272     if (!incoming_payload || !incoming_payload->content ||
3273         !incoming_payload->content->is_file()) {
3274       NS_LOG(WARNING) << __func__ << ": No payload found for file - "
3275                       << file.id();
3276       return false;
3277     }
3278 
3279     file.set_file_path(attachment_info.file_path);
3280   }
3281 
3282   for (auto& text : share_target.text_attachments) {
3283     AttachmentInfo& attachment_info = attachment_info_map_[text.id()];
3284     base::Optional<int64_t> payload_id = attachment_info.payload_id;
3285     if (!payload_id) {
3286       NS_LOG(WARNING) << __func__ << ": No payload id found for text - "
3287                       << text.id();
3288       return false;
3289     }
3290 
3291     location::nearby::connections::mojom::Payload* incoming_payload =
3292         nearby_connections_manager_->GetIncomingPayload(*payload_id);
3293     if (!incoming_payload || !incoming_payload->content ||
3294         !incoming_payload->content->is_bytes()) {
3295       NS_LOG(WARNING) << __func__ << ": No payload found for text - "
3296                       << text.id();
3297       return false;
3298     }
3299 
3300     std::vector<uint8_t>& bytes = incoming_payload->content->get_bytes()->bytes;
3301     if (bytes.empty()) {
3302       NS_LOG(WARNING)
3303           << __func__
3304           << ": Incoming bytes is empty for text payload with payload_id - "
3305           << *payload_id;
3306       return false;
3307     }
3308 
3309     std::string text_body(bytes.begin(), bytes.end());
3310     text.set_text_body(text_body);
3311 
3312     attachment_info.text_body = std::move(text_body);
3313   }
3314   return true;
3315 }
3316 
RemoveIncomingPayloads(ShareTarget share_target)3317 void NearbySharingServiceImpl::RemoveIncomingPayloads(
3318     ShareTarget share_target) {
3319   if (!share_target.is_incoming)
3320     return;
3321 
3322   NS_LOG(INFO) << __func__ << ": Cleaning up payloads due to transfer failure";
3323 
3324   nearby_connections_manager_->ClearIncomingPayloads();
3325   std::vector<base::FilePath> files_for_deletion;
3326   for (const auto& file : share_target.file_attachments) {
3327     auto it = attachment_info_map_.find(file.id());
3328     if (it == attachment_info_map_.end())
3329       continue;
3330 
3331     files_for_deletion.push_back(it->second.file_path);
3332   }
3333 
3334   file_handler_.DeleteFilesFromDisk(std::move(files_for_deletion));
3335 }
3336 
Disconnect(const ShareTarget & share_target,TransferMetadata metadata)3337 void NearbySharingServiceImpl::Disconnect(const ShareTarget& share_target,
3338                                           TransferMetadata metadata) {
3339   ShareTargetInfo* share_target_info = GetShareTargetInfo(share_target);
3340   if (!share_target_info) {
3341     NS_LOG(WARNING)
3342         << __func__
3343         << ": Failed to disconnect. No share target info found for target - "
3344         << share_target.device_name;
3345     return;
3346   }
3347 
3348   base::Optional<std::string> endpoint_id = share_target_info->endpoint_id();
3349   if (!endpoint_id) {
3350     NS_LOG(WARNING)
3351         << __func__
3352         << ": Failed to disconnect. No endpoint id found for share target - "
3353         << share_target.device_name;
3354     return;
3355   }
3356 
3357   // Failed to send or receive. No point in continuing, so disconnect
3358   // immediately.
3359   if (metadata.status() != TransferMetadata::Status::kComplete) {
3360     if (share_target_info->connection()) {
3361       share_target_info->connection()->Close();
3362     } else {
3363       nearby_connections_manager_->Disconnect(*endpoint_id);
3364     }
3365     return;
3366   }
3367 
3368   // Files received successfully. Receivers can immediately cancel.
3369   if (share_target.is_incoming) {
3370     if (share_target_info->connection()) {
3371       share_target_info->connection()->Close();
3372     } else {
3373       nearby_connections_manager_->Disconnect(*endpoint_id);
3374     }
3375     return;
3376   }
3377 
3378   // Disconnect after a timeout to make sure any pending payloads are sent.
3379   auto timer = std::make_unique<base::CancelableOnceClosure>(base::BindOnce(
3380       &NearbySharingServiceImpl::OnDisconnectingConnectionTimeout,
3381       weak_ptr_factory_.GetWeakPtr(), *endpoint_id));
3382   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
3383       FROM_HERE, timer->callback(), kOutgoingDisconnectionDelay);
3384   disconnection_timeout_alarms_[*endpoint_id] = std::move(timer);
3385 
3386   // Stop the disconnection timeout if the connection has been closed already.
3387   if (share_target_info->connection()) {
3388     share_target_info->connection()->SetDisconnectionListener(base::BindOnce(
3389         &NearbySharingServiceImpl::OnDisconnectingConnectionDisconnected,
3390         weak_ptr_factory_.GetWeakPtr(), share_target, *endpoint_id));
3391   }
3392 }
3393 
OnDisconnectingConnectionTimeout(const std::string & endpoint_id)3394 void NearbySharingServiceImpl::OnDisconnectingConnectionTimeout(
3395     const std::string& endpoint_id) {
3396   disconnection_timeout_alarms_.erase(endpoint_id);
3397   nearby_connections_manager_->Disconnect(endpoint_id);
3398 }
3399 
OnDisconnectingConnectionDisconnected(const ShareTarget & share_target,const std::string & endpoint_id)3400 void NearbySharingServiceImpl::OnDisconnectingConnectionDisconnected(
3401     const ShareTarget& share_target,
3402     const std::string& endpoint_id) {
3403   disconnection_timeout_alarms_.erase(endpoint_id);
3404   UnregisterShareTarget(share_target);
3405 }
3406 
GetOrCreateShareTargetInfo(const ShareTarget & share_target,const std::string & endpoint_id)3407 ShareTargetInfo& NearbySharingServiceImpl::GetOrCreateShareTargetInfo(
3408     const ShareTarget& share_target,
3409     const std::string& endpoint_id) {
3410   if (share_target.is_incoming) {
3411     auto& info = incoming_share_target_info_map_[share_target.id];
3412     info.set_endpoint_id(endpoint_id);
3413     return info;
3414   } else {
3415     // We need to explicitly remove any previous share target for
3416     // |endpoint_id| if one exists, notifying observers that a share target is
3417     // lost.
3418     const auto it = outgoing_share_target_map_.find(endpoint_id);
3419     if (it != outgoing_share_target_map_.end() &&
3420         it->second.id != share_target.id) {
3421       RemoveOutgoingShareTargetWithEndpointId(endpoint_id);
3422     }
3423 
3424     NS_LOG(VERBOSE) << __func__ << ": Adding (endpoint_id=" << endpoint_id
3425                     << ", share_target_id=" << share_target.id
3426                     << ") to outgoing share target map";
3427     outgoing_share_target_map_.insert_or_assign(endpoint_id, share_target);
3428     auto& info = outgoing_share_target_info_map_[share_target.id];
3429     info.set_endpoint_id(endpoint_id);
3430     return info;
3431   }
3432 }
3433 
GetShareTargetInfo(const ShareTarget & share_target)3434 ShareTargetInfo* NearbySharingServiceImpl::GetShareTargetInfo(
3435     const ShareTarget& share_target) {
3436   if (share_target.is_incoming)
3437     return GetIncomingShareTargetInfo(share_target);
3438   else
3439     return GetOutgoingShareTargetInfo(share_target);
3440 }
3441 
GetIncomingShareTargetInfo(const ShareTarget & share_target)3442 IncomingShareTargetInfo* NearbySharingServiceImpl::GetIncomingShareTargetInfo(
3443     const ShareTarget& share_target) {
3444   auto it = incoming_share_target_info_map_.find(share_target.id);
3445   if (it == incoming_share_target_info_map_.end())
3446     return nullptr;
3447 
3448   return &it->second;
3449 }
3450 
GetOutgoingShareTargetInfo(const ShareTarget & share_target)3451 OutgoingShareTargetInfo* NearbySharingServiceImpl::GetOutgoingShareTargetInfo(
3452     const ShareTarget& share_target) {
3453   auto it = outgoing_share_target_info_map_.find(share_target.id);
3454   if (it == outgoing_share_target_info_map_.end())
3455     return nullptr;
3456 
3457   return &it->second;
3458 }
3459 
GetConnection(const ShareTarget & share_target)3460 NearbyConnection* NearbySharingServiceImpl::GetConnection(
3461     const ShareTarget& share_target) {
3462   ShareTargetInfo* share_target_info = GetShareTargetInfo(share_target);
3463   return share_target_info ? share_target_info->connection() : nullptr;
3464 }
3465 
3466 base::Optional<std::vector<uint8_t>>
GetBluetoothMacAddress(const ShareTarget & share_target)3467 NearbySharingServiceImpl::GetBluetoothMacAddress(
3468     const ShareTarget& share_target) {
3469   ShareTargetInfo* info = GetShareTargetInfo(share_target);
3470   if (!info)
3471     return base::nullopt;
3472 
3473   const base::Optional<NearbyShareDecryptedPublicCertificate>& certificate =
3474       info->certificate();
3475   if (!certificate ||
3476       !certificate->unencrypted_metadata().has_bluetooth_mac_address()) {
3477     return base::nullopt;
3478   }
3479 
3480   std::string mac_address =
3481       certificate->unencrypted_metadata().bluetooth_mac_address();
3482   if (mac_address.size() != 6)
3483     return base::nullopt;
3484 
3485   return std::vector<uint8_t>(mac_address.begin(), mac_address.end());
3486 }
3487 
ClearOutgoingShareTargetInfoMap()3488 void NearbySharingServiceImpl::ClearOutgoingShareTargetInfoMap() {
3489   NS_LOG(VERBOSE) << __func__ << ": Clearing outgoing share target map.";
3490   while (!outgoing_share_target_map_.empty()) {
3491     RemoveOutgoingShareTargetWithEndpointId(
3492         /*endpoint_id=*/outgoing_share_target_map_.begin()->first);
3493   }
3494   DCHECK(outgoing_share_target_map_.empty());
3495   DCHECK(outgoing_share_target_info_map_.empty());
3496 }
3497 
SetAttachmentPayloadId(const Attachment & attachment,int64_t payload_id)3498 void NearbySharingServiceImpl::SetAttachmentPayloadId(
3499     const Attachment& attachment,
3500     int64_t payload_id) {
3501   attachment_info_map_[attachment.id()].payload_id = payload_id;
3502 }
3503 
GetAttachmentPayloadId(int64_t attachment_id)3504 base::Optional<int64_t> NearbySharingServiceImpl::GetAttachmentPayloadId(
3505     int64_t attachment_id) {
3506   auto it = attachment_info_map_.find(attachment_id);
3507   if (it == attachment_info_map_.end())
3508     return base::nullopt;
3509 
3510   return it->second.payload_id;
3511 }
3512 
UnregisterShareTarget(const ShareTarget & share_target)3513 void NearbySharingServiceImpl::UnregisterShareTarget(
3514     const ShareTarget& share_target) {
3515   NS_LOG(VERBOSE) << __func__ << ": Unregistering share target - "
3516                   << share_target.device_name;
3517 
3518   if (share_target.is_incoming) {
3519     if (last_incoming_metadata_ &&
3520         last_incoming_metadata_->first.id == share_target.id) {
3521       last_incoming_metadata_.reset();
3522     }
3523 
3524     // Clear legacy incoming payloads to release resource.
3525     nearby_connections_manager_->ClearIncomingPayloads();
3526     incoming_share_target_info_map_.erase(share_target.id);
3527   } else {
3528     if (last_outgoing_metadata_ &&
3529         last_outgoing_metadata_->first.id == share_target.id) {
3530       last_outgoing_metadata_.reset();
3531     }
3532     // Find the endpoint id that matches the given share target.
3533     base::Optional<std::string> endpoint_id;
3534     auto it = outgoing_share_target_info_map_.find(share_target.id);
3535     if (it != outgoing_share_target_info_map_.end())
3536       endpoint_id = it->second.endpoint_id();
3537 
3538     // TODO(crbug/1108348): Support caching manager by keeping track of the
3539     // share_target/endpoint_id for next time.
3540     ClearOutgoingShareTargetInfoMap();
3541 
3542     NS_LOG(VERBOSE) << __func__ << ": Unregister share target: "
3543                     << share_target.device_name;
3544   }
3545   mutual_acceptance_timeout_alarm_.Cancel();
3546 }
3547 
OnStartAdvertisingResult(bool used_device_name,NearbyConnectionsManager::ConnectionsStatus status)3548 void NearbySharingServiceImpl::OnStartAdvertisingResult(
3549     bool used_device_name,
3550     NearbyConnectionsManager::ConnectionsStatus status) {
3551   RecordNearbyShareStartAdvertisingResultMetric(
3552       /*is_high_visibility=*/used_device_name, status);
3553 
3554   if (status == NearbyConnectionsManager::ConnectionsStatus::kSuccess) {
3555     NS_LOG(VERBOSE)
3556         << "StartAdvertising over Nearby Connections was successful.";
3557     SetInHighVisibility(used_device_name);
3558   } else {
3559     NS_LOG(ERROR) << "StartAdvertising over Nearby Connections failed: "
3560                   << NearbyConnectionsManager::ConnectionsStatusToString(
3561                          status);
3562     SetInHighVisibility(false);
3563   }
3564 }
3565 
SetInHighVisibility(bool new_in_high_visibility)3566 void NearbySharingServiceImpl::SetInHighVisibility(
3567     bool new_in_high_visibility) {
3568   if (in_high_visibility == new_in_high_visibility)
3569     return;
3570 
3571   in_high_visibility = new_in_high_visibility;
3572   for (auto& observer : observers_) {
3573     observer.OnHighVisibilityChanged(in_high_visibility);
3574   }
3575 }
3576