1 // Copyright 2018 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/chromeos/device_sync/device_sync_client_factory.h"
6
7 #include "base/macros.h"
8 #include "base/timer/timer.h"
9 #include "chrome/browser/chromeos/cryptauth/client_app_metadata_provider_service.h"
10 #include "chrome/browser/chromeos/cryptauth/client_app_metadata_provider_service_factory.h"
11 #include "chrome/browser/chromeos/cryptauth/gcm_device_info_provider_impl.h"
12 #include "chrome/browser/chromeos/profiles/profile_helper.h"
13 #include "chrome/browser/gcm/gcm_profile_service_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/signin/identity_manager_factory.h"
16 #include "chromeos/components/multidevice/stub_multidevice_util.h"
17 #include "chromeos/services/device_sync/device_sync_impl.h"
18 #include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
19 #include "chromeos/services/device_sync/public/cpp/device_sync_client_impl.h"
20 #include "chromeos/services/device_sync/stub_device_sync.h"
21 #include "chromeos/services/multidevice_setup/public/cpp/prefs.h"
22 #include "components/gcm_driver/gcm_profile_service.h"
23 #include "components/keyed_service/content/browser_context_dependency_manager.h"
24 #include "components/keyed_service/core/keyed_service.h"
25 #include "components/prefs/pref_service.h"
26 #include "services/network/public/cpp/shared_url_loader_factory.h"
27
28 namespace chromeos {
29
30 namespace device_sync {
31
32 namespace {
33
34 // CryptAuth enrollment is allowed only if at least one multi-device feature is
35 // enabled. This ensures that we do not unnecessarily register devices on the
36 // CryptAuth back-end when the registration would never actually be used.
IsEnrollmentAllowedByPolicy(content::BrowserContext * context)37 bool IsEnrollmentAllowedByPolicy(content::BrowserContext* context) {
38 return multidevice_setup::AreAnyMultiDeviceFeaturesAllowed(
39 Profile::FromBrowserContext(context)->GetPrefs());
40 }
41
CreateDeviceSyncImplForProfile(Profile * profile)42 std::unique_ptr<DeviceSyncBase> CreateDeviceSyncImplForProfile(
43 Profile* profile) {
44 return DeviceSyncImpl::Factory::Create(
45 IdentityManagerFactory::GetForProfile(profile),
46 gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(),
47 profile->GetPrefs(), chromeos::GcmDeviceInfoProviderImpl::GetInstance(),
48 chromeos::ClientAppMetadataProviderServiceFactory::GetForProfile(profile),
49 profile->GetURLLoaderFactory(), std::make_unique<base::OneShotTimer>());
50 }
51
52 } // namespace
53
54 // Class that wraps DeviceSyncClient in a KeyedService.
55 class DeviceSyncClientHolder : public KeyedService {
56 public:
DeviceSyncClientHolder(content::BrowserContext * context)57 explicit DeviceSyncClientHolder(content::BrowserContext* context)
58 : device_sync_(CreateDeviceSyncImplForProfile(
59 Profile::FromBrowserContext(context))),
60 device_sync_client_(DeviceSyncClientImpl::Factory::Create()) {
61 // Connect the client's mojo remote to the implementation.
62 device_sync_->BindReceiver(device_sync_client_->GetDeviceSyncRemote()
63 ->BindNewPipeAndPassReceiver());
64 // Finish client initialization.
65 device_sync_client_->Initialize(base::ThreadTaskRunnerHandle::Get());
66 }
67
device_sync_client()68 DeviceSyncClient* device_sync_client() { return device_sync_client_.get(); }
69
70 private:
71 // KeyedService:
Shutdown()72 void Shutdown() override {
73 device_sync_client_.reset();
74 device_sync_->CloseAllReceivers();
75 device_sync_.reset();
76 }
77
78 std::unique_ptr<DeviceSyncBase> device_sync_;
79 std::unique_ptr<DeviceSyncClient> device_sync_client_;
80
81 DISALLOW_COPY_AND_ASSIGN(DeviceSyncClientHolder);
82 };
83
DeviceSyncClientFactory()84 DeviceSyncClientFactory::DeviceSyncClientFactory()
85 : BrowserContextKeyedServiceFactory(
86 "DeviceSyncClient",
87 BrowserContextDependencyManager::GetInstance()) {
88 DependsOn(IdentityManagerFactory::GetInstance());
89 DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
90
91 // If ShouldUseMultideviceStubs() is true, set a stub factory to facilitate
92 // fake devices for testing in the Linux Chrome OS build. Note that this is
93 // not done when a custom factory has already been set.
94 if (multidevice::ShouldUseMultideviceStubs() &&
95 !DeviceSyncImpl::Factory::IsCustomFactorySet()) {
96 SetStubDeviceSyncFactory();
97 }
98 }
99
~DeviceSyncClientFactory()100 DeviceSyncClientFactory::~DeviceSyncClientFactory() {}
101
102 // static
GetForProfile(Profile * profile)103 DeviceSyncClient* DeviceSyncClientFactory::GetForProfile(Profile* profile) {
104 DeviceSyncClientHolder* holder = static_cast<DeviceSyncClientHolder*>(
105 GetInstance()->GetServiceForBrowserContext(profile, true));
106
107 return holder ? holder->device_sync_client() : nullptr;
108 }
109
110 // static
GetInstance()111 DeviceSyncClientFactory* DeviceSyncClientFactory::GetInstance() {
112 return base::Singleton<DeviceSyncClientFactory>::get();
113 }
114
BuildServiceInstanceFor(content::BrowserContext * context) const115 KeyedService* DeviceSyncClientFactory::BuildServiceInstanceFor(
116 content::BrowserContext* context) const {
117 // TODO(crbug.com/848347): Check prohibited by policy in services that depend
118 // on this Factory, not here.
119 if (IsEnrollmentAllowedByPolicy(context))
120 return new DeviceSyncClientHolder(context);
121
122 return nullptr;
123 }
124
ServiceIsNULLWhileTesting() const125 bool DeviceSyncClientFactory::ServiceIsNULLWhileTesting() const {
126 return true;
127 }
128
129 } // namespace device_sync
130
131 } // namespace chromeos
132