| 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
|
| index 4cc0fdd38b0acf28280c6df8b7cef754703a3db2..47c42bca20c82a914092966ef30dac06388277c7 100644
|
| --- a/google_apis/gcm/gcm_client_impl.cc
|
| +++ b/google_apis/gcm/gcm_client_impl.cc
|
| @@ -11,6 +11,7 @@
|
| #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/time/default_clock.h"
|
| #include "google_apis/gcm/base/mcs_message.h"
|
| #include "google_apis/gcm/base/mcs_util.h"
|
| @@ -74,6 +75,8 @@ enum MessageType {
|
| const char kMCSEndpointMain[] = "https://mtalk.google.com:5228";
|
| const char kMCSEndpointFallback[] = "https://mtalk.google.com:443";
|
|
|
| +const char kCheckinIntervalKey[] = "checkin_interval";
|
| +const int64 kDefaultCheckinInterval = 172800LL; // seconds = 2 days.
|
| const int kMaxRegistrationRetries = 5;
|
| const char kMessageTypeDataMessage[] = "gcm";
|
| const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
|
| @@ -212,12 +215,16 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) {
|
|
|
| device_checkin_info_.android_id = result->device_android_id;
|
| device_checkin_info_.secret = result->device_security_token;
|
| + gservices_settings_ = result->gservices_settings;
|
| + gservices_digest_ = result->gservices_digest;
|
| InitializeMCSClient(result.Pass());
|
| if (!device_checkin_info_.IsValid()) {
|
| device_checkin_info_.Reset();
|
| state_ = INITIAL_DEVICE_CHECKIN;
|
| - StartCheckin(device_checkin_info_);
|
| + StartCheckin();
|
| return;
|
| + } else {
|
| + SchedulePeriodicCheckin(result->last_checkin_time);
|
| }
|
|
|
| OnReady();
|
| @@ -281,33 +288,61 @@ void GCMClientImpl::ResetState() {
|
| // TODO(fgorski): reset all of the necessart objects and start over.
|
| }
|
|
|
| -void GCMClientImpl::StartCheckin(const CheckinInfo& checkin_info) {
|
| +void GCMClientImpl::StartCheckin() {
|
| + CheckinRequest::RequestInfo request_info(
|
| + device_checkin_info_.android_id,
|
| + device_checkin_info_.secret,
|
| + gservices_digest_,
|
| + account_ids_,
|
| + chrome_build_proto_);
|
| checkin_request_.reset(
|
| - new CheckinRequest(base::Bind(&GCMClientImpl::OnCheckinCompleted,
|
| - weak_ptr_factory_.GetWeakPtr()),
|
| + new CheckinRequest(request_info,
|
| kDefaultBackoffPolicy,
|
| - chrome_build_proto_,
|
| - checkin_info.android_id,
|
| - checkin_info.secret,
|
| - account_ids_,
|
| + base::Bind(&GCMClientImpl::OnCheckinCompleted,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| url_request_context_getter_));
|
| checkin_request_->Start();
|
| }
|
|
|
| -void GCMClientImpl::OnCheckinCompleted(uint64 android_id,
|
| - uint64 security_token) {
|
| - checkin_request_.reset();
|
| +void GCMClientImpl::SchedulePeriodicCheckin(
|
| + const base::Time& last_checkin_time) {
|
| + base::TimeDelta time_to_next_checkin =
|
| + last_checkin_time + GetCheckinInterval() - clock_->Now();
|
| + if (time_to_next_checkin < base::TimeDelta::FromSeconds(0LL))
|
| + time_to_next_checkin = base::TimeDelta::FromSeconds(0LL);
|
| + // TODO(fgorski): Make sure that once dynamic events (like accounts list
|
| + // change) trigger checkin we reset the timer.
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMClientImpl::StartCheckin,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| + time_to_next_checkin);
|
| +}
|
|
|
| - CheckinInfo checkin_info;
|
| - checkin_info.android_id = android_id;
|
| - checkin_info.secret = security_token;
|
| +base::TimeDelta GCMClientImpl::GetCheckinInterval() const {
|
| + GServicesSettingsMap::const_iterator iter =
|
| + gservices_settings_.find(kCheckinIntervalKey);
|
| + int64 checkin_interval_sec = kDefaultCheckinInterval;
|
| + if (iter != gservices_settings_.end())
|
| + base::StringToInt64(iter->second, &checkin_interval_sec);
|
| + return base::TimeDelta::FromSeconds(checkin_interval_sec);
|
| +}
|
| +
|
| +void GCMClientImpl::OnCheckinCompleted(
|
| + const checkin_proto::AndroidCheckinResponse& checkin_response) {
|
| + checkin_request_.reset();
|
|
|
| - if (!checkin_info.IsValid()) {
|
| - // TODO(fgorski): I don't think a retry here will help, we should probalby
|
| + 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 {
|
| @@ -315,10 +350,13 @@ void GCMClientImpl::OnCheckinCompleted(uint64 android_id,
|
| if (device_checkin_info_.android_id != checkin_info.android_id ||
|
| device_checkin_info_.secret != checkin_info.secret) {
|
| ResetState();
|
| - } else {
|
| - // TODO(fgorski): Reset the checkin timer.
|
| }
|
| }
|
| +
|
| + if (device_checkin_info_.IsValid()) {
|
| + UpdateGServicesSettings(checkin_response);
|
| + SchedulePeriodicCheckin(clock_->Now());
|
| + }
|
| }
|
|
|
| void GCMClientImpl::SetDeviceCredentialsCallback(bool success) {
|
| @@ -664,4 +702,32 @@ void GCMClientImpl::HandleIncomingSendError(
|
| send_error_details);
|
| }
|
|
|
| +void GCMClientImpl::UpdateGServicesSettings(
|
| + const checkin_proto::AndroidCheckinResponse& checkin_response) {
|
| + if (!checkin_response.has_digest() ||
|
| + checkin_response.digest() == gservices_digest_) {
|
| + return;
|
| + }
|
| +
|
| + gservices_digest_ = checkin_response.digest();
|
| + gservices_settings_.clear();
|
| +
|
| + for (int i = 0; i < checkin_response.setting_size(); ++i) {
|
| + std::string name = checkin_response.setting(i).name();
|
| + std::string value = checkin_response.setting(i).value();
|
| + gservices_settings_[name] = value;
|
| + }
|
| +
|
| + gcm_store_->SetGServicesSettings(
|
| + gservices_settings_,
|
| + gservices_digest_,
|
| + clock_->Now(),
|
| + base::Bind(&GCMClientImpl::UpdateGServicesSettingsCallback,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void GCMClientImpl::UpdateGServicesSettingsCallback(bool success) {
|
| + DCHECK(success);
|
| +}
|
| +
|
| } // namespace gcm
|
|
|