| 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 "components/gcm_driver/gcm_client_impl.h" | 5 #include "components/gcm_driver/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" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/sequenced_task_runner.h" | 13 #include "base/sequenced_task_runner.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/time/default_clock.h" | 17 #include "base/time/default_clock.h" |
| 18 #include "base/timer/timer.h" | 18 #include "base/timer/timer.h" |
| 19 #include "components/gcm_driver/gcm_account_mapper.h" | 19 #include "components/gcm_driver/gcm_account_mapper.h" |
| 20 #include "components/gcm_driver/gcm_backoff_policy.h" | 20 #include "components/gcm_driver/gcm_backoff_policy.h" |
| 21 #include "google_apis/gcm/base/encryptor.h" | 21 #include "google_apis/gcm/base/encryptor.h" |
| 22 #include "google_apis/gcm/base/mcs_message.h" | 22 #include "google_apis/gcm/base/mcs_message.h" |
| 23 #include "google_apis/gcm/base/mcs_util.h" | 23 #include "google_apis/gcm/base/mcs_util.h" |
| 24 #include "google_apis/gcm/engine/checkin_request.h" | 24 #include "google_apis/gcm/engine/checkin_request.h" |
| 25 #include "google_apis/gcm/engine/connection_factory_impl.h" | 25 #include "google_apis/gcm/engine/connection_factory_impl.h" |
| 26 #include "google_apis/gcm/engine/gcm_registration_request_handler.h" |
| 26 #include "google_apis/gcm/engine/gcm_store_impl.h" | 27 #include "google_apis/gcm/engine/gcm_store_impl.h" |
| 28 #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" |
| 29 #include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h" |
| 30 #include "google_apis/gcm/engine/instance_id_get_token_request_handler.h" |
| 27 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" | 31 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" |
| 28 #include "google_apis/gcm/protocol/checkin.pb.h" | 32 #include "google_apis/gcm/protocol/checkin.pb.h" |
| 29 #include "google_apis/gcm/protocol/mcs.pb.h" | 33 #include "google_apis/gcm/protocol/mcs.pb.h" |
| 30 #include "net/http/http_network_session.h" | 34 #include "net/http/http_network_session.h" |
| 31 #include "net/http/http_transaction_factory.h" | 35 #include "net/http/http_transaction_factory.h" |
| 32 #include "net/url_request/url_request_context.h" | 36 #include "net/url_request/url_request_context.h" |
| 33 #include "url/gurl.h" | 37 #include "url/gurl.h" |
| 34 | 38 |
| 35 namespace gcm { | 39 namespace gcm { |
| 36 | 40 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 60 | 64 |
| 61 enum ResetStoreError { | 65 enum ResetStoreError { |
| 62 DESTROYING_STORE_FAILED, | 66 DESTROYING_STORE_FAILED, |
| 63 INFINITE_STORE_RESET, | 67 INFINITE_STORE_RESET, |
| 64 // NOTE: always keep this entry at the end. Add new value only immediately | 68 // NOTE: always keep this entry at the end. Add new value only immediately |
| 65 // above this line. Make sure to update the corresponding histogram enum | 69 // above this line. Make sure to update the corresponding histogram enum |
| 66 // accordingly. | 70 // accordingly. |
| 67 RESET_STORE_ERROR_COUNT | 71 RESET_STORE_ERROR_COUNT |
| 68 }; | 72 }; |
| 69 | 73 |
| 74 const char kGCMScope[] = "GCM"; |
| 70 const int kMaxRegistrationRetries = 5; | 75 const int kMaxRegistrationRetries = 5; |
| 71 const char kMessageTypeDataMessage[] = "gcm"; | 76 const char kMessageTypeDataMessage[] = "gcm"; |
| 72 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; | 77 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
| 73 const char kMessageTypeKey[] = "message_type"; | 78 const char kMessageTypeKey[] = "message_type"; |
| 74 const char kMessageTypeSendErrorKey[] = "send_error"; | 79 const char kMessageTypeSendErrorKey[] = "send_error"; |
| 75 const char kSendErrorMessageIdKey[] = "google.message_id"; | 80 const char kSendErrorMessageIdKey[] = "google.message_id"; |
| 76 const char kSendMessageFromValue[] = "gcm@chrome.com"; | 81 const char kSendMessageFromValue[] = "gcm@chrome.com"; |
| 77 const int64 kDefaultUserSerialNumber = 0LL; | 82 const int64 kDefaultUserSerialNumber = 0LL; |
| 78 | 83 |
| 79 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { | 84 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 MessageType DecodeMessageType(const std::string& value) { | 167 MessageType DecodeMessageType(const std::string& value) { |
| 163 if (kMessageTypeDeletedMessagesKey == value) | 168 if (kMessageTypeDeletedMessagesKey == value) |
| 164 return DELETED_MESSAGES; | 169 return DELETED_MESSAGES; |
| 165 if (kMessageTypeSendErrorKey == value) | 170 if (kMessageTypeSendErrorKey == value) |
| 166 return SEND_ERROR; | 171 return SEND_ERROR; |
| 167 if (kMessageTypeDataMessage == value) | 172 if (kMessageTypeDataMessage == value) |
| 168 return DATA_MESSAGE; | 173 return DATA_MESSAGE; |
| 169 return UNKNOWN; | 174 return UNKNOWN; |
| 170 } | 175 } |
| 171 | 176 |
| 177 int ConstructGCMVersion(const std::string& chrome_version) { |
| 178 // Major Chrome version is passed as GCM version. |
| 179 size_t pos = chrome_version.find('.'); |
| 180 if (pos == std::string::npos) { |
| 181 NOTREACHED(); |
| 182 return 0; |
| 183 } |
| 184 |
| 185 int gcm_version = 0; |
| 186 base::StringToInt( |
| 187 base::StringPiece(chrome_version.c_str(), pos), &gcm_version); |
| 188 return gcm_version; |
| 189 } |
| 190 |
| 191 std::string SerializeInstanceIDData(const std::string& instance_id, |
| 192 const std::string& extra_data) { |
| 193 DCHECK(!instance_id.empty() && !extra_data.empty()); |
| 194 DCHECK(instance_id.find(',') == std::string::npos); |
| 195 return instance_id + "," + extra_data; |
| 196 } |
| 197 |
| 198 bool DeserializeInstanceIDData(const std::string& serialized_data, |
| 199 std::string* instance_id, |
| 200 std::string* extra_data) { |
| 201 DCHECK(instance_id && extra_data); |
| 202 std::size_t pos = serialized_data.find(','); |
| 203 if (pos == std::string::npos) |
| 204 return false; |
| 205 *instance_id = serialized_data.substr(0, pos); |
| 206 *extra_data = serialized_data.substr(pos + 1); |
| 207 return !instance_id->empty() && !extra_data->empty(); |
| 208 } |
| 209 |
| 172 void RecordOutgoingMessageToUMA( | 210 void RecordOutgoingMessageToUMA( |
| 173 const gcm::GCMClient::OutgoingMessage& message) { | 211 const gcm::GCMClient::OutgoingMessage& message) { |
| 174 OutgoingMessageTTLCategory ttl_category; | 212 OutgoingMessageTTLCategory ttl_category; |
| 175 if (message.time_to_live == 0) | 213 if (message.time_to_live == 0) |
| 176 ttl_category = TTL_ZERO; | 214 ttl_category = TTL_ZERO; |
| 177 else if (message.time_to_live <= 60 ) | 215 else if (message.time_to_live <= 60 ) |
| 178 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; | 216 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE; |
| 179 else if (message.time_to_live <= 60 * 60) | 217 else if (message.time_to_live <= 60 * 60) |
| 180 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; | 218 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR; |
| 181 else if (message.time_to_live <= 24 * 60 * 60) | 219 else if (message.time_to_live <= 24 * 60 * 60) |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 366 |
| 329 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { | 367 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| 330 DCHECK_EQ(LOADING, state_); | 368 DCHECK_EQ(LOADING, state_); |
| 331 | 369 |
| 332 if (!result->success) { | 370 if (!result->success) { |
| 333 ResetStore(); | 371 ResetStore(); |
| 334 return; | 372 return; |
| 335 } | 373 } |
| 336 gcm_store_reset_ = false; | 374 gcm_store_reset_ = false; |
| 337 | 375 |
| 338 registrations_ = result->registrations; | |
| 339 device_checkin_info_.android_id = result->device_android_id; | 376 device_checkin_info_.android_id = result->device_android_id; |
| 340 device_checkin_info_.secret = result->device_security_token; | 377 device_checkin_info_.secret = result->device_security_token; |
| 341 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; | 378 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; |
| 342 // A case where there were previously no accounts reported with checkin is | 379 // A case where there were previously no accounts reported with checkin is |
| 343 // considered to be the same as when the list of accounts is empty. It enables | 380 // considered to be the same as when the list of accounts is empty. It enables |
| 344 // scheduling a periodic checkin for devices with no signed in users | 381 // scheduling a periodic checkin for devices with no signed in users |
| 345 // immediately after restart, while keeping |accounts_set == false| delays the | 382 // immediately after restart, while keeping |accounts_set == false| delays the |
| 346 // checkin until the list of accounts is set explicitly. | 383 // checkin until the list of accounts is set explicitly. |
| 347 if (result->last_checkin_accounts.size() == 0) | 384 if (result->last_checkin_accounts.size() == 0) |
| 348 device_checkin_info_.accounts_set = true; | 385 device_checkin_info_.accounts_set = true; |
| 349 last_checkin_time_ = result->last_checkin_time; | 386 last_checkin_time_ = result->last_checkin_time; |
| 350 gservices_settings_.UpdateFromLoadResult(*result); | 387 gservices_settings_.UpdateFromLoadResult(*result); |
| 351 instance_id_data_ = result->instance_id_data; | 388 |
| 389 for (auto iter = result->registrations.begin(); |
| 390 iter != result->registrations.end(); |
| 391 ++iter) { |
| 392 std::string registration_id; |
| 393 scoped_ptr<RegistrationInfo> registration = |
| 394 RegistrationInfo::BuildFromString( |
| 395 iter->first, iter->second, ®istration_id); |
| 396 // TODO(jianli): Add UMA to track the error case. |
| 397 if (registration.get()) |
| 398 registrations_[make_linked_ptr(registration.release())] = registration_id; |
| 399 } |
| 400 |
| 401 for (auto iter = result->instance_id_data.begin(); |
| 402 iter != result->instance_id_data.end(); |
| 403 ++iter) { |
| 404 std::string instance_id; |
| 405 std::string extra_data; |
| 406 if (DeserializeInstanceIDData(iter->second, &instance_id, &extra_data)) |
| 407 instance_id_data_[iter->first] = std::make_pair(instance_id, extra_data); |
| 408 } |
| 409 |
| 352 load_result_ = result.Pass(); | 410 load_result_ = result.Pass(); |
| 353 state_ = LOADED; | 411 state_ = LOADED; |
| 354 | 412 |
| 355 // Don't initiate the GCM connection when GCM is in delayed start mode and | 413 // Don't initiate the GCM connection when GCM is in delayed start mode and |
| 356 // not any standalone app has registered GCM yet. | 414 // not any standalone app has registered GCM yet. |
| 357 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) | 415 if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) |
| 358 return; | 416 return; |
| 359 | 417 |
| 360 StartGCM(); | 418 StartGCM(); |
| 361 } | 419 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 583 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 526 weak_ptr_factory_.GetWeakPtr())); | 584 weak_ptr_factory_.GetWeakPtr())); |
| 527 } | 585 } |
| 528 | 586 |
| 529 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { | 587 void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { |
| 530 DCHECK(mcs_client_); | 588 DCHECK(mcs_client_); |
| 531 mcs_client_->UpdateHeartbeatTimer(timer.Pass()); | 589 mcs_client_->UpdateHeartbeatTimer(timer.Pass()); |
| 532 } | 590 } |
| 533 | 591 |
| 534 void GCMClientImpl::AddInstanceIDData(const std::string& app_id, | 592 void GCMClientImpl::AddInstanceIDData(const std::string& app_id, |
| 535 const std::string& instance_id_data) { | 593 const std::string& instance_id, |
| 536 instance_id_data_[app_id] = instance_id_data; | 594 const std::string& extra_data) { |
| 595 instance_id_data_[app_id] = std::make_pair(instance_id, extra_data); |
| 537 gcm_store_->AddInstanceIDData( | 596 gcm_store_->AddInstanceIDData( |
| 538 app_id, | 597 app_id, |
| 539 instance_id_data, | 598 SerializeInstanceIDData(instance_id, extra_data), |
| 540 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 599 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 541 weak_ptr_factory_.GetWeakPtr())); | 600 weak_ptr_factory_.GetWeakPtr())); |
| 542 } | 601 } |
| 543 | 602 |
| 544 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) { | 603 void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) { |
| 545 instance_id_data_.erase(app_id); | 604 instance_id_data_.erase(app_id); |
| 546 gcm_store_->RemoveInstanceIDData( | 605 gcm_store_->RemoveInstanceIDData( |
| 547 app_id, | 606 app_id, |
| 548 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, | 607 base::Bind(&GCMClientImpl::IgnoreWriteResultCallback, |
| 549 weak_ptr_factory_.GetWeakPtr())); | 608 weak_ptr_factory_.GetWeakPtr())); |
| 550 } | 609 } |
| 551 | 610 |
| 552 std::string GCMClientImpl::GetInstanceIDData(const std::string& app_id) { | 611 void GCMClientImpl::GetInstanceIDData(const std::string& app_id, |
| 612 std::string* instance_id, |
| 613 std::string* extra_data) { |
| 614 DCHECK(instance_id && extra_data); |
| 615 |
| 553 auto iter = instance_id_data_.find(app_id); | 616 auto iter = instance_id_data_.find(app_id); |
| 554 if (iter == instance_id_data_.end()) | 617 if (iter == instance_id_data_.end()) |
| 555 return std::string(); | 618 return; |
| 556 return iter->second; | 619 *instance_id = iter->second.first; |
| 620 *extra_data = iter->second.second; |
| 557 } | 621 } |
| 558 | 622 |
| 559 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, | 623 void GCMClientImpl::AddHeartbeatInterval(const std::string& scope, |
| 560 int interval_ms) { | 624 int interval_ms) { |
| 561 DCHECK(mcs_client_); | 625 DCHECK(mcs_client_); |
| 562 mcs_client_->AddHeartbeatInterval(scope, interval_ms); | 626 mcs_client_->AddHeartbeatInterval(scope, interval_ms); |
| 563 } | 627 } |
| 564 | 628 |
| 565 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { | 629 void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) { |
| 566 DCHECK(mcs_client_); | 630 DCHECK(mcs_client_); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 delegate_->OnDisconnected(); | 778 delegate_->OnDisconnected(); |
| 715 mcs_client_.reset(); | 779 mcs_client_.reset(); |
| 716 checkin_request_.reset(); | 780 checkin_request_.reset(); |
| 717 // Delete all of the pending registration and unregistration requests. | 781 // Delete all of the pending registration and unregistration requests. |
| 718 STLDeleteValues(&pending_registration_requests_); | 782 STLDeleteValues(&pending_registration_requests_); |
| 719 STLDeleteValues(&pending_unregistration_requests_); | 783 STLDeleteValues(&pending_unregistration_requests_); |
| 720 state_ = INITIALIZED; | 784 state_ = INITIALIZED; |
| 721 gcm_store_->Close(); | 785 gcm_store_->Close(); |
| 722 } | 786 } |
| 723 | 787 |
| 724 void GCMClientImpl::Register(const std::string& app_id, | 788 void GCMClientImpl::Register( |
| 725 const std::vector<std::string>& sender_ids) { | 789 const linked_ptr<RegistrationInfo>& registration_info) { |
| 726 DCHECK_EQ(state_, READY); | 790 DCHECK_EQ(state_, READY); |
| 727 | 791 |
| 728 // If the same sender ids is provided, return the cached registration ID | 792 // Find and use the cached registration ID. |
| 729 // directly. | |
| 730 RegistrationInfoMap::const_iterator registrations_iter = | 793 RegistrationInfoMap::const_iterator registrations_iter = |
| 731 registrations_.find(app_id); | 794 registrations_.find(registration_info); |
| 732 if (registrations_iter != registrations_.end() && | 795 if (registrations_iter != registrations_.end()) { |
| 733 registrations_iter->second->sender_ids == sender_ids) { | 796 bool matched = true; |
| 734 delegate_->OnRegisterFinished( | 797 |
| 735 app_id, registrations_iter->second->registration_id, SUCCESS); | 798 // For GCM registration, we also match the sender IDs since multiple |
| 736 return; | 799 // registrations are not supported. |
| 800 const GCMRegistrationInfo* gcm_registration_info = |
| 801 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| 802 if (gcm_registration_info) { |
| 803 const GCMRegistrationInfo* cached_gcm_registration_info = |
| 804 GCMRegistrationInfo::FromRegistrationInfo( |
| 805 registrations_iter->first.get()); |
| 806 DCHECK(cached_gcm_registration_info); |
| 807 if (cached_gcm_registration_info && |
| 808 gcm_registration_info->sender_ids != |
| 809 cached_gcm_registration_info->sender_ids) { |
| 810 matched = false; |
| 811 } |
| 812 } |
| 813 |
| 814 if (matched) { |
| 815 delegate_->OnRegisterFinished( |
| 816 registration_info, registrations_iter->second, SUCCESS); |
| 817 return; |
| 818 } |
| 819 } |
| 820 |
| 821 scoped_ptr<RegistrationRequest::CustomRequestHandler> request_handler; |
| 822 std::string source_to_record; |
| 823 |
| 824 const GCMRegistrationInfo* gcm_registration_info = |
| 825 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| 826 if (gcm_registration_info) { |
| 827 std::string senders; |
| 828 for (auto iter = gcm_registration_info->sender_ids.begin(); |
| 829 iter != gcm_registration_info->sender_ids.end(); |
| 830 ++iter) { |
| 831 if (!senders.empty()) |
| 832 senders.append(","); |
| 833 senders.append(*iter); |
| 834 } |
| 835 UMA_HISTOGRAM_COUNTS("GCM.RegistrationSenderIdCount", |
| 836 gcm_registration_info->sender_ids.size()); |
| 837 |
| 838 request_handler.reset(new GCMRegistrationRequestHandler(senders)); |
| 839 source_to_record = senders; |
| 840 } |
| 841 |
| 842 const InstanceIDTokenInfo* instance_id_token_info = |
| 843 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); |
| 844 if (instance_id_token_info) { |
| 845 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); |
| 846 DCHECK(instance_id_iter != instance_id_data_.end()); |
| 847 |
| 848 request_handler.reset(new InstanceIDGetTokenRequestHandler( |
| 849 instance_id_iter->second.first, |
| 850 instance_id_token_info->authorized_entity, |
| 851 instance_id_token_info->scope, |
| 852 ConstructGCMVersion(chrome_build_info_.version), |
| 853 instance_id_token_info->options)); |
| 854 source_to_record = instance_id_token_info->authorized_entity; |
| 737 } | 855 } |
| 738 | 856 |
| 739 RegistrationRequest::RequestInfo request_info( | 857 RegistrationRequest::RequestInfo request_info( |
| 740 device_checkin_info_.android_id, | 858 device_checkin_info_.android_id, |
| 741 device_checkin_info_.secret, | 859 device_checkin_info_.secret, |
| 742 app_id, | 860 registration_info->app_id); |
| 743 sender_ids); | |
| 744 DCHECK_EQ(0u, pending_registration_requests_.count(app_id)); | |
| 745 | 861 |
| 746 RegistrationRequest* registration_request = | 862 RegistrationRequest* registration_request = |
| 747 new RegistrationRequest(gservices_settings_.GetRegistrationURL(), | 863 new RegistrationRequest(gservices_settings_.GetRegistrationURL(), |
| 748 request_info, | 864 request_info, |
| 865 request_handler.Pass(), |
| 749 GetGCMBackoffPolicy(), | 866 GetGCMBackoffPolicy(), |
| 750 base::Bind(&GCMClientImpl::OnRegisterCompleted, | 867 base::Bind(&GCMClientImpl::OnRegisterCompleted, |
| 751 weak_ptr_factory_.GetWeakPtr(), | 868 weak_ptr_factory_.GetWeakPtr(), |
| 752 app_id, | 869 registration_info), |
| 753 sender_ids), | |
| 754 kMaxRegistrationRetries, | 870 kMaxRegistrationRetries, |
| 755 url_request_context_getter_, | 871 url_request_context_getter_, |
| 756 &recorder_); | 872 &recorder_, |
| 757 pending_registration_requests_[app_id] = registration_request; | 873 source_to_record); |
| 874 pending_registration_requests_[registration_info] = registration_request; |
| 758 registration_request->Start(); | 875 registration_request->Start(); |
| 759 } | 876 } |
| 760 | 877 |
| 761 void GCMClientImpl::OnRegisterCompleted( | 878 void GCMClientImpl::OnRegisterCompleted( |
| 762 const std::string& app_id, | 879 const linked_ptr<RegistrationInfo>& registration_info, |
| 763 const std::vector<std::string>& sender_ids, | |
| 764 RegistrationRequest::Status status, | 880 RegistrationRequest::Status status, |
| 765 const std::string& registration_id) { | 881 const std::string& registration_id) { |
| 766 DCHECK(delegate_); | 882 DCHECK(delegate_); |
| 767 | 883 |
| 768 Result result; | 884 Result result; |
| 769 PendingRegistrationRequests::iterator iter = | 885 PendingRegistrationRequests::iterator iter = |
| 770 pending_registration_requests_.find(app_id); | 886 pending_registration_requests_.find(registration_info); |
| 771 if (iter == pending_registration_requests_.end()) | 887 if (iter == pending_registration_requests_.end()) |
| 772 result = UNKNOWN_ERROR; | 888 result = UNKNOWN_ERROR; |
| 773 else if (status == RegistrationRequest::INVALID_SENDER) | 889 else if (status == RegistrationRequest::INVALID_SENDER) |
| 774 result = INVALID_PARAMETER; | 890 result = INVALID_PARAMETER; |
| 775 else if (registration_id.empty()) | 891 else if (registration_id.empty()) |
| 776 result = SERVER_ERROR; | 892 result = SERVER_ERROR; |
| 777 else | 893 else |
| 778 result = SUCCESS; | 894 result = SUCCESS; |
| 779 | 895 |
| 780 if (result == SUCCESS) { | 896 if (result == SUCCESS) { |
| 781 // Cache it. | 897 // Cache it. |
| 782 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); | 898 registrations_[registration_info] = registration_id; |
| 783 registration->sender_ids = sender_ids; | |
| 784 registration->registration_id = registration_id; | |
| 785 registrations_[app_id] = registration; | |
| 786 | 899 |
| 787 // Save it in the persistent store. | 900 // Save it in the persistent store. |
| 788 gcm_store_->AddRegistration( | 901 gcm_store_->AddRegistration( |
| 789 app_id, | 902 registration_info->GetSerializedKey(), |
| 790 registration, | 903 registration_info->GetSerializedValue(registration_id), |
| 791 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 904 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 792 weak_ptr_factory_.GetWeakPtr())); | 905 weak_ptr_factory_.GetWeakPtr())); |
| 793 } | 906 } |
| 794 | 907 |
| 795 delegate_->OnRegisterFinished( | 908 delegate_->OnRegisterFinished( |
| 796 app_id, result == SUCCESS ? registration_id : std::string(), result); | 909 registration_info, |
| 910 result == SUCCESS ? registration_id : std::string(), |
| 911 result); |
| 797 | 912 |
| 798 if (iter != pending_registration_requests_.end()) { | 913 if (iter != pending_registration_requests_.end()) { |
| 799 delete iter->second; | 914 delete iter->second; |
| 800 pending_registration_requests_.erase(iter); | 915 pending_registration_requests_.erase(iter); |
| 801 } | 916 } |
| 802 } | 917 } |
| 803 | 918 |
| 804 void GCMClientImpl::Unregister(const std::string& app_id) { | 919 void GCMClientImpl::Unregister( |
| 920 const linked_ptr<RegistrationInfo>& registration_info) { |
| 805 DCHECK_EQ(state_, READY); | 921 DCHECK_EQ(state_, READY); |
| 806 if (pending_unregistration_requests_.count(app_id) == 1) | 922 if (pending_unregistration_requests_.count(registration_info) == 1) |
| 807 return; | 923 return; |
| 808 | 924 |
| 809 // Remove from the cache and persistent store. | 925 // Remove from the cache and persistent store. |
| 810 registrations_.erase(app_id); | 926 registrations_.erase(registration_info); |
| 811 gcm_store_->RemoveRegistration( | 927 gcm_store_->RemoveRegistration( |
| 812 app_id, | 928 registration_info->GetSerializedKey(), |
| 813 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, | 929 base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| 814 weak_ptr_factory_.GetWeakPtr())); | 930 weak_ptr_factory_.GetWeakPtr())); |
| 815 | 931 |
| 932 scoped_ptr<UnregistrationRequest::CustomRequestHandler> request_handler; |
| 933 |
| 934 const GCMRegistrationInfo* gcm_registration_info = |
| 935 GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| 936 if (gcm_registration_info) { |
| 937 request_handler.reset( |
| 938 new GCMUnregistrationRequestHandler(registration_info->app_id)); |
| 939 } |
| 940 |
| 941 const InstanceIDTokenInfo* instance_id_token_info = |
| 942 InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get()); |
| 943 if (instance_id_token_info) { |
| 944 auto instance_id_iter = instance_id_data_.find(registration_info->app_id); |
| 945 DCHECK(instance_id_iter != instance_id_data_.end()); |
| 946 |
| 947 request_handler.reset(new InstanceIDDeleteTokenRequestHandler( |
| 948 instance_id_iter->second.first, |
| 949 instance_id_token_info->authorized_entity, |
| 950 instance_id_token_info->scope, |
| 951 ConstructGCMVersion(chrome_build_info_.version))); |
| 952 } |
| 953 |
| 816 UnregistrationRequest::RequestInfo request_info( | 954 UnregistrationRequest::RequestInfo request_info( |
| 817 device_checkin_info_.android_id, | 955 device_checkin_info_.android_id, |
| 818 device_checkin_info_.secret, | 956 device_checkin_info_.secret, |
| 819 app_id); | 957 registration_info->app_id); |
| 820 | 958 |
| 821 UnregistrationRequest* unregistration_request = new UnregistrationRequest( | 959 UnregistrationRequest* unregistration_request = new UnregistrationRequest( |
| 822 gservices_settings_.GetRegistrationURL(), | 960 gservices_settings_.GetRegistrationURL(), |
| 823 request_info, | 961 request_info, |
| 962 request_handler.Pass(), |
| 824 GetGCMBackoffPolicy(), | 963 GetGCMBackoffPolicy(), |
| 825 base::Bind(&GCMClientImpl::OnUnregisterCompleted, | 964 base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
| 826 weak_ptr_factory_.GetWeakPtr(), | 965 weak_ptr_factory_.GetWeakPtr(), |
| 827 app_id), | 966 registration_info), |
| 828 url_request_context_getter_, | 967 url_request_context_getter_, |
| 829 &recorder_); | 968 &recorder_); |
| 830 pending_unregistration_requests_[app_id] = unregistration_request; | 969 pending_unregistration_requests_[registration_info] = unregistration_request; |
| 831 unregistration_request->Start(); | 970 unregistration_request->Start(); |
| 832 } | 971 } |
| 833 | 972 |
| 834 void GCMClientImpl::OnUnregisterCompleted( | 973 void GCMClientImpl::OnUnregisterCompleted( |
| 835 const std::string& app_id, | 974 const linked_ptr<RegistrationInfo>& registration_info, |
| 836 UnregistrationRequest::Status status) { | 975 UnregistrationRequest::Status status) { |
| 837 DVLOG(1) << "Unregister completed for app: " << app_id | 976 DVLOG(1) << "Unregister completed for app: " << registration_info->app_id |
| 838 << " with " << (status ? "success." : "failure."); | 977 << " with " << (status ? "success." : "failure."); |
| 839 delegate_->OnUnregisterFinished( | 978 delegate_->OnUnregisterFinished( |
| 840 app_id, | 979 registration_info, |
| 841 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); | 980 status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); |
| 842 | 981 |
| 843 PendingUnregistrationRequests::iterator iter = | 982 PendingUnregistrationRequests::iterator iter = |
| 844 pending_unregistration_requests_.find(app_id); | 983 pending_unregistration_requests_.find(registration_info); |
| 845 if (iter == pending_unregistration_requests_.end()) | 984 if (iter == pending_unregistration_requests_.end()) |
| 846 return; | 985 return; |
| 847 | 986 |
| 848 delete iter->second; | 987 delete iter->second; |
| 849 pending_unregistration_requests_.erase(iter); | 988 pending_unregistration_requests_.erase(iter); |
| 850 } | 989 } |
| 851 | 990 |
| 852 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { | 991 void GCMClientImpl::OnGCMStoreDestroyed(bool success) { |
| 853 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; | 992 DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!"; |
| 854 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); | 993 UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 if (mcs_client_.get()) { | 1061 if (mcs_client_.get()) { |
| 923 stats.send_queue_size = mcs_client_->GetSendQueueSize(); | 1062 stats.send_queue_size = mcs_client_->GetSendQueueSize(); |
| 924 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); | 1063 stats.resend_queue_size = mcs_client_->GetResendQueueSize(); |
| 925 } | 1064 } |
| 926 if (device_checkin_info_.android_id > 0) | 1065 if (device_checkin_info_.android_id > 0) |
| 927 stats.android_id = device_checkin_info_.android_id; | 1066 stats.android_id = device_checkin_info_.android_id; |
| 928 recorder_.CollectActivities(&stats.recorded_activities); | 1067 recorder_.CollectActivities(&stats.recorded_activities); |
| 929 | 1068 |
| 930 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); | 1069 for (RegistrationInfoMap::const_iterator it = registrations_.begin(); |
| 931 it != registrations_.end(); ++it) { | 1070 it != registrations_.end(); ++it) { |
| 932 stats.registered_app_ids.push_back(it->first); | 1071 stats.registered_app_ids.push_back(it->first->app_id); |
| 933 } | 1072 } |
| 934 return stats; | 1073 return stats; |
| 935 } | 1074 } |
| 936 | 1075 |
| 937 void GCMClientImpl::OnActivityRecorded() { | 1076 void GCMClientImpl::OnActivityRecorded() { |
| 938 delegate_->OnActivityRecorded(); | 1077 delegate_->OnActivityRecorded(); |
| 939 } | 1078 } |
| 940 | 1079 |
| 941 void GCMClientImpl::OnConnected(const GURL& current_server, | 1080 void GCMClientImpl::OnConnected(const GURL& current_server, |
| 942 const net::IPEndPoint& ip_endpoint) { | 1081 const net::IPEndPoint& ip_endpoint) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 DVLOG(1) << "Unknown message_type received. Message ignored. " | 1179 DVLOG(1) << "Unknown message_type received. Message ignored. " |
| 1041 << "App ID: " << data_message_stanza.category() << "."; | 1180 << "App ID: " << data_message_stanza.category() << "."; |
| 1042 break; | 1181 break; |
| 1043 } | 1182 } |
| 1044 } | 1183 } |
| 1045 | 1184 |
| 1046 void GCMClientImpl::HandleIncomingDataMessage( | 1185 void GCMClientImpl::HandleIncomingDataMessage( |
| 1047 const mcs_proto::DataMessageStanza& data_message_stanza, | 1186 const mcs_proto::DataMessageStanza& data_message_stanza, |
| 1048 MessageData& message_data) { | 1187 MessageData& message_data) { |
| 1049 std::string app_id = data_message_stanza.category(); | 1188 std::string app_id = data_message_stanza.category(); |
| 1189 std::string sender = data_message_stanza.from(); |
| 1050 | 1190 |
| 1051 // Drop the message when the app is not registered for the sender of the | 1191 // Drop the message when the app is not registered for the sender of the |
| 1052 // message. | 1192 // message. |
| 1053 RegistrationInfoMap::iterator iter = registrations_.find(app_id); | 1193 bool registered = false; |
| 1054 bool not_registered = | 1194 |
| 1055 iter == registrations_.end() || | 1195 // First, find among all GCM registrations. |
| 1056 std::find(iter->second->sender_ids.begin(), | 1196 scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo); |
| 1057 iter->second->sender_ids.end(), | 1197 gcm_registration->app_id = app_id; |
| 1058 data_message_stanza.from()) == iter->second->sender_ids.end(); | 1198 auto gcm_registration_iter = registrations_.find( |
| 1059 recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), | 1199 make_linked_ptr<RegistrationInfo>(gcm_registration.release())); |
| 1060 data_message_stanza.ByteSize(), !not_registered, | 1200 if (gcm_registration_iter != registrations_.end()) { |
| 1201 GCMRegistrationInfo* cached_gcm_registration = |
| 1202 GCMRegistrationInfo::FromRegistrationInfo( |
| 1203 gcm_registration_iter->first.get()); |
| 1204 if (cached_gcm_registration && |
| 1205 std::find(cached_gcm_registration->sender_ids.begin(), |
| 1206 cached_gcm_registration->sender_ids.end(), |
| 1207 sender) != cached_gcm_registration->sender_ids.end()) { |
| 1208 registered = true; |
| 1209 } |
| 1210 } |
| 1211 |
| 1212 // Then, find among all InstanceID registrations. |
| 1213 if (!registered) { |
| 1214 scoped_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo); |
| 1215 instance_id_token->app_id = app_id; |
| 1216 instance_id_token->authorized_entity = sender; |
| 1217 instance_id_token->scope = kGCMScope; |
| 1218 auto instance_id_token_iter = registrations_.find( |
| 1219 make_linked_ptr<RegistrationInfo>(instance_id_token.release())); |
| 1220 if (instance_id_token_iter != registrations_.end()) |
| 1221 registered = true; |
| 1222 } |
| 1223 |
| 1224 recorder_.RecordDataMessageReceived(app_id, sender, |
| 1225 data_message_stanza.ByteSize(), registered, |
| 1061 GCMStatsRecorder::DATA_MESSAGE); | 1226 GCMStatsRecorder::DATA_MESSAGE); |
| 1062 if (not_registered) { | 1227 if (!registered) |
| 1063 return; | 1228 return; |
| 1064 } | |
| 1065 | 1229 |
| 1066 IncomingMessage incoming_message; | 1230 IncomingMessage incoming_message; |
| 1067 incoming_message.sender_id = data_message_stanza.from(); | 1231 incoming_message.sender_id = data_message_stanza.from(); |
| 1068 if (data_message_stanza.has_token()) | 1232 if (data_message_stanza.has_token()) |
| 1069 incoming_message.collapse_key = data_message_stanza.token(); | 1233 incoming_message.collapse_key = data_message_stanza.token(); |
| 1070 incoming_message.data = message_data; | 1234 incoming_message.data = message_data; |
| 1071 delegate_->OnMessageReceived(app_id, incoming_message); | 1235 delegate_->OnMessageReceived(app_id, incoming_message); |
| 1072 } | 1236 } |
| 1073 | 1237 |
| 1074 void GCMClientImpl::HandleIncomingSendError( | 1238 void GCMClientImpl::HandleIncomingSendError( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1092 delegate_->OnMessageSendError(data_message_stanza.category(), | 1256 delegate_->OnMessageSendError(data_message_stanza.category(), |
| 1093 send_error_details); | 1257 send_error_details); |
| 1094 } | 1258 } |
| 1095 | 1259 |
| 1096 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1260 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
| 1097 if (registrations_.empty()) | 1261 if (registrations_.empty()) |
| 1098 return false; | 1262 return false; |
| 1099 // Note that account mapper is not counted as a standalone app since it is | 1263 // Note that account mapper is not counted as a standalone app since it is |
| 1100 // automatically started when other app uses GCM. | 1264 // automatically started when other app uses GCM. |
| 1101 return registrations_.size() > 1 || | 1265 return registrations_.size() > 1 || |
| 1102 !registrations_.count(kGCMAccountMapperAppId); | 1266 !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
| 1103 } | 1267 } |
| 1104 | 1268 |
| 1105 } // namespace gcm | 1269 } // namespace gcm |
| OLD | NEW |