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