OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/gcm_driver/gcm_client_impl.h" | 5 #include "components/gcm_driver/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" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 net::NetLog* net_log, | 240 net::NetLog* net_log, |
241 GCMStatsRecorder* recorder) { | 241 GCMStatsRecorder* recorder) { |
242 return make_scoped_ptr<ConnectionFactory>( | 242 return make_scoped_ptr<ConnectionFactory>( |
243 new ConnectionFactoryImpl(endpoints, | 243 new ConnectionFactoryImpl(endpoints, |
244 backoff_policy, | 244 backoff_policy, |
245 network_session, | 245 network_session, |
246 net_log, | 246 net_log, |
247 recorder)); | 247 recorder)); |
248 } | 248 } |
249 | 249 |
250 GCMClientImpl::CheckinInfo::CheckinInfo() | |
251 : android_id(0), secret(0), accounts_set(false) { | |
252 } | |
253 | |
254 GCMClientImpl::CheckinInfo::~CheckinInfo() { | |
255 } | |
256 | |
257 void GCMClientImpl::CheckinInfo::SnapshotCheckinAccounts() { | |
258 last_checkin_accounts.clear(); | |
259 for (std::map<std::string, std::string>::iterator iter = | |
260 account_tokens.begin(); | |
261 iter != account_tokens.end(); | |
262 ++iter) { | |
263 last_checkin_accounts.insert(iter->first); | |
264 } | |
265 } | |
266 | |
267 void GCMClientImpl::CheckinInfo::Reset() { | |
268 android_id = 0; | |
269 secret = 0; | |
270 accounts_set = false; | |
271 account_tokens.clear(); | |
272 last_checkin_accounts.clear(); | |
273 } | |
274 | |
250 GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) | 275 GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) |
251 : internals_builder_(internals_builder.Pass()), | 276 : internals_builder_(internals_builder.Pass()), |
252 state_(UNINITIALIZED), | 277 state_(UNINITIALIZED), |
253 delegate_(NULL), | 278 delegate_(NULL), |
254 clock_(internals_builder_->BuildClock()), | 279 clock_(internals_builder_->BuildClock()), |
255 url_request_context_getter_(NULL), | 280 url_request_context_getter_(NULL), |
256 pending_registration_requests_deleter_(&pending_registration_requests_), | 281 pending_registration_requests_deleter_(&pending_registration_requests_), |
257 pending_unregistration_requests_deleter_( | 282 pending_unregistration_requests_deleter_( |
258 &pending_unregistration_requests_), | 283 &pending_unregistration_requests_), |
259 periodic_checkin_ptr_factory_(this), | 284 periodic_checkin_ptr_factory_(this), |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 DCHECK_EQ(LOADING, state_); | 332 DCHECK_EQ(LOADING, state_); |
308 | 333 |
309 if (!result->success) { | 334 if (!result->success) { |
310 ResetState(); | 335 ResetState(); |
311 return; | 336 return; |
312 } | 337 } |
313 | 338 |
314 registrations_ = result->registrations; | 339 registrations_ = result->registrations; |
315 device_checkin_info_.android_id = result->device_android_id; | 340 device_checkin_info_.android_id = result->device_android_id; |
316 device_checkin_info_.secret = result->device_security_token; | 341 device_checkin_info_.secret = result->device_security_token; |
342 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; | |
343 // A case where there were previously no accounts reported with checkin is | |
344 // considered to be the same as when the list of accounts is empty. It enables | |
345 // scheduling a periodic checkin for devices with no signed in users | |
346 // immediately after restart, while keeping |accounts_set == false| delays the | |
347 // checkin until the list of accounts is set explicitly. | |
348 if (result->last_checkin_accounts.size() == 0) | |
349 device_checkin_info_.accounts_set = true; | |
317 last_checkin_time_ = result->last_checkin_time; | 350 last_checkin_time_ = result->last_checkin_time; |
318 gservices_settings_.UpdateFromLoadResult(*result); | 351 gservices_settings_.UpdateFromLoadResult(*result); |
319 InitializeMCSClient(result.Pass()); | 352 InitializeMCSClient(result.Pass()); |
320 | 353 |
321 if (device_checkin_info_.IsValid()) { | 354 if (device_checkin_info_.IsValid()) { |
322 SchedulePeriodicCheckin(); | 355 SchedulePeriodicCheckin(); |
323 OnReady(); | 356 OnReady(); |
324 return; | 357 return; |
325 } | 358 } |
326 | 359 |
(...skipping 29 matching lines...) Expand all Loading... | |
356 weak_ptr_factory_.GetWeakPtr()), | 389 weak_ptr_factory_.GetWeakPtr()), |
357 result.Pass()); | 390 result.Pass()); |
358 } | 391 } |
359 | 392 |
360 void GCMClientImpl::OnFirstTimeDeviceCheckinCompleted( | 393 void GCMClientImpl::OnFirstTimeDeviceCheckinCompleted( |
361 const CheckinInfo& checkin_info) { | 394 const CheckinInfo& checkin_info) { |
362 DCHECK(!device_checkin_info_.IsValid()); | 395 DCHECK(!device_checkin_info_.IsValid()); |
363 | 396 |
364 device_checkin_info_.android_id = checkin_info.android_id; | 397 device_checkin_info_.android_id = checkin_info.android_id; |
365 device_checkin_info_.secret = checkin_info.secret; | 398 device_checkin_info_.secret = checkin_info.secret; |
399 // If accounts were not set by now, we can consider them set (to empty list) | |
400 // to make sure periodic checkins get scheduled after initial checkin. | |
401 device_checkin_info_.accounts_set = true; | |
366 gcm_store_->SetDeviceCredentials( | 402 gcm_store_->SetDeviceCredentials( |
367 checkin_info.android_id, checkin_info.secret, | 403 checkin_info.android_id, checkin_info.secret, |
368 base::Bind(&GCMClientImpl::SetDeviceCredentialsCallback, | 404 base::Bind(&GCMClientImpl::SetDeviceCredentialsCallback, |
369 weak_ptr_factory_.GetWeakPtr())); | 405 weak_ptr_factory_.GetWeakPtr())); |
370 | 406 |
371 OnReady(); | 407 OnReady(); |
372 } | 408 } |
373 | 409 |
374 void GCMClientImpl::OnReady() { | 410 void GCMClientImpl::OnReady() { |
375 state_ = READY; | 411 state_ = READY; |
376 StartMCSLogin(); | 412 StartMCSLogin(); |
377 | 413 |
378 delegate_->OnGCMReady(); | 414 delegate_->OnGCMReady(); |
379 } | 415 } |
380 | 416 |
381 void GCMClientImpl::StartMCSLogin() { | 417 void GCMClientImpl::StartMCSLogin() { |
382 DCHECK_EQ(READY, state_); | 418 DCHECK_EQ(READY, state_); |
383 DCHECK(device_checkin_info_.IsValid()); | 419 DCHECK(device_checkin_info_.IsValid()); |
384 mcs_client_->Login(device_checkin_info_.android_id, | 420 mcs_client_->Login(device_checkin_info_.android_id, |
385 device_checkin_info_.secret); | 421 device_checkin_info_.secret); |
386 } | 422 } |
387 | 423 |
388 void GCMClientImpl::ResetState() { | 424 void GCMClientImpl::ResetState() { |
389 state_ = UNINITIALIZED; | 425 state_ = UNINITIALIZED; |
390 // TODO(fgorski): reset all of the necessart objects and start over. | 426 // TODO(fgorski): reset all of the necessart objects and start over. |
391 } | 427 } |
392 | 428 |
429 void GCMClientImpl::SetAccountsForCheckin( | |
430 const std::map<std::string, std::string>& account_tokens) { | |
431 bool accounts_set_before = device_checkin_info_.accounts_set; | |
432 device_checkin_info_.account_tokens = account_tokens; | |
433 device_checkin_info_.accounts_set = true; | |
434 | |
435 DVLOG(1) << "Set account called with: " << account_tokens.size() | |
436 << " accounts."; | |
437 | |
438 if (state_ != READY && state_ != INITIAL_DEVICE_CHECKIN) | |
439 return; | |
440 | |
441 bool account_removed = false; | |
442 for (std::set<std::string>::iterator iter = | |
443 device_checkin_info_.last_checkin_accounts.begin(); | |
444 iter != device_checkin_info_.last_checkin_accounts.end(); | |
445 ++iter) { | |
446 if (account_tokens.find(*iter) == account_tokens.end()) | |
447 account_removed = true; | |
448 } | |
449 | |
450 // Checkin will be forced when any of the accounts was removed during the | |
451 // current Chrome session or if there has been an account removed between the | |
452 // 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.
| |
453 if (account_removed) { | |
454 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.
| |
455 checkin_request_.reset(); | |
456 StartCheckin(); | |
457 } else if (!accounts_set_before) { | |
458 SchedulePeriodicCheckin(); | |
459 DVLOG(1) << "Scheduled periodic checkin."; | |
460 } | |
461 } | |
462 | |
393 void GCMClientImpl::StartCheckin() { | 463 void GCMClientImpl::StartCheckin() { |
394 // Make sure no checkin is in progress. | 464 // Make sure no checkin is in progress. |
395 if (checkin_request_.get()) | 465 if (checkin_request_.get()) |
396 return; | 466 return; |
397 | 467 |
398 checkin_proto::ChromeBuildProto chrome_build_proto; | 468 checkin_proto::ChromeBuildProto chrome_build_proto; |
399 ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto); | 469 ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto); |
400 CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id, | 470 CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id, |
401 device_checkin_info_.secret, | 471 device_checkin_info_.secret, |
472 device_checkin_info_.account_tokens, | |
402 gservices_settings_.digest(), | 473 gservices_settings_.digest(), |
403 chrome_build_proto); | 474 chrome_build_proto); |
404 checkin_request_.reset( | 475 checkin_request_.reset( |
405 new CheckinRequest(gservices_settings_.GetCheckinURL(), | 476 new CheckinRequest(gservices_settings_.GetCheckinURL(), |
406 request_info, | 477 request_info, |
407 kDefaultBackoffPolicy, | 478 kDefaultBackoffPolicy, |
408 base::Bind(&GCMClientImpl::OnCheckinCompleted, | 479 base::Bind(&GCMClientImpl::OnCheckinCompleted, |
409 weak_ptr_factory_.GetWeakPtr()), | 480 weak_ptr_factory_.GetWeakPtr()), |
410 url_request_context_getter_, | 481 url_request_context_getter_, |
411 &recorder_)); | 482 &recorder_)); |
483 // Taking a snapshot of the accounts count here, as there might be an asynch | |
484 // update of the account tokens while checkin is in progress. | |
485 device_checkin_info_.SnapshotCheckinAccounts(); | |
412 checkin_request_->Start(); | 486 checkin_request_->Start(); |
413 } | 487 } |
414 | 488 |
415 void GCMClientImpl::OnCheckinCompleted( | 489 void GCMClientImpl::OnCheckinCompleted( |
416 const checkin_proto::AndroidCheckinResponse& checkin_response) { | 490 const checkin_proto::AndroidCheckinResponse& checkin_response) { |
417 checkin_request_.reset(); | 491 checkin_request_.reset(); |
418 | 492 |
419 if (!checkin_response.has_android_id() || | 493 if (!checkin_response.has_android_id() || |
420 !checkin_response.has_security_token()) { | 494 !checkin_response.has_security_token()) { |
421 // TODO(fgorski): I don't think a retry here will help, we should probably | 495 // TODO(fgorski): I don't think a retry here will help, we should probably |
(...skipping 19 matching lines...) Expand all Loading... | |
441 // First update G-services settings, as something might have changed. | 515 // First update G-services settings, as something might have changed. |
442 if (gservices_settings_.UpdateFromCheckinResponse(checkin_response)) { | 516 if (gservices_settings_.UpdateFromCheckinResponse(checkin_response)) { |
443 gcm_store_->SetGServicesSettings( | 517 gcm_store_->SetGServicesSettings( |
444 gservices_settings_.settings_map(), | 518 gservices_settings_.settings_map(), |
445 gservices_settings_.digest(), | 519 gservices_settings_.digest(), |
446 base::Bind(&GCMClientImpl::SetGServicesSettingsCallback, | 520 base::Bind(&GCMClientImpl::SetGServicesSettingsCallback, |
447 weak_ptr_factory_.GetWeakPtr())); | 521 weak_ptr_factory_.GetWeakPtr())); |
448 } | 522 } |
449 | 523 |
450 last_checkin_time_ = clock_->Now(); | 524 last_checkin_time_ = clock_->Now(); |
451 gcm_store_->SetLastCheckinTime( | 525 gcm_store_->SetLastCheckinInfo( |
452 last_checkin_time_, | 526 last_checkin_time_, |
453 base::Bind(&GCMClientImpl::SetLastCheckinTimeCallback, | 527 device_checkin_info_.last_checkin_accounts, |
528 base::Bind(&GCMClientImpl::SetLastCheckinInfoCallback, | |
454 weak_ptr_factory_.GetWeakPtr())); | 529 weak_ptr_factory_.GetWeakPtr())); |
455 SchedulePeriodicCheckin(); | 530 SchedulePeriodicCheckin(); |
456 } | 531 } |
457 } | 532 } |
458 | 533 |
459 void GCMClientImpl::SetGServicesSettingsCallback(bool success) { | 534 void GCMClientImpl::SetGServicesSettingsCallback(bool success) { |
460 DCHECK(success); | 535 DCHECK(success); |
461 } | 536 } |
462 | 537 |
463 void GCMClientImpl::SchedulePeriodicCheckin() { | 538 void GCMClientImpl::SchedulePeriodicCheckin() { |
464 // Make sure no checkin is in progress. | 539 // Make sure no checkin is in progress. |
465 if (checkin_request_.get()) | 540 if (checkin_request_.get() || !device_checkin_info_.accounts_set) |
466 return; | 541 return; |
467 | 542 |
468 // There should be only one periodic checkin pending at a time. Removing | 543 // There should be only one periodic checkin pending at a time. Removing |
469 // pending periodic checkin to schedule a new one. | 544 // pending periodic checkin to schedule a new one. |
470 periodic_checkin_ptr_factory_.InvalidateWeakPtrs(); | 545 periodic_checkin_ptr_factory_.InvalidateWeakPtrs(); |
471 | 546 |
472 base::TimeDelta time_to_next_checkin = GetTimeToNextCheckin(); | 547 base::TimeDelta time_to_next_checkin = GetTimeToNextCheckin(); |
473 if (time_to_next_checkin < base::TimeDelta()) | 548 if (time_to_next_checkin < base::TimeDelta()) |
474 time_to_next_checkin = base::TimeDelta(); | 549 time_to_next_checkin = base::TimeDelta(); |
475 | 550 |
476 base::MessageLoop::current()->PostDelayedTask( | 551 base::MessageLoop::current()->PostDelayedTask( |
477 FROM_HERE, | 552 FROM_HERE, |
478 base::Bind(&GCMClientImpl::StartCheckin, | 553 base::Bind(&GCMClientImpl::StartCheckin, |
479 periodic_checkin_ptr_factory_.GetWeakPtr()), | 554 periodic_checkin_ptr_factory_.GetWeakPtr()), |
480 time_to_next_checkin); | 555 time_to_next_checkin); |
481 } | 556 } |
482 | 557 |
483 base::TimeDelta GCMClientImpl::GetTimeToNextCheckin() const { | 558 base::TimeDelta GCMClientImpl::GetTimeToNextCheckin() const { |
484 return last_checkin_time_ + gservices_settings_.GetCheckinInterval() - | 559 return last_checkin_time_ + gservices_settings_.GetCheckinInterval() - |
485 clock_->Now(); | 560 clock_->Now(); |
486 } | 561 } |
487 | 562 |
488 void GCMClientImpl::SetLastCheckinTimeCallback(bool success) { | 563 void GCMClientImpl::SetLastCheckinInfoCallback(bool success) { |
489 // TODO(fgorski): This is one of the signals that store needs a rebuild. | 564 // TODO(fgorski): This is one of the signals that store needs a rebuild. |
490 DCHECK(success); | 565 DCHECK(success); |
491 } | 566 } |
492 | 567 |
493 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { | 568 void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { |
494 // TODO(fgorski): This is one of the signals that store needs a rebuild. | 569 // TODO(fgorski): This is one of the signals that store needs a rebuild. |
495 DCHECK(success); | 570 DCHECK(success); |
496 } | 571 } |
497 | 572 |
498 void GCMClientImpl::UpdateRegistrationCallback(bool success) { | 573 void GCMClientImpl::UpdateRegistrationCallback(bool success) { |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
882 | 957 |
883 recorder_.RecordIncomingSendError( | 958 recorder_.RecordIncomingSendError( |
884 data_message_stanza.category(), | 959 data_message_stanza.category(), |
885 data_message_stanza.to(), | 960 data_message_stanza.to(), |
886 data_message_stanza.id()); | 961 data_message_stanza.id()); |
887 delegate_->OnMessageSendError(data_message_stanza.category(), | 962 delegate_->OnMessageSendError(data_message_stanza.category(), |
888 send_error_details); | 963 send_error_details); |
889 } | 964 } |
890 | 965 |
891 } // namespace gcm | 966 } // namespace gcm |
OLD | NEW |