Chromium Code Reviews| Index: components/gcm_driver/gcm_client_impl.cc |
| diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc |
| index 8fb162da91764c46d2ecfe98333e021929fb5018..8e343a1d0b11e488f466080b46b0e3c996479269 100644 |
| --- a/components/gcm_driver/gcm_client_impl.cc |
| +++ b/components/gcm_driver/gcm_client_impl.cc |
| @@ -67,6 +67,7 @@ enum ResetStoreError { |
| RESET_STORE_ERROR_COUNT |
| }; |
| +const char kGCMScope[] = "GCM"; |
| const int kMaxRegistrationRetries = 5; |
| const char kMessageTypeDataMessage[] = "gcm"; |
| const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
| @@ -335,7 +336,6 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| } |
| gcm_store_reset_ = false; |
| - registrations_ = result->registrations; |
| device_checkin_info_.android_id = result->device_android_id; |
| device_checkin_info_.secret = result->device_security_token; |
| device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; |
| @@ -348,7 +348,20 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| device_checkin_info_.accounts_set = true; |
| last_checkin_time_ = result->last_checkin_time; |
| gservices_settings_.UpdateFromLoadResult(*result); |
| + |
| + for (auto iter = result->registrations.begin(); |
| + iter != result->registrations.end(); |
| + ++iter) { |
| + std::string registration_id; |
| + scoped_ptr<RegistrationInfo> registration = |
| + RegistrationInfo::BuildFromString( |
| + iter->first, iter->second, ®istration_id); |
| + if (registration.get()) |
|
fgorski
2015/05/13 18:32:38
else?
jianli
2015/05/13 22:42:56
If we can get registration, it means that either t
|
| + registrations_[make_linked_ptr(registration.release())] = registration_id; |
| + } |
| + |
| instance_id_data_ = result->instance_id_data; |
| + |
| load_result_ = result.Pass(); |
| state_ = LOADED; |
| @@ -710,53 +723,63 @@ void GCMClientImpl::Stop() { |
| gcm_store_->Close(); |
| } |
| -void GCMClientImpl::Register(const std::string& app_id, |
| - const std::vector<std::string>& sender_ids) { |
| +void GCMClientImpl::Register( |
| + const linked_ptr<RegistrationInfo>& registration_info) { |
| DCHECK_EQ(state_, READY); |
| - // If the same sender ids is provided, return the cached registration ID |
| - // directly. |
| + // Find and use the cached registration ID. |
| RegistrationInfoMap::const_iterator registrations_iter = |
| - registrations_.find(app_id); |
| - if (registrations_iter != registrations_.end() && |
| - registrations_iter->second->sender_ids == sender_ids) { |
| - delegate_->OnRegisterFinished( |
| - app_id, registrations_iter->second->registration_id, SUCCESS); |
| - return; |
| - } |
| + registrations_.find(registration_info); |
| + if (registrations_iter != registrations_.end()) { |
| + bool matched = true; |
| + |
| + // For GCM registration, we also match the sender IDs since multiple |
| + // registrations are not supported. |
| + const GCMRegistrationInfo* gcm_registration_info = |
| + GCMRegistrationInfo::FromRegistrationInfo(registration_info.get()); |
| + if (gcm_registration_info) { |
| + const GCMRegistrationInfo* cached_gcm_registration_info = |
| + GCMRegistrationInfo::FromRegistrationInfo( |
| + registrations_iter->first.get()); |
| + DCHECK(cached_gcm_registration_info); |
| + if (cached_gcm_registration_info && |
| + gcm_registration_info->sender_ids != |
| + cached_gcm_registration_info->sender_ids) { |
| + matched = false; |
| + } |
| + } |
| - RegistrationRequest::RequestInfo request_info( |
| - device_checkin_info_.android_id, |
| - device_checkin_info_.secret, |
| - app_id, |
| - sender_ids); |
| - DCHECK_EQ(0u, pending_registration_requests_.count(app_id)); |
| + if (matched) { |
| + delegate_->OnRegisterFinished( |
| + registration_info, registrations_iter->second, SUCCESS); |
| + return; |
| + } |
| + } |
| RegistrationRequest* registration_request = |
| - new RegistrationRequest(gservices_settings_.GetRegistrationURL(), |
| - request_info, |
| - GetGCMBackoffPolicy(), |
| - base::Bind(&GCMClientImpl::OnRegisterCompleted, |
| - weak_ptr_factory_.GetWeakPtr(), |
| - app_id, |
| - sender_ids), |
| - kMaxRegistrationRetries, |
| - url_request_context_getter_, |
| - &recorder_); |
| - pending_registration_requests_[app_id] = registration_request; |
| + new RegistrationRequest( |
| + gservices_settings_.GetRegistrationURL(), |
| + BuildRegistrationRequestInfo(*registration_info).Pass(), |
| + GetGCMBackoffPolicy(), |
| + base::Bind(&GCMClientImpl::OnRegisterCompleted, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + registration_info), |
| + kMaxRegistrationRetries, |
| + url_request_context_getter_, |
| + &recorder_); |
| + pending_registration_requests_[registration_info] = registration_request; |
| registration_request->Start(); |
| } |
| void GCMClientImpl::OnRegisterCompleted( |
| - const std::string& app_id, |
| - const std::vector<std::string>& sender_ids, |
| + const linked_ptr<RegistrationInfo>& registration_info, |
| RegistrationRequest::Status status, |
| const std::string& registration_id) { |
| DCHECK(delegate_); |
| Result result; |
| PendingRegistrationRequests::iterator iter = |
| - pending_registration_requests_.find(app_id); |
| + pending_registration_requests_.find(registration_info); |
| if (iter == pending_registration_requests_.end()) |
| result = UNKNOWN_ERROR; |
| else if (status == RegistrationRequest::INVALID_SENDER) |
|
fgorski
2015/05/13 18:32:38
Are there any new cases on the server side? Could
jianli
2015/05/13 22:42:56
Confirmed that no new cases.
|
| @@ -768,21 +791,20 @@ void GCMClientImpl::OnRegisterCompleted( |
| if (result == SUCCESS) { |
| // Cache it. |
| - linked_ptr<RegistrationInfo> registration(new RegistrationInfo); |
| - registration->sender_ids = sender_ids; |
| - registration->registration_id = registration_id; |
| - registrations_[app_id] = registration; |
| + registrations_[registration_info] = registration_id; |
| // Save it in the persistent store. |
| gcm_store_->AddRegistration( |
| - app_id, |
| - registration, |
| + registration_info->GetSerializedKey(), |
| + registration_info->GetSerializedValue(registration_id), |
| base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| delegate_->OnRegisterFinished( |
| - app_id, result == SUCCESS ? registration_id : std::string(), result); |
| + registration_info, |
| + result == SUCCESS ? registration_id : std::string(), |
| + result); |
| if (iter != pending_registration_requests_.end()) { |
| delete iter->second; |
| @@ -790,47 +812,43 @@ void GCMClientImpl::OnRegisterCompleted( |
| } |
| } |
| -void GCMClientImpl::Unregister(const std::string& app_id) { |
| +void GCMClientImpl::Unregister( |
| + const linked_ptr<RegistrationInfo>& registration_info) { |
| DCHECK_EQ(state_, READY); |
| - if (pending_unregistration_requests_.count(app_id) == 1) |
| + if (pending_unregistration_requests_.count(registration_info) == 1) |
| return; |
| // Remove from the cache and persistent store. |
| - registrations_.erase(app_id); |
| + registrations_.erase(registration_info); |
| gcm_store_->RemoveRegistration( |
| - app_id, |
| + registration_info->GetSerializedKey(), |
| base::Bind(&GCMClientImpl::UpdateRegistrationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| - UnregistrationRequest::RequestInfo request_info( |
| - device_checkin_info_.android_id, |
| - device_checkin_info_.secret, |
| - app_id); |
| - |
| UnregistrationRequest* unregistration_request = new UnregistrationRequest( |
| gservices_settings_.GetRegistrationURL(), |
| - request_info, |
| + BuildUnregistrationRequestInfo(*registration_info).Pass(), |
| GetGCMBackoffPolicy(), |
| base::Bind(&GCMClientImpl::OnUnregisterCompleted, |
| weak_ptr_factory_.GetWeakPtr(), |
| - app_id), |
| + registration_info), |
| url_request_context_getter_, |
| &recorder_); |
| - pending_unregistration_requests_[app_id] = unregistration_request; |
| + pending_unregistration_requests_[registration_info] = unregistration_request; |
| unregistration_request->Start(); |
| } |
| void GCMClientImpl::OnUnregisterCompleted( |
| - const std::string& app_id, |
| + const linked_ptr<RegistrationInfo>& registration_info, |
| UnregistrationRequest::Status status) { |
| - DVLOG(1) << "Unregister completed for app: " << app_id |
| + DVLOG(1) << "Unregister completed for app: " << registration_info->app_id |
| << " with " << (status ? "success." : "failure."); |
| delegate_->OnUnregisterFinished( |
| - app_id, |
| + registration_info, |
| status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR); |
| PendingUnregistrationRequests::iterator iter = |
| - pending_unregistration_requests_.find(app_id); |
| + pending_unregistration_requests_.find(registration_info); |
| if (iter == pending_unregistration_requests_.end()) |
| return; |
| @@ -892,6 +910,70 @@ std::string GCMClientImpl::GetStateString() const { |
| } |
| } |
| +scoped_ptr<RegistrationRequest::RequestInfo> |
| +GCMClientImpl::BuildRegistrationRequestInfo( |
| + const RegistrationInfo& registration_info) const { |
| + const GCMRegistrationInfo* gcm_registration_info = |
| + GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| + if (gcm_registration_info) { |
| + scoped_ptr<RegistrationRequest::GCMRequestInfo> request_info( |
| + new RegistrationRequest::GCMRequestInfo); |
| + request_info->chrome_version = chrome_build_info_.version; |
| + request_info->android_id = device_checkin_info_.android_id; |
| + request_info->security_token = device_checkin_info_.secret; |
| + request_info->app_id = registration_info.app_id; |
| + request_info->sender_ids = gcm_registration_info->sender_ids; |
| + return request_info.Pass(); |
| + } |
| + |
| + const InstanceIDTokenInfo* instance_id_token_info = |
| + InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| + if (!instance_id_token_info) |
| + return scoped_ptr<RegistrationRequest::RequestInfo>(); |
| + |
| + scoped_ptr<RegistrationRequest::InstanceIDRequestInfo> request_info( |
| + new RegistrationRequest::InstanceIDRequestInfo); |
| + request_info->chrome_version = chrome_build_info_.version; |
| + request_info->android_id = device_checkin_info_.android_id; |
| + request_info->security_token = device_checkin_info_.secret; |
| + request_info->app_id = registration_info.app_id; |
| + request_info->authorized_entity = instance_id_token_info->authorized_entity; |
| + request_info->scope = instance_id_token_info->scope; |
| + request_info->options = instance_id_token_info->options; |
| + return request_info.Pass(); |
| +} |
| + |
| +scoped_ptr<UnregistrationRequest::RequestInfo> |
| +GCMClientImpl::BuildUnregistrationRequestInfo( |
|
fgorski
2015/05/13 18:32:39
Looks like this code belongs in registration_info
jianli
2015/05/13 22:42:56
To move these codes into registration_info, we wil
|
| + const RegistrationInfo& registration_info) const { |
| + const GCMRegistrationInfo* gcm_registration_info = |
| + GCMRegistrationInfo::FromRegistrationInfo(®istration_info); |
| + if (gcm_registration_info) { |
| + scoped_ptr<UnregistrationRequest::GCMRequestInfo> request_info( |
| + new UnregistrationRequest::GCMRequestInfo); |
| + request_info->chrome_version = chrome_build_info_.version; |
| + request_info->android_id = device_checkin_info_.android_id; |
| + request_info->security_token = device_checkin_info_.secret; |
| + request_info->app_id = registration_info.app_id; |
| + return request_info.Pass(); |
| + } |
| + |
| + const InstanceIDTokenInfo* instance_id_token_info = |
| + InstanceIDTokenInfo::FromRegistrationInfo(®istration_info); |
| + if (!instance_id_token_info) |
| + return scoped_ptr<UnregistrationRequest::RequestInfo>(); |
| + |
| + scoped_ptr<UnregistrationRequest::InstanceIDRequestInfo> request_info( |
| + new UnregistrationRequest::InstanceIDRequestInfo); |
| + request_info->chrome_version = chrome_build_info_.version; |
| + request_info->android_id = device_checkin_info_.android_id; |
| + request_info->security_token = device_checkin_info_.secret; |
| + request_info->app_id = registration_info.app_id; |
| + request_info->authorized_entity = instance_id_token_info->authorized_entity; |
| + request_info->scope = instance_id_token_info->scope; |
| + return request_info.Pass(); |
| +} |
| + |
| void GCMClientImpl::SetRecording(bool recording) { |
| recorder_.SetRecording(recording); |
| } |
| @@ -918,7 +1000,7 @@ GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { |
| for (RegistrationInfoMap::const_iterator it = registrations_.begin(); |
| it != registrations_.end(); ++it) { |
| - stats.registered_app_ids.push_back(it->first); |
| + stats.registered_app_ids.push_back(it->first->app_id); |
| } |
| return stats; |
| } |
| @@ -1036,21 +1118,45 @@ void GCMClientImpl::HandleIncomingDataMessage( |
| const mcs_proto::DataMessageStanza& data_message_stanza, |
| MessageData& message_data) { |
| std::string app_id = data_message_stanza.category(); |
| + std::string sender = data_message_stanza.from(); |
| // Drop the message when the app is not registered for the sender of the |
| // message. |
| - RegistrationInfoMap::iterator iter = registrations_.find(app_id); |
| - bool not_registered = |
| - iter == registrations_.end() || |
| - std::find(iter->second->sender_ids.begin(), |
| - iter->second->sender_ids.end(), |
| - data_message_stanza.from()) == iter->second->sender_ids.end(); |
| - recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(), |
| - data_message_stanza.ByteSize(), !not_registered, |
| + bool registered = false; |
| + |
| + // First, find among all GCM registrations. |
| + scoped_ptr<GCMRegistrationInfo> gcm_registration(new GCMRegistrationInfo); |
| + gcm_registration->app_id = app_id; |
| + auto gcm_registration_iter = registrations_.find( |
| + make_linked_ptr<RegistrationInfo>(gcm_registration.release())); |
| + if (gcm_registration_iter != registrations_.end()) { |
| + GCMRegistrationInfo* cached_gcm_registration = |
| + GCMRegistrationInfo::FromRegistrationInfo( |
| + gcm_registration_iter->first.get()); |
| + if (cached_gcm_registration && |
| + std::find(cached_gcm_registration->sender_ids.begin(), |
| + cached_gcm_registration->sender_ids.end(), |
| + sender) != cached_gcm_registration->sender_ids.end()) |
| + registered = true; |
|
fgorski
2015/05/13 18:32:38
surround with {} because of multi-line condition
jianli
2015/05/13 22:42:56
Done.
|
| + } |
| + |
| + // Then, find among all InstanceID registrations. |
| + if (!registered) { |
| + scoped_ptr<InstanceIDTokenInfo> instance_id_token(new InstanceIDTokenInfo); |
| + instance_id_token->app_id = app_id; |
| + instance_id_token->authorized_entity = sender; |
| + instance_id_token->scope = kGCMScope; |
| + auto instance_id_token_iter = registrations_.find( |
| + make_linked_ptr<RegistrationInfo>(instance_id_token.release())); |
| + if (instance_id_token_iter != registrations_.end()) |
| + registered = true; |
| + } |
| + |
| + recorder_.RecordDataMessageReceived(app_id, sender, |
| + data_message_stanza.ByteSize(), registered, |
| GCMStatsRecorder::DATA_MESSAGE); |
| - if (not_registered) { |
| + if (!registered) |
| return; |
| - } |
| IncomingMessage incoming_message; |
| incoming_message.sender_id = data_message_stanza.from(); |
| @@ -1088,7 +1194,7 @@ bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
| // Note that account mapper is not counted as a standalone app since it is |
| // automatically started when other app uses GCM. |
| return registrations_.size() > 1 || |
| - !registrations_.count(kGCMAccountMapperAppId); |
| + !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId); |
|
fgorski
2015/05/13 18:32:39
Where is that defined?
jianli
2015/05/13 22:42:56
In registration_info.h
|
| } |
| } // namespace gcm |