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

Unified Diff: google_apis/gcm/gcm_client_impl.cc

Issue 310973002: Move GCMClient related files to gcm_driver component (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync Created 6 years, 6 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 | « google_apis/gcm/gcm_client_impl.h ('k') | google_apis/gcm/gcm_client_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: google_apis/gcm/gcm_client_impl.cc
diff --git a/google_apis/gcm/gcm_client_impl.cc b/google_apis/gcm/gcm_client_impl.cc
deleted file mode 100644
index b5a3ae6e5c15b4fed6a296193b57144d18429583..0000000000000000000000000000000000000000
--- a/google_apis/gcm/gcm_client_impl.cc
+++ /dev/null
@@ -1,877 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "google_apis/gcm/gcm_client_impl.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/default_clock.h"
-#include "google_apis/gcm/base/encryptor.h"
-#include "google_apis/gcm/base/mcs_message.h"
-#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_store_impl.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"
-#include "net/http/http_network_session.h"
-#include "net/url_request/url_request_context.h"
-#include "url/gurl.h"
-
-namespace gcm {
-
-namespace {
-
-// Backoff policy. Shared across reconnection logic and checkin/(un)registration
-// retries.
-// Note: In order to ensure a minimum of 20 seconds between server errors (for
-// server reasons), we have a 30s +- 10s (33%) jitter initial backoff.
-// TODO(zea): consider sharing/synchronizing the scheduling of backoff retries
-// themselves.
-const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
- // Number of initial errors (in sequence) to ignore before applying
- // exponential back-off rules.
- 0,
-
- // Initial delay for exponential back-off in ms.
- 30 * 1000, // 30 seconds.
-
- // Factor by which the waiting time will be multiplied.
- 2,
-
- // Fuzzing percentage. ex: 10% will spread requests randomly
- // between 90%-100% of the calculated time.
- 0.33, // 33%.
-
- // Maximum amount of time we are willing to delay our request in ms.
- 10 * 60 * 1000, // 10 minutes.
-
- // Time to keep an entry from being discarded even when it
- // has no significant state, -1 to never discard.
- -1,
-
- // Don't use initial delay unless the last request was an error.
- false,
-};
-
-// Indicates a message type of the received message.
-enum MessageType {
- UNKNOWN, // Undetermined type.
- DATA_MESSAGE, // Regular data message.
- DELETED_MESSAGES, // Messages were deleted on the server.
- SEND_ERROR, // Error sending a message.
-};
-
-enum OutgoingMessageTTLCategory {
- TTL_ZERO,
- TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE,
- TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR,
- TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY,
- TTL_LESS_THAN_OR_EQUAL_TO_ONE_WEEK,
- TTL_MORE_THAN_ONE_WEEK,
- TTL_MAXIMUM,
- // NOTE: always keep this entry at the end. Add new TTL category only
- // immediately above this line. Make sure to update the corresponding
- // histogram enum accordingly.
- TTL_CATEGORY_COUNT
-};
-
-const int kMaxRegistrationRetries = 5;
-const char kMessageTypeDataMessage[] = "gcm";
-const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
-const char kMessageTypeKey[] = "message_type";
-const char kMessageTypeSendErrorKey[] = "send_error";
-const char kSendErrorMessageIdKey[] = "google.message_id";
-const char kSendMessageFromValue[] = "gcm@chrome.com";
-const int64 kDefaultUserSerialNumber = 0LL;
-
-GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
- switch (status) {
- case MCSClient::QUEUED:
- return GCMClient::SUCCESS;
- case MCSClient::QUEUE_SIZE_LIMIT_REACHED:
- return GCMClient::NETWORK_ERROR;
- case MCSClient::APP_QUEUE_SIZE_LIMIT_REACHED:
- return GCMClient::NETWORK_ERROR;
- case MCSClient::MESSAGE_TOO_LARGE:
- return GCMClient::INVALID_PARAMETER;
- case MCSClient::NO_CONNECTION_ON_ZERO_TTL:
- return GCMClient::NETWORK_ERROR;
- case MCSClient::TTL_EXCEEDED:
- return GCMClient::NETWORK_ERROR;
- case MCSClient::SENT:
- default:
- NOTREACHED();
- break;
- }
- return GCMClientImpl::UNKNOWN_ERROR;
-}
-
-void ToCheckinProtoVersion(
- const GCMClient::ChromeBuildInfo& chrome_build_info,
- checkin_proto::ChromeBuildProto* android_build_info) {
- checkin_proto::ChromeBuildProto_Platform platform;
- switch (chrome_build_info.platform) {
- case GCMClient::PLATFORM_WIN:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN;
- break;
- case GCMClient::PLATFORM_MAC:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC;
- break;
- case GCMClient::PLATFORM_LINUX:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
- break;
- case GCMClient::PLATFORM_IOS:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_IOS;
- break;
- case GCMClient::PLATFORM_ANDROID:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_ANDROID;
- break;
- case GCMClient::PLATFORM_CROS:
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS;
- break;
- case GCMClient::PLATFORM_UNKNOWN:
- // For unknown platform, return as LINUX.
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
- break;
- default:
- NOTREACHED();
- platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
- break;
- }
- android_build_info->set_platform(platform);
-
- checkin_proto::ChromeBuildProto_Channel channel;
- switch (chrome_build_info.channel) {
- case GCMClient::CHANNEL_STABLE:
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE;
- break;
- case GCMClient::CHANNEL_BETA:
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_BETA;
- break;
- case GCMClient::CHANNEL_DEV:
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_DEV;
- break;
- case GCMClient::CHANNEL_CANARY:
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_CANARY;
- break;
- case GCMClient::CHANNEL_UNKNOWN:
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN;
- break;
- default:
- NOTREACHED();
- channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN;
- break;
- }
- android_build_info->set_channel(channel);
-
- android_build_info->set_chrome_version(chrome_build_info.version);
-}
-
-MessageType DecodeMessageType(const std::string& value) {
- if (kMessageTypeDeletedMessagesKey == value)
- return DELETED_MESSAGES;
- if (kMessageTypeSendErrorKey == value)
- return SEND_ERROR;
- if (kMessageTypeDataMessage == value)
- return DATA_MESSAGE;
- return UNKNOWN;
-}
-
-void RecordOutgoingMessageToUMA(
- const gcm::GCMClient::OutgoingMessage& message) {
- OutgoingMessageTTLCategory ttl_category;
- if (message.time_to_live == 0)
- ttl_category = TTL_ZERO;
- else if (message.time_to_live <= 60 )
- ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE;
- else if (message.time_to_live <= 60 * 60)
- ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR;
- else if (message.time_to_live <= 24 * 60 * 60)
- ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY;
- else if (message.time_to_live <= 7 * 24 * 60 * 60)
- ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_WEEK;
- else if (message.time_to_live < gcm::GCMClient::OutgoingMessage::kMaximumTTL)
- ttl_category = TTL_MORE_THAN_ONE_WEEK;
- else
- ttl_category = TTL_MAXIMUM;
-
- UMA_HISTOGRAM_ENUMERATION("GCM.GCMOutgoingMessageTTLCategory",
- ttl_category,
- TTL_CATEGORY_COUNT);
-}
-
-} // namespace
-
-GCMInternalsBuilder::GCMInternalsBuilder() {}
-GCMInternalsBuilder::~GCMInternalsBuilder() {}
-
-scoped_ptr<base::Clock> GCMInternalsBuilder::BuildClock() {
- return make_scoped_ptr<base::Clock>(new base::DefaultClock());
-}
-
-scoped_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient(
- const std::string& version,
- base::Clock* clock,
- ConnectionFactory* connection_factory,
- GCMStore* gcm_store,
- GCMStatsRecorder* recorder) {
- return make_scoped_ptr<MCSClient>(
- new MCSClient(version,
- clock,
- connection_factory,
- gcm_store,
- recorder));
-}
-
-scoped_ptr<ConnectionFactory> GCMInternalsBuilder::BuildConnectionFactory(
- const std::vector<GURL>& endpoints,
- const net::BackoffEntry::Policy& backoff_policy,
- scoped_refptr<net::HttpNetworkSession> network_session,
- net::NetLog* net_log,
- GCMStatsRecorder* recorder) {
- return make_scoped_ptr<ConnectionFactory>(
- new ConnectionFactoryImpl(endpoints,
- backoff_policy,
- network_session,
- net_log,
- recorder));
-}
-
-GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder)
- : internals_builder_(internals_builder.Pass()),
- state_(UNINITIALIZED),
- clock_(internals_builder_->BuildClock()),
- url_request_context_getter_(NULL),
- pending_registration_requests_deleter_(&pending_registration_requests_),
- pending_unregistration_requests_deleter_(
- &pending_unregistration_requests_),
- periodic_checkin_ptr_factory_(this),
- weak_ptr_factory_(this) {
-}
-
-GCMClientImpl::~GCMClientImpl() {
-}
-
-void GCMClientImpl::Initialize(
- const ChromeBuildInfo& chrome_build_info,
- const base::FilePath& path,
- const std::vector<std::string>& account_ids,
- const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>&
- url_request_context_getter,
- scoped_ptr<Encryptor> encryptor,
- GCMClient::Delegate* delegate) {
- DCHECK_EQ(UNINITIALIZED, state_);
- DCHECK(url_request_context_getter);
- DCHECK(delegate);
-
- url_request_context_getter_ = url_request_context_getter;
- const net::HttpNetworkSession::Params* network_session_params =
- url_request_context_getter_->GetURLRequestContext()->
- GetNetworkSessionParams();
- DCHECK(network_session_params);
- network_session_ = new net::HttpNetworkSession(*network_session_params);
-
- chrome_build_info_ = chrome_build_info;
- account_ids_ = account_ids;
-
- gcm_store_.reset(
- new GCMStoreImpl(path, blocking_task_runner, encryptor.Pass()));
-
- delegate_ = delegate;
-
- recorder_.SetDelegate(this);
-
- state_ = INITIALIZED;
-}
-
-void GCMClientImpl::Start() {
- DCHECK_EQ(INITIALIZED, state_);
-
- // Once the loading is completed, the check-in will be initiated.
- gcm_store_->Load(base::Bind(&GCMClientImpl::OnLoadCompleted,
- weak_ptr_factory_.GetWeakPtr()));
- state_ = LOADING;
-}
-
-void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) {
- DCHECK_EQ(LOADING, state_);
-
- if (!result->success) {
- ResetState();
- return;
- }
-
- registrations_ = result->registrations;
- device_checkin_info_.android_id = result->device_android_id;
- device_checkin_info_.secret = result->device_security_token;
- last_checkin_time_ = result->last_checkin_time;
- gservices_settings_.UpdateFromLoadResult(*result);
- InitializeMCSClient(result.Pass());
-
- if (device_checkin_info_.IsValid()) {
- SchedulePeriodicCheckin();
- OnReady();
- return;
- }
-
- state_ = INITIAL_DEVICE_CHECKIN;
- device_checkin_info_.Reset();
- StartCheckin();
-}
-
-void GCMClientImpl::InitializeMCSClient(
- scoped_ptr<GCMStore::LoadResult> result) {
- std::vector<GURL> endpoints;
- endpoints.push_back(gservices_settings_.GetMCSMainEndpoint());
- endpoints.push_back(gservices_settings_.GetMCSFallbackEndpoint());
- connection_factory_ = internals_builder_->BuildConnectionFactory(
- endpoints,
- kDefaultBackoffPolicy,
- network_session_,
- net_log_.net_log(),
- &recorder_);
- mcs_client_ = internals_builder_->BuildMCSClient(
- chrome_build_info_.version,
- clock_.get(),
- connection_factory_.get(),
- gcm_store_.get(),
- &recorder_).Pass();
-
- mcs_client_->Initialize(
- base::Bind(&GCMClientImpl::OnMCSError, weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&GCMClientImpl::OnMessageReceivedFromMCS,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&GCMClientImpl::OnMessageSentToMCS,
- weak_ptr_factory_.GetWeakPtr()),
- result.Pass());
-}
-
-void GCMClientImpl::OnFirstTimeDeviceCheckinCompleted(
- const CheckinInfo& checkin_info) {
- DCHECK(!device_checkin_info_.IsValid());
-
- device_checkin_info_.android_id = checkin_info.android_id;
- device_checkin_info_.secret = checkin_info.secret;
- gcm_store_->SetDeviceCredentials(
- checkin_info.android_id, checkin_info.secret,
- base::Bind(&GCMClientImpl::SetDeviceCredentialsCallback,
- weak_ptr_factory_.GetWeakPtr()));
-
- OnReady();
-}
-
-void GCMClientImpl::OnReady() {
- state_ = READY;
- StartMCSLogin();
-
- delegate_->OnGCMReady();
-}
-
-void GCMClientImpl::StartMCSLogin() {
- DCHECK_EQ(READY, state_);
- DCHECK(device_checkin_info_.IsValid());
- mcs_client_->Login(device_checkin_info_.android_id,
- device_checkin_info_.secret);
-}
-
-void GCMClientImpl::ResetState() {
- state_ = UNINITIALIZED;
- // TODO(fgorski): reset all of the necessart objects and start over.
-}
-
-void GCMClientImpl::StartCheckin() {
- // Make sure no checkin is in progress.
- if (checkin_request_.get())
- return;
-
- checkin_proto::ChromeBuildProto chrome_build_proto;
- ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto);
- CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id,
- device_checkin_info_.secret,
- gservices_settings_.digest(),
- account_ids_,
- chrome_build_proto);
- checkin_request_.reset(
- new CheckinRequest(gservices_settings_.GetCheckinURL(),
- request_info,
- kDefaultBackoffPolicy,
- base::Bind(&GCMClientImpl::OnCheckinCompleted,
- weak_ptr_factory_.GetWeakPtr()),
- url_request_context_getter_,
- &recorder_));
- checkin_request_->Start();
-}
-
-void GCMClientImpl::OnCheckinCompleted(
- const checkin_proto::AndroidCheckinResponse& checkin_response) {
- checkin_request_.reset();
-
- if (!checkin_response.has_android_id() ||
- !checkin_response.has_security_token()) {
- // TODO(fgorski): I don't think a retry here will help, we should probably
- // start over. By checking in with (0, 0).
- return;
- }
-
- CheckinInfo checkin_info;
- checkin_info.android_id = checkin_response.android_id();
- checkin_info.secret = checkin_response.security_token();
-
- if (state_ == INITIAL_DEVICE_CHECKIN) {
- OnFirstTimeDeviceCheckinCompleted(checkin_info);
- } else {
- // checkin_info is not expected to change after a periodic checkin as it
- // would invalidate the registratoin IDs.
- DCHECK_EQ(READY, state_);
- DCHECK_EQ(device_checkin_info_.android_id, checkin_info.android_id);
- DCHECK_EQ(device_checkin_info_.secret, checkin_info.secret);
- }
-
- if (device_checkin_info_.IsValid()) {
- // First update G-services settings, as something might have changed.
- if (gservices_settings_.UpdateFromCheckinResponse(checkin_response)) {
- gcm_store_->SetGServicesSettings(
- gservices_settings_.settings_map(),
- gservices_settings_.digest(),
- base::Bind(&GCMClientImpl::SetGServicesSettingsCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- last_checkin_time_ = clock_->Now();
- gcm_store_->SetLastCheckinTime(
- last_checkin_time_,
- base::Bind(&GCMClientImpl::SetLastCheckinTimeCallback,
- weak_ptr_factory_.GetWeakPtr()));
- SchedulePeriodicCheckin();
- }
-}
-
-void GCMClientImpl::SetGServicesSettingsCallback(bool success) {
- DCHECK(success);
-}
-
-void GCMClientImpl::SchedulePeriodicCheckin() {
- // Make sure no checkin is in progress.
- if (checkin_request_.get())
- return;
-
- // There should be only one periodic checkin pending at a time. Removing
- // pending periodic checkin to schedule a new one.
- periodic_checkin_ptr_factory_.InvalidateWeakPtrs();
-
- base::TimeDelta time_to_next_checkin = GetTimeToNextCheckin();
- if (time_to_next_checkin < base::TimeDelta())
- time_to_next_checkin = base::TimeDelta();
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&GCMClientImpl::StartCheckin,
- periodic_checkin_ptr_factory_.GetWeakPtr()),
- time_to_next_checkin);
-}
-
-base::TimeDelta GCMClientImpl::GetTimeToNextCheckin() const {
- return last_checkin_time_ + gservices_settings_.GetCheckinInterval() -
- clock_->Now();
-}
-
-void GCMClientImpl::SetLastCheckinTimeCallback(bool success) {
- // TODO(fgorski): This is one of the signals that store needs a rebuild.
- DCHECK(success);
-}
-
-void GCMClientImpl::SetDeviceCredentialsCallback(bool success) {
- // TODO(fgorski): This is one of the signals that store needs a rebuild.
- DCHECK(success);
-}
-
-void GCMClientImpl::UpdateRegistrationCallback(bool success) {
- // TODO(fgorski): This is one of the signals that store needs a rebuild.
- DCHECK(success);
-}
-
-void GCMClientImpl::Stop() {
- device_checkin_info_.Reset();
- connection_factory_.reset();
- mcs_client_.reset();
- checkin_request_.reset();
- pending_registration_requests_.clear();
- state_ = INITIALIZED;
- gcm_store_->Close();
-}
-
-void GCMClientImpl::CheckOut() {
- Stop();
- gcm_store_->Destroy(base::Bind(&GCMClientImpl::OnGCMStoreDestroyed,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void GCMClientImpl::Register(const std::string& app_id,
- const std::vector<std::string>& sender_ids) {
- DCHECK_EQ(state_, READY);
-
- // If the same sender ids is provided, return the cached registration ID
- // directly.
- 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;
- }
-
- 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));
-
- RegistrationRequest* registration_request =
- new RegistrationRequest(gservices_settings_.GetRegistrationURL(),
- request_info,
- kDefaultBackoffPolicy,
- 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;
- registration_request->Start();
-}
-
-void GCMClientImpl::OnRegisterCompleted(
- const std::string& app_id,
- const std::vector<std::string>& sender_ids,
- RegistrationRequest::Status status,
- const std::string& registration_id) {
- DCHECK(delegate_);
-
- Result result;
- PendingRegistrationRequests::iterator iter =
- pending_registration_requests_.find(app_id);
- if (iter == pending_registration_requests_.end())
- result = UNKNOWN_ERROR;
- else if (status == RegistrationRequest::INVALID_SENDER)
- result = INVALID_PARAMETER;
- else if (registration_id.empty())
- result = SERVER_ERROR;
- else
- result = SUCCESS;
-
- 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;
-
- // Save it in the persistent store.
- gcm_store_->AddRegistration(
- app_id,
- registration,
- base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- delegate_->OnRegisterFinished(
- app_id, result == SUCCESS ? registration_id : std::string(), result);
-
- if (iter != pending_registration_requests_.end()) {
- delete iter->second;
- pending_registration_requests_.erase(iter);
- }
-}
-
-void GCMClientImpl::Unregister(const std::string& app_id) {
- DCHECK_EQ(state_, READY);
- if (pending_unregistration_requests_.count(app_id) == 1)
- return;
-
- // Remove from the cache and persistent store.
- registrations_.erase(app_id);
- gcm_store_->RemoveRegistration(
- app_id,
- 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,
- kDefaultBackoffPolicy,
- base::Bind(&GCMClientImpl::OnUnregisterCompleted,
- weak_ptr_factory_.GetWeakPtr(),
- app_id),
- url_request_context_getter_,
- &recorder_);
- pending_unregistration_requests_[app_id] = unregistration_request;
- unregistration_request->Start();
-}
-
-void GCMClientImpl::OnUnregisterCompleted(
- const std::string& app_id,
- UnregistrationRequest::Status status) {
- DVLOG(1) << "Unregister completed for app: " << app_id
- << " with " << (status ? "success." : "failure.");
- delegate_->OnUnregisterFinished(
- app_id,
- status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR);
-
- PendingUnregistrationRequests::iterator iter =
- pending_unregistration_requests_.find(app_id);
- if (iter == pending_unregistration_requests_.end())
- return;
-
- delete iter->second;
- pending_unregistration_requests_.erase(iter);
-}
-
-void GCMClientImpl::OnGCMStoreDestroyed(bool success) {
- DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!";
- UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success);
-}
-
-void GCMClientImpl::Send(const std::string& app_id,
- const std::string& receiver_id,
- const OutgoingMessage& message) {
- DCHECK_EQ(state_, READY);
-
- RecordOutgoingMessageToUMA(message);
-
- mcs_proto::DataMessageStanza stanza;
- stanza.set_ttl(message.time_to_live);
- stanza.set_sent(clock_->Now().ToInternalValue() /
- base::Time::kMicrosecondsPerSecond);
- stanza.set_id(message.id);
- stanza.set_from(kSendMessageFromValue);
- stanza.set_to(receiver_id);
- stanza.set_category(app_id);
-
- for (MessageData::const_iterator iter = message.data.begin();
- iter != message.data.end();
- ++iter) {
- mcs_proto::AppData* app_data = stanza.add_app_data();
- app_data->set_key(iter->first);
- app_data->set_value(iter->second);
- }
-
- MCSMessage mcs_message(stanza);
- DVLOG(1) << "MCS message size: " << mcs_message.size();
- mcs_client_->SendMessage(mcs_message);
-}
-
-std::string GCMClientImpl::GetStateString() const {
- switch(state_) {
- case GCMClientImpl::INITIALIZED:
- return "INITIALIZED";
- case GCMClientImpl::UNINITIALIZED:
- return "UNINITIALIZED";
- case GCMClientImpl::LOADING:
- return "LOADING";
- case GCMClientImpl::INITIAL_DEVICE_CHECKIN:
- return "INITIAL_DEVICE_CHECKIN";
- case GCMClientImpl::READY:
- return "READY";
- default:
- NOTREACHED();
- return std::string();
- }
-}
-
-void GCMClientImpl::SetRecording(bool recording) {
- recorder_.SetRecording(recording);
-}
-
-void GCMClientImpl::ClearActivityLogs() {
- recorder_.Clear();
-}
-
-GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const {
- GCMClient::GCMStatistics stats;
- stats.gcm_client_created = true;
- stats.is_recording = recorder_.is_recording();
- stats.gcm_client_state = GetStateString();
- stats.connection_client_created = mcs_client_.get() != NULL;
- if (mcs_client_.get()) {
- stats.connection_state = mcs_client_->GetStateString();
- stats.send_queue_size = mcs_client_->GetSendQueueSize();
- stats.resend_queue_size = mcs_client_->GetResendQueueSize();
- }
- if (device_checkin_info_.android_id > 0)
- stats.android_id = device_checkin_info_.android_id;
- recorder_.CollectActivities(&stats.recorded_activities);
-
- for (RegistrationInfoMap::const_iterator it = registrations_.begin();
- it != registrations_.end(); ++it) {
- stats.registered_app_ids.push_back(it->first);
- }
- return stats;
-}
-
-void GCMClientImpl::OnActivityRecorded() {
- delegate_->OnActivityRecorded();
-}
-
-void GCMClientImpl::OnMessageReceivedFromMCS(const gcm::MCSMessage& message) {
- switch (message.tag()) {
- case kLoginResponseTag:
- DVLOG(1) << "Login response received by GCM Client. Ignoring.";
- return;
- case kDataMessageStanzaTag:
- DVLOG(1) << "A downstream message received. Processing...";
- HandleIncomingMessage(message);
- return;
- default:
- NOTREACHED() << "Message with unexpected tag received by GCMClient";
- return;
- }
-}
-
-void GCMClientImpl::OnMessageSentToMCS(int64 user_serial_number,
- const std::string& app_id,
- const std::string& message_id,
- MCSClient::MessageSendStatus status) {
- DCHECK_EQ(user_serial_number, kDefaultUserSerialNumber);
- DCHECK(delegate_);
-
- // TTL_EXCEEDED is singled out here, because it can happen long time after the
- // message was sent. That is why it comes as |OnMessageSendError| event rather
- // than |OnSendFinished|. SendErrorDetails.additional_data is left empty.
- // All other errors will be raised immediately, through asynchronous callback.
- // It is expected that TTL_EXCEEDED will be issued for a message that was
- // previously issued |OnSendFinished| with status SUCCESS.
- // For now, we do not report that the message has been sent and acked
- // successfully.
- // TODO(jianli): Consider adding UMA for this status.
- if (status == MCSClient::TTL_EXCEEDED) {
- SendErrorDetails send_error_details;
- send_error_details.message_id = message_id;
- send_error_details.result = GCMClient::TTL_EXCEEDED;
- delegate_->OnMessageSendError(app_id, send_error_details);
- } else if (status != MCSClient::SENT) {
- delegate_->OnSendFinished(app_id, message_id, ToGCMClientResult(status));
- }
-}
-
-void GCMClientImpl::OnMCSError() {
- // TODO(fgorski): For now it replaces the initialization method. Long term it
- // should have an error or status passed in.
-}
-
-void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
- DCHECK(delegate_);
-
- const mcs_proto::DataMessageStanza& data_message_stanza =
- reinterpret_cast<const mcs_proto::DataMessageStanza&>(
- message.GetProtobuf());
- DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber);
-
- // Copying all the data from the stanza to a MessageData object. When present,
- // keys like kMessageTypeKey or kSendErrorMessageIdKey will be filtered out
- // later.
- MessageData message_data;
- for (int i = 0; i < data_message_stanza.app_data_size(); ++i) {
- std::string key = data_message_stanza.app_data(i).key();
- message_data[key] = data_message_stanza.app_data(i).value();
- }
-
- MessageType message_type = DATA_MESSAGE;
- MessageData::iterator iter = message_data.find(kMessageTypeKey);
- if (iter != message_data.end()) {
- message_type = DecodeMessageType(iter->second);
- message_data.erase(iter);
- }
-
- switch (message_type) {
- case DATA_MESSAGE:
- HandleIncomingDataMessage(data_message_stanza, message_data);
- break;
- case DELETED_MESSAGES:
- recorder_.RecordDataMessageReceived(data_message_stanza.category(),
- data_message_stanza.from(),
- data_message_stanza.ByteSize(),
- true,
- GCMStatsRecorder::DELETED_MESSAGES);
- delegate_->OnMessagesDeleted(data_message_stanza.category());
- break;
- case SEND_ERROR:
- HandleIncomingSendError(data_message_stanza, message_data);
- break;
- case UNKNOWN:
- default: // Treat default the same as UNKNOWN.
- DVLOG(1) << "Unknown message_type received. Message ignored. "
- << "App ID: " << data_message_stanza.category() << ".";
- break;
- }
-}
-
-void GCMClientImpl::HandleIncomingDataMessage(
- const mcs_proto::DataMessageStanza& data_message_stanza,
- MessageData& message_data) {
- std::string app_id = data_message_stanza.category();
-
- // 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,
- GCMStatsRecorder::DATA_MESSAGE);
- if (not_registered) {
- return;
- }
-
- IncomingMessage incoming_message;
- incoming_message.sender_id = data_message_stanza.from();
- if (data_message_stanza.has_token())
- incoming_message.collapse_key = data_message_stanza.token();
- incoming_message.data = message_data;
- delegate_->OnMessageReceived(app_id, incoming_message);
-}
-
-void GCMClientImpl::HandleIncomingSendError(
- const mcs_proto::DataMessageStanza& data_message_stanza,
- MessageData& message_data) {
- SendErrorDetails send_error_details;
- send_error_details.additional_data = message_data;
- send_error_details.result = SERVER_ERROR;
-
- MessageData::iterator iter =
- send_error_details.additional_data.find(kSendErrorMessageIdKey);
- if (iter != send_error_details.additional_data.end()) {
- send_error_details.message_id = iter->second;
- send_error_details.additional_data.erase(iter);
- }
-
- recorder_.RecordIncomingSendError(
- data_message_stanza.category(),
- data_message_stanza.to(),
- data_message_stanza.id());
- delegate_->OnMessageSendError(data_message_stanza.category(),
- send_error_details);
-}
-
-} // namespace gcm
« no previous file with comments | « google_apis/gcm/gcm_client_impl.h ('k') | google_apis/gcm/gcm_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698