sync_worker.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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 29namespace sync_file_system { 30 31class RemoteChangeProcessor; 32 33namespace drive_backend { 34 35namespace { 36 37void EmptyStatusCallback(SyncStatusCode status) {} 38 39void 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 47SyncWorker::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 64SyncWorker::~SyncWorker() { 65 observers_.Clear(); 66} 67 68void 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 82void 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 104void 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 118void 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 132void 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 146void 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 160void 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 167RemoteServiceState SyncWorker::GetCurrentState() const { 168 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 169 170 if (!sync_enabled_) 171 return REMOTE_SERVICE_DISABLED; 172 return service_state_; 173} 174 175void 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 198scoped_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 206scoped_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 214void 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 233void SyncWorker::PromoteDemotedChanges(const base::Closure& callback) { 234 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 235 236 MetadataDatabase* metadata_db = GetMetadataDatabase(); 237 if (metadata_db && metadata_db->HasLowPriorityDirtyTracker()) { 238 metadata_db->PromoteLowerPriorityTrackersToNormal(); 239 FOR_EACH_OBSERVER( 240 Observer, 241 observers_, 242 OnPendingFileListUpdated(metadata_db->CountDirtyTracker())); 243 } 244 callback.Run(); 245} 246 247void SyncWorker::ApplyLocalChange( 248 const FileChange& local_change, 249 const base::FilePath& local_path, 250 const SyncFileMetadata& local_metadata, 251 const fileapi::FileSystemURL& url, 252 const SyncStatusCallback& callback) { 253 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 254 255 LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer( 256 context_.get(), local_metadata, local_change, local_path, url); 257 task_manager_->ScheduleSyncTask( 258 FROM_HERE, 259 scoped_ptr<SyncTask>(syncer), 260 SyncTaskManager::PRIORITY_MED, 261 base::Bind(&SyncWorker::DidApplyLocalChange, 262 weak_ptr_factory_.GetWeakPtr(), 263 syncer, 264 callback)); 265} 266 267void SyncWorker::MaybeScheduleNextTask() { 268 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 269 270 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) 271 return; 272 273 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated. 274 // TODO(tzik): Add an interface to get the number of dirty trackers to 275 // MetadataDatabase. 276 277 if (MaybeStartFetchChanges()) 278 return; 279 280 if (!call_on_idle_callback_.is_null()) { 281 base::Closure callback = call_on_idle_callback_; 282 call_on_idle_callback_.Reset(); 283 callback.Run(); 284 } 285} 286 287void SyncWorker::NotifyLastOperationStatus( 288 SyncStatusCode status, 289 bool used_network) { 290 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 291 292 UpdateServiceStateFromSyncStatusCode(status, used_network); 293 294 if (GetMetadataDatabase()) { 295 FOR_EACH_OBSERVER( 296 Observer, observers_, 297 OnPendingFileListUpdated(GetMetadataDatabase()->CountDirtyTracker())); 298 } 299} 300 301void SyncWorker::RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) { 302 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 303 304 context_->GetUITaskRunner()->PostTask( 305 FROM_HERE, 306 base::Bind(&TaskLogger::RecordLog, 307 context_->GetTaskLogger(), 308 base::Passed(&task_log))); 309} 310 311void SyncWorker::ActivateService(RemoteServiceState service_state, 312 const std::string& description) { 313 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 314 UpdateServiceState(service_state, description); 315 if (!GetMetadataDatabase()) { 316 PostInitializeTask(); 317 return; 318 } 319 320 should_check_remote_change_ = true; 321 MaybeScheduleNextTask(); 322} 323 324void SyncWorker::DeactivateService(const std::string& description) { 325 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 326 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, description); 327} 328 329void SyncWorker::DetachFromSequence() { 330 task_manager_->DetachFromSequence(); 331 context_->DetachFromSequence(); 332 sequence_checker_.DetachFromSequence(); 333} 334 335void SyncWorker::AddObserver(Observer* observer) { 336 observers_.AddObserver(observer); 337} 338 339void SyncWorker::DoDisableApp(const std::string& app_id, 340 const SyncStatusCallback& callback) { 341 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 342 343 if (GetMetadataDatabase()) { 344 GetMetadataDatabase()->DisableApp(app_id, callback); 345 } else { 346 callback.Run(SYNC_STATUS_OK); 347 } 348} 349 350void SyncWorker::DoEnableApp(const std::string& app_id, 351 const SyncStatusCallback& callback) { 352 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 353 354 if (GetMetadataDatabase()) { 355 GetMetadataDatabase()->EnableApp(app_id, callback); 356 } else { 357 callback.Run(SYNC_STATUS_OK); 358 } 359} 360 361void SyncWorker::PostInitializeTask() { 362 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 363 DCHECK(!GetMetadataDatabase()); 364 365 // This initializer task may not run if MetadataDatabase in context_ is 366 // already initialized when it runs. 367 SyncEngineInitializer* initializer = 368 new SyncEngineInitializer(context_.get(), 369 base_dir_.Append(kDatabaseName), 370 env_override_); 371 task_manager_->ScheduleSyncTask( 372 FROM_HERE, 373 scoped_ptr<SyncTask>(initializer), 374 SyncTaskManager::PRIORITY_HIGH, 375 base::Bind(&SyncWorker::DidInitialize, 376 weak_ptr_factory_.GetWeakPtr(), 377 initializer)); 378} 379 380void SyncWorker::DidInitialize(SyncEngineInitializer* initializer, 381 SyncStatusCode status) { 382 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 383 384 if (status == SYNC_STATUS_ACCESS_FORBIDDEN) { 385 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN, "Access forbidden"); 386 return; 387 } 388 if (status != SYNC_STATUS_OK) { 389 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, 390 "Could not initialize remote service"); 391 return; 392 } 393 394 scoped_ptr<MetadataDatabase> metadata_database = 395 initializer->PassMetadataDatabase(); 396 if (metadata_database) 397 context_->SetMetadataDatabase(metadata_database.Pass()); 398 399 UpdateRegisteredApps(); 400} 401 402void SyncWorker::UpdateRegisteredApps() { 403 MetadataDatabase* metadata_db = GetMetadataDatabase(); 404 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 405 DCHECK(metadata_db); 406 407 scoped_ptr<std::vector<std::string> > app_ids(new std::vector<std::string>); 408 metadata_db->GetRegisteredAppIDs(app_ids.get()); 409 410 AppStatusMap* app_status = new AppStatusMap; 411 base::Closure callback = 412 base::Bind(&SyncWorker::DidQueryAppStatus, 413 weak_ptr_factory_.GetWeakPtr(), 414 base::Owned(app_status)); 415 416 context_->GetUITaskRunner()->PostTask( 417 FROM_HERE, 418 base::Bind(&SyncWorker::QueryAppStatusOnUIThread, 419 extension_service_, 420 base::Owned(app_ids.release()), 421 app_status, 422 RelayCallbackToTaskRunner( 423 context_->GetWorkerTaskRunner(), 424 FROM_HERE, callback))); 425} 426 427void SyncWorker::QueryAppStatusOnUIThread( 428 const base::WeakPtr<ExtensionServiceInterface>& extension_service_ptr, 429 const std::vector<std::string>* app_ids, 430 AppStatusMap* status, 431 const base::Closure& callback) { 432 ExtensionServiceInterface* extension_service = extension_service_ptr.get(); 433 if (!extension_service) { 434 callback.Run(); 435 return; 436 } 437 438 for (std::vector<std::string>::const_iterator itr = app_ids->begin(); 439 itr != app_ids->end(); ++itr) { 440 const std::string& app_id = *itr; 441 if (!extension_service->GetInstalledExtension(app_id)) 442 (*status)[app_id] = APP_STATUS_UNINSTALLED; 443 else if (!extension_service->IsExtensionEnabled(app_id)) 444 (*status)[app_id] = APP_STATUS_DISABLED; 445 else 446 (*status)[app_id] = APP_STATUS_ENABLED; 447 } 448 449 callback.Run(); 450} 451 452void SyncWorker::DidQueryAppStatus(const AppStatusMap* app_status) { 453 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 454 455 MetadataDatabase* metadata_db = GetMetadataDatabase(); 456 DCHECK(metadata_db); 457 458 // Update the status of every origin using status from ExtensionService. 459 for (AppStatusMap::const_iterator itr = app_status->begin(); 460 itr != app_status->end(); ++itr) { 461 const std::string& app_id = itr->first; 462 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id); 463 464 if (itr->second == APP_STATUS_UNINSTALLED) { 465 // Extension has been uninstalled. 466 // (At this stage we can't know if it was unpacked extension or not, 467 // so just purge the remote folder.) 468 UninstallOrigin(origin, 469 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE, 470 base::Bind(&EmptyStatusCallback)); 471 continue; 472 } 473 474 FileTracker tracker; 475 if (!metadata_db->FindAppRootTracker(app_id, &tracker)) { 476 // App will register itself on first run. 477 continue; 478 } 479 480 DCHECK(itr->second == APP_STATUS_ENABLED || 481 itr->second == APP_STATUS_DISABLED); 482 bool is_app_enabled = (itr->second == APP_STATUS_ENABLED); 483 bool is_app_root_tracker_enabled = 484 (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT); 485 if (is_app_enabled && !is_app_root_tracker_enabled) 486 EnableOrigin(origin, base::Bind(&EmptyStatusCallback)); 487 else if (!is_app_enabled && is_app_root_tracker_enabled) 488 DisableOrigin(origin, base::Bind(&EmptyStatusCallback)); 489 } 490} 491 492void SyncWorker::DidProcessRemoteChange(RemoteToLocalSyncer* syncer, 493 const SyncFileCallback& callback, 494 SyncStatusCode status) { 495 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 496 497 if (syncer->is_sync_root_deletion()) { 498 MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase()); 499 PostInitializeTask(); 500 callback.Run(status, syncer->url()); 501 return; 502 } 503 504 if (status == SYNC_STATUS_OK) { 505 if (syncer->sync_action() != SYNC_ACTION_NONE && 506 syncer->url().is_valid()) { 507 FOR_EACH_OBSERVER( 508 Observer, observers_, 509 OnFileStatusChanged( 510 syncer->url(), 511 SYNC_FILE_STATUS_SYNCED, 512 syncer->sync_action(), 513 SYNC_DIRECTION_REMOTE_TO_LOCAL)); 514 } 515 516 if (syncer->sync_action() == SYNC_ACTION_DELETED && 517 syncer->url().is_valid() && 518 fileapi::VirtualPath::IsRootPath(syncer->url().path())) { 519 RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback)); 520 } 521 should_check_conflict_ = true; 522 } 523 callback.Run(status, syncer->url()); 524} 525 526void SyncWorker::DidApplyLocalChange(LocalToRemoteSyncer* syncer, 527 const SyncStatusCallback& callback, 528 SyncStatusCode status) { 529 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 530 531 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) && 532 syncer->url().is_valid() && 533 syncer->sync_action() != SYNC_ACTION_NONE) { 534 fileapi::FileSystemURL updated_url = syncer->url(); 535 if (!syncer->target_path().empty()) { 536 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(), 537 syncer->target_path()); 538 } 539 FOR_EACH_OBSERVER(Observer, observers_, 540 OnFileStatusChanged(updated_url, 541 SYNC_FILE_STATUS_SYNCED, 542 syncer->sync_action(), 543 SYNC_DIRECTION_LOCAL_TO_REMOTE)); 544 } 545 546 if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) { 547 RegisterOrigin(syncer->url().origin(), 548 base::Bind(&EmptyStatusCallback)); 549 } 550 551 if (syncer->needs_remote_change_listing() && 552 !listing_remote_changes_) { 553 task_manager_->ScheduleSyncTask( 554 FROM_HERE, 555 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 556 SyncTaskManager::PRIORITY_HIGH, 557 base::Bind(&SyncWorker::DidFetchChanges, 558 weak_ptr_factory_.GetWeakPtr())); 559 should_check_remote_change_ = false; 560 listing_remote_changes_ = true; 561 time_to_check_changes_ = 562 base::TimeTicks::Now() + 563 base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds); 564 } 565 566 if (status == SYNC_STATUS_OK) 567 should_check_conflict_ = true; 568 569 callback.Run(status); 570} 571 572bool SyncWorker::MaybeStartFetchChanges() { 573 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 574 575 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) 576 return false; 577 578 if (!GetMetadataDatabase()) 579 return false; 580 581 if (listing_remote_changes_) 582 return false; 583 584 base::TimeTicks now = base::TimeTicks::Now(); 585 if (!should_check_remote_change_ && now < time_to_check_changes_) { 586 if (!GetMetadataDatabase()->HasDirtyTracker() && 587 should_check_conflict_) { 588 should_check_conflict_ = false; 589 return task_manager_->ScheduleSyncTaskIfIdle( 590 FROM_HERE, 591 scoped_ptr<SyncTask>(new ConflictResolver(context_.get())), 592 base::Bind(&SyncWorker::DidResolveConflict, 593 weak_ptr_factory_.GetWeakPtr())); 594 } 595 return false; 596 } 597 598 if (task_manager_->ScheduleSyncTaskIfIdle( 599 FROM_HERE, 600 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 601 base::Bind(&SyncWorker::DidFetchChanges, 602 weak_ptr_factory_.GetWeakPtr()))) { 603 should_check_remote_change_ = false; 604 listing_remote_changes_ = true; 605 time_to_check_changes_ = 606 now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds); 607 return true; 608 } 609 return false; 610} 611 612void SyncWorker::DidResolveConflict(SyncStatusCode status) { 613 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 614 615 if (status == SYNC_STATUS_OK) 616 should_check_conflict_ = true; 617} 618 619void SyncWorker::DidFetchChanges(SyncStatusCode status) { 620 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 621 622 if (status == SYNC_STATUS_OK) 623 should_check_conflict_ = true; 624 listing_remote_changes_ = false; 625} 626 627void SyncWorker::UpdateServiceStateFromSyncStatusCode( 628 SyncStatusCode status, 629 bool used_network) { 630 switch (status) { 631 case SYNC_STATUS_OK: 632 if (used_network) 633 UpdateServiceState(REMOTE_SERVICE_OK, std::string()); 634 break; 635 636 // Authentication error. 637 case SYNC_STATUS_AUTHENTICATION_FAILED: 638 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, 639 "Authentication required"); 640 break; 641 642 // OAuth token error. 643 case SYNC_STATUS_ACCESS_FORBIDDEN: 644 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN, 645 "Access forbidden"); 646 break; 647 648 // Errors which could make the service temporarily unavailable. 649 case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE: 650 case SYNC_STATUS_NETWORK_ERROR: 651 case SYNC_STATUS_ABORT: 652 case SYNC_STATUS_FAILED: 653 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, 654 "Network or temporary service error."); 655 break; 656 657 // Errors which would require manual user intervention to resolve. 658 case SYNC_DATABASE_ERROR_CORRUPTION: 659 case SYNC_DATABASE_ERROR_IO_ERROR: 660 case SYNC_DATABASE_ERROR_FAILED: 661 UpdateServiceState(REMOTE_SERVICE_DISABLED, 662 "Unrecoverable database error"); 663 break; 664 665 default: 666 // Other errors don't affect service state 667 break; 668 } 669} 670 671void SyncWorker::UpdateServiceState(RemoteServiceState state, 672 const std::string& description) { 673 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 674 675 RemoteServiceState old_state = GetCurrentState(); 676 service_state_ = state; 677 678 if (old_state == GetCurrentState()) 679 return; 680 681 util::Log(logging::LOG_VERBOSE, FROM_HERE, 682 "Service state changed: %d->%d: %s", 683 old_state, GetCurrentState(), description.c_str()); 684 685 FOR_EACH_OBSERVER( 686 Observer, observers_, 687 UpdateServiceState(GetCurrentState(), description)); 688} 689 690void SyncWorker::CallOnIdleForTesting(const base::Closure& callback) { 691 if (task_manager_->ScheduleTaskIfIdle( 692 FROM_HERE, 693 base::Bind(&InvokeIdleCallback, callback), 694 base::Bind(&EmptyStatusCallback))) 695 return; 696 call_on_idle_callback_ = base::Bind( 697 &SyncWorker::CallOnIdleForTesting, 698 weak_ptr_factory_.GetWeakPtr(), 699 callback); 700} 701 702drive::DriveServiceInterface* SyncWorker::GetDriveService() { 703 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 704 return context_->GetDriveService(); 705} 706 707drive::DriveUploaderInterface* SyncWorker::GetDriveUploader() { 708 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 709 return context_->GetDriveUploader(); 710} 711 712MetadataDatabase* SyncWorker::GetMetadataDatabase() { 713 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 714 return context_->GetMetadataDatabase(); 715} 716 717} // namespace drive_backend 718} // namespace sync_file_system 719