Fix the duplicatedly commited composition text when switching IME.
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / affiliated_invalidation_service_provider_impl.cc
blob1c81969b4b46eeefd88f8d6bd55352e283ea68b5
1 // Copyright 2015 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.
5 #include "chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/browser_process_platform_part_chromeos.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
14 #include "chrome/browser/chromeos/policy/ticl_device_settings_provider.h"
15 #include "chrome/browser/chromeos/profiles/profile_helper.h"
16 #include "chrome/browser/chromeos/settings/device_identity_provider.h"
17 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
18 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/common/chrome_content_client.h"
22 #include "components/invalidation/impl/invalidation_state_tracker.h"
23 #include "components/invalidation/impl/invalidator_storage.h"
24 #include "components/invalidation/impl/profile_invalidation_provider.h"
25 #include "components/invalidation/impl/ticl_invalidation_service.h"
26 #include "components/invalidation/impl/ticl_settings_provider.h"
27 #include "components/invalidation/public/invalidation_handler.h"
28 #include "components/invalidation/public/invalidation_service.h"
29 #include "components/invalidation/public/invalidator_state.h"
30 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
31 #include "components/user_manager/user.h"
32 #include "content/public/browser/notification_details.h"
33 #include "content/public/browser/notification_service.h"
34 #include "google_apis/gaia/identity_provider.h"
36 namespace policy {
38 class AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver
39 : public syncer::InvalidationHandler {
40 public:
41 explicit InvalidationServiceObserver(
42 AffiliatedInvalidationServiceProviderImpl* parent,
43 invalidation::InvalidationService* invalidation_service);
44 ~InvalidationServiceObserver() override;
46 invalidation::InvalidationService* GetInvalidationService();
47 bool IsServiceConnected() const;
49 // public syncer::InvalidationHandler:
50 void OnInvalidatorStateChange(syncer::InvalidatorState state) override;
51 void OnIncomingInvalidation(
52 const syncer::ObjectIdInvalidationMap& invalidation_map) override;
53 std::string GetOwnerName() const override;
55 private:
56 AffiliatedInvalidationServiceProviderImpl* parent_;
57 invalidation::InvalidationService* invalidation_service_;
58 bool is_service_connected_;
59 bool is_observer_ready_;
61 DISALLOW_COPY_AND_ASSIGN(InvalidationServiceObserver);
64 AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
65 InvalidationServiceObserver(
66 AffiliatedInvalidationServiceProviderImpl* parent,
67 invalidation::InvalidationService* invalidation_service)
68 : parent_(parent),
69 invalidation_service_(invalidation_service),
70 is_service_connected_(false),
71 is_observer_ready_(false) {
72 invalidation_service_->RegisterInvalidationHandler(this);
73 is_service_connected_ = invalidation_service->GetInvalidatorState() ==
74 syncer::INVALIDATIONS_ENABLED;
75 is_observer_ready_ = true;
78 AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
79 ~InvalidationServiceObserver() {
80 is_observer_ready_ = false;
81 invalidation_service_->UnregisterInvalidationHandler(this);
84 invalidation::InvalidationService*
85 AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
86 GetInvalidationService() {
87 return invalidation_service_;
90 bool AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
91 IsServiceConnected() const {
92 return is_service_connected_;
95 void AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
96 OnInvalidatorStateChange(syncer::InvalidatorState state) {
97 if (!is_observer_ready_)
98 return;
100 const bool is_service_connected = (state == syncer::INVALIDATIONS_ENABLED);
101 if (is_service_connected == is_service_connected_)
102 return;
104 is_service_connected_ = is_service_connected;
105 if (is_service_connected_)
106 parent_->OnInvalidationServiceConnected(invalidation_service_);
107 else
108 parent_->OnInvalidationServiceDisconnected(invalidation_service_);
111 void AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
112 OnIncomingInvalidation(
113 const syncer::ObjectIdInvalidationMap& invalidation_map) {
116 std::string
117 AffiliatedInvalidationServiceProviderImpl::InvalidationServiceObserver::
118 GetOwnerName() const {
119 return "AffiliatedInvalidationService";
122 AffiliatedInvalidationServiceProviderImpl::
123 AffiliatedInvalidationServiceProviderImpl()
124 : invalidation_service_(nullptr),
125 consumer_count_(0),
126 is_shut_down_(false) {
127 // The AffiliatedInvalidationServiceProviderImpl should be created before any
128 // user Profiles.
129 DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty());
131 // Subscribe to notification about new user profiles becoming available.
132 registrar_.Add(this,
133 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
134 content::NotificationService::AllSources());
137 AffiliatedInvalidationServiceProviderImpl::
138 ~AffiliatedInvalidationServiceProviderImpl() {
139 // Verify that the provider was shut down first.
140 DCHECK(is_shut_down_);
143 void AffiliatedInvalidationServiceProviderImpl::Observe(
144 int type,
145 const content::NotificationSource& source,
146 const content::NotificationDetails& details) {
147 DCHECK_EQ(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, type);
148 DCHECK(!is_shut_down_);
149 Profile* profile = content::Details<Profile>(details).ptr();
150 invalidation::ProfileInvalidationProvider* invalidation_provider =
151 invalidation::ProfileInvalidationProviderFactory::GetForProfile(profile);
152 if (!invalidation_provider) {
153 // If the Profile does not support invalidation (e.g. guest, incognito),
154 // ignore it.
155 return;
157 const user_manager::User* user =
158 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
159 if (!user ||
160 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
161 GetUserAffiliation(user->email()) != USER_AFFILIATION_MANAGED) {
162 // If the Profile belongs to a user who is not affiliated with the device's
163 // enrollment domain, ignore it.
164 return;
167 // Create a state observer for the user's invalidation service.
168 invalidation::InvalidationService* invalidation_service =
169 invalidation_provider->GetInvalidationService();
170 profile_invalidation_service_observers_.push_back(
171 new InvalidationServiceObserver(this, invalidation_service));
173 if (profile_invalidation_service_observers_.back()->IsServiceConnected()) {
174 // If the invalidation service is connected, check whether to switch to it.
175 OnInvalidationServiceConnected(invalidation_service);
179 void AffiliatedInvalidationServiceProviderImpl::RegisterConsumer(
180 Consumer* consumer) {
181 if (consumers_.HasObserver(consumer) || is_shut_down_)
182 return;
184 consumers_.AddObserver(consumer);
185 ++consumer_count_;
187 if (invalidation_service_)
188 consumer->OnInvalidationServiceSet(invalidation_service_);
189 else if (consumer_count_ == 1)
190 FindConnectedInvalidationService();
193 void AffiliatedInvalidationServiceProviderImpl::UnregisterConsumer(
194 Consumer* consumer) {
195 if (!consumers_.HasObserver(consumer))
196 return;
198 consumers_.RemoveObserver(consumer);
199 --consumer_count_;
201 if (invalidation_service_ && consumer_count_ == 0) {
202 invalidation_service_ = nullptr;
203 DestroyDeviceInvalidationService();
207 void AffiliatedInvalidationServiceProviderImpl::Shutdown() {
208 is_shut_down_ = true;
210 registrar_.RemoveAll();
211 profile_invalidation_service_observers_.clear();
212 device_invalidation_service_observer_.reset();
214 if (invalidation_service_) {
215 invalidation_service_ = nullptr;
216 // Explicitly notify consumers that the invalidation service they were using
217 // is no longer available.
218 SetInvalidationService(nullptr);
221 DestroyDeviceInvalidationService();
224 invalidation::TiclInvalidationService*
225 AffiliatedInvalidationServiceProviderImpl::
226 GetDeviceInvalidationServiceForTest() const {
227 return device_invalidation_service_.get();
230 void AffiliatedInvalidationServiceProviderImpl::OnInvalidationServiceConnected(
231 invalidation::InvalidationService* invalidation_service) {
232 DCHECK(!is_shut_down_);
234 if (consumer_count_ == 0) {
235 // If there are no consumers, no invalidation service is required.
236 return;
239 if (!device_invalidation_service_) {
240 // The lack of a device-global invalidation service implies that another
241 // connected invalidation service is being made available to consumers
242 // already. There is no need to switch from that to the service which just
243 // connected.
244 return;
247 // Make the invalidation service that just connected available to consumers.
248 invalidation_service_ = nullptr;
249 SetInvalidationService(invalidation_service);
251 if (invalidation_service_ &&
252 device_invalidation_service_ &&
253 invalidation_service_ != device_invalidation_service_.get()) {
254 // If a different invalidation service is being made available to consumers
255 // now, destroy the device-global one.
256 DestroyDeviceInvalidationService();
261 void
262 AffiliatedInvalidationServiceProviderImpl::OnInvalidationServiceDisconnected(
263 invalidation::InvalidationService* invalidation_service) {
264 DCHECK(!is_shut_down_);
266 if (invalidation_service != invalidation_service_) {
267 // If the invalidation service which disconnected was not being made
268 // available to consumers, return.
269 return;
272 // The invalidation service which disconnected was being made available to
273 // consumers. Stop making it available.
274 DCHECK(consumer_count_);
275 invalidation_service_ = nullptr;
277 // Try to make another invalidation service available to consumers.
278 FindConnectedInvalidationService();
280 // If no other connected invalidation service was found, explicitly notify
281 // consumers that the invalidation service they were using is no longer
282 // available.
283 if (!invalidation_service_)
284 SetInvalidationService(nullptr);
287 void
288 AffiliatedInvalidationServiceProviderImpl::FindConnectedInvalidationService() {
289 DCHECK(!invalidation_service_);
290 DCHECK(consumer_count_);
291 DCHECK(!is_shut_down_);
293 for (ScopedVector<InvalidationServiceObserver>::const_iterator it =
294 profile_invalidation_service_observers_.begin();
295 it != profile_invalidation_service_observers_.end(); ++it) {
296 if ((*it)->IsServiceConnected()) {
297 // If a connected invalidation service belonging to an affiliated
298 // logged-in user is found, make it available to consumers.
299 DestroyDeviceInvalidationService();
300 SetInvalidationService((*it)->GetInvalidationService());
301 return;
305 if (!device_invalidation_service_) {
306 // If no other connected invalidation service was found and no device-global
307 // invalidation service exists, create one.
308 device_invalidation_service_.reset(
309 new invalidation::TiclInvalidationService(
310 GetUserAgent(),
311 scoped_ptr<IdentityProvider>(new chromeos::DeviceIdentityProvider(
312 chromeos::DeviceOAuth2TokenServiceFactory::Get())),
313 scoped_ptr<invalidation::TiclSettingsProvider>(
314 new TiclDeviceSettingsProvider),
315 g_browser_process->gcm_driver(),
316 g_browser_process->system_request_context()));
317 device_invalidation_service_->Init(
318 scoped_ptr<syncer::InvalidationStateTracker>(
319 new invalidation::InvalidatorStorage(
320 g_browser_process->local_state())));
321 device_invalidation_service_observer_.reset(
322 new InvalidationServiceObserver(
323 this,
324 device_invalidation_service_.get()));
327 if (device_invalidation_service_observer_->IsServiceConnected()) {
328 // If the device-global invalidation service is connected already, make it
329 // available to consumers immediately. Otherwise, the invalidation service
330 // will be made available to clients when it successfully connects.
331 OnInvalidationServiceConnected(device_invalidation_service_.get());
335 void AffiliatedInvalidationServiceProviderImpl::SetInvalidationService(
336 invalidation::InvalidationService* invalidation_service) {
337 DCHECK(!invalidation_service_);
338 invalidation_service_ = invalidation_service;
339 FOR_EACH_OBSERVER(Consumer,
340 consumers_,
341 OnInvalidationServiceSet(invalidation_service_));
344 void
345 AffiliatedInvalidationServiceProviderImpl::DestroyDeviceInvalidationService() {
346 device_invalidation_service_observer_.reset();
347 device_invalidation_service_.reset();
350 } // namespace policy