Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: sync/notifier/chrome_invalidation_client.cc

Issue 10907070: [Sync] Rename classes in sync/ that start with Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "sync/notifier/chrome_invalidation_client.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/callback.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/tracked_objects.h"
14 #include "google/cacheinvalidation/include/invalidation-client.h"
15 #include "google/cacheinvalidation/include/types.h"
16 #include "google/cacheinvalidation/types.pb.h"
17 #include "jingle/notifier/listener/push_client.h"
18 #include "sync/notifier/invalidation_util.h"
19 #include "sync/notifier/registration_manager.h"
20
21 namespace {
22
23 const char kApplicationName[] = "chrome-sync";
24
25 } // namespace
26
27 namespace syncer {
28
29 ChromeInvalidationClient::Listener::~Listener() {}
30
31 ChromeInvalidationClient::ChromeInvalidationClient(
32 scoped_ptr<notifier::PushClient> push_client)
33 : push_client_(push_client.get()),
34 chrome_system_resources_(push_client.Pass(),
35 ALLOW_THIS_IN_INITIALIZER_LIST(this)),
36 listener_(NULL),
37 ticl_state_(DEFAULT_NOTIFICATION_ERROR),
38 push_client_state_(DEFAULT_NOTIFICATION_ERROR) {
39 DCHECK(CalledOnValidThread());
40 push_client_->AddObserver(this);
41 }
42
43 ChromeInvalidationClient::~ChromeInvalidationClient() {
44 DCHECK(CalledOnValidThread());
45 push_client_->RemoveObserver(this);
46 Stop();
47 DCHECK(!listener_);
48 }
49
50 void ChromeInvalidationClient::Start(
51 const CreateInvalidationClientCallback&
52 create_invalidation_client_callback,
53 const std::string& client_id, const std::string& client_info,
54 const std::string& state,
55 const InvalidationVersionMap& initial_max_invalidation_versions,
56 const WeakHandle<InvalidationStateTracker>& invalidation_state_tracker,
57 Listener* listener) {
58 DCHECK(CalledOnValidThread());
59 Stop();
60
61 chrome_system_resources_.set_platform(client_info);
62 chrome_system_resources_.Start();
63
64 // The Storage resource is implemented as a write-through cache. We populate
65 // it with the initial state on startup, so subsequent writes go to disk and
66 // update the in-memory cache, while reads just return the cached state.
67 chrome_system_resources_.storage()->SetInitialState(state);
68
69 max_invalidation_versions_ = initial_max_invalidation_versions;
70 if (max_invalidation_versions_.empty()) {
71 DVLOG(2) << "No initial max invalidation versions for any id";
72 } else {
73 for (InvalidationVersionMap::const_iterator it =
74 max_invalidation_versions_.begin();
75 it != max_invalidation_versions_.end(); ++it) {
76 DVLOG(2) << "Initial max invalidation version for "
77 << ObjectIdToString(it->first) << " is "
78 << it->second;
79 }
80 }
81 invalidation_state_tracker_ = invalidation_state_tracker;
82 DCHECK(invalidation_state_tracker_.IsInitialized());
83
84 DCHECK(!listener_);
85 DCHECK(listener);
86 listener_ = listener;
87
88 int client_type = ipc::invalidation::ClientType::CHROME_SYNC;
89 invalidation_client_.reset(
90 create_invalidation_client_callback.Run(
91 &chrome_system_resources_, client_type, client_id,
92 kApplicationName, this));
93 invalidation_client_->Start();
94
95 registration_manager_.reset(
96 new RegistrationManager(invalidation_client_.get()));
97 }
98
99 void ChromeInvalidationClient::UpdateCredentials(
100 const std::string& email, const std::string& token) {
101 DCHECK(CalledOnValidThread());
102 chrome_system_resources_.network()->UpdateCredentials(email, token);
103 }
104
105 void ChromeInvalidationClient::UpdateRegisteredIds(const ObjectIdSet& ids) {
106 DCHECK(CalledOnValidThread());
107 registered_ids_ = ids;
108 // |ticl_state_| can go to NO_NOTIFICATION_ERROR even without a
109 // working XMPP connection (as observed by us), so check it instead
110 // of GetState() (see http://crbug.com/139424).
111 if (ticl_state_ == NO_NOTIFICATION_ERROR && registration_manager_.get()) {
112 DoRegistrationUpdate();
113 }
114 }
115
116 void ChromeInvalidationClient::Ready(
117 invalidation::InvalidationClient* client) {
118 DCHECK(CalledOnValidThread());
119 DCHECK_EQ(client, invalidation_client_.get());
120 ticl_state_ = NO_NOTIFICATION_ERROR;
121 EmitStateChange();
122 DoRegistrationUpdate();
123 }
124
125 void ChromeInvalidationClient::Invalidate(
126 invalidation::InvalidationClient* client,
127 const invalidation::Invalidation& invalidation,
128 const invalidation::AckHandle& ack_handle) {
129 DCHECK(CalledOnValidThread());
130 DCHECK_EQ(client, invalidation_client_.get());
131 DVLOG(1) << "Invalidate: " << InvalidationToString(invalidation);
132
133 const invalidation::ObjectId& id = invalidation.object_id();
134
135 // The invalidation API spec allows for the possibility of redundant
136 // invalidations, so keep track of the max versions and drop
137 // invalidations with old versions.
138 //
139 // TODO(akalin): Now that we keep track of registered ids, we
140 // should drop invalidations for unregistered ids. We may also
141 // have to filter it at a higher level, as invalidations for
142 // newly-unregistered ids may already be in flight.
143 InvalidationVersionMap::const_iterator it =
144 max_invalidation_versions_.find(id);
145 if ((it != max_invalidation_versions_.end()) &&
146 (invalidation.version() <= it->second)) {
147 // Drop redundant invalidations.
148 client->Acknowledge(ack_handle);
149 return;
150 }
151 DVLOG(2) << "Setting max invalidation version for " << ObjectIdToString(id)
152 << " to " << invalidation.version();
153 max_invalidation_versions_[id] = invalidation.version();
154 invalidation_state_tracker_.Call(
155 FROM_HERE,
156 &InvalidationStateTracker::SetMaxVersion,
157 id, invalidation.version());
158
159 std::string payload;
160 // payload() CHECK()'s has_payload(), so we must check it ourselves first.
161 if (invalidation.has_payload())
162 payload = invalidation.payload();
163
164 ObjectIdStateMap id_state_map;
165 id_state_map[id].payload = payload;
166 EmitInvalidation(id_state_map);
167 // TODO(akalin): We should really acknowledge only after we get the
168 // updates from the sync server. (see http://crbug.com/78462).
169 client->Acknowledge(ack_handle);
170 }
171
172 void ChromeInvalidationClient::InvalidateUnknownVersion(
173 invalidation::InvalidationClient* client,
174 const invalidation::ObjectId& object_id,
175 const invalidation::AckHandle& ack_handle) {
176 DCHECK(CalledOnValidThread());
177 DCHECK_EQ(client, invalidation_client_.get());
178 DVLOG(1) << "InvalidateUnknownVersion";
179
180 ObjectIdStateMap id_state_map;
181 id_state_map[object_id].payload = std::string();
182 EmitInvalidation(id_state_map);
183 // TODO(akalin): We should really acknowledge only after we get the
184 // updates from the sync server. (see http://crbug.com/78462).
185 client->Acknowledge(ack_handle);
186 }
187
188 // This should behave as if we got an invalidation with version
189 // UNKNOWN_OBJECT_VERSION for all known data types.
190 void ChromeInvalidationClient::InvalidateAll(
191 invalidation::InvalidationClient* client,
192 const invalidation::AckHandle& ack_handle) {
193 DCHECK(CalledOnValidThread());
194 DCHECK_EQ(client, invalidation_client_.get());
195 DVLOG(1) << "InvalidateAll";
196
197 ObjectIdStateMap id_state_map;
198 for (ObjectIdSet::const_iterator it = registered_ids_.begin();
199 it != registered_ids_.end(); ++it) {
200 id_state_map[*it].payload = std::string();
201 }
202 EmitInvalidation(id_state_map);
203 // TODO(akalin): We should really acknowledge only after we get the
204 // updates from the sync server. (see http://crbug.com/76482).
205 client->Acknowledge(ack_handle);
206 }
207
208 void ChromeInvalidationClient::EmitInvalidation(
209 const ObjectIdStateMap& id_state_map) {
210 DCHECK(CalledOnValidThread());
211 listener_->OnInvalidate(id_state_map);
212 }
213
214 void ChromeInvalidationClient::InformRegistrationStatus(
215 invalidation::InvalidationClient* client,
216 const invalidation::ObjectId& object_id,
217 InvalidationListener::RegistrationState new_state) {
218 DCHECK(CalledOnValidThread());
219 DCHECK_EQ(client, invalidation_client_.get());
220 DVLOG(1) << "InformRegistrationStatus: "
221 << ObjectIdToString(object_id) << " " << new_state;
222
223 if (new_state != InvalidationListener::REGISTERED) {
224 // Let |registration_manager_| handle the registration backoff policy.
225 registration_manager_->MarkRegistrationLost(object_id);
226 }
227 }
228
229 void ChromeInvalidationClient::InformRegistrationFailure(
230 invalidation::InvalidationClient* client,
231 const invalidation::ObjectId& object_id,
232 bool is_transient,
233 const std::string& error_message) {
234 DCHECK(CalledOnValidThread());
235 DCHECK_EQ(client, invalidation_client_.get());
236 DVLOG(1) << "InformRegistrationFailure: "
237 << ObjectIdToString(object_id)
238 << "is_transient=" << is_transient
239 << ", message=" << error_message;
240
241 if (is_transient) {
242 // We don't care about |unknown_hint|; we let
243 // |registration_manager_| handle the registration backoff policy.
244 registration_manager_->MarkRegistrationLost(object_id);
245 } else {
246 // Non-transient failures require an action to resolve. This could happen
247 // because:
248 // - the server doesn't yet recognize the data type, which could happen for
249 // brand-new data types.
250 // - the user has changed his password and hasn't updated it yet locally.
251 // Either way, block future registration attempts for |object_id|. However,
252 // we don't forget any saved invalidation state since we may use it once the
253 // error is addressed.
254 registration_manager_->DisableId(object_id);
255 }
256 }
257
258 void ChromeInvalidationClient::ReissueRegistrations(
259 invalidation::InvalidationClient* client,
260 const std::string& prefix,
261 int prefix_length) {
262 DCHECK(CalledOnValidThread());
263 DCHECK_EQ(client, invalidation_client_.get());
264 DVLOG(1) << "AllRegistrationsLost";
265 registration_manager_->MarkAllRegistrationsLost();
266 }
267
268 void ChromeInvalidationClient::InformError(
269 invalidation::InvalidationClient* client,
270 const invalidation::ErrorInfo& error_info) {
271 DCHECK(CalledOnValidThread());
272 DCHECK_EQ(client, invalidation_client_.get());
273 LOG(ERROR) << "Ticl error " << error_info.error_reason() << ": "
274 << error_info.error_message()
275 << " (transient = " << error_info.is_transient() << ")";
276 if (error_info.error_reason() == invalidation::ErrorReason::AUTH_FAILURE) {
277 ticl_state_ = NOTIFICATION_CREDENTIALS_REJECTED;
278 } else {
279 ticl_state_ = TRANSIENT_NOTIFICATION_ERROR;
280 }
281 EmitStateChange();
282 }
283
284 void ChromeInvalidationClient::WriteState(const std::string& state) {
285 DCHECK(CalledOnValidThread());
286 DVLOG(1) << "WriteState";
287 invalidation_state_tracker_.Call(
288 FROM_HERE, &InvalidationStateTracker::SetInvalidationState, state);
289 }
290
291 void ChromeInvalidationClient::DoRegistrationUpdate() {
292 DCHECK(CalledOnValidThread());
293 const ObjectIdSet& unregistered_ids =
294 registration_manager_->UpdateRegisteredIds(registered_ids_);
295 invalidation_state_tracker_.Call(
296 FROM_HERE, &InvalidationStateTracker::Forget, unregistered_ids);
297 }
298
299 void ChromeInvalidationClient::StopForTest() {
300 DCHECK(CalledOnValidThread());
301 Stop();
302 }
303
304 void ChromeInvalidationClient::Stop() {
305 DCHECK(CalledOnValidThread());
306 if (!invalidation_client_.get()) {
307 return;
308 }
309
310 registration_manager_.reset();
311 chrome_system_resources_.Stop();
312 invalidation_client_->Stop();
313
314 invalidation_client_.reset();
315 listener_ = NULL;
316
317 invalidation_state_tracker_.Reset();
318 max_invalidation_versions_.clear();
319 ticl_state_ = DEFAULT_NOTIFICATION_ERROR;
320 push_client_state_ = DEFAULT_NOTIFICATION_ERROR;
321 }
322
323 NotificationsDisabledReason ChromeInvalidationClient::GetState() const {
324 DCHECK(CalledOnValidThread());
325 if (ticl_state_ == NOTIFICATION_CREDENTIALS_REJECTED ||
326 push_client_state_ == NOTIFICATION_CREDENTIALS_REJECTED) {
327 // If either the ticl or the push client rejected our credentials,
328 // return NOTIFICATION_CREDENTIALS_REJECTED.
329 return NOTIFICATION_CREDENTIALS_REJECTED;
330 }
331 if (ticl_state_ == NO_NOTIFICATION_ERROR &&
332 push_client_state_ == NO_NOTIFICATION_ERROR) {
333 // If the ticl is ready and the push client notifications are
334 // enabled, return NO_NOTIFICATION_ERROR.
335 return NO_NOTIFICATION_ERROR;
336 }
337 // Otherwise, we have a transient error.
338 return TRANSIENT_NOTIFICATION_ERROR;
339 }
340
341 void ChromeInvalidationClient::EmitStateChange() {
342 DCHECK(CalledOnValidThread());
343 if (GetState() == NO_NOTIFICATION_ERROR) {
344 listener_->OnNotificationsEnabled();
345 } else {
346 listener_->OnNotificationsDisabled(GetState());
347 }
348 }
349
350 void ChromeInvalidationClient::OnNotificationsEnabled() {
351 DCHECK(CalledOnValidThread());
352 push_client_state_ = NO_NOTIFICATION_ERROR;
353 EmitStateChange();
354 }
355
356 void ChromeInvalidationClient::OnNotificationsDisabled(
357 notifier::NotificationsDisabledReason reason) {
358 DCHECK(CalledOnValidThread());
359 push_client_state_ = FromNotifierReason(reason);
360 EmitStateChange();
361 }
362
363 void ChromeInvalidationClient::OnIncomingNotification(
364 const notifier::Notification& notification) {
365 DCHECK(CalledOnValidThread());
366 // Do nothing, since this is already handled by |invalidation_client_|.
367 }
368
369 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698