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

Side by Side Diff: google_apis/gcm/gcm_client_impl.cc

Issue 215363007: [GCM] Adding basic G-services handling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Adding unit tests and addressing CR feedback Created 6 years, 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "google_apis/gcm/gcm_client_impl.h" 5 #include "google_apis/gcm/gcm_client_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/sequenced_task_runner.h" 13 #include "base/sequenced_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
14 #include "base/time/default_clock.h" 15 #include "base/time/default_clock.h"
15 #include "google_apis/gcm/base/mcs_message.h" 16 #include "google_apis/gcm/base/mcs_message.h"
16 #include "google_apis/gcm/base/mcs_util.h" 17 #include "google_apis/gcm/base/mcs_util.h"
17 #include "google_apis/gcm/engine/checkin_request.h" 18 #include "google_apis/gcm/engine/checkin_request.h"
18 #include "google_apis/gcm/engine/connection_factory_impl.h" 19 #include "google_apis/gcm/engine/connection_factory_impl.h"
19 #include "google_apis/gcm/engine/gcm_store_impl.h" 20 #include "google_apis/gcm/engine/gcm_store_impl.h"
20 #include "google_apis/gcm/engine/mcs_client.h" 21 #include "google_apis/gcm/engine/mcs_client.h"
21 #include "google_apis/gcm/protocol/mcs.pb.h" 22 #include "google_apis/gcm/protocol/mcs.pb.h"
22 #include "net/http/http_network_session.h" 23 #include "net/http/http_network_session.h"
23 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 SEND_ERROR, // Error sending a message. 68 SEND_ERROR, // Error sending a message.
68 }; 69 };
69 70
70 // MCS endpoints. SSL Key pinning is done automatically due to the *.google.com 71 // MCS endpoints. SSL Key pinning is done automatically due to the *.google.com
71 // pinning rule. 72 // pinning rule.
72 // Note: modifying the endpoints will affect the ability to compare the 73 // Note: modifying the endpoints will affect the ability to compare the
73 // GCM.CurrentEnpoint histogram across versions. 74 // GCM.CurrentEnpoint histogram across versions.
74 const char kMCSEndpointMain[] = "https://mtalk.google.com:5228"; 75 const char kMCSEndpointMain[] = "https://mtalk.google.com:5228";
75 const char kMCSEndpointFallback[] = "https://mtalk.google.com:443"; 76 const char kMCSEndpointFallback[] = "https://mtalk.google.com:443";
76 77
78 const char kCheckinIntervalKey[] = "checkin_interval";
79 const int64 kDefaultCheckinInterval = 172800LL; // seconds = 2 days.
80 const char kDeleteSettingPrefix[] = "delete_";
77 const int kMaxRegistrationRetries = 5; 81 const int kMaxRegistrationRetries = 5;
78 const char kMessageTypeDataMessage[] = "gcm"; 82 const char kMessageTypeDataMessage[] = "gcm";
79 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; 83 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
80 const char kMessageTypeKey[] = "message_type"; 84 const char kMessageTypeKey[] = "message_type";
81 const char kMessageTypeSendErrorKey[] = "send_error"; 85 const char kMessageTypeSendErrorKey[] = "send_error";
82 const char kSendErrorMessageIdKey[] = "google.message_id"; 86 const char kSendErrorMessageIdKey[] = "google.message_id";
83 const char kSendMessageFromValue[] = "gcm@chrome.com"; 87 const char kSendMessageFromValue[] = "gcm@chrome.com";
84 const int64 kDefaultUserSerialNumber = 0LL; 88 const int64 kDefaultUserSerialNumber = 0LL;
85 89
86 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { 90 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 209
206 if (!result->success) { 210 if (!result->success) {
207 ResetState(); 211 ResetState();
208 return; 212 return;
209 } 213 }
210 214
211 registrations_ = result->registrations; 215 registrations_ = result->registrations;
212 216
213 device_checkin_info_.android_id = result->device_android_id; 217 device_checkin_info_.android_id = result->device_android_id;
214 device_checkin_info_.secret = result->device_security_token; 218 device_checkin_info_.secret = result->device_security_token;
219 gservices_settings_ = result->gservices_settings;
215 InitializeMCSClient(result.Pass()); 220 InitializeMCSClient(result.Pass());
216 if (!device_checkin_info_.IsValid()) { 221 if (!device_checkin_info_.IsValid()) {
217 device_checkin_info_.Reset(); 222 device_checkin_info_.Reset();
218 state_ = INITIAL_DEVICE_CHECKIN; 223 state_ = INITIAL_DEVICE_CHECKIN;
219 StartCheckin(device_checkin_info_); 224 StartCheckin();
220 return; 225 return;
226 } else {
227 SchedulePeriodicCheckin(result->last_checkin_time);
221 } 228 }
222 229
223 OnReady(); 230 OnReady();
224 } 231 }
225 232
226 void GCMClientImpl::InitializeMCSClient( 233 void GCMClientImpl::InitializeMCSClient(
227 scoped_ptr<GCMStore::LoadResult> result) { 234 scoped_ptr<GCMStore::LoadResult> result) {
228 std::vector<GURL> endpoints; 235 std::vector<GURL> endpoints;
229 endpoints.push_back(GURL(kMCSEndpointMain)); 236 endpoints.push_back(GURL(kMCSEndpointMain));
230 endpoints.push_back(GURL(kMCSEndpointFallback)); 237 endpoints.push_back(GURL(kMCSEndpointFallback));
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 DCHECK(device_checkin_info_.IsValid()); 281 DCHECK(device_checkin_info_.IsValid());
275 mcs_client_->Login(device_checkin_info_.android_id, 282 mcs_client_->Login(device_checkin_info_.android_id,
276 device_checkin_info_.secret); 283 device_checkin_info_.secret);
277 } 284 }
278 285
279 void GCMClientImpl::ResetState() { 286 void GCMClientImpl::ResetState() {
280 state_ = UNINITIALIZED; 287 state_ = UNINITIALIZED;
281 // TODO(fgorski): reset all of the necessart objects and start over. 288 // TODO(fgorski): reset all of the necessart objects and start over.
282 } 289 }
283 290
284 void GCMClientImpl::StartCheckin(const CheckinInfo& checkin_info) { 291 void GCMClientImpl::StartCheckin() {
285 checkin_request_.reset( 292 checkin_request_.reset(
286 new CheckinRequest(base::Bind(&GCMClientImpl::OnCheckinCompleted, 293 new CheckinRequest(base::Bind(&GCMClientImpl::OnCheckinCompleted,
287 weak_ptr_factory_.GetWeakPtr()), 294 weak_ptr_factory_.GetWeakPtr()),
288 kDefaultBackoffPolicy, 295 kDefaultBackoffPolicy,
289 chrome_build_proto_, 296 chrome_build_proto_,
290 checkin_info.android_id, 297 device_checkin_info_.android_id,
291 checkin_info.secret, 298 device_checkin_info_.secret,
292 account_ids_, 299 account_ids_,
293 url_request_context_getter_)); 300 url_request_context_getter_));
294 checkin_request_->Start(); 301 checkin_request_->Start();
295 } 302 }
296 303
297 void GCMClientImpl::OnCheckinCompleted(uint64 android_id, 304 void GCMClientImpl::SchedulePeriodicCheckin(
298 uint64 security_token) { 305 const base::Time& last_checkin_time) {
306 base::TimeDelta time_to_next_checkin =
307 last_checkin_time + GetCheckinInterval() - clock_->Now();
308 if (time_to_next_checkin < base::TimeDelta::FromSeconds(0LL))
309 time_to_next_checkin = base::TimeDelta::FromSeconds(0LL);
310 base::MessageLoop::current()->PostDelayedTask(
311 FROM_HERE,
312 base::Bind(&GCMClientImpl::StartCheckin,
313 weak_ptr_factory_.GetWeakPtr()),
314 time_to_next_checkin);
315 }
316
317 base::TimeDelta GCMClientImpl::GetCheckinInterval() {
318 GServicesSettingsMap::const_iterator iter =
319 gservices_settings_.find(kCheckinIntervalKey);
320 int64 checkin_interval_sec = kDefaultCheckinInterval;
321 if (iter != gservices_settings_.end())
322 base::StringToInt64(iter->second, &checkin_interval_sec);
323 return base::TimeDelta::FromSeconds(checkin_interval_sec);
324 }
325
326 void GCMClientImpl::OnCheckinCompleted(
327 const checkin_proto::AndroidCheckinResponse& checkin_response) {
299 checkin_request_.reset(); 328 checkin_request_.reset();
300 329
301 CheckinInfo checkin_info; 330 if (!checkin_response.has_android_id() ||
302 checkin_info.android_id = android_id; 331 !checkin_response.has_security_token()) {
303 checkin_info.secret = security_token; 332 // TODO(fgorski): I don't think a retry here will help, we should probably
304
305 if (!checkin_info.IsValid()) {
306 // TODO(fgorski): I don't think a retry here will help, we should probalby
307 // start over. By checking in with (0, 0). 333 // start over. By checking in with (0, 0).
308 return; 334 return;
309 } 335 }
310 336
337 CheckinInfo checkin_info;
338 checkin_info.android_id = checkin_response.android_id();
339 checkin_info.secret = checkin_response.security_token();
340
311 if (state_ == INITIAL_DEVICE_CHECKIN) { 341 if (state_ == INITIAL_DEVICE_CHECKIN) {
312 OnFirstTimeDeviceCheckinCompleted(checkin_info); 342 OnFirstTimeDeviceCheckinCompleted(checkin_info);
313 } else { 343 } else {
314 DCHECK_EQ(READY, state_); 344 DCHECK_EQ(READY, state_);
315 if (device_checkin_info_.android_id != checkin_info.android_id || 345 if (device_checkin_info_.android_id != checkin_info.android_id ||
316 device_checkin_info_.secret != checkin_info.secret) { 346 device_checkin_info_.secret != checkin_info.secret) {
317 ResetState(); 347 ResetState();
318 } else {
319 // TODO(fgorski): Reset the checkin timer.
320 } 348 }
321 } 349 }
350
351 if (device_checkin_info_.IsValid()) {
352 UpdateGServicesSettings(checkin_response);
353 SchedulePeriodicCheckin(clock_->Now());
354 }
322 } 355 }
323 356
324 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { 357 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) {
325 // TODO(fgorski): This is one of the signals that store needs a rebuild. 358 // TODO(fgorski): This is one of the signals that store needs a rebuild.
326 DCHECK(success); 359 DCHECK(success);
327 } 360 }
328 361
329 void GCMClientImpl::UpdateRegistrationCallback(bool success) { 362 void GCMClientImpl::UpdateRegistrationCallback(bool success) {
330 // TODO(fgorski): This is one of the signals that store needs a rebuild. 363 // TODO(fgorski): This is one of the signals that store needs a rebuild.
331 DCHECK(success); 364 DCHECK(success);
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 send_error_details.additional_data.find(kSendErrorMessageIdKey); 690 send_error_details.additional_data.find(kSendErrorMessageIdKey);
658 if (iter != send_error_details.additional_data.end()) { 691 if (iter != send_error_details.additional_data.end()) {
659 send_error_details.message_id = iter->second; 692 send_error_details.message_id = iter->second;
660 send_error_details.additional_data.erase(iter); 693 send_error_details.additional_data.erase(iter);
661 } 694 }
662 695
663 delegate_->OnMessageSendError(data_message_stanza.category(), 696 delegate_->OnMessageSendError(data_message_stanza.category(),
664 send_error_details); 697 send_error_details);
665 } 698 }
666 699
700 void GCMClientImpl::UpdateGServicesSettings(
701 const checkin_proto::AndroidCheckinResponse& checkin_response) {
702 std::vector<std::string> settings_to_remove;
703 std::map<std::string, std::string> settings_to_add;
704
705 // Check if we are only dealing with a diff of settings or full update.
jianli 2014/03/31 17:45:35 Per the comment in checkin.proto: // 2. If 'set
fgorski 2014/03/31 21:50:08 In v2 of the protocol settings_diff is not used an
706 bool settings_diff = false;
707 if (checkin_response.has_settings_diff()) {
708 if (checkin_response.settings_diff()) {
709 settings_diff = true;
710 } else {
711 for (GServicesSettingsMap::const_iterator it =
712 gservices_settings_.begin();
713 it != gservices_settings_.end(); ++it) {
714 settings_to_remove.push_back(it->first);
715 }
716 gservices_settings_.clear();
717 }
718 }
719
720 for (int i = 0; i < checkin_response.setting_size(); ++i) {
721 std::string name = checkin_response.setting(i).name();
722 // When the settings_diff is set to true in the protobuf, the entries that
723 // start from "delete_" are meant to be removing the settings.
724 if (settings_diff && name.find(kDeleteSettingPrefix) == 0) {
725 name = name.substr(arraysize(kDeleteSettingPrefix) - 1);
726 GServicesSettingsMap::iterator iter = gservices_settings_.find(name);
727 if (iter != gservices_settings_.end()) {
728 settings_to_remove.push_back(name);
729 gservices_settings_.erase(iter);
730 }
731 } else {
732 std::string value = checkin_response.setting(i).value();
733 gservices_settings_[name] = value;
734 settings_to_add[name] = value;
735 }
736 }
737
738 gcm_store_->UpdateGServicesSettings(
739 settings_to_remove,
740 settings_to_add,
741 clock_->Now(),
742 base::Bind(&GCMClientImpl::UpdateGServicesSettingsCallback,
743 weak_ptr_factory_.GetWeakPtr()));
744 }
745
746 void GCMClientImpl::UpdateGServicesSettingsCallback(bool success) {
747 DCHECK(success);
748 }
749
667 } // namespace gcm 750 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698