Sharing Device registration implementation
Bug: 966034
Change-Id: I6942c435906b40dcdbed04beaeb73586a8a60ae6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1669302
Reviewed-by: Ryan Hamilton <[email protected]>
Reviewed-by: Nicolas Zea <[email protected]>
Reviewed-by: Richard Knoll <[email protected]>
Commit-Queue: Himanshu Jaju <[email protected]>
Cr-Commit-Position: refs/heads/master@{#673810}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index b252ce4..16c0d514 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1502,10 +1502,14 @@
"sharing/ack_message_handler.h",
"sharing/click_to_call/feature.cc",
"sharing/click_to_call/feature.h",
+ "sharing/fcm_constants.cc",
+ "sharing/fcm_constants.h",
"sharing/features.cc",
"sharing/features.h",
"sharing/sharing_device_info.cc",
"sharing/sharing_device_info.h",
+ "sharing/sharing_device_registration.cc",
+ "sharing/sharing_device_registration.h",
"sharing/sharing_fcm_handler.cc",
"sharing/sharing_fcm_handler.h",
"sharing/sharing_fcm_sender.cc",
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 4f5a428..5e0ecea3 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -84,6 +84,7 @@
#include "chrome/browser/push_messaging/push_messaging_service_factory.h"
#include "chrome/browser/push_messaging/push_messaging_service_impl.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/sharing/sharing_service_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_ui_util.h"
#include "chrome/browser/site_isolation/site_isolation_policy.h"
@@ -756,6 +757,10 @@
delegate_->OnProfileCreated(this, true, IsNewProfile());
}
+ // Ensure that the SharingService is initialized now that io_data_ is
+ // initialized.
+ SharingServiceFactory::GetForBrowserContext(this);
+
{
SCOPED_UMA_HISTOGRAM_TIMER("Profile.NotifyProfileCreatedTime");
content::NotificationService::current()->Notify(
diff --git a/chrome/browser/sharing/fake_local_device_info_provider.cc b/chrome/browser/sharing/fake_local_device_info_provider.cc
new file mode 100644
index 0000000..0380fcb9
--- /dev/null
+++ b/chrome/browser/sharing/fake_local_device_info_provider.cc
@@ -0,0 +1,36 @@
+// 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/fake_local_device_info_provider.h"
+
+#include "base/time/time.h"
+
+FakeLocalDeviceInfoProvider::FakeLocalDeviceInfoProvider()
+ : device_info_("id",
+ "name",
+ "chrome_version",
+ "user_agent",
+ sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+ "device_id",
+ /* last_updated_timestamp= */ base::Time::Now(),
+ /* send_tab_to_self_receiving_enabled= */ false) {}
+
+FakeLocalDeviceInfoProvider::~FakeLocalDeviceInfoProvider() = default;
+
+version_info::Channel FakeLocalDeviceInfoProvider::GetChannel() const {
+ NOTIMPLEMENTED();
+ return version_info::Channel::UNKNOWN;
+}
+
+const syncer::DeviceInfo* FakeLocalDeviceInfoProvider::GetLocalDeviceInfo()
+ const {
+ return &device_info_;
+}
+
+std::unique_ptr<FakeLocalDeviceInfoProvider::Subscription>
+FakeLocalDeviceInfoProvider::RegisterOnInitializedCallback(
+ const base::RepeatingClosure& callback) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
diff --git a/chrome/browser/sharing/fake_local_device_info_provider.h b/chrome/browser/sharing/fake_local_device_info_provider.h
new file mode 100644
index 0000000..8133c32
--- /dev/null
+++ b/chrome/browser/sharing/fake_local_device_info_provider.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SHARING_FAKE_LOCAL_DEVICE_INFO_PROVIDER_H_
+#define CHROME_BROWSER_SHARING_FAKE_LOCAL_DEVICE_INFO_PROVIDER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/sync_device_info/device_info.h"
+#include "components/sync_device_info/local_device_info_provider.h"
+
+class FakeLocalDeviceInfoProvider : public syncer::LocalDeviceInfoProvider {
+ public:
+ FakeLocalDeviceInfoProvider();
+ ~FakeLocalDeviceInfoProvider() override;
+
+ // Overrides for syncer::LocalDeviceInfoProvider.
+ version_info::Channel GetChannel() const override;
+ const syncer::DeviceInfo* GetLocalDeviceInfo() const override;
+ std::unique_ptr<Subscription> RegisterOnInitializedCallback(
+ const base::RepeatingClosure& callback) override;
+
+ private:
+ syncer::DeviceInfo device_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeLocalDeviceInfoProvider);
+};
+
+#endif // CHROME_BROWSER_SHARING_FAKE_LOCAL_DEVICE_INFO_PROVIDER_H_
diff --git a/chrome/browser/sharing/fcm_constants.cc b/chrome/browser/sharing/fcm_constants.cc
new file mode 100644
index 0000000..6abe9e9
--- /dev/null
+++ b/chrome/browser/sharing/fcm_constants.cc
@@ -0,0 +1,9 @@
+// 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/fcm_constants.h"
+
+const char kFCMScope[] = "GCM";
+
+const char kSharingFCMAppID[] = "com.google.chrome.sharing.fcm";
diff --git a/chrome/browser/sharing/fcm_constants.h b/chrome/browser/sharing/fcm_constants.h
new file mode 100644
index 0000000..b5d3e30
--- /dev/null
+++ b/chrome/browser/sharing/fcm_constants.h
@@ -0,0 +1,14 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SHARING_FCM_CONSTANTS_H_
+#define CHROME_BROWSER_SHARING_FCM_CONSTANTS_H_
+
+// InstanceID scope for Google Cloud Messaging to get GCM enabled token.
+extern const char kFCMScope[];
+
+// Sender ID linked to GCM messages for Sharing.
+extern const char kSharingFCMAppID[];
+
+#endif // CHROME_BROWSER_SHARING_FCM_CONSTANTS_H_
diff --git a/chrome/browser/sharing/sharing_device_info.h b/chrome/browser/sharing/sharing_device_info.h
index 22f04eb..4f40303 100644
--- a/chrome/browser/sharing/sharing_device_info.h
+++ b/chrome/browser/sharing/sharing_device_info.h
@@ -32,7 +32,7 @@
// Returns the time at which this device was last online.
base::Time last_online_timestamp() const;
- // Gets a bitmask of available capaiblities of the device, defined in
+ // Gets a bitmask of available capabilities of the device, defined in
// SharingDeviceCapability enum.
int capabilities() const;
diff --git a/chrome/browser/sharing/sharing_device_registration.cc b/chrome/browser/sharing/sharing_device_registration.cc
new file mode 100644
index 0000000..3084725
--- /dev/null
+++ b/chrome/browser/sharing/sharing_device_registration.cc
@@ -0,0 +1,102 @@
+// 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_device_registration.h"
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/base64url.h"
+#include "base/bind.h"
+#include "base/optional.h"
+#include "chrome/browser/sharing/fcm_constants.h"
+#include "chrome/browser/sharing/sharing_device_info.h"
+#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/sharing/vapid_key_manager.h"
+#include "components/gcm_driver/crypto/p256_key_util.h"
+#include "components/gcm_driver/gcm_driver.h"
+#include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/sync_device_info/device_info.h"
+#include "components/sync_device_info/local_device_info_provider.h"
+#include "crypto/ec_private_key.h"
+
+SharingDeviceRegistration::SharingDeviceRegistration(
+ SharingSyncPreference* sharing_sync_preference,
+ instance_id::InstanceIDDriver* instance_id_driver,
+ VapidKeyManager* vapid_key_manager,
+ gcm::GCMDriver* gcm_driver,
+ syncer::LocalDeviceInfoProvider* local_device_info_provider)
+ : sharing_sync_preference_(sharing_sync_preference),
+ instance_id_driver_(instance_id_driver),
+ vapid_key_manager_(vapid_key_manager),
+ gcm_driver_(gcm_driver),
+ local_device_info_provider_(local_device_info_provider),
+ weak_ptr_factory_(this) {}
+
+SharingDeviceRegistration::~SharingDeviceRegistration() = default;
+
+void SharingDeviceRegistration::RegisterDevice(RegistrationCallback callback) {
+ // TODO(himanshujaju) : Extract a static function to convert ECPrivateKey* to
+ // Base64PublicKey in library.
+ crypto::ECPrivateKey* vapid_key = vapid_key_manager_->GetOrCreateKey();
+ if (!vapid_key) {
+ std::move(callback).Run(Result::FAILURE);
+ return;
+ }
+
+ std::string public_key;
+ if (!gcm::GetRawPublicKey(*vapid_key, &public_key)) {
+ std::move(callback).Run(Result::FAILURE);
+ return;
+ }
+
+ std::string base64_public_key;
+ base::Base64UrlEncode(public_key, base::Base64UrlEncodePolicy::OMIT_PADDING,
+ &base64_public_key);
+
+ instance_id_driver_->GetInstanceID(kSharingFCMAppID)
+ ->GetToken(
+ base64_public_key, kFCMScope,
+ /*options=*/{},
+ /*is_lazy=*/false,
+ base::BindOnce(&SharingDeviceRegistration::OnFCMTokenReceived,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SharingDeviceRegistration::OnFCMTokenReceived(
+ RegistrationCallback callback,
+ const std::string& fcm_registration_token,
+ instance_id::InstanceID::Result result) {
+ if (result != instance_id::InstanceID::SUCCESS) {
+ std::move(callback).Run(Result::FAILURE);
+ return;
+ }
+
+ gcm_driver_->GetEncryptionInfo(
+ kSharingFCMAppID,
+ base::AdaptCallbackForRepeating(
+ base::BindOnce(&SharingDeviceRegistration::OnEncryptionInfoReceived,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ fcm_registration_token)));
+}
+
+void SharingDeviceRegistration::OnEncryptionInfoReceived(
+ RegistrationCallback callback,
+ const std::string& fcm_registration_token,
+ const std::string& p256dh,
+ const std::string& auth_secret) const {
+ int device_capabilities = GetDeviceCapabilities();
+ std::string device_guid =
+ local_device_info_provider_->GetLocalDeviceInfo()->guid();
+ SharingSyncPreference::Device device(fcm_registration_token, p256dh,
+ auth_secret, device_capabilities);
+
+ sharing_sync_preference_->SetSyncDevice(device_guid, device);
+ std::move(callback).Run(Result::SUCCESS);
+}
+
+int SharingDeviceRegistration::GetDeviceCapabilities() const {
+ int device_capabilities = static_cast<int>(SharingDeviceCapability::kNone);
+ return device_capabilities;
+}
diff --git a/chrome/browser/sharing/sharing_device_registration.h b/chrome/browser/sharing/sharing_device_registration.h
new file mode 100644
index 0000000..22b6ad5
--- /dev/null
+++ b/chrome/browser/sharing/sharing_device_registration.h
@@ -0,0 +1,91 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SHARING_SHARING_DEVICE_REGISTRATION_H_
+#define CHROME_BROWSER_SHARING_SHARING_DEVICE_REGISTRATION_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+
+namespace instance_id {
+class InstanceIDDriver;
+}
+
+namespace gcm {
+class GCMDriver;
+}
+
+namespace syncer {
+class LocalDeviceInfoProvider;
+}
+
+class SharingSyncPreference;
+
+class VapidKeyManager;
+
+// Responsible for registering and unregistering device with
+// SharingSyncPreference.
+class SharingDeviceRegistration {
+ public:
+ // Result of device registration with Sharing.
+ enum class Result {
+ // Device registered successfully.
+ SUCCESS = 0,
+ // Device registration failed.
+ FAILURE = 1
+ };
+
+ using RegistrationCallback = base::OnceCallback<void(Result)>;
+
+ SharingDeviceRegistration(
+ SharingSyncPreference* prefs,
+ instance_id::InstanceIDDriver* instance_id_driver,
+ VapidKeyManager* vapid_key_manager,
+ gcm::GCMDriver* gcm_driver,
+ syncer::LocalDeviceInfoProvider* device_info_tracker);
+ ~SharingDeviceRegistration();
+
+ // Registers device with sharing sync preferences. Takes a |callback| function
+ // which receives the result of FCM registration for device.
+ void RegisterDevice(RegistrationCallback callback);
+
+ private:
+ // Callback function responsible for validating FCM registration token and
+ // retrieving public encryption key and authentication secret associated with
+ // FCM App ID of Sharing. Also responsible for calling |callback| with
+ // |result| of GetToken.
+ void OnFCMTokenReceived(RegistrationCallback callback,
+ const std::string& fcm_registration_token,
+ instance_id::InstanceID::Result result);
+
+ // Callback function responsible for saving device registration information in
+ // SharingSyncPreference.
+ void OnEncryptionInfoReceived(RegistrationCallback callback,
+ const std::string& fcm_registration_token,
+ const std::string& p256dh,
+ const std::string& auth_secret) const;
+
+ // Computes and returns a bitmask of all capabilities supported by the device.
+ int GetDeviceCapabilities() const;
+
+ SharingSyncPreference* sharing_sync_preference_;
+
+ instance_id::InstanceIDDriver* instance_id_driver_;
+
+ VapidKeyManager* vapid_key_manager_;
+
+ gcm::GCMDriver* gcm_driver_;
+
+ syncer::LocalDeviceInfoProvider* local_device_info_provider_;
+
+ base::WeakPtrFactory<SharingDeviceRegistration> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharingDeviceRegistration);
+};
+
+#endif // CHROME_BROWSER_SHARING_SHARING_DEVICE_REGISTRATION_H_
diff --git a/chrome/browser/sharing/sharing_device_registration_unittest.cc b/chrome/browser/sharing/sharing_device_registration_unittest.cc
new file mode 100644
index 0000000..ac088831
--- /dev/null
+++ b/chrome/browser/sharing/sharing_device_registration_unittest.cc
@@ -0,0 +1,184 @@
+// 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_device_registration.h"
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/sharing/fake_local_device_info_provider.h"
+#include "chrome/browser/sharing/sharing_device_info.h"
+#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/sharing/vapid_key_manager.h"
+#include "components/gcm_driver/fake_gcm_driver.h"
+#include "components/gcm_driver/gcm_driver.h"
+#include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/sync_device_info/device_info.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "google_apis/gcm/engine/account_mapping.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using namespace gcm;
+using namespace instance_id;
+using namespace testing;
+
+namespace {
+const char kAppID[] = "test_app_id";
+const char kFCMToken[] = "test_fcm_token";
+const char kDevicep256dh[] = "test_p256_dh";
+const char kDeviceAuthSecret[] = "test_auth_secret";
+
+class MockInstanceIDDriver : public InstanceIDDriver {
+ public:
+ MockInstanceIDDriver() : InstanceIDDriver(/*gcm_driver=*/nullptr) {}
+ ~MockInstanceIDDriver() override = default;
+
+ MOCK_METHOD1(GetInstanceID, InstanceID*(const std::string& app_id));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockInstanceIDDriver);
+};
+
+class FakeInstanceID : public InstanceID {
+ public:
+ FakeInstanceID() : InstanceID(kAppID, /*gcm_driver = */ nullptr) {}
+ ~FakeInstanceID() override = default;
+
+ void GetID(const GetIDCallback& callback) override { NOTIMPLEMENTED(); }
+
+ void GetCreationTime(const GetCreationTimeCallback& callback) override {
+ NOTIMPLEMENTED();
+ }
+
+ void GetToken(const std::string& authorized_entity,
+ const std::string& scope,
+ const std::map<std::string, std::string>& options,
+ bool is_lazy,
+ GetTokenCallback callback) override {
+ std::move(callback).Run(kFCMToken, result_);
+ }
+
+ void ValidateToken(const std::string& authorized_entity,
+ const std::string& scope,
+ const std::string& token,
+ const ValidateTokenCallback& callback) override {
+ NOTIMPLEMENTED();
+ }
+
+ void DeleteTokenImpl(const std::string& authorized_entity,
+ const std::string& scope,
+ DeleteTokenCallback callback) override {
+ NOTIMPLEMENTED();
+ }
+
+ void DeleteIDImpl(DeleteIDCallback callback) override { NOTIMPLEMENTED(); }
+
+ void SetFCMResult(InstanceID::Result result) { result_ = result; }
+
+ private:
+ InstanceID::Result result_;
+};
+
+class FakeEncryptionGCMDriver : public FakeGCMDriver {
+ public:
+ FakeEncryptionGCMDriver() {}
+ ~FakeEncryptionGCMDriver() override {}
+
+ void GetEncryptionInfo(const std::string& app_id,
+ const GetEncryptionInfoCallback& callback) override {
+ std::move(callback).Run(kDevicep256dh, kDeviceAuthSecret);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeEncryptionGCMDriver);
+};
+
+class SharingDeviceRegistrationTest : public testing::Test {
+ public:
+ SharingDeviceRegistrationTest()
+ : sync_prefs_(&prefs_),
+ vapid_key_manager_(&sync_prefs_),
+ sharing_device_registration_(&sync_prefs_,
+ &mock_instance_id_driver_,
+ &vapid_key_manager_,
+ &fake_encryption_gcm_driver_,
+ &fake_local_device_info_provider_) {
+ SharingSyncPreference::RegisterProfilePrefs(prefs_.registry());
+ }
+
+ void SetUp() {
+ ON_CALL(mock_instance_id_driver_, GetInstanceID(_))
+ .WillByDefault(testing::Return(&fake_instance_id_));
+ }
+
+ void RegisterDeviceSync() {
+ base::RunLoop run_loop;
+ sharing_device_registration_.RegisterDevice(
+ base::BindLambdaForTesting([&](SharingDeviceRegistration::Result r) {
+ result_ = r;
+ devices_ = sync_prefs_.GetSyncedDevices();
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+
+ void SetInstanceIDFCMResult(InstanceID::Result result) {
+ fake_instance_id_.SetFCMResult(result);
+ }
+
+ protected:
+ content::TestBrowserThreadBundle thread_bundle_;
+
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+ FakeEncryptionGCMDriver fake_encryption_gcm_driver_;
+ NiceMock<MockInstanceIDDriver> mock_instance_id_driver_;
+ FakeLocalDeviceInfoProvider fake_local_device_info_provider_;
+ FakeInstanceID fake_instance_id_;
+
+ SharingSyncPreference sync_prefs_;
+ VapidKeyManager vapid_key_manager_;
+ SharingDeviceRegistration sharing_device_registration_;
+
+ // callback results
+ std::map<std::string, SharingSyncPreference::Device> devices_;
+ SharingDeviceRegistration::Result result_;
+};
+
+} // namespace
+
+TEST_F(SharingDeviceRegistrationTest, RegisterDeviceTest_Success) {
+ SetInstanceIDFCMResult(InstanceID::Result::SUCCESS);
+
+ RegisterDeviceSync();
+
+ EXPECT_EQ(SharingDeviceRegistration::Result::SUCCESS, result_);
+ std::string guid =
+ fake_local_device_info_provider_.GetLocalDeviceInfo()->guid();
+ auto it = devices_.find(guid);
+
+ ASSERT_NE(devices_.end(), it);
+ SharingSyncPreference::Device device(std::move(it->second));
+ EXPECT_EQ(kDeviceAuthSecret, device.auth_secret);
+ EXPECT_EQ(kDevicep256dh, device.p256dh);
+ EXPECT_EQ(kFCMToken, device.fcm_token);
+ EXPECT_EQ(static_cast<int>(SharingDeviceCapability::kNone),
+ device.capabilities);
+}
+
+TEST_F(SharingDeviceRegistrationTest, RegisterDeviceTest_Fail) {
+ SetInstanceIDFCMResult(InstanceID::Result::NETWORK_ERROR);
+
+ RegisterDeviceSync();
+
+ EXPECT_EQ(SharingDeviceRegistration::Result::FAILURE, result_);
+ std::string guid =
+ fake_local_device_info_provider_.GetLocalDeviceInfo()->guid();
+ auto it = devices_.find(guid);
+ EXPECT_EQ(devices_.end(), it);
+}
diff --git a/chrome/browser/sharing/sharing_fcm_handler.cc b/chrome/browser/sharing/sharing_fcm_handler.cc
index 65f9b2f4..f8e8010 100644
--- a/chrome/browser/sharing/sharing_fcm_handler.cc
+++ b/chrome/browser/sharing/sharing_fcm_handler.cc
@@ -4,15 +4,12 @@
#include "chrome/browser/sharing/sharing_fcm_handler.h"
+#include "chrome/browser/sharing/fcm_constants.h"
#include "chrome/browser/sharing/sharing_fcm_sender.h"
#include "chrome/browser/sharing/sharing_message_handler.h"
#include "chrome/browser/sharing/sharing_service_factory.h"
#include "components/gcm_driver/gcm_driver.h"
-namespace {
-const char kSharingFCMAppID[] = "com.google.chrome.sharing.fcm";
-} // namespace
-
SharingFCMHandler::SharingFCMHandler(gcm::GCMDriver* gcm_driver,
SharingFCMSender* sharing_fcm_sender)
: gcm_driver_(gcm_driver),
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc
index 1a7ed4a..dfc65d32 100644
--- a/chrome/browser/sharing/sharing_service.cc
+++ b/chrome/browser/sharing/sharing_service.cc
@@ -8,10 +8,16 @@
#include <map>
#include <unordered_set>
+#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/time/time.h"
+#include "chrome/browser/sharing/features.h"
#include "chrome/browser/sharing/sharing_device_info.h"
+#include "chrome/browser/sharing/sharing_device_registration.h"
#include "chrome/browser/sharing/sharing_message_handler.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/sharing/vapid_key_manager.h"
+#include "components/sync/driver/sync_service.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_device_info/device_info_tracker.h"
@@ -22,14 +28,30 @@
SharingService::SharingService(
std::unique_ptr<SharingSyncPreference> sync_prefs,
- syncer::DeviceInfoTracker* device_info_tracker)
+ std::unique_ptr<SharingDeviceRegistration> sharing_device_registration,
+ std::unique_ptr<VapidKeyManager> vapid_key_manager,
+ syncer::DeviceInfoTracker* device_info_tracker,
+ syncer::SyncService* sync_service)
: sync_prefs_(std::move(sync_prefs)),
- device_info_tracker_(device_info_tracker) {
+ sharing_device_registration_(std::move(sharing_device_registration)),
+ vapid_key_manager_(std::move(vapid_key_manager)),
+ device_info_tracker_(device_info_tracker),
+ sync_service_(sync_service),
+ weak_ptr_factory_(this) {
DCHECK(sync_prefs_);
+ DCHECK(sharing_device_registration_);
+ DCHECK(vapid_key_manager_);
DCHECK(device_info_tracker_);
+ DCHECK(sync_service_);
+
+ if (!sync_service_->HasObserver(this))
+ sync_service_->AddObserver(this);
}
-SharingService::~SharingService() = default;
+SharingService::~SharingService() {
+ if (sync_service_ && sync_service_->HasObserver(this))
+ sync_service_->RemoveObserver(this);
+}
std::vector<SharingDeviceInfo> SharingService::GetDeviceCandidates(
int required_capabilities) const {
@@ -88,3 +110,33 @@
void SharingService::RegisterHandler(
chrome_browser_sharing::SharingMessage::PayloadCase payload_type,
SharingMessageHandler* handler) {}
+
+void SharingService::OnSyncShutdown(syncer::SyncService* sync) {
+ if (sync_service_ && sync_service_->HasObserver(this))
+ sync_service_->RemoveObserver(this);
+ sync_service_ = nullptr;
+}
+
+void SharingService::OnStateChanged(syncer::SyncService* sync) {
+ if (IsEnabled()) {
+ sharing_device_registration_->RegisterDevice(base::BindOnce(
+ &SharingService::OnDeviceRegistered, weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+void SharingService::OnDeviceRegistered(
+ SharingDeviceRegistration::Result result) {
+ // TODO(himanshujaju) : Add retry logic and logging
+}
+
+bool SharingService::IsEnabled() const {
+ bool sync_enabled_and_active =
+ sync_service_ &&
+ sync_service_->GetTransportState() ==
+ syncer::SyncService::TransportState::ACTIVE &&
+ sync_service_->GetActiveDataTypes().Has(syncer::PREFERENCES);
+ bool device_registration_enabled =
+ base::FeatureList::IsEnabled(kSharingDeviceRegistration);
+
+ return sync_enabled_and_active && device_registration_enabled;
+}
diff --git a/chrome/browser/sharing/sharing_service.h b/chrome/browser/sharing/sharing_service.h
index 4002fd6..dbe05d67 100644
--- a/chrome/browser/sharing/sharing_service.h
+++ b/chrome/browser/sharing/sharing_service.h
@@ -9,23 +9,32 @@
#include <string>
#include <vector>
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/sharing/proto/sharing_message.pb.h"
+#include "chrome/browser/sharing/sharing_device_registration.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/sync/driver/sync_service_observer.h"
namespace syncer {
class DeviceInfoTracker;
+class SyncService;
} // namespace syncer
class SharingDeviceInfo;
class SharingMessageHandler;
class SharingSyncPreference;
+class VapidKeyManager;
// Class to manage lifecycle of sharing feature, and provide APIs to send
// sharing messages to other devices.
-class SharingService : public KeyedService {
+class SharingService : public KeyedService, syncer::SyncServiceObserver {
public:
- SharingService(std::unique_ptr<SharingSyncPreference> sync_prefs,
- syncer::DeviceInfoTracker* device_info_tracker);
+ SharingService(
+ std::unique_ptr<SharingSyncPreference> sync_prefs,
+ std::unique_ptr<SharingDeviceRegistration> sharing_device_registration,
+ std::unique_ptr<VapidKeyManager> vapid_key_manager,
+ syncer::DeviceInfoTracker* device_info_tracker,
+ syncer::SyncService* sync_service);
~SharingService() override;
// Returns a list of DeviceInfo that is available to receive messages.
@@ -45,8 +54,22 @@
SharingMessageHandler* handler);
private:
+ // Overrides for syncer::SyncServiceObserver.
+ void OnSyncShutdown(syncer::SyncService* sync) override;
+ void OnStateChanged(syncer::SyncService* sync) override;
+
+ void OnDeviceRegistered(SharingDeviceRegistration::Result result);
+
+ // Returns true if cross-device Sharing features enabled, false otherwise.
+ bool IsEnabled() const;
+
std::unique_ptr<SharingSyncPreference> sync_prefs_;
+ std::unique_ptr<SharingDeviceRegistration> sharing_device_registration_;
+ std::unique_ptr<VapidKeyManager> vapid_key_manager_;
syncer::DeviceInfoTracker* device_info_tracker_;
+ syncer::SyncService* sync_service_;
+
+ base::WeakPtrFactory<SharingService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SharingService);
};
diff --git a/chrome/browser/sharing/sharing_service_factory.cc b/chrome/browser/sharing/sharing_service_factory.cc
index 7b294a2..9dc7c105 100644
--- a/chrome/browser/sharing/sharing_service_factory.cc
+++ b/chrome/browser/sharing/sharing_service_factory.cc
@@ -7,13 +7,23 @@
#include <memory>
#include "base/memory/singleton.h"
+#include "chrome/browser/gcm/gcm_profile_service_factory.h"
+#include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sharing/sharing_device_registration.h"
#include "chrome/browser/sharing/sharing_service.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/sharing/vapid_key_manager.h"
#include "chrome/browser/sync/device_info_sync_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "components/gcm_driver/gcm_driver.h"
+#include "components/gcm_driver/gcm_profile_service.h"
+#include "components/gcm_driver/instance_id/instance_id_profile_service.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/sync/driver/sync_service.h"
#include "components/sync_device_info/device_info_sync_service.h"
+#include "components/sync_device_info/local_device_info_provider.h"
#include "content/public/browser/browser_context.h"
namespace {
@@ -36,7 +46,10 @@
: BrowserContextKeyedServiceFactory(
kServiceName,
BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
+ DependsOn(instance_id::InstanceIDProfileServiceFactory::GetInstance());
DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
+ DependsOn(ProfileSyncServiceFactory::GetInstance());
}
SharingServiceFactory::~SharingServiceFactory() = default;
@@ -44,15 +57,36 @@
KeyedService* SharingServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
+ syncer::SyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile);
+ if (!sync_service)
+ return nullptr;
+
+ gcm::GCMProfileService* gcm_profile_service =
+ gcm::GCMProfileServiceFactory::GetForProfile(profile);
+ instance_id::InstanceIDProfileService* instance_id_service =
+ instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile);
syncer::DeviceInfoTracker* device_info_tracker =
DeviceInfoSyncServiceFactory::GetForProfile(profile)
->GetDeviceInfoTracker();
+ syncer::LocalDeviceInfoProvider* local_device_info_provider =
+ DeviceInfoSyncServiceFactory::GetForProfile(profile)
+ ->GetLocalDeviceInfoProvider();
std::unique_ptr<SharingSyncPreference> sync_prefs =
std::make_unique<SharingSyncPreference>(profile->GetPrefs());
+ std::unique_ptr<VapidKeyManager> vapid_key_manager =
+ std::make_unique<VapidKeyManager>(sync_prefs.get());
+ std::unique_ptr<SharingDeviceRegistration> sharing_device_registration =
+ std::make_unique<SharingDeviceRegistration>(
+ sync_prefs.get(), instance_id_service->driver(),
+ vapid_key_manager.get(), gcm_profile_service->driver(),
+ local_device_info_provider);
- return new SharingService(std::move(sync_prefs), device_info_tracker);
+ return new SharingService(
+ std::move(sync_prefs), std::move(sharing_device_registration),
+ std::move(vapid_key_manager), device_info_tracker, sync_service);
}
content::BrowserContext* SharingServiceFactory::GetBrowserContextToUse(
@@ -60,8 +94,10 @@
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
+// Due to the dependency on SyncService, this cannot be instantiated before
+// the profile is fully initialized.
bool SharingServiceFactory::ServiceIsCreatedWithBrowserContext() const {
- return true;
+ return false;
}
bool SharingServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/sharing/sharing_service_unittest.cc b/chrome/browser/sharing/sharing_service_unittest.cc
index 3e41aa2..78f18aa 100644
--- a/chrome/browser/sharing/sharing_service_unittest.cc
+++ b/chrome/browser/sharing/sharing_service_unittest.cc
@@ -10,26 +10,52 @@
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/test/scoped_task_environment.h"
+#include "chrome/browser/sharing/fake_local_device_info_provider.h"
#include "chrome/browser/sharing/sharing_device_info.h"
+#include "chrome/browser/sharing/sharing_device_registration.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/sharing/vapid_key_manager.h"
+#include "components/gcm_driver/fake_gcm_driver.h"
+#include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/sync/driver/fake_sync_service.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_device_info/fake_device_info_tracker.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::test::ScopedTaskEnvironment;
+using namespace instance_id;
+using namespace testing;
namespace {
constexpr int kNoCapabilities =
static_cast<int>(SharingDeviceCapability::kNone);
+class MockInstanceIDDriver : public InstanceIDDriver {
+ public:
+ MockInstanceIDDriver() : InstanceIDDriver(/*gcm_driver=*/nullptr) {}
+ ~MockInstanceIDDriver() override = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockInstanceIDDriver);
+};
+
class SharingServiceTest : public testing::Test {
public:
SharingServiceTest() {
sync_prefs_ = new SharingSyncPreference(&prefs_);
+ vapid_key_manager_ = new VapidKeyManager(sync_prefs_);
+ sharing_device_registration_ = new SharingDeviceRegistration(
+ sync_prefs_, &mock_instance_id_driver_, vapid_key_manager_,
+ &fake_gcm_driver_, &fake_local_device_info_provider_);
+
sharing_service_ = std::make_unique<SharingService>(
- base::WrapUnique(sync_prefs_), &device_info_tracker_);
+ base::WrapUnique(sync_prefs_),
+ base::WrapUnique(sharing_device_registration_),
+ base::WrapUnique(vapid_key_manager_), &device_info_tracker_,
+ &fake_sync_service_);
SharingSyncPreference::RegisterProfilePrefs(prefs_.registry());
}
@@ -53,8 +79,16 @@
ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME};
syncer::FakeDeviceInfoTracker device_info_tracker_;
- SharingSyncPreference* sync_prefs_ = nullptr;
- std::unique_ptr<SharingService> sharing_service_;
+ gcm::FakeGCMDriver fake_gcm_driver_;
+ FakeLocalDeviceInfoProvider fake_local_device_info_provider_;
+ syncer::FakeSyncService fake_sync_service_;
+
+ NiceMock<MockInstanceIDDriver> mock_instance_id_driver_;
+
+ SharingSyncPreference* sync_prefs_;
+ VapidKeyManager* vapid_key_manager_;
+ SharingDeviceRegistration* sharing_device_registration_;
+ std::unique_ptr<SharingService> sharing_service_ = nullptr;
private:
sync_preferences::TestingPrefServiceSyncable prefs_;
@@ -150,3 +184,5 @@
ASSERT_EQ(1u, candidates.size());
EXPECT_EQ(id2, candidates[0].guid());
}
+
+// TODO(himanshujaju) Add tests for RegisterDevice
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 481aabc..3f84cc3 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3049,6 +3049,9 @@
"../browser/sessions/chrome_serialized_navigation_driver_unittest.cc",
"../browser/sessions/restore_on_startup_policy_handler_unittest.cc",
"../browser/sessions/session_common_utils_unittest.cc",
+ "../browser/sharing/fake_local_device_info_provider.cc",
+ "../browser/sharing/fake_local_device_info_provider.h",
+ "../browser/sharing/sharing_device_registration_unittest.cc",
"../browser/sharing/sharing_fcm_handler_unittest.cc",
"../browser/sharing/sharing_service_unittest.cc",
"../browser/sharing/sharing_sync_preference_unittest.cc",