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 e36d36c79735e46432bac2d1fb6764b0de917f43..d2b4773e71aba23e86032c597559b10e203bed33 100644 |
| --- a/components/gcm_driver/gcm_client_impl.cc |
| +++ b/components/gcm_driver/gcm_client_impl.cc |
| @@ -247,6 +247,31 @@ scoped_ptr<ConnectionFactory> GCMInternalsBuilder::BuildConnectionFactory( |
| recorder)); |
| } |
| +GCMClientImpl::CheckinInfo::CheckinInfo() |
| + : android_id(0), secret(0), accounts_set(false) { |
| +} |
| + |
| +GCMClientImpl::CheckinInfo::~CheckinInfo() { |
| +} |
| + |
| +void GCMClientImpl::CheckinInfo::SnapshotCheckinAccounts() { |
| + last_checkin_accounts.clear(); |
| + for (std::map<std::string, std::string>::iterator iter = |
| + account_tokens.begin(); |
| + iter != account_tokens.end(); |
| + ++iter) { |
| + last_checkin_accounts.insert(iter->first); |
| + } |
| +} |
| + |
| +void GCMClientImpl::CheckinInfo::Reset() { |
| + android_id = 0; |
| + secret = 0; |
| + accounts_set = false; |
| + account_tokens.clear(); |
| + last_checkin_accounts.clear(); |
| +} |
| + |
| GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) |
| : internals_builder_(internals_builder.Pass()), |
| state_(UNINITIALIZED), |
| @@ -314,6 +339,14 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| 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; |
| + // A case where there were previously no accounts reported with checkin is |
| + // considered to be the same as when the list of accounts is empty. It enables |
| + // scheduling a periodic checkin for devices with no signed in users |
| + // immediately after restart, while keeping |accounts_set == false| delays the |
| + // checkin until the list of accounts is set explicitly. |
| + if (result->last_checkin_accounts.size() == 0) |
| + device_checkin_info_.accounts_set = true; |
| last_checkin_time_ = result->last_checkin_time; |
| gservices_settings_.UpdateFromLoadResult(*result); |
| InitializeMCSClient(result.Pass()); |
| @@ -363,6 +396,9 @@ void GCMClientImpl::OnFirstTimeDeviceCheckinCompleted( |
| device_checkin_info_.android_id = checkin_info.android_id; |
| device_checkin_info_.secret = checkin_info.secret; |
| + // If accounts were not set by now, we can consider them set (to empty list) |
| + // to make sure periodic checkins get scheduled after initial checkin. |
| + device_checkin_info_.accounts_set = true; |
| gcm_store_->SetDeviceCredentials( |
| checkin_info.android_id, checkin_info.secret, |
| base::Bind(&GCMClientImpl::SetDeviceCredentialsCallback, |
| @@ -390,6 +426,40 @@ void GCMClientImpl::ResetState() { |
| // TODO(fgorski): reset all of the necessart objects and start over. |
| } |
| +void GCMClientImpl::SetAccountsForCheckin( |
| + const std::map<std::string, std::string>& account_tokens) { |
| + bool accounts_set_before = device_checkin_info_.accounts_set; |
| + device_checkin_info_.account_tokens = account_tokens; |
| + device_checkin_info_.accounts_set = true; |
| + |
| + DVLOG(1) << "Set account called with: " << account_tokens.size() |
| + << " accounts."; |
| + |
| + if (state_ != READY && state_ != INITIAL_DEVICE_CHECKIN) |
| + return; |
| + |
| + bool account_removed = false; |
| + for (std::set<std::string>::iterator iter = |
| + device_checkin_info_.last_checkin_accounts.begin(); |
| + iter != device_checkin_info_.last_checkin_accounts.end(); |
| + ++iter) { |
| + if (account_tokens.find(*iter) == account_tokens.end()) |
| + account_removed = true; |
| + } |
| + |
| + // Checkin will be forced when any of the accounts was removed during the |
| + // current Chrome session or if there has been an account removed between the |
| + // restarts of Chrome. If there is a checkin in progress, it will be canceled. |
|
Nicolas Zea
2014/07/16 20:53:54
Comment about why we don't perform a checkin if an
fgorski
2014/07/17 03:35:35
Done.
|
| + if (account_removed) { |
| + DVLOG(1) << "Detecting that account has been removed, forcing checkin."; |
|
Nicolas Zea
2014/07/16 20:53:54
nit: Detecting -> Detected
fgorski
2014/07/17 03:35:34
Done.
|
| + checkin_request_.reset(); |
| + StartCheckin(); |
| + } else if (!accounts_set_before) { |
| + SchedulePeriodicCheckin(); |
| + DVLOG(1) << "Scheduled periodic checkin."; |
| + } |
| +} |
| + |
| void GCMClientImpl::StartCheckin() { |
| // Make sure no checkin is in progress. |
| if (checkin_request_.get()) |
| @@ -399,6 +469,7 @@ void GCMClientImpl::StartCheckin() { |
| ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto); |
| CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id, |
| device_checkin_info_.secret, |
| + device_checkin_info_.account_tokens, |
| gservices_settings_.digest(), |
| chrome_build_proto); |
| checkin_request_.reset( |
| @@ -409,6 +480,9 @@ void GCMClientImpl::StartCheckin() { |
| weak_ptr_factory_.GetWeakPtr()), |
| url_request_context_getter_, |
| &recorder_)); |
| + // Taking a snapshot of the accounts count here, as there might be an asynch |
| + // update of the account tokens while checkin is in progress. |
| + device_checkin_info_.SnapshotCheckinAccounts(); |
| checkin_request_->Start(); |
| } |
| @@ -448,9 +522,10 @@ void GCMClientImpl::OnCheckinCompleted( |
| } |
| last_checkin_time_ = clock_->Now(); |
| - gcm_store_->SetLastCheckinTime( |
| + gcm_store_->SetLastCheckinInfo( |
| last_checkin_time_, |
| - base::Bind(&GCMClientImpl::SetLastCheckinTimeCallback, |
| + device_checkin_info_.last_checkin_accounts, |
| + base::Bind(&GCMClientImpl::SetLastCheckinInfoCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| SchedulePeriodicCheckin(); |
| } |
| @@ -462,7 +537,7 @@ void GCMClientImpl::SetGServicesSettingsCallback(bool success) { |
| void GCMClientImpl::SchedulePeriodicCheckin() { |
| // Make sure no checkin is in progress. |
| - if (checkin_request_.get()) |
| + if (checkin_request_.get() || !device_checkin_info_.accounts_set) |
| return; |
| // There should be only one periodic checkin pending at a time. Removing |
| @@ -485,7 +560,7 @@ base::TimeDelta GCMClientImpl::GetTimeToNextCheckin() const { |
| clock_->Now(); |
| } |
| -void GCMClientImpl::SetLastCheckinTimeCallback(bool success) { |
| +void GCMClientImpl::SetLastCheckinInfoCallback(bool success) { |
| // TODO(fgorski): This is one of the signals that store needs a rebuild. |
| DCHECK(success); |
| } |