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

Unified Diff: components/gcm_driver/gcm_client_impl.cc

Issue 1137463003: Support getting and deleting token for Instance ID. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Patch to land Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/gcm_driver/gcm_client_impl.h ('k') | components/gcm_driver/gcm_client_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 448e416f30d74c70a29c0ea8d6af532aedc5db60..13d7b623e3b556b5df2445784006da6ad201d471 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -23,7 +23,11 @@
#include "google_apis/gcm/base/mcs_util.h"
#include "google_apis/gcm/engine/checkin_request.h"
#include "google_apis/gcm/engine/connection_factory_impl.h"
+#include "google_apis/gcm/engine/gcm_registration_request_handler.h"
#include "google_apis/gcm/engine/gcm_store_impl.h"
+#include "google_apis/gcm/engine/gcm_unregistration_request_handler.h"
+#include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h"
+#include "google_apis/gcm/engine/instance_id_get_token_request_handler.h"
#include "google_apis/gcm/monitoring/gcm_stats_recorder.h"
#include "google_apis/gcm/protocol/checkin.pb.h"
#include "google_apis/gcm/protocol/mcs.pb.h"
@@ -67,6 +71,7 @@ enum ResetStoreError {
RESET_STORE_ERROR_COUNT
};
+const char kGCMScope[] = "GCM";
const int kMaxRegistrationRetries = 5;
const char kMessageTypeDataMessage[] = "gcm";
const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
@@ -169,6 +174,39 @@ MessageType DecodeMessageType(const std::string& value) {
return UNKNOWN;
}
+int ConstructGCMVersion(const std::string& chrome_version) {
+ // Major Chrome version is passed as GCM version.
+ size_t pos = chrome_version.find('.');
+ if (pos == std::string::npos) {
+ NOTREACHED();
+ return 0;
+ }
+
+ int gcm_version = 0;
+ base::StringToInt(
+ base::StringPiece(chrome_version.c_str(), pos), &gcm_version);
+ return gcm_version;
+}
+
+std::string SerializeInstanceIDData(const std::string& instance_id,
+ const std::string& extra_data) {
+ DCHECK(!instance_id.empty() && !extra_data.empty());
+ DCHECK(instance_id.find(',') == std::string::npos);
+ return instance_id + "," + extra_data;
+}
+
+bool DeserializeInstanceIDData(const std::string& serialized_data,
+ std::string* instance_id,
+ std::string* extra_data) {
+ DCHECK(instance_id && extra_data);
+ std::size_t pos = serialized_data.find(',');
+ if (pos == std::string::npos)
+ return false;
+ *instance_id = serialized_data.substr(0, pos);
+ *extra_data = serialized_data.substr(pos + 1);
+ return !instance_id->empty() && !extra_data->empty();
+}
+
void RecordOutgoingMessageToUMA(
const gcm::GCMClient::OutgoingMessage& message) {
OutgoingMessageTTLCategory ttl_category;
@@ -335,7 +373,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 +385,28 @@ 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);
- instance_id_data_ = result->instance_id_data;
+
+ 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, &registration_id);
+ // TODO(jianli): Add UMA to track the error case.
+ if (registration.get())
+ registrations_[make_linked_ptr(registration.release())] = registration_id;
+ }
+
+ for (auto iter = result->instance_id_data.begin();
+ iter != result->instance_id_data.end();
+ ++iter) {
+ std::string instance_id;
+ std::string extra_data;
+ if (DeserializeInstanceIDData(iter->second, &instance_id, &extra_data))
+ instance_id_data_[iter->first] = std::make_pair(instance_id, extra_data);
+ }
+
load_result_ = result.Pass();
state_ = LOADED;
@@ -532,11 +590,12 @@ void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) {
}
void GCMClientImpl::AddInstanceIDData(const std::string& app_id,
- const std::string& instance_id_data) {
- instance_id_data_[app_id] = instance_id_data;
+ const std::string& instance_id,
+ const std::string& extra_data) {
+ instance_id_data_[app_id] = std::make_pair(instance_id, extra_data);
gcm_store_->AddInstanceIDData(
app_id,
- instance_id_data,
+ SerializeInstanceIDData(instance_id, extra_data),
base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -549,11 +608,16 @@ void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) {
weak_ptr_factory_.GetWeakPtr()));
}
-std::string GCMClientImpl::GetInstanceIDData(const std::string& app_id) {
+void GCMClientImpl::GetInstanceIDData(const std::string& app_id,
+ std::string* instance_id,
+ std::string* extra_data) {
+ DCHECK(instance_id && extra_data);
+
auto iter = instance_id_data_.find(app_id);
if (iter == instance_id_data_.end())
- return std::string();
- return iter->second;
+ return;
+ *instance_id = iter->second.first;
+ *extra_data = iter->second.second;
}
void GCMClientImpl::AddHeartbeatInterval(const std::string& scope,
@@ -721,53 +785,105 @@ 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;
+ }
+ }
+
+ if (matched) {
+ delegate_->OnRegisterFinished(
+ registration_info, registrations_iter->second, SUCCESS);
+ return;
+ }
+ }
+
+ scoped_ptr<RegistrationRequest::CustomRequestHandler> request_handler;
+ std::string source_to_record;
+
+ const GCMRegistrationInfo* gcm_registration_info =
+ GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
+ if (gcm_registration_info) {
+ std::string senders;
+ for (auto iter = gcm_registration_info->sender_ids.begin();
+ iter != gcm_registration_info->sender_ids.end();
+ ++iter) {
+ if (!senders.empty())
+ senders.append(",");
+ senders.append(*iter);
+ }
+ UMA_HISTOGRAM_COUNTS("GCM.RegistrationSenderIdCount",
+ gcm_registration_info->sender_ids.size());
+
+ request_handler.reset(new GCMRegistrationRequestHandler(senders));
+ source_to_record = senders;
+ }
+
+ const InstanceIDTokenInfo* instance_id_token_info =
+ InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
+ if (instance_id_token_info) {
+ auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
+ DCHECK(instance_id_iter != instance_id_data_.end());
+
+ request_handler.reset(new InstanceIDGetTokenRequestHandler(
+ instance_id_iter->second.first,
+ instance_id_token_info->authorized_entity,
+ instance_id_token_info->scope,
+ ConstructGCMVersion(chrome_build_info_.version),
+ instance_id_token_info->options));
+ source_to_record = instance_id_token_info->authorized_entity;
}
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));
+ registration_info->app_id);
RegistrationRequest* registration_request =
new RegistrationRequest(gservices_settings_.GetRegistrationURL(),
request_info,
+ request_handler.Pass(),
GetGCMBackoffPolicy(),
base::Bind(&GCMClientImpl::OnRegisterCompleted,
- weak_ptr_factory_.GetWeakPtr(),
- app_id,
- sender_ids),
+ weak_ptr_factory_.GetWeakPtr(),
+ registration_info),
kMaxRegistrationRetries,
url_request_context_getter_,
- &recorder_);
- pending_registration_requests_[app_id] = registration_request;
+ &recorder_,
+ source_to_record);
+ 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)
@@ -779,21 +895,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;
@@ -801,47 +916,71 @@ 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()));
+ scoped_ptr<UnregistrationRequest::CustomRequestHandler> request_handler;
+
+ const GCMRegistrationInfo* gcm_registration_info =
+ GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
+ if (gcm_registration_info) {
+ request_handler.reset(
+ new GCMUnregistrationRequestHandler(registration_info->app_id));
+ }
+
+ const InstanceIDTokenInfo* instance_id_token_info =
+ InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
+ if (instance_id_token_info) {
+ auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
+ DCHECK(instance_id_iter != instance_id_data_.end());
+
+ request_handler.reset(new InstanceIDDeleteTokenRequestHandler(
+ instance_id_iter->second.first,
+ instance_id_token_info->authorized_entity,
+ instance_id_token_info->scope,
+ ConstructGCMVersion(chrome_build_info_.version)));
+ }
+
UnregistrationRequest::RequestInfo request_info(
device_checkin_info_.android_id,
device_checkin_info_.secret,
- app_id);
+ registration_info->app_id);
UnregistrationRequest* unregistration_request = new UnregistrationRequest(
gservices_settings_.GetRegistrationURL(),
request_info,
+ request_handler.Pass(),
GetGCMBackoffPolicy(),
base::Bind(&GCMClientImpl::OnUnregisterCompleted,
- weak_ptr_factory_.GetWeakPtr(),
- app_id),
+ weak_ptr_factory_.GetWeakPtr(),
+ 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;
@@ -929,7 +1068,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;
}
@@ -1047,21 +1186,46 @@ 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;
+ }
+ }
+
+ // 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();
@@ -1099,7 +1263,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);
}
} // namespace gcm
« no previous file with comments | « components/gcm_driver/gcm_client_impl.h ('k') | components/gcm_driver/gcm_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698