OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/policy/device_cloud_policy_invalidator.h" | 5 #include "chrome/browser/chromeos/policy/device_cloud_policy_invalidator.h" |
6 | 6 |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/logging.h" | 7 #include "base/logging.h" |
11 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
12 #include "base/time/clock.h" | 9 #include "base/time/clock.h" |
13 #include "base/time/default_clock.h" | 10 #include "base/time/default_clock.h" |
14 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/browser_process_platform_part_chromeos.h" | 12 #include "chrome/browser/browser_process_platform_part_chromeos.h" |
16 #include "chrome/browser/chrome_notification_types.h" | |
17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" | 13 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
18 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" | 14 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" |
19 #include "chrome/browser/chromeos/policy/ticl_device_settings_provider.h" | |
20 #include "chrome/browser/chromeos/profiles/profile_helper.h" | |
21 #include "chrome/browser/chromeos/settings/device_identity_provider.h" | |
22 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
" | |
23 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" | |
24 #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h" | 15 #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h" |
25 #include "chrome/browser/profiles/profile_manager.h" | |
26 #include "chrome/common/chrome_content_client.h" | |
27 #include "components/invalidation/invalidation_handler.h" | |
28 #include "components/invalidation/invalidation_service.h" | |
29 #include "components/invalidation/invalidation_state_tracker.h" | |
30 #include "components/invalidation/invalidator_state.h" | |
31 #include "components/invalidation/invalidator_storage.h" | |
32 #include "components/invalidation/profile_invalidation_provider.h" | |
33 #include "components/invalidation/ticl_invalidation_service.h" | |
34 #include "components/invalidation/ticl_settings_provider.h" | |
35 #include "components/policy/core/common/cloud/cloud_policy_constants.h" | |
36 #include "components/user_manager/user.h" | |
37 #include "content/public/browser/notification_details.h" | |
38 #include "content/public/browser/notification_service.h" | |
39 #include "google_apis/gaia/identity_provider.h" | |
40 #include "net/url_request/url_request_context_getter.h" | |
41 #include "policy/proto/device_management_backend.pb.h" | 16 #include "policy/proto/device_management_backend.pb.h" |
42 | 17 |
43 class Profile; | |
44 | |
45 namespace policy { | 18 namespace policy { |
46 | 19 |
47 class DeviceCloudPolicyInvalidator::InvalidationServiceObserver | 20 DeviceCloudPolicyInvalidator::DeviceCloudPolicyInvalidator( |
48 : public syncer::InvalidationHandler { | 21 AffiliatedInvalidationServiceProvider* invalidation_service_provider) |
49 public: | 22 : invalidation_service_provider_(invalidation_service_provider), |
50 explicit InvalidationServiceObserver( | |
51 DeviceCloudPolicyInvalidator* parent, | |
52 invalidation::InvalidationService* invalidation_service); | |
53 ~InvalidationServiceObserver() override; | |
54 | |
55 invalidation::InvalidationService* GetInvalidationService(); | |
56 bool IsServiceConnected() const; | |
57 | |
58 // public syncer::InvalidationHandler: | |
59 void OnInvalidatorStateChange(syncer::InvalidatorState state) override; | |
60 void OnIncomingInvalidation( | |
61 const syncer::ObjectIdInvalidationMap& invalidation_map) override; | |
62 std::string GetOwnerName() const override; | |
63 | |
64 private: | |
65 DeviceCloudPolicyInvalidator* parent_; | |
66 invalidation::InvalidationService* invalidation_service_; | |
67 bool is_service_connected_; | |
68 | |
69 DISALLOW_COPY_AND_ASSIGN(InvalidationServiceObserver); | |
70 }; | |
71 | |
72 DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
73 InvalidationServiceObserver( | |
74 DeviceCloudPolicyInvalidator* parent, | |
75 invalidation::InvalidationService* invalidation_service) | |
76 : parent_(parent), | |
77 invalidation_service_(invalidation_service), | |
78 is_service_connected_(invalidation_service->GetInvalidatorState() == | |
79 syncer::INVALIDATIONS_ENABLED) { | |
80 invalidation_service_->RegisterInvalidationHandler(this); | |
81 } | |
82 | |
83 DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
84 ~InvalidationServiceObserver() { | |
85 invalidation_service_->UnregisterInvalidationHandler(this); | |
86 } | |
87 | |
88 invalidation::InvalidationService* | |
89 DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
90 GetInvalidationService() { | |
91 return invalidation_service_; | |
92 } | |
93 | |
94 bool DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
95 IsServiceConnected() const { | |
96 return is_service_connected_; | |
97 } | |
98 | |
99 void DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
100 OnInvalidatorStateChange(syncer::InvalidatorState state) { | |
101 const bool is_service_connected = (state == syncer::INVALIDATIONS_ENABLED); | |
102 if (is_service_connected == is_service_connected_) | |
103 return; | |
104 | |
105 is_service_connected_ = is_service_connected; | |
106 if (is_service_connected_) | |
107 parent_->OnInvalidationServiceConnected(invalidation_service_); | |
108 else | |
109 parent_->OnInvalidationServiceDisconnected(invalidation_service_); | |
110 } | |
111 | |
112 void DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
113 OnIncomingInvalidation( | |
114 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
115 } | |
116 | |
117 std::string DeviceCloudPolicyInvalidator::InvalidationServiceObserver:: | |
118 GetOwnerName() const { | |
119 return "DevicePolicy"; | |
120 } | |
121 | |
122 DeviceCloudPolicyInvalidator::DeviceCloudPolicyInvalidator() | |
123 : invalidation_service_(NULL), | |
124 highest_handled_invalidation_version_(0) { | 23 highest_handled_invalidation_version_(0) { |
125 // The DeviceCloudPolicyInvalidator should be created before any user | 24 invalidation_service_provider_->RegisterConsumer(this); |
126 // Profiles. | |
127 DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty()); | |
128 | |
129 // Subscribe to notification about new user profiles becoming available. | |
130 registrar_.Add(this, | |
131 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, | |
132 content::NotificationService::AllSources()); | |
133 | |
134 TryToCreateInvalidator(); | |
135 } | 25 } |
136 | 26 |
137 DeviceCloudPolicyInvalidator::~DeviceCloudPolicyInvalidator() { | 27 DeviceCloudPolicyInvalidator::~DeviceCloudPolicyInvalidator() { |
138 DestroyInvalidator(); | 28 DestroyInvalidator(); |
| 29 invalidation_service_provider_->UnregisterConsumer(this); |
139 } | 30 } |
140 | 31 |
141 void DeviceCloudPolicyInvalidator::Observe( | 32 void DeviceCloudPolicyInvalidator::OnInvalidationServiceSet( |
142 int type, | 33 invalidation::InvalidationService* invalidation_service) { |
143 const content::NotificationSource& source, | 34 DestroyInvalidator(); |
144 const content::NotificationDetails& details) { | 35 if (invalidation_service) |
145 DCHECK_EQ(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, type); | 36 CreateInvalidator(invalidation_service); |
146 Profile* profile = content::Details<Profile>(details).ptr(); | |
147 invalidation::ProfileInvalidationProvider* invalidation_provider = | |
148 invalidation::ProfileInvalidationProviderFactory::GetForProfile(profile); | |
149 if (!invalidation_provider) { | |
150 // If the Profile does not support invalidation (e.g. guest, incognito), | |
151 // ignore it. | |
152 return; | |
153 } | |
154 user_manager::User* user = | |
155 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
156 if (!user || | |
157 g_browser_process->platform_part()->browser_policy_connector_chromeos()-> | |
158 GetUserAffiliation(user->email()) != USER_AFFILIATION_MANAGED) { | |
159 // If the Profile belongs to a user who is not affiliated with the domain | |
160 // the device is enrolled into, ignore it. | |
161 return; | |
162 } | |
163 // Create a state observer for the user's invalidation service. | |
164 profile_invalidation_service_observers_.push_back( | |
165 new InvalidationServiceObserver( | |
166 this, | |
167 invalidation_provider->GetInvalidationService())); | |
168 | |
169 TryToCreateInvalidator(); | |
170 } | 37 } |
171 | 38 |
172 void DeviceCloudPolicyInvalidator::OnInvalidationServiceConnected( | 39 CloudPolicyInvalidator* |
173 invalidation::InvalidationService* invalidation_service) { | 40 DeviceCloudPolicyInvalidator::GetInvalidatorForTest() const { |
174 if (!device_invalidation_service_) { | 41 return invalidator_.get(); |
175 // The lack of a device-global invalidation service implies that a | |
176 // |CloudPolicyInvalidator| backed by another connected service exists | |
177 // already. There is no need to switch from that to the service which just | |
178 // connected. | |
179 return; | |
180 } | |
181 | |
182 if (invalidation_service != device_invalidation_service_.get()) { | |
183 // If an invalidation service other than the device-global one connected, | |
184 // destroy the device-global service and the |CloudPolicyInvalidator| backed | |
185 // by it, if any. | |
186 DestroyInvalidator(); | |
187 DestroyDeviceInvalidationService(); | |
188 } | |
189 | |
190 // Create a |CloudPolicyInvalidator| backed by the invalidation service which | |
191 // just connected. | |
192 CreateInvalidator(invalidation_service); | |
193 } | |
194 | |
195 void DeviceCloudPolicyInvalidator::OnInvalidationServiceDisconnected( | |
196 invalidation::InvalidationService* invalidation_service) { | |
197 if (invalidation_service != invalidation_service_) { | |
198 // If the invalidation service which disconnected is not backing the current | |
199 // |CloudPolicyInvalidator|, return. | |
200 return; | |
201 } | |
202 | |
203 // Destroy the |CloudPolicyInvalidator| backed by the invalidation service | |
204 // which just disconnected. | |
205 DestroyInvalidator(); | |
206 | |
207 // Try to create a |CloudPolicyInvalidator| backed by another invalidation | |
208 // service. | |
209 TryToCreateInvalidator(); | |
210 } | |
211 | |
212 void DeviceCloudPolicyInvalidator::TryToCreateInvalidator() { | |
213 if (invalidator_) { | |
214 // If a |CloudPolicyInvalidator| exists already, return. | |
215 return; | |
216 } | |
217 | |
218 for (ScopedVector<InvalidationServiceObserver>::const_iterator it = | |
219 profile_invalidation_service_observers_.begin(); | |
220 it != profile_invalidation_service_observers_.end(); ++it) { | |
221 if ((*it)->IsServiceConnected()) { | |
222 // If a connected invalidation service belonging to an affiliated | |
223 // logged-in user is found, create a |CloudPolicyInvalidator| backed by | |
224 // that service and destroy the device-global service, if any. | |
225 DestroyDeviceInvalidationService(); | |
226 CreateInvalidator((*it)->GetInvalidationService()); | |
227 return; | |
228 } | |
229 } | |
230 | |
231 if (!device_invalidation_service_) { | |
232 // If no other connected invalidation service was found, ensure that a | |
233 // device-global service is running. | |
234 device_invalidation_service_.reset( | |
235 new invalidation::TiclInvalidationService( | |
236 GetUserAgent(), | |
237 scoped_ptr<IdentityProvider>(new chromeos::DeviceIdentityProvider( | |
238 chromeos::DeviceOAuth2TokenServiceFactory::Get())), | |
239 scoped_ptr<invalidation::TiclSettingsProvider>( | |
240 new TiclDeviceSettingsProvider), | |
241 g_browser_process->gcm_driver(), | |
242 g_browser_process->system_request_context())); | |
243 device_invalidation_service_->Init( | |
244 scoped_ptr<syncer::InvalidationStateTracker>( | |
245 new invalidation::InvalidatorStorage( | |
246 g_browser_process->local_state()))); | |
247 device_invalidation_service_observer_.reset( | |
248 new InvalidationServiceObserver( | |
249 this, | |
250 device_invalidation_service_.get())); | |
251 } | |
252 | |
253 if (device_invalidation_service_observer_->IsServiceConnected()) { | |
254 // If the device-global invalidation service is connected, create a | |
255 // |CloudPolicyInvalidator| backed by it. Otherwise, a | |
256 // |CloudPolicyInvalidator| will be created later when a connected service | |
257 // becomes available. | |
258 CreateInvalidator(device_invalidation_service_.get()); | |
259 } | |
260 } | 42 } |
261 | 43 |
262 void DeviceCloudPolicyInvalidator::CreateInvalidator( | 44 void DeviceCloudPolicyInvalidator::CreateInvalidator( |
263 invalidation::InvalidationService* invalidation_service) { | 45 invalidation::InvalidationService* invalidation_service) { |
264 invalidation_service_ = invalidation_service; | |
265 DCHECK(!invalidator_); | 46 DCHECK(!invalidator_); |
266 invalidator_.reset(new CloudPolicyInvalidator( | 47 invalidator_.reset(new CloudPolicyInvalidator( |
267 enterprise_management::DeviceRegisterRequest::DEVICE, | 48 enterprise_management::DeviceRegisterRequest::DEVICE, |
268 g_browser_process->platform_part()->browser_policy_connector_chromeos()-> | 49 g_browser_process->platform_part()->browser_policy_connector_chromeos()-> |
269 GetDeviceCloudPolicyManager()->core(), | 50 GetDeviceCloudPolicyManager()->core(), |
270 base::MessageLoopProxy::current(), | 51 base::MessageLoopProxy::current(), |
271 scoped_ptr<base::Clock>(new base::DefaultClock()), | 52 scoped_ptr<base::Clock>(new base::DefaultClock()), |
272 highest_handled_invalidation_version_)); | 53 highest_handled_invalidation_version_)); |
273 invalidator_->Initialize(invalidation_service); | 54 invalidator_->Initialize(invalidation_service); |
274 } | 55 } |
275 | 56 |
276 void DeviceCloudPolicyInvalidator::DestroyInvalidator() { | 57 void DeviceCloudPolicyInvalidator::DestroyInvalidator() { |
277 if (invalidator_) { | 58 if (!invalidator_) |
278 highest_handled_invalidation_version_ = | 59 return; |
279 invalidator_->highest_handled_invalidation_version(); | 60 |
280 invalidator_->Shutdown(); | 61 highest_handled_invalidation_version_ = |
281 } | 62 invalidator_->highest_handled_invalidation_version(); |
| 63 invalidator_->Shutdown(); |
282 invalidator_.reset(); | 64 invalidator_.reset(); |
283 invalidation_service_ = NULL; | |
284 } | |
285 | |
286 void DeviceCloudPolicyInvalidator::DestroyDeviceInvalidationService() { | |
287 device_invalidation_service_observer_.reset(); | |
288 device_invalidation_service_.reset(); | |
289 } | 65 } |
290 | 66 |
291 } // namespace policy | 67 } // namespace policy |
OLD | NEW |