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