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