blob: abd5c1520bf3f1cd7241e75fa380f1204296891e [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/sharing/sharing_fcm_sender.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "chrome/browser/sharing/sharing_constants.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
#include "chrome/browser/sharing/vapid_key_manager.h"
#include "components/gcm_driver/common/gcm_message.h"
#include "components/gcm_driver/gcm_driver.h"
#include "components/sync_device_info/device_info.h"
SharingFCMSender::SharingFCMSender(
gcm::GCMDriver* gcm_driver,
syncer::LocalDeviceInfoProvider* device_info_provider,
SharingSyncPreference* sync_preference,
VapidKeyManager* vapid_key_manager)
: gcm_driver_(gcm_driver),
device_info_provider_(device_info_provider),
sync_preference_(sync_preference),
vapid_key_manager_(vapid_key_manager) {}
SharingFCMSender::~SharingFCMSender() = default;
void SharingFCMSender::SendMessageToDevice(
syncer::DeviceInfo::SharingInfo target,
base::TimeDelta time_to_live,
SharingMessage message,
SendMessageCallback callback) {
auto send_message_closure = base::BindOnce(
&SharingFCMSender::DoSendMessageToDevice, weak_ptr_factory_.GetWeakPtr(),
std::move(target), time_to_live, std::move(message), std::move(callback));
if (device_info_provider_->GetLocalDeviceInfo()) {
std::move(send_message_closure).Run();
return;
}
if (!local_device_info_ready_subscription_) {
local_device_info_ready_subscription_ =
device_info_provider_->RegisterOnInitializedCallback(
base::AdaptCallbackForRepeating(
base::BindOnce(&SharingFCMSender::OnLocalDeviceInfoInitialized,
weak_ptr_factory_.GetWeakPtr())));
}
send_message_queue_.emplace_back(std::move(send_message_closure));
}
void SharingFCMSender::OnLocalDeviceInfoInitialized() {
for (auto& closure : send_message_queue_)
std::move(closure).Run();
send_message_queue_.clear();
local_device_info_ready_subscription_.reset();
}
void SharingFCMSender::DoSendMessageToDevice(
syncer::DeviceInfo::SharingInfo target,
base::TimeDelta time_to_live,
SharingMessage message,
SendMessageCallback callback) {
base::Optional<SharingSyncPreference::FCMRegistration> fcm_registration =
sync_preference_->GetFCMRegistration();
base::Optional<syncer::DeviceInfo::SharingInfo> sharing_info =
sync_preference_->GetLocalSharingInfo();
if (!fcm_registration || !sharing_info) {
LOG(ERROR) << "Unable to retrieve FCM registration or sharing info";
std::move(callback).Run(SharingSendMessageResult::kInternalError,
base::nullopt);
return;
}
const syncer::DeviceInfo* local_device_info =
device_info_provider_->GetLocalDeviceInfo();
message.set_sender_guid(local_device_info->guid());
if (message.payload_case() != SharingMessage::kAckMessage) {
message.set_sender_device_name(local_device_info->client_name());
auto* sender_info = message.mutable_sender_info();
sender_info->set_fcm_token(sharing_info->fcm_token);
sender_info->set_p256dh(sharing_info->p256dh);
sender_info->set_auth_secret(sharing_info->auth_secret);
}
gcm::WebPushMessage web_push_message;
web_push_message.time_to_live = time_to_live.InSeconds();
web_push_message.urgency = gcm::WebPushMessage::Urgency::kHigh;
message.SerializeToString(&web_push_message.payload);
gcm_driver_->SendWebPushMessage(
kSharingFCMAppID, fcm_registration->authorized_entity, target.p256dh,
target.auth_secret, target.fcm_token,
vapid_key_manager_->GetOrCreateKey(), std::move(web_push_message),
base::BindOnce(&SharingFCMSender::OnMessageSent,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void SharingFCMSender::OnMessageSent(SendMessageCallback callback,
gcm::SendWebPushMessageResult result,
base::Optional<std::string> message_id) {
SharingSendMessageResult send_message_result;
switch (result) {
case gcm::SendWebPushMessageResult::kSuccessful:
send_message_result = SharingSendMessageResult::kSuccessful;
break;
case gcm::SendWebPushMessageResult::kDeviceGone:
send_message_result = SharingSendMessageResult::kDeviceNotFound;
break;
case gcm::SendWebPushMessageResult::kNetworkError:
send_message_result = SharingSendMessageResult::kNetworkError;
break;
case gcm::SendWebPushMessageResult::kPayloadTooLarge:
send_message_result = SharingSendMessageResult::kPayloadTooLarge;
break;
case gcm::SendWebPushMessageResult::kEncryptionFailed:
case gcm::SendWebPushMessageResult::kCreateJWTFailed:
case gcm::SendWebPushMessageResult::kServerError:
case gcm::SendWebPushMessageResult::kParseResponseFailed:
case gcm::SendWebPushMessageResult::kVapidKeyInvalid:
send_message_result = SharingSendMessageResult::kInternalError;
break;
}
std::move(callback).Run(send_message_result, message_id);
}