OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "google_apis/gcm/gcm_client_impl.h" | 5 #include "google_apis/gcm/gcm_client_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 return DATA_MESSAGE; | 108 return DATA_MESSAGE; |
109 return UNKNOWN; | 109 return UNKNOWN; |
110 } | 110 } |
111 | 111 |
112 } // namespace | 112 } // namespace |
113 | 113 |
114 GCMClientImpl::GCMClientImpl() | 114 GCMClientImpl::GCMClientImpl() |
115 : state_(UNINITIALIZED), | 115 : state_(UNINITIALIZED), |
116 clock_(new base::DefaultClock()), | 116 clock_(new base::DefaultClock()), |
117 url_request_context_getter_(NULL), | 117 url_request_context_getter_(NULL), |
118 pending_registrations_deleter_(&pending_registrations_), | 118 pending_registration_requests_deleter_(&pending_registration_requests_), |
119 pending_unregistrations_deleter_(&pending_unregistrations_), | 119 pending_unregistration_requests_deleter_( |
| 120 &pending_unregistration_requests_), |
120 weak_ptr_factory_(this) { | 121 weak_ptr_factory_(this) { |
121 } | 122 } |
122 | 123 |
123 GCMClientImpl::~GCMClientImpl() { | 124 GCMClientImpl::~GCMClientImpl() { |
124 } | 125 } |
125 | 126 |
126 void GCMClientImpl::Initialize( | 127 void GCMClientImpl::Initialize( |
127 const checkin_proto::ChromeBuildProto& chrome_build_proto, | 128 const checkin_proto::ChromeBuildProto& chrome_build_proto, |
128 const base::FilePath& path, | 129 const base::FilePath& path, |
129 const std::vector<std::string>& account_ids, | 130 const std::vector<std::string>& account_ids, |
(...skipping 26 matching lines...) Expand all Loading... |
156 } | 157 } |
157 | 158 |
158 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { | 159 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
159 DCHECK_EQ(LOADING, state_); | 160 DCHECK_EQ(LOADING, state_); |
160 | 161 |
161 if (!result->success) { | 162 if (!result->success) { |
162 ResetState(); | 163 ResetState(); |
163 return; | 164 return; |
164 } | 165 } |
165 | 166 |
| 167 registrations_ = result->registrations; |
| 168 |
166 device_checkin_info_.android_id = result->device_android_id; | 169 device_checkin_info_.android_id = result->device_android_id; |
167 device_checkin_info_.secret = result->device_security_token; | 170 device_checkin_info_.secret = result->device_security_token; |
168 InitializeMCSClient(result.Pass()); | 171 InitializeMCSClient(result.Pass()); |
169 if (!device_checkin_info_.IsValid()) { | 172 if (!device_checkin_info_.IsValid()) { |
170 device_checkin_info_.Reset(); | 173 device_checkin_info_.Reset(); |
171 state_ = INITIAL_DEVICE_CHECKIN; | 174 state_ = INITIAL_DEVICE_CHECKIN; |
172 StartCheckin(device_checkin_info_); | 175 StartCheckin(device_checkin_info_); |
173 return; | 176 return; |
174 } | 177 } |
175 | 178 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 // TODO(fgorski): Reset the checkin timer. | 280 // TODO(fgorski): Reset the checkin timer. |
278 } | 281 } |
279 } | 282 } |
280 } | 283 } |
281 | 284 |
282 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { | 285 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { |
283 // TODO(fgorski): This is one of the signals that store needs a rebuild. | 286 // TODO(fgorski): This is one of the signals that store needs a rebuild. |
284 DCHECK(success); | 287 DCHECK(success); |
285 } | 288 } |
286 | 289 |
| 290 void GCMClientImpl::UpdateRegistrationCallback(bool success) { |
| 291 // TODO(fgorski): This is one of the signals that store needs a rebuild. |
| 292 DCHECK(success); |
| 293 } |
| 294 |
287 void GCMClientImpl::Stop() { | 295 void GCMClientImpl::Stop() { |
288 device_checkin_info_.Reset(); | 296 device_checkin_info_.Reset(); |
289 mcs_client_.reset(); | 297 mcs_client_.reset(); |
290 checkin_request_.reset(); | 298 checkin_request_.reset(); |
291 pending_registrations_.clear(); | 299 pending_registration_requests_.clear(); |
292 state_ = INITIALIZED; | 300 state_ = INITIALIZED; |
293 gcm_store_->Close(); | 301 gcm_store_->Close(); |
294 } | 302 } |
295 | 303 |
296 void GCMClientImpl::CheckOut() { | 304 void GCMClientImpl::CheckOut() { |
297 Stop(); | 305 Stop(); |
298 gcm_store_->Destroy(base::Bind(&GCMClientImpl::OnGCMStoreDestroyed, | 306 gcm_store_->Destroy(base::Bind(&GCMClientImpl::OnGCMStoreDestroyed, |
299 weak_ptr_factory_.GetWeakPtr())); | 307 weak_ptr_factory_.GetWeakPtr())); |
300 } | 308 } |
301 | 309 |
302 void GCMClientImpl::Register(const std::string& app_id, | 310 void GCMClientImpl::Register(const std::string& app_id, |
303 const std::vector<std::string>& sender_ids) { | 311 const std::vector<std::string>& sender_ids) { |
304 DCHECK_EQ(state_, READY); | 312 DCHECK_EQ(state_, READY); |
| 313 |
| 314 // If the same sender ids is provided, return the cached registration ID |
| 315 // directly. |
| 316 RegistrationInfoMap::const_iterator registrations_iter = |
| 317 registrations_.find(app_id); |
| 318 if (registrations_iter != registrations_.end() && |
| 319 registrations_iter->second->sender_ids == sender_ids) { |
| 320 delegate_->OnRegisterFinished( |
| 321 app_id, registrations_iter->second->registration_id, SUCCESS); |
| 322 return; |
| 323 } |
| 324 |
305 RegistrationRequest::RequestInfo request_info( | 325 RegistrationRequest::RequestInfo request_info( |
306 device_checkin_info_.android_id, | 326 device_checkin_info_.android_id, |
307 device_checkin_info_.secret, | 327 device_checkin_info_.secret, |
308 app_id, | 328 app_id, |
309 sender_ids); | 329 sender_ids); |
310 DCHECK_EQ(0u, pending_registrations_.count(app_id)); | 330 DCHECK_EQ(0u, pending_registration_requests_.count(app_id)); |
311 | 331 |
312 RegistrationRequest* registration_request = | 332 RegistrationRequest* registration_request = |
313 new RegistrationRequest(request_info, | 333 new RegistrationRequest(request_info, |
314 kDefaultBackoffPolicy, | 334 kDefaultBackoffPolicy, |
315 base::Bind(&GCMClientImpl::OnRegisterCompleted, | 335 base::Bind(&GCMClientImpl::OnRegisterCompleted, |
316 weak_ptr_factory_.GetWeakPtr(), | 336 weak_ptr_factory_.GetWeakPtr(), |
317 app_id), | 337 app_id, |
| 338 sender_ids), |
318 kMaxRegistrationRetries, | 339 kMaxRegistrationRetries, |
319 url_request_context_getter_); | 340 url_request_context_getter_); |
320 pending_registrations_[app_id] = registration_request; | 341 pending_registration_requests_[app_id] = registration_request; |
321 registration_request->Start(); | 342 registration_request->Start(); |
322 } | 343 } |
323 | 344 |
324 void GCMClientImpl::OnRegisterCompleted(const std::string& app_id, | 345 void GCMClientImpl::OnRegisterCompleted( |
325 RegistrationRequest::Status status, | 346 const std::string& app_id, |
326 const std::string& registration_id) { | 347 const std::vector<std::string>& sender_ids, |
| 348 RegistrationRequest::Status status, |
| 349 const std::string& registration_id) { |
327 DCHECK(delegate_); | 350 DCHECK(delegate_); |
328 | 351 |
329 Result result; | 352 Result result; |
330 PendingRegistrations::iterator iter = pending_registrations_.find(app_id); | 353 PendingRegistrationRequests::iterator iter = |
331 if (iter == pending_registrations_.end()) | 354 pending_registration_requests_.find(app_id); |
| 355 if (iter == pending_registration_requests_.end()) |
332 result = UNKNOWN_ERROR; | 356 result = UNKNOWN_ERROR; |
333 else if (status == RegistrationRequest::INVALID_SENDER) | 357 else if (status == RegistrationRequest::INVALID_SENDER) |
334 result = INVALID_PARAMETER; | 358 result = INVALID_PARAMETER; |
335 else if (registration_id.empty()) | 359 else if (registration_id.empty()) |
336 result = SERVER_ERROR; | 360 result = SERVER_ERROR; |
337 else | 361 else |
338 result = SUCCESS; | 362 result = SUCCESS; |
339 | 363 |
| 364 if (result == SUCCESS) { |
| 365 // Cache it. |
| 366 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); |
| 367 registration->sender_ids = sender_ids; |
| 368 registration->registration_id = registration_id; |
| 369 registrations_[app_id] = registration; |
| 370 |
| 371 // Save it in the persistent store. |
| 372 gcm_store_->AddRegistration( |
| 373 app_id, |
| 374 registration, |
| 375 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 376 weak_ptr_factory_.GetWeakPtr())); |
| 377 } |
| 378 |
340 delegate_->OnRegisterFinished( | 379 delegate_->OnRegisterFinished( |
341 app_id, result == SUCCESS ? registration_id : std::string(), result); | 380 app_id, result == SUCCESS ? registration_id : std::string(), result); |
342 | 381 |
343 if (iter != pending_registrations_.end()) { | 382 if (iter != pending_registration_requests_.end()) { |
344 delete iter->second; | 383 delete iter->second; |
345 pending_registrations_.erase(iter); | 384 pending_registration_requests_.erase(iter); |
346 } | 385 } |
347 } | 386 } |
348 | 387 |
349 void GCMClientImpl::Unregister(const std::string& app_id) { | 388 void GCMClientImpl::Unregister(const std::string& app_id) { |
350 DCHECK_EQ(state_, READY); | 389 DCHECK_EQ(state_, READY); |
351 if (pending_unregistrations_.count(app_id) == 1) | 390 if (pending_unregistration_requests_.count(app_id) == 1) |
352 return; | 391 return; |
353 | 392 |
| 393 // Remove from the cache and persistent store. |
| 394 registrations_.erase(app_id); |
| 395 gcm_store_->RemoveRegistration( |
| 396 app_id, |
| 397 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 398 weak_ptr_factory_.GetWeakPtr())); |
| 399 |
354 UnregistrationRequest::RequestInfo request_info( | 400 UnregistrationRequest::RequestInfo request_info( |
355 device_checkin_info_.android_id, | 401 device_checkin_info_.android_id, |
356 device_checkin_info_.secret, | 402 device_checkin_info_.secret, |
357 app_id); | 403 app_id); |
358 | 404 |
359 UnregistrationRequest* unregistration_request = | 405 UnregistrationRequest* unregistration_request = |
360 new UnregistrationRequest( | 406 new UnregistrationRequest( |
361 request_info, | 407 request_info, |
362 kDefaultBackoffPolicy, | 408 kDefaultBackoffPolicy, |
363 base::Bind(&GCMClientImpl::OnUnregisterCompleted, | 409 base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
364 weak_ptr_factory_.GetWeakPtr(), | 410 weak_ptr_factory_.GetWeakPtr(), |
365 app_id), | 411 app_id), |
366 url_request_context_getter_); | 412 url_request_context_getter_); |
367 pending_unregistrations_[app_id] = unregistration_request; | 413 pending_unregistration_requests_[app_id] = unregistration_request; |
368 unregistration_request->Start(); | 414 unregistration_request->Start(); |
369 } | 415 } |
370 | 416 |
371 void GCMClientImpl::OnUnregisterCompleted( | 417 void GCMClientImpl::OnUnregisterCompleted( |
372 const std::string& app_id, | 418 const std::string& app_id, |
373 UnregistrationRequest::Status status) { | 419 UnregistrationRequest::Status status) { |
374 DVLOG(1) << "Unregister completed for app: " << app_id | 420 DVLOG(1) << "Unregister completed for app: " << app_id |
375 << " with " << (status ? "success." : "failure."); | 421 << " with " << (status ? "success." : "failure."); |
376 delegate_->OnUnregisterFinished( | 422 delegate_->OnUnregisterFinished( |
377 app_id, | 423 app_id, |
378 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); | 424 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); |
379 | 425 |
380 PendingUnregistrations::iterator iter = pending_unregistrations_.find(app_id); | 426 PendingUnregistrationRequests::iterator iter = |
381 if (iter == pending_unregistrations_.end()) | 427 pending_unregistration_requests_.find(app_id); |
| 428 if (iter == pending_unregistration_requests_.end()) |
382 return; | 429 return; |
383 | 430 |
384 delete iter->second; | 431 delete iter->second; |
385 pending_unregistrations_.erase(iter); | 432 pending_unregistration_requests_.erase(iter); |
386 } | 433 } |
387 | 434 |
388 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { | 435 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { |
389 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; | 436 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; |
390 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); | 437 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); |
391 } | 438 } |
392 | 439 |
393 void GCMClientImpl::Send(const std::string& app_id, | 440 void GCMClientImpl::Send(const std::string& app_id, |
394 const std::string& receiver_id, | 441 const std::string& receiver_id, |
395 const OutgoingMessage& message) { | 442 const OutgoingMessage& message) { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 default: // Treat default the same as UNKNOWN. | 579 default: // Treat default the same as UNKNOWN. |
533 DVLOG(1) << "Unknown message_type received. Message ignored. " | 580 DVLOG(1) << "Unknown message_type received. Message ignored. " |
534 << "App ID: " << data_message_stanza.category() << "."; | 581 << "App ID: " << data_message_stanza.category() << "."; |
535 break; | 582 break; |
536 } | 583 } |
537 } | 584 } |
538 | 585 |
539 void GCMClientImpl::HandleIncomingDataMessage( | 586 void GCMClientImpl::HandleIncomingDataMessage( |
540 const mcs_proto::DataMessageStanza& data_message_stanza, | 587 const mcs_proto::DataMessageStanza& data_message_stanza, |
541 MessageData& message_data) { | 588 MessageData& message_data) { |
| 589 std::string app_id = data_message_stanza.category(); |
| 590 |
| 591 // Drop the message when the app is not registered for the sender of the |
| 592 // message. |
| 593 RegistrationInfoMap::iterator iter = registrations_.find(app_id); |
| 594 if (iter == registrations_.end() || |
| 595 std::find(iter->second->sender_ids.begin(), |
| 596 iter->second->sender_ids.end(), |
| 597 data_message_stanza.from()) == iter->second->sender_ids.end()) { |
| 598 return; |
| 599 } |
| 600 |
542 IncomingMessage incoming_message; | 601 IncomingMessage incoming_message; |
543 incoming_message.sender_id = data_message_stanza.from(); | 602 incoming_message.sender_id = data_message_stanza.from(); |
544 if (data_message_stanza.has_token()) | 603 if (data_message_stanza.has_token()) |
545 incoming_message.collapse_key = data_message_stanza.token(); | 604 incoming_message.collapse_key = data_message_stanza.token(); |
546 incoming_message.data = message_data; | 605 incoming_message.data = message_data; |
547 delegate_->OnMessageReceived(data_message_stanza.category(), | 606 delegate_->OnMessageReceived(app_id, incoming_message); |
548 incoming_message); | |
549 } | 607 } |
550 | 608 |
551 void GCMClientImpl::HandleIncomingSendError( | 609 void GCMClientImpl::HandleIncomingSendError( |
552 const mcs_proto::DataMessageStanza& data_message_stanza, | 610 const mcs_proto::DataMessageStanza& data_message_stanza, |
553 MessageData& message_data) { | 611 MessageData& message_data) { |
554 SendErrorDetails send_error_details; | 612 SendErrorDetails send_error_details; |
555 send_error_details.additional_data = message_data; | 613 send_error_details.additional_data = message_data; |
556 send_error_details.result = SERVER_ERROR; | 614 send_error_details.result = SERVER_ERROR; |
557 | 615 |
558 MessageData::iterator iter = | 616 MessageData::iterator iter = |
559 send_error_details.additional_data.find(kSendErrorMessageIdKey); | 617 send_error_details.additional_data.find(kSendErrorMessageIdKey); |
560 if (iter != send_error_details.additional_data.end()) { | 618 if (iter != send_error_details.additional_data.end()) { |
561 send_error_details.message_id = iter->second; | 619 send_error_details.message_id = iter->second; |
562 send_error_details.additional_data.erase(iter); | 620 send_error_details.additional_data.erase(iter); |
563 } | 621 } |
564 | 622 |
565 delegate_->OnMessageSendError(data_message_stanza.category(), | 623 delegate_->OnMessageSendError(data_message_stanza.category(), |
566 send_error_details); | 624 send_error_details); |
567 } | 625 } |
568 | 626 |
569 void GCMClientImpl::SetMCSClientForTesting(scoped_ptr<MCSClient> mcs_client) { | 627 void GCMClientImpl::SetMCSClientForTesting(scoped_ptr<MCSClient> mcs_client) { |
570 mcs_client_ = mcs_client.Pass(); | 628 mcs_client_ = mcs_client.Pass(); |
571 } | 629 } |
572 | 630 |
573 } // namespace gcm | 631 } // namespace gcm |
OLD | NEW |