Chromium Code Reviews| 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 |