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.
5 #include "chrome/browser/sync_file_system/drive_backend/sync_worker.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"
29 namespace sync_file_system {
31 class RemoteChangeProcessor;
33 namespace drive_backend {
37 void EmptyStatusCallback(SyncStatusCode status) {}
39 void InvokeIdleCallback(const base::Closure& idle_callback,
40 const SyncStatusCallback& callback) {
42 callback.Run(SYNC_STATUS_OK);
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),
58 extension_service_(extension_service),
59 weak_ptr_factory_(this) {
60 sequence_checker_.DetachFromSequence();
61 DCHECK(base_dir_.IsAbsolute());
64 SyncWorker::~SyncWorker() {
68 void SyncWorker::Initialize(scoped_ptr<SyncEngineContext> context) {
69 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
70 DCHECK(!task_manager_);
72 context_ = context.Pass();
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);
82 void SyncWorker::RegisterOrigin(
84 const SyncStatusCallback& callback) {
85 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
87 if (!GetMetadataDatabase())
90 scoped_ptr<RegisterAppTask> task(
91 new RegisterAppTask(context_.get(), origin.host()));
92 if (task->CanFinishImmediately()) {
93 callback.Run(SYNC_STATUS_OK);
97 task_manager_->ScheduleSyncTask(
98 FROM_HERE, task.Pass(), SyncTaskManager::PRIORITY_HIGH, callback);
101 void SyncWorker::EnableOrigin(
103 const SyncStatusCallback& callback) {
104 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
106 task_manager_->ScheduleTask(
108 base::Bind(&SyncWorker::DoEnableApp,
109 weak_ptr_factory_.GetWeakPtr(),
111 SyncTaskManager::PRIORITY_HIGH,
115 void SyncWorker::DisableOrigin(
117 const SyncStatusCallback& callback) {
118 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
120 task_manager_->ScheduleTask(
122 base::Bind(&SyncWorker::DoDisableApp,
123 weak_ptr_factory_.GetWeakPtr(),
125 SyncTaskManager::PRIORITY_HIGH,
129 void SyncWorker::UninstallOrigin(
131 RemoteFileSyncService::UninstallFlag flag,
132 const SyncStatusCallback& callback) {
133 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
135 task_manager_->ScheduleSyncTask(
137 scoped_ptr<SyncTask>(
138 new UninstallAppTask(context_.get(), origin.host(), flag)),
139 SyncTaskManager::PRIORITY_HIGH,
143 void SyncWorker::ProcessRemoteChange(const SyncFileCallback& callback) {
144 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
146 RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(context_.get());
147 task_manager_->ScheduleSyncTask(
149 scoped_ptr<SyncTask>(syncer),
150 SyncTaskManager::PRIORITY_MED,
151 base::Bind(&SyncWorker::DidProcessRemoteChange,
152 weak_ptr_factory_.GetWeakPtr(),
157 void SyncWorker::SetRemoteChangeProcessor(
158 RemoteChangeProcessorOnWorker* remote_change_processor_on_worker) {
159 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
161 context_->SetRemoteChangeProcessor(remote_change_processor_on_worker);
164 RemoteServiceState SyncWorker::GetCurrentState() const {
165 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
168 return REMOTE_SERVICE_DISABLED;
169 return service_state_;
172 void SyncWorker::GetOriginStatusMap(
173 const RemoteFileSyncService::StatusMapCallback& callback) {
174 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
176 if (!GetMetadataDatabase())
179 std::vector<std::string> app_ids;
180 GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
182 scoped_ptr<RemoteFileSyncService::OriginStatusMap>
183 status_map(new RemoteFileSyncService::OriginStatusMap);
184 for (std::vector<std::string>::const_iterator itr = app_ids.begin();
185 itr != app_ids.end(); ++itr) {
186 const std::string& app_id = *itr;
187 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
188 (*status_map)[origin] =
189 GetMetadataDatabase()->IsAppEnabled(app_id) ? "Enabled" : "Disabled";
192 callback.Run(status_map.Pass());
195 scoped_ptr<base::ListValue> SyncWorker::DumpFiles(const GURL& origin) {
196 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
198 if (!GetMetadataDatabase())
199 return scoped_ptr<base::ListValue>();
200 return GetMetadataDatabase()->DumpFiles(origin.host());
203 scoped_ptr<base::ListValue> SyncWorker::DumpDatabase() {
204 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
206 if (!GetMetadataDatabase())
207 return scoped_ptr<base::ListValue>();
208 return GetMetadataDatabase()->DumpDatabase();
211 void SyncWorker::SetSyncEnabled(bool enabled) {
212 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
214 if (sync_enabled_ == enabled)
217 RemoteServiceState old_state = GetCurrentState();
218 sync_enabled_ = enabled;
219 if (old_state == GetCurrentState())
227 enabled ? "Sync is enabled" : "Sync is disabled"));
230 void SyncWorker::PromoteDemotedChanges(const base::Closure& callback) {
231 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
233 MetadataDatabase* metadata_db = GetMetadataDatabase();
234 if (metadata_db && metadata_db->HasDemotedDirtyTracker()) {
235 metadata_db->PromoteDemotedTrackers();
239 OnPendingFileListUpdated(metadata_db->CountDirtyTracker()));
244 void SyncWorker::ApplyLocalChange(const FileChange& local_change,
245 const base::FilePath& local_path,
246 const SyncFileMetadata& local_metadata,
247 const storage::FileSystemURL& url,
248 const SyncStatusCallback& callback) {
249 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
251 LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer(
252 context_.get(), local_metadata, local_change, local_path, url);
253 task_manager_->ScheduleSyncTask(
255 scoped_ptr<SyncTask>(syncer),
256 SyncTaskManager::PRIORITY_MED,
257 base::Bind(&SyncWorker::DidApplyLocalChange,
258 weak_ptr_factory_.GetWeakPtr(),
263 void SyncWorker::MaybeScheduleNextTask() {
264 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
266 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
269 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated.
270 // TODO(tzik): Add an interface to get the number of dirty trackers to
273 if (MaybeStartFetchChanges())
276 if (!call_on_idle_callback_.is_null()) {
277 base::Closure callback = call_on_idle_callback_;
278 call_on_idle_callback_.Reset();
283 void SyncWorker::NotifyLastOperationStatus(
284 SyncStatusCode status,
286 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
288 UpdateServiceStateFromSyncStatusCode(status, used_network);
290 if (GetMetadataDatabase()) {
292 Observer, observers_,
293 OnPendingFileListUpdated(GetMetadataDatabase()->CountDirtyTracker()));
297 void SyncWorker::RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) {
298 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
300 context_->GetUITaskRunner()->PostTask(
302 base::Bind(&TaskLogger::RecordLog,
303 context_->GetTaskLogger(),
304 base::Passed(&task_log)));
307 void SyncWorker::ActivateService(RemoteServiceState service_state,
308 const std::string& description) {
309 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
310 UpdateServiceState(service_state, description);
311 if (!GetMetadataDatabase()) {
312 PostInitializeTask();
316 should_check_remote_change_ = true;
317 MaybeScheduleNextTask();
320 void SyncWorker::DeactivateService(const std::string& description) {
321 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
322 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, description);
325 void SyncWorker::DetachFromSequence() {
326 task_manager_->DetachFromSequence();
327 context_->DetachFromSequence();
328 sequence_checker_.DetachFromSequence();
331 void SyncWorker::AddObserver(Observer* observer) {
332 observers_.AddObserver(observer);
335 void SyncWorker::DoDisableApp(const std::string& app_id,
336 const SyncStatusCallback& callback) {
337 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
339 if (!GetMetadataDatabase()) {
340 callback.Run(SYNC_STATUS_OK);
344 SyncStatusCode status = GetMetadataDatabase()->DisableApp(app_id);
345 callback.Run(status);
348 void SyncWorker::DoEnableApp(const std::string& app_id,
349 const SyncStatusCallback& callback) {
350 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
352 if (!GetMetadataDatabase()) {
353 callback.Run(SYNC_STATUS_OK);
357 SyncStatusCode status = GetMetadataDatabase()->EnableApp(app_id);
358 callback.Run(status);
361 void SyncWorker::PostInitializeTask() {
362 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
363 DCHECK(!GetMetadataDatabase());
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),
371 task_manager_->ScheduleSyncTask(
373 scoped_ptr<SyncTask>(initializer),
374 SyncTaskManager::PRIORITY_HIGH,
375 base::Bind(&SyncWorker::DidInitialize,
376 weak_ptr_factory_.GetWeakPtr(),
380 void SyncWorker::DidInitialize(SyncEngineInitializer* initializer,
381 SyncStatusCode status) {
382 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
384 if (status == SYNC_STATUS_ACCESS_FORBIDDEN) {
385 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN, "Access forbidden");
388 if (status != SYNC_STATUS_OK) {
389 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
390 "Could not initialize remote service");
394 scoped_ptr<MetadataDatabase> metadata_database =
395 initializer->PassMetadataDatabase();
396 if (metadata_database) {
397 context_->SetMetadataDatabase(metadata_database.Pass());
401 UpdateServiceState(REMOTE_SERVICE_OK, std::string());
402 UpdateRegisteredApps();
405 void SyncWorker::UpdateRegisteredApps() {
406 MetadataDatabase* metadata_db = GetMetadataDatabase();
407 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
410 scoped_ptr<std::vector<std::string> > app_ids(new std::vector<std::string>);
411 metadata_db->GetRegisteredAppIDs(app_ids.get());
413 AppStatusMap* app_status = new AppStatusMap;
414 base::Closure callback =
415 base::Bind(&SyncWorker::DidQueryAppStatus,
416 weak_ptr_factory_.GetWeakPtr(),
417 base::Owned(app_status));
419 context_->GetUITaskRunner()->PostTask(
421 base::Bind(&SyncWorker::QueryAppStatusOnUIThread,
423 base::Owned(app_ids.release()),
425 RelayCallbackToTaskRunner(
426 context_->GetWorkerTaskRunner(),
427 FROM_HERE, callback)));
430 void SyncWorker::QueryAppStatusOnUIThread(
431 const base::WeakPtr<ExtensionServiceInterface>& extension_service_ptr,
432 const std::vector<std::string>* app_ids,
433 AppStatusMap* status,
434 const base::Closure& callback) {
435 ExtensionServiceInterface* extension_service = extension_service_ptr.get();
436 if (!extension_service) {
441 for (std::vector<std::string>::const_iterator itr = app_ids->begin();
442 itr != app_ids->end(); ++itr) {
443 const std::string& app_id = *itr;
444 if (!extension_service->GetInstalledExtension(app_id))
445 (*status)[app_id] = APP_STATUS_UNINSTALLED;
446 else if (!extension_service->IsExtensionEnabled(app_id))
447 (*status)[app_id] = APP_STATUS_DISABLED;
449 (*status)[app_id] = APP_STATUS_ENABLED;
455 void SyncWorker::DidQueryAppStatus(const AppStatusMap* app_status) {
456 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
458 MetadataDatabase* metadata_db = GetMetadataDatabase();
461 // Update the status of every origin using status from ExtensionService.
462 for (AppStatusMap::const_iterator itr = app_status->begin();
463 itr != app_status->end(); ++itr) {
464 const std::string& app_id = itr->first;
465 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
467 if (itr->second == APP_STATUS_UNINSTALLED) {
468 // Extension has been uninstalled.
469 // (At this stage we can't know if it was unpacked extension or not,
470 // so just purge the remote folder.)
471 UninstallOrigin(origin,
472 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
473 base::Bind(&EmptyStatusCallback));
478 if (!metadata_db->FindAppRootTracker(app_id, &tracker)) {
479 // App will register itself on first run.
483 DCHECK(itr->second == APP_STATUS_ENABLED ||
484 itr->second == APP_STATUS_DISABLED);
485 bool is_app_enabled = (itr->second == APP_STATUS_ENABLED);
486 bool is_app_root_tracker_enabled =
487 (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT);
488 if (is_app_enabled && !is_app_root_tracker_enabled)
489 EnableOrigin(origin, base::Bind(&EmptyStatusCallback));
490 else if (!is_app_enabled && is_app_root_tracker_enabled)
491 DisableOrigin(origin, base::Bind(&EmptyStatusCallback));
495 void SyncWorker::DidProcessRemoteChange(RemoteToLocalSyncer* syncer,
496 const SyncFileCallback& callback,
497 SyncStatusCode status) {
498 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
500 if (syncer->is_sync_root_deletion()) {
501 MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase());
502 PostInitializeTask();
503 callback.Run(status, syncer->url());
507 if (status == SYNC_STATUS_OK) {
508 if (syncer->sync_action() != SYNC_ACTION_NONE &&
509 syncer->url().is_valid()) {
511 Observer, observers_,
515 SYNC_FILE_STATUS_SYNCED,
516 syncer->sync_action(),
517 SYNC_DIRECTION_REMOTE_TO_LOCAL));
520 if (syncer->sync_action() == SYNC_ACTION_DELETED &&
521 syncer->url().is_valid() &&
522 storage::VirtualPath::IsRootPath(syncer->url().path())) {
523 RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback));
525 should_check_conflict_ = true;
527 callback.Run(status, syncer->url());
530 void SyncWorker::DidApplyLocalChange(LocalToRemoteSyncer* syncer,
531 const SyncStatusCallback& callback,
532 SyncStatusCode status) {
533 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
535 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) &&
536 syncer->url().is_valid() &&
537 syncer->sync_action() != SYNC_ACTION_NONE) {
538 storage::FileSystemURL updated_url = syncer->url();
539 if (!syncer->target_path().empty()) {
540 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(),
541 syncer->target_path());
543 FOR_EACH_OBSERVER(Observer, observers_,
544 OnFileStatusChanged(updated_url,
546 SYNC_FILE_STATUS_SYNCED,
547 syncer->sync_action(),
548 SYNC_DIRECTION_LOCAL_TO_REMOTE));
551 if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) {
552 RegisterOrigin(syncer->url().origin(),
553 base::Bind(&EmptyStatusCallback));
556 if (syncer->needs_remote_change_listing() &&
557 !listing_remote_changes_) {
558 task_manager_->ScheduleSyncTask(
560 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
561 SyncTaskManager::PRIORITY_HIGH,
562 base::Bind(&SyncWorker::DidFetchChanges,
563 weak_ptr_factory_.GetWeakPtr()));
564 should_check_remote_change_ = false;
565 listing_remote_changes_ = true;
566 time_to_check_changes_ =
567 base::TimeTicks::Now() +
568 base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
571 if (status == SYNC_STATUS_OK)
572 should_check_conflict_ = true;
574 callback.Run(status);
577 bool SyncWorker::MaybeStartFetchChanges() {
578 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
580 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
583 if (!GetMetadataDatabase())
586 if (listing_remote_changes_)
589 base::TimeTicks now = base::TimeTicks::Now();
590 if (!should_check_remote_change_ && now < time_to_check_changes_) {
591 if (!GetMetadataDatabase()->HasDirtyTracker() &&
592 should_check_conflict_) {
593 should_check_conflict_ = false;
594 return task_manager_->ScheduleSyncTaskIfIdle(
596 scoped_ptr<SyncTask>(new ConflictResolver(context_.get())),
597 base::Bind(&SyncWorker::DidResolveConflict,
598 weak_ptr_factory_.GetWeakPtr()));
603 if (task_manager_->ScheduleSyncTaskIfIdle(
605 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
606 base::Bind(&SyncWorker::DidFetchChanges,
607 weak_ptr_factory_.GetWeakPtr()))) {
608 should_check_remote_change_ = false;
609 listing_remote_changes_ = true;
610 time_to_check_changes_ =
611 now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
617 void SyncWorker::DidResolveConflict(SyncStatusCode status) {
618 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
620 if (status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY)
621 should_check_conflict_ = true;
624 void SyncWorker::DidFetchChanges(SyncStatusCode status) {
625 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
627 if (status == SYNC_STATUS_OK)
628 should_check_conflict_ = true;
629 listing_remote_changes_ = false;
632 void SyncWorker::UpdateServiceStateFromSyncStatusCode(
633 SyncStatusCode status,
638 UpdateServiceState(REMOTE_SERVICE_OK, std::string());
641 // Authentication error.
642 case SYNC_STATUS_AUTHENTICATION_FAILED:
643 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
644 "Authentication required");
647 // OAuth token error.
648 case SYNC_STATUS_ACCESS_FORBIDDEN:
649 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN,
653 // Errors which could make the service temporarily unavailable.
654 case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE:
655 case SYNC_STATUS_NETWORK_ERROR:
656 case SYNC_STATUS_ABORT:
657 case SYNC_STATUS_FAILED:
658 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
659 "Network or temporary service error.");
662 // Errors which would require manual user intervention to resolve.
663 case SYNC_DATABASE_ERROR_CORRUPTION:
664 case SYNC_DATABASE_ERROR_IO_ERROR:
665 case SYNC_DATABASE_ERROR_FAILED:
666 UpdateServiceState(REMOTE_SERVICE_DISABLED,
667 "Unrecoverable database error");
671 // Other errors don't affect service state
676 void SyncWorker::UpdateServiceState(RemoteServiceState state,
677 const std::string& description) {
678 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
680 RemoteServiceState old_state = GetCurrentState();
681 service_state_ = state;
683 if (old_state == GetCurrentState())
686 util::Log(logging::LOG_VERBOSE, FROM_HERE,
687 "Service state changed: %d->%d: %s",
688 old_state, GetCurrentState(), description.c_str());
691 Observer, observers_,
692 UpdateServiceState(GetCurrentState(), description));
695 void SyncWorker::CallOnIdleForTesting(const base::Closure& callback) {
696 if (task_manager_->ScheduleTaskIfIdle(
698 base::Bind(&InvokeIdleCallback, callback),
699 base::Bind(&EmptyStatusCallback)))
701 call_on_idle_callback_ = base::Bind(
702 &SyncWorker::CallOnIdleForTesting,
703 weak_ptr_factory_.GetWeakPtr(),
707 drive::DriveServiceInterface* SyncWorker::GetDriveService() {
708 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
709 return context_->GetDriveService();
712 drive::DriveUploaderInterface* SyncWorker::GetDriveUploader() {
713 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
714 return context_->GetDriveUploader();
717 MetadataDatabase* SyncWorker::GetMetadataDatabase() {
718 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
719 return context_->GetMetadataDatabase();
722 } // namespace drive_backend
723 } // namespace sync_file_system