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