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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync_file_system/drive_backend/sync_worker.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "chrome/browser/drive/drive_service_interface.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h" 13 #include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h" 14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 15 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h" 16 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h" 17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 18 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h" 19 #include "chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.h" 20 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h" 21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 22 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h" 23 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h" 24 #include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h" 25 #include "chrome/browser/sync_file_system/logger.h" 26 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" 27 #include "webkit/common/fileapi/file_system_util.h" 28 29 namespace sync_file_system { 30 31 class RemoteChangeProcessor; 32 33 namespace drive_backend { 34 35 namespace { 36 37 void EmptyStatusCallback(SyncStatusCode status) {} 38 39 } // namespace 40 41 SyncWorker::SyncWorker( 42 const base::FilePath& base_dir, 43 const base::WeakPtr<ExtensionServiceInterface>& extension_service, 44 leveldb::Env* env_override) 45 : base_dir_(base_dir), 46 env_override_(env_override), 47 service_state_(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE), 48 should_check_conflict_(true), 49 should_check_remote_change_(true), 50 listing_remote_changes_(false), 51 sync_enabled_(false), 52 default_conflict_resolution_policy_( 53 CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN), 54 network_available_(false), 55 extension_service_(extension_service), 56 has_refresh_token_(false), 57 weak_ptr_factory_(this) { 58 sequence_checker_.DetachFromSequence(); 59 DCHECK(base_dir_.IsAbsolute()); 60 } 61 62 SyncWorker::~SyncWorker() { 63 observers_.Clear(); 64 } 65 66 void SyncWorker::Initialize(scoped_ptr<SyncEngineContext> context) { 67 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 68 DCHECK(!task_manager_); 69 70 context_ = context.Pass(); 71 72 task_manager_.reset(new SyncTaskManager( 73 weak_ptr_factory_.GetWeakPtr(), 0 /* maximum_background_task */, 74 context_->GetWorkerTaskRunner())); 75 task_manager_->Initialize(SYNC_STATUS_OK); 76 77 PostInitializeTask(); 78 79 net::NetworkChangeNotifier::ConnectionType type = 80 net::NetworkChangeNotifier::GetConnectionType(); 81 network_available_ = 82 type != net::NetworkChangeNotifier::CONNECTION_NONE; 83 } 84 85 void SyncWorker::RegisterOrigin( 86 const GURL& origin, 87 const SyncStatusCallback& callback) { 88 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 89 90 if (!GetMetadataDatabase() && has_refresh_token_) 91 PostInitializeTask(); 92 93 scoped_ptr<RegisterAppTask> task( 94 new RegisterAppTask(context_.get(), origin.host())); 95 if (task->CanFinishImmediately()) { 96 callback.Run(SYNC_STATUS_OK); 97 return; 98 } 99 100 task_manager_->ScheduleSyncTask( 101 FROM_HERE, 102 task.PassAs<SyncTask>(), 103 SyncTaskManager::PRIORITY_HIGH, 104 callback); 105 } 106 107 void SyncWorker::EnableOrigin( 108 const GURL& origin, 109 const SyncStatusCallback& callback) { 110 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 111 112 task_manager_->ScheduleTask( 113 FROM_HERE, 114 base::Bind(&SyncWorker::DoEnableApp, 115 weak_ptr_factory_.GetWeakPtr(), 116 origin.host()), 117 SyncTaskManager::PRIORITY_HIGH, 118 callback); 119 } 120 121 void SyncWorker::DisableOrigin( 122 const GURL& origin, 123 const SyncStatusCallback& callback) { 124 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 125 126 task_manager_->ScheduleTask( 127 FROM_HERE, 128 base::Bind(&SyncWorker::DoDisableApp, 129 weak_ptr_factory_.GetWeakPtr(), 130 origin.host()), 131 SyncTaskManager::PRIORITY_HIGH, 132 callback); 133 } 134 135 void SyncWorker::UninstallOrigin( 136 const GURL& origin, 137 RemoteFileSyncService::UninstallFlag flag, 138 const SyncStatusCallback& callback) { 139 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 140 141 task_manager_->ScheduleSyncTask( 142 FROM_HERE, 143 scoped_ptr<SyncTask>( 144 new UninstallAppTask(context_.get(), origin.host(), flag)), 145 SyncTaskManager::PRIORITY_HIGH, 146 callback); 147 } 148 149 void SyncWorker::ProcessRemoteChange( 150 const SyncFileCallback& callback) { 151 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 152 153 RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(context_.get()); 154 task_manager_->ScheduleSyncTask( 155 FROM_HERE, 156 scoped_ptr<SyncTask>(syncer), 157 SyncTaskManager::PRIORITY_MED, 158 base::Bind(&SyncWorker::DidProcessRemoteChange, 159 weak_ptr_factory_.GetWeakPtr(), 160 syncer, 161 callback)); 162 } 163 164 void SyncWorker::SetRemoteChangeProcessor( 165 RemoteChangeProcessorOnWorker* remote_change_processor_on_worker) { 166 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 167 168 context_->SetRemoteChangeProcessor(remote_change_processor_on_worker); 169 } 170 171 RemoteServiceState SyncWorker::GetCurrentState() const { 172 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 173 174 if (!sync_enabled_) 175 return REMOTE_SERVICE_DISABLED; 176 return service_state_; 177 } 178 179 void SyncWorker::GetOriginStatusMap( 180 const RemoteFileSyncService::StatusMapCallback& callback) { 181 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 182 183 if (!GetMetadataDatabase()) 184 return; 185 186 std::vector<std::string> app_ids; 187 GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids); 188 189 scoped_ptr<RemoteFileSyncService::OriginStatusMap> 190 status_map(new RemoteFileSyncService::OriginStatusMap); 191 for (std::vector<std::string>::const_iterator itr = app_ids.begin(); 192 itr != app_ids.end(); ++itr) { 193 const std::string& app_id = *itr; 194 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id); 195 (*status_map)[origin] = 196 GetMetadataDatabase()->IsAppEnabled(app_id) ? "Enabled" : "Disabled"; 197 } 198 199 callback.Run(status_map.Pass()); 200 } 201 202 scoped_ptr<base::ListValue> SyncWorker::DumpFiles(const GURL& origin) { 203 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 204 205 if (!GetMetadataDatabase()) 206 return scoped_ptr<base::ListValue>(); 207 return GetMetadataDatabase()->DumpFiles(origin.host()); 208 } 209 210 scoped_ptr<base::ListValue> SyncWorker::DumpDatabase() { 211 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 212 213 if (!GetMetadataDatabase()) 214 return scoped_ptr<base::ListValue>(); 215 return GetMetadataDatabase()->DumpDatabase(); 216 } 217 218 void SyncWorker::SetSyncEnabled(bool enabled) { 219 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 220 221 if (sync_enabled_ == enabled) 222 return; 223 224 RemoteServiceState old_state = GetCurrentState(); 225 sync_enabled_ = enabled; 226 if (old_state == GetCurrentState()) 227 return; 228 229 FOR_EACH_OBSERVER( 230 Observer, 231 observers_, 232 UpdateServiceState( 233 GetCurrentState(), 234 enabled ? "Sync is enabled" : "Sync is disabled")); 235 } 236 237 void SyncWorker::PromoteDemotedChanges() { 238 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 239 240 MetadataDatabase* metadata_db = GetMetadataDatabase(); 241 if (metadata_db && metadata_db->HasLowPriorityDirtyTracker()) { 242 metadata_db->PromoteLowerPriorityTrackersToNormal(); 243 FOR_EACH_OBSERVER( 244 Observer, 245 observers_, 246 OnPendingFileListUpdated(metadata_db->CountDirtyTracker())); 247 } 248 } 249 250 void SyncWorker::ApplyLocalChange( 251 const FileChange& local_change, 252 const base::FilePath& local_path, 253 const SyncFileMetadata& local_metadata, 254 const fileapi::FileSystemURL& url, 255 const SyncStatusCallback& callback) { 256 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 257 258 LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer( 259 context_.get(), local_metadata, local_change, local_path, url); 260 task_manager_->ScheduleSyncTask( 261 FROM_HERE, 262 scoped_ptr<SyncTask>(syncer), 263 SyncTaskManager::PRIORITY_MED, 264 base::Bind(&SyncWorker::DidApplyLocalChange, 265 weak_ptr_factory_.GetWeakPtr(), 266 syncer, 267 callback)); 268 } 269 270 void SyncWorker::MaybeScheduleNextTask() { 271 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 272 273 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) 274 return; 275 276 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated. 277 // TODO(tzik): Add an interface to get the number of dirty trackers to 278 // MetadataDatabase. 279 280 MaybeStartFetchChanges(); 281 } 282 283 void SyncWorker::NotifyLastOperationStatus( 284 SyncStatusCode status, 285 bool used_network) { 286 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 287 288 UpdateServiceStateFromSyncStatusCode(status, used_network); 289 290 if (GetMetadataDatabase()) { 291 FOR_EACH_OBSERVER( 292 Observer, observers_, 293 OnPendingFileListUpdated(GetMetadataDatabase()->CountDirtyTracker())); 294 } 295 } 296 297 void SyncWorker::RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) { 298 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 299 300 context_->GetUITaskRunner()->PostTask( 301 FROM_HERE, 302 base::Bind(&TaskLogger::RecordLog, 303 context_->GetTaskLogger(), 304 base::Passed(&task_log))); 305 } 306 307 void SyncWorker::OnNotificationReceived() { 308 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 309 310 if (service_state_ == REMOTE_SERVICE_TEMPORARY_UNAVAILABLE) 311 UpdateServiceState(REMOTE_SERVICE_OK, "Got push notification for Drive."); 312 313 should_check_remote_change_ = true; 314 MaybeScheduleNextTask(); 315 } 316 317 void SyncWorker::OnReadyToSendRequests() { 318 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 319 320 has_refresh_token_ = true; 321 322 if (service_state_ == REMOTE_SERVICE_OK) 323 return; 324 UpdateServiceState(REMOTE_SERVICE_OK, "Authenticated"); 325 326 if (!GetMetadataDatabase()) { 327 PostInitializeTask(); 328 return; 329 } 330 331 should_check_remote_change_ = true; 332 MaybeScheduleNextTask(); 333 } 334 335 void SyncWorker::OnRefreshTokenInvalid() { 336 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 337 338 has_refresh_token_ = false; 339 340 UpdateServiceState( 341 REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 342 "Found invalid refresh token."); 343 } 344 345 void SyncWorker::OnNetworkChanged( 346 net::NetworkChangeNotifier::ConnectionType type) { 347 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 348 349 bool new_network_availability = 350 type != net::NetworkChangeNotifier::CONNECTION_NONE; 351 352 if (network_available_ && !new_network_availability) { 353 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, "Disconnected"); 354 } else if (!network_available_ && new_network_availability) { 355 UpdateServiceState(REMOTE_SERVICE_OK, "Connected"); 356 should_check_remote_change_ = true; 357 MaybeStartFetchChanges(); 358 } 359 network_available_ = new_network_availability; 360 } 361 362 drive::DriveServiceInterface* SyncWorker::GetDriveService() { 363 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 364 return context_->GetDriveService(); 365 } 366 367 drive::DriveUploaderInterface* SyncWorker::GetDriveUploader() { 368 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 369 return context_->GetDriveUploader(); 370 } 371 372 MetadataDatabase* SyncWorker::GetMetadataDatabase() { 373 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 374 return context_->GetMetadataDatabase(); 375 } 376 377 SyncTaskManager* SyncWorker::GetSyncTaskManager() { 378 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 379 return task_manager_.get(); 380 } 381 382 void SyncWorker::DetachFromSequence() { 383 context_->DetachFromSequence(); 384 sequence_checker_.DetachFromSequence(); 385 } 386 387 void SyncWorker::AddObserver(Observer* observer) { 388 observers_.AddObserver(observer); 389 } 390 391 void SyncWorker::SetHasRefreshToken(bool has_refresh_token) { 392 has_refresh_token_ = has_refresh_token; 393 } 394 395 void SyncWorker::DoDisableApp(const std::string& app_id, 396 const SyncStatusCallback& callback) { 397 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 398 399 if (GetMetadataDatabase()) { 400 GetMetadataDatabase()->DisableApp(app_id, callback); 401 } else { 402 callback.Run(SYNC_STATUS_OK); 403 } 404 } 405 406 void SyncWorker::DoEnableApp(const std::string& app_id, 407 const SyncStatusCallback& callback) { 408 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 409 410 if (GetMetadataDatabase()) { 411 GetMetadataDatabase()->EnableApp(app_id, callback); 412 } else { 413 callback.Run(SYNC_STATUS_OK); 414 } 415 } 416 417 void SyncWorker::PostInitializeTask() { 418 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 419 DCHECK(!GetMetadataDatabase()); 420 421 // This initializer task may not run if MetadataDatabase in context_ is 422 // already initialized when it runs. 423 SyncEngineInitializer* initializer = 424 new SyncEngineInitializer(context_.get(), 425 base_dir_.Append(kDatabaseName), 426 env_override_); 427 task_manager_->ScheduleSyncTask( 428 FROM_HERE, 429 scoped_ptr<SyncTask>(initializer), 430 SyncTaskManager::PRIORITY_HIGH, 431 base::Bind(&SyncWorker::DidInitialize, 432 weak_ptr_factory_.GetWeakPtr(), 433 initializer)); 434 } 435 436 void SyncWorker::DidInitialize(SyncEngineInitializer* initializer, 437 SyncStatusCode status) { 438 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 439 440 if (status != SYNC_STATUS_OK) { 441 if (has_refresh_token_) { 442 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, 443 "Could not initialize remote service"); 444 } else { 445 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 446 "Authentication required."); 447 } 448 return; 449 } 450 451 scoped_ptr<MetadataDatabase> metadata_database = 452 initializer->PassMetadataDatabase(); 453 if (metadata_database) 454 context_->SetMetadataDatabase(metadata_database.Pass()); 455 456 UpdateRegisteredApps(); 457 } 458 459 void SyncWorker::UpdateRegisteredApps() { 460 MetadataDatabase* metadata_db = GetMetadataDatabase(); 461 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 462 DCHECK(metadata_db); 463 464 scoped_ptr<std::vector<std::string> > app_ids(new std::vector<std::string>); 465 metadata_db->GetRegisteredAppIDs(app_ids.get()); 466 467 AppStatusMap* app_status = new AppStatusMap; 468 base::Closure callback = 469 base::Bind(&SyncWorker::DidQueryAppStatus, 470 weak_ptr_factory_.GetWeakPtr(), 471 base::Owned(app_status)); 472 473 context_->GetUITaskRunner()->PostTask( 474 FROM_HERE, 475 base::Bind(&SyncWorker::QueryAppStatusOnUIThread, 476 extension_service_, 477 base::Owned(app_ids.release()), 478 app_status, 479 RelayCallbackToTaskRunner( 480 context_->GetWorkerTaskRunner(), 481 FROM_HERE, callback))); 482 } 483 484 void SyncWorker::QueryAppStatusOnUIThread( 485 const base::WeakPtr<ExtensionServiceInterface>& extension_service_ptr, 486 const std::vector<std::string>* app_ids, 487 AppStatusMap* status, 488 const base::Closure& callback) { 489 ExtensionServiceInterface* extension_service = extension_service_ptr.get(); 490 if (!extension_service) { 491 callback.Run(); 492 return; 493 } 494 495 for (std::vector<std::string>::const_iterator itr = app_ids->begin(); 496 itr != app_ids->end(); ++itr) { 497 const std::string& app_id = *itr; 498 if (!extension_service->GetInstalledExtension(app_id)) 499 (*status)[app_id] = APP_STATUS_UNINSTALLED; 500 else if (!extension_service->IsExtensionEnabled(app_id)) 501 (*status)[app_id] = APP_STATUS_DISABLED; 502 else 503 (*status)[app_id] = APP_STATUS_ENABLED; 504 } 505 506 callback.Run(); 507 } 508 509 void SyncWorker::DidQueryAppStatus(const AppStatusMap* app_status) { 510 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 511 512 MetadataDatabase* metadata_db = GetMetadataDatabase(); 513 DCHECK(metadata_db); 514 515 // Update the status of every origin using status from ExtensionService. 516 for (AppStatusMap::const_iterator itr = app_status->begin(); 517 itr != app_status->end(); ++itr) { 518 const std::string& app_id = itr->first; 519 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id); 520 521 if (itr->second == APP_STATUS_UNINSTALLED) { 522 // Extension has been uninstalled. 523 // (At this stage we can't know if it was unpacked extension or not, 524 // so just purge the remote folder.) 525 UninstallOrigin(origin, 526 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE, 527 base::Bind(&EmptyStatusCallback)); 528 continue; 529 } 530 531 FileTracker tracker; 532 if (!metadata_db->FindAppRootTracker(app_id, &tracker)) { 533 // App will register itself on first run. 534 continue; 535 } 536 537 DCHECK(itr->second == APP_STATUS_ENABLED || 538 itr->second == APP_STATUS_DISABLED); 539 bool is_app_enabled = (itr->second == APP_STATUS_ENABLED); 540 bool is_app_root_tracker_enabled = 541 (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT); 542 if (is_app_enabled && !is_app_root_tracker_enabled) 543 EnableOrigin(origin, base::Bind(&EmptyStatusCallback)); 544 else if (!is_app_enabled && is_app_root_tracker_enabled) 545 DisableOrigin(origin, base::Bind(&EmptyStatusCallback)); 546 } 547 } 548 549 void SyncWorker::DidProcessRemoteChange(RemoteToLocalSyncer* syncer, 550 const SyncFileCallback& callback, 551 SyncStatusCode status) { 552 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 553 554 if (syncer->is_sync_root_deletion()) { 555 MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase()); 556 PostInitializeTask(); 557 callback.Run(status, syncer->url()); 558 return; 559 } 560 561 if (status == SYNC_STATUS_OK) { 562 if (syncer->sync_action() != SYNC_ACTION_NONE && 563 syncer->url().is_valid()) { 564 FOR_EACH_OBSERVER( 565 Observer, observers_, 566 OnFileStatusChanged( 567 syncer->url(), 568 SYNC_FILE_STATUS_SYNCED, 569 syncer->sync_action(), 570 SYNC_DIRECTION_REMOTE_TO_LOCAL)); 571 } 572 573 if (syncer->sync_action() == SYNC_ACTION_DELETED && 574 syncer->url().is_valid() && 575 fileapi::VirtualPath::IsRootPath(syncer->url().path())) { 576 RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback)); 577 } 578 should_check_conflict_ = true; 579 } 580 callback.Run(status, syncer->url()); 581 } 582 583 void SyncWorker::DidApplyLocalChange(LocalToRemoteSyncer* syncer, 584 const SyncStatusCallback& callback, 585 SyncStatusCode status) { 586 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 587 588 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) && 589 syncer->url().is_valid() && 590 syncer->sync_action() != SYNC_ACTION_NONE) { 591 fileapi::FileSystemURL updated_url = syncer->url(); 592 if (!syncer->target_path().empty()) { 593 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(), 594 syncer->target_path()); 595 } 596 FOR_EACH_OBSERVER(Observer, observers_, 597 OnFileStatusChanged(updated_url, 598 SYNC_FILE_STATUS_SYNCED, 599 syncer->sync_action(), 600 SYNC_DIRECTION_LOCAL_TO_REMOTE)); 601 } 602 603 if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) { 604 RegisterOrigin(syncer->url().origin(), 605 base::Bind(&EmptyStatusCallback)); 606 } 607 608 if (syncer->needs_remote_change_listing() && 609 !listing_remote_changes_) { 610 task_manager_->ScheduleSyncTask( 611 FROM_HERE, 612 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 613 SyncTaskManager::PRIORITY_HIGH, 614 base::Bind(&SyncWorker::DidFetchChanges, 615 weak_ptr_factory_.GetWeakPtr())); 616 should_check_remote_change_ = false; 617 listing_remote_changes_ = true; 618 time_to_check_changes_ = 619 base::TimeTicks::Now() + 620 base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds); 621 } 622 623 if (status == SYNC_STATUS_OK) 624 should_check_conflict_ = true; 625 626 callback.Run(status); 627 } 628 629 void SyncWorker::MaybeStartFetchChanges() { 630 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 631 632 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) 633 return; 634 635 if (!GetMetadataDatabase()) 636 return; 637 638 if (listing_remote_changes_) 639 return; 640 641 base::TimeTicks now = base::TimeTicks::Now(); 642 if (!should_check_remote_change_ && now < time_to_check_changes_) { 643 if (!GetMetadataDatabase()->HasDirtyTracker() && 644 should_check_conflict_) { 645 should_check_conflict_ = false; 646 task_manager_->ScheduleSyncTaskIfIdle( 647 FROM_HERE, 648 scoped_ptr<SyncTask>(new ConflictResolver(context_.get())), 649 base::Bind(&SyncWorker::DidResolveConflict, 650 weak_ptr_factory_.GetWeakPtr())); 651 } 652 return; 653 } 654 655 if (task_manager_->ScheduleSyncTaskIfIdle( 656 FROM_HERE, 657 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 658 base::Bind(&SyncWorker::DidFetchChanges, 659 weak_ptr_factory_.GetWeakPtr()))) { 660 should_check_remote_change_ = false; 661 listing_remote_changes_ = true; 662 time_to_check_changes_ = 663 now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds); 664 } 665 } 666 667 void SyncWorker::DidResolveConflict(SyncStatusCode status) { 668 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 669 670 if (status == SYNC_STATUS_OK) 671 should_check_conflict_ = true; 672 } 673 674 void SyncWorker::DidFetchChanges(SyncStatusCode status) { 675 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 676 677 if (status == SYNC_STATUS_OK) 678 should_check_conflict_ = true; 679 listing_remote_changes_ = false; 680 } 681 682 void SyncWorker::UpdateServiceStateFromSyncStatusCode( 683 SyncStatusCode status, 684 bool used_network) { 685 switch (status) { 686 case SYNC_STATUS_OK: 687 if (used_network) 688 UpdateServiceState(REMOTE_SERVICE_OK, std::string()); 689 break; 690 691 // Authentication error. 692 case SYNC_STATUS_AUTHENTICATION_FAILED: 693 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 694 "Authentication required"); 695 break; 696 697 // OAuth token error. 698 case SYNC_STATUS_ACCESS_FORBIDDEN: 699 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 700 "Access forbidden"); 701 break; 702 703 // Errors which could make the service temporarily unavailable. 704 case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE: 705 case SYNC_STATUS_NETWORK_ERROR: 706 case SYNC_STATUS_ABORT: 707 case SYNC_STATUS_FAILED: 708 if (has_refresh_token_) { 709 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, 710 "Network or temporary service error."); 711 } else { 712 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 713 "Authentication required"); 714 } 715 break; 716 717 // Errors which would require manual user intervention to resolve. 718 case SYNC_DATABASE_ERROR_CORRUPTION: 719 case SYNC_DATABASE_ERROR_IO_ERROR: 720 case SYNC_DATABASE_ERROR_FAILED: 721 UpdateServiceState(REMOTE_SERVICE_DISABLED, 722 "Unrecoverable database error"); 723 break; 724 725 default: 726 // Other errors don't affect service state 727 break; 728 } 729 } 730 731 void SyncWorker::UpdateServiceState(RemoteServiceState state, 732 const std::string& description) { 733 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 734 735 RemoteServiceState old_state = GetCurrentState(); 736 service_state_ = state; 737 738 if (old_state == GetCurrentState()) 739 return; 740 741 util::Log(logging::LOG_VERBOSE, FROM_HERE, 742 "Service state changed: %d->%d: %s", 743 old_state, GetCurrentState(), description.c_str()); 744 745 FOR_EACH_OBSERVER( 746 Observer, observers_, 747 UpdateServiceState(GetCurrentState(), description)); 748 } 749 750 } // namespace drive_backend 751 } // namespace sync_file_system 752