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 |