sync_engine.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
1// Copyright 2013 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_engine.h" 6 7#include <vector> 8 9#include "base/bind.h" 10#include "base/threading/sequenced_worker_pool.h" 11#include "base/values.h" 12#include "chrome/browser/drive/drive_api_service.h" 13#include "chrome/browser/drive/drive_notification_manager.h" 14#include "chrome/browser/drive/drive_notification_manager_factory.h" 15#include "chrome/browser/drive/drive_service_interface.h" 16#include "chrome/browser/drive/drive_uploader.h" 17#include "chrome/browser/extensions/extension_service.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 20#include "chrome/browser/signin/signin_manager_factory.h" 21#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h" 22#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 23#include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h" 24#include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h" 25#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 26#include "chrome/browser/sync_file_system/drive_backend/register_app_task.h" 27#include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h" 28#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 29#include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h" 30#include "chrome/browser/sync_file_system/drive_backend/sync_task.h" 31#include "chrome/browser/sync_file_system/drive_backend/sync_worker.h" 32#include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h" 33#include "chrome/browser/sync_file_system/file_status_observer.h" 34#include "chrome/browser/sync_file_system/logger.h" 35#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 36#include "components/signin/core/browser/profile_oauth2_token_service.h" 37#include "components/signin/core/browser/signin_manager.h" 38#include "content/public/browser/browser_thread.h" 39#include "extensions/browser/extension_system.h" 40#include "extensions/browser/extension_system_provider.h" 41#include "extensions/browser/extensions_browser_client.h" 42#include "extensions/common/extension.h" 43#include "google_apis/drive/drive_api_url_generator.h" 44#include "google_apis/drive/gdata_wapi_url_generator.h" 45#include "webkit/common/blob/scoped_file.h" 46#include "webkit/common/fileapi/file_system_util.h" 47 48namespace sync_file_system { 49 50class RemoteChangeProcessor; 51 52namespace drive_backend { 53namespace { 54 55void EmptyStatusCallback(SyncStatusCode status) {} 56 57} // namespace 58 59scoped_ptr<SyncEngine> SyncEngine::CreateForBrowserContext( 60 content::BrowserContext* context) { 61 scoped_refptr<base::SequencedWorkerPool> worker_pool( 62 content::BrowserThread::GetBlockingPool()); 63 scoped_refptr<base::SequencedTaskRunner> drive_task_runner( 64 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 65 worker_pool->GetSequenceToken(), 66 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 67 68 Profile* profile = Profile::FromBrowserContext(context); 69 ProfileOAuth2TokenService* token_service = 70 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 71 scoped_ptr<drive::DriveServiceInterface> drive_service( 72 new drive::DriveAPIService( 73 token_service, 74 context->GetRequestContext(), 75 drive_task_runner.get(), 76 GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), 77 GURL(google_apis::DriveApiUrlGenerator:: 78 kBaseDownloadUrlForProduction), 79 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), 80 std::string() /* custom_user_agent */)); 81 SigninManagerBase* signin_manager = 82 SigninManagerFactory::GetForProfile(profile); 83 drive_service->Initialize(signin_manager->GetAuthenticatedAccountId()); 84 85 scoped_ptr<drive::DriveUploaderInterface> drive_uploader( 86 new drive::DriveUploader(drive_service.get(), drive_task_runner.get())); 87 88 drive::DriveNotificationManager* notification_manager = 89 drive::DriveNotificationManagerFactory::GetForBrowserContext(context); 90 ExtensionService* extension_service = 91 extensions::ExtensionSystem::Get(context)->extension_service(); 92 93 scoped_refptr<base::SequencedTaskRunner> task_runner( 94 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 95 worker_pool->GetSequenceToken(), 96 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 97 98 scoped_ptr<drive_backend::SyncEngine> sync_engine( 99 new SyncEngine(drive_service.Pass(), 100 drive_uploader.Pass(), 101 notification_manager, 102 extension_service, 103 signin_manager)); 104 sync_engine->Initialize(GetSyncFileSystemDir(context->GetPath()), 105 task_runner.get(), 106 NULL); 107 108 return sync_engine.Pass(); 109} 110 111void SyncEngine::AppendDependsOnFactories( 112 std::set<BrowserContextKeyedServiceFactory*>* factories) { 113 DCHECK(factories); 114 factories->insert(drive::DriveNotificationManagerFactory::GetInstance()); 115 factories->insert(SigninManagerFactory::GetInstance()); 116 factories->insert( 117 extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); 118} 119 120SyncEngine::~SyncEngine() { 121 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 122 GetDriveService()->RemoveObserver(this); 123 if (notification_manager_) 124 notification_manager_->RemoveObserver(this); 125} 126 127void SyncEngine::Initialize(const base::FilePath& base_dir, 128 base::SequencedTaskRunner* task_runner, 129 leveldb::Env* env_override) { 130 scoped_ptr<SyncEngineContext> sync_engine_context( 131 new SyncEngineContext(drive_service_.get(), 132 drive_uploader_.get(), 133 task_runner)); 134 // TODO(peria): Move this create function to thread pool. 135 sync_worker_ = SyncWorker::CreateOnWorker(weak_ptr_factory_.GetWeakPtr(), 136 base_dir, 137 sync_engine_context.Pass(), 138 env_override); 139 140 if (notification_manager_) 141 notification_manager_->AddObserver(this); 142 GetDriveService()->AddObserver(this); 143 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 144} 145 146void SyncEngine::AddServiceObserver(SyncServiceObserver* observer) { 147 service_observers_.AddObserver(observer); 148} 149 150void SyncEngine::AddFileStatusObserver(FileStatusObserver* observer) { 151 file_status_observers_.AddObserver(observer); 152} 153 154void SyncEngine::RegisterOrigin( 155 const GURL& origin, const SyncStatusCallback& callback) { 156 sync_worker_->RegisterOrigin(origin, callback); 157} 158 159void SyncEngine::EnableOrigin( 160 const GURL& origin, const SyncStatusCallback& callback) { 161 sync_worker_->EnableOrigin(origin, callback); 162} 163 164void SyncEngine::DisableOrigin( 165 const GURL& origin, const SyncStatusCallback& callback) { 166 sync_worker_->DisableOrigin(origin, callback); 167} 168 169void SyncEngine::UninstallOrigin( 170 const GURL& origin, 171 UninstallFlag flag, 172 const SyncStatusCallback& callback) { 173 sync_worker_->UninstallOrigin(origin, flag, callback); 174} 175 176void SyncEngine::ProcessRemoteChange(const SyncFileCallback& callback) { 177 sync_worker_->ProcessRemoteChange(callback); 178} 179 180void SyncEngine::SetRemoteChangeProcessor( 181 RemoteChangeProcessor* processor) { 182 sync_worker_->SetRemoteChangeProcessor(processor); 183} 184 185LocalChangeProcessor* SyncEngine::GetLocalChangeProcessor() { 186 return this; 187} 188 189bool SyncEngine::IsConflicting(const fileapi::FileSystemURL& url) { 190 // TODO(tzik): Implement this before we support manual conflict resolution. 191 return false; 192} 193 194RemoteServiceState SyncEngine::GetCurrentState() const { 195 return sync_worker_->GetCurrentState(); 196} 197 198void SyncEngine::GetOriginStatusMap(OriginStatusMap* status_map) { 199 sync_worker_->GetOriginStatusMap(status_map); 200} 201 202scoped_ptr<base::ListValue> SyncEngine::DumpFiles(const GURL& origin) { 203 return sync_worker_->DumpFiles(origin); 204} 205 206scoped_ptr<base::ListValue> SyncEngine::DumpDatabase() { 207 return sync_worker_->DumpDatabase(); 208} 209 210void SyncEngine::SetSyncEnabled(bool enabled) { 211 sync_worker_->SetSyncEnabled(enabled); 212} 213 214void SyncEngine::UpdateSyncEnabled(bool enabled) { 215 const char* status_message = enabled ? "Sync is enabled" : "Sync is disabled"; 216 FOR_EACH_OBSERVER( 217 Observer, service_observers_, 218 OnRemoteServiceStateUpdated(GetCurrentState(), status_message)); 219} 220 221SyncStatusCode SyncEngine::SetDefaultConflictResolutionPolicy( 222 ConflictResolutionPolicy policy) { 223 return sync_worker_->SetDefaultConflictResolutionPolicy(policy); 224} 225 226SyncStatusCode SyncEngine::SetConflictResolutionPolicy( 227 const GURL& origin, 228 ConflictResolutionPolicy policy) { 229 return sync_worker_->SetConflictResolutionPolicy(origin, policy); 230} 231 232ConflictResolutionPolicy SyncEngine::GetDefaultConflictResolutionPolicy() 233 const { 234 return sync_worker_->GetDefaultConflictResolutionPolicy(); 235} 236 237ConflictResolutionPolicy SyncEngine::GetConflictResolutionPolicy( 238 const GURL& origin) const { 239 return sync_worker_->GetConflictResolutionPolicy(origin); 240} 241 242void SyncEngine::GetRemoteVersions( 243 const fileapi::FileSystemURL& url, 244 const RemoteVersionsCallback& callback) { 245 // TODO(tzik): Implement this before we support manual conflict resolution. 246 callback.Run(SYNC_STATUS_FAILED, std::vector<Version>()); 247} 248 249void SyncEngine::DownloadRemoteVersion( 250 const fileapi::FileSystemURL& url, 251 const std::string& version_id, 252 const DownloadVersionCallback& callback) { 253 // TODO(tzik): Implement this before we support manual conflict resolution. 254 callback.Run(SYNC_STATUS_FAILED, webkit_blob::ScopedFile()); 255} 256 257void SyncEngine::PromoteDemotedChanges() { 258 MetadataDatabase* metadata_db = GetMetadataDatabase(); 259 if (metadata_db && metadata_db->HasLowPriorityDirtyTracker()) { 260 metadata_db->PromoteLowerPriorityTrackersToNormal(); 261 FOR_EACH_OBSERVER( 262 Observer, 263 service_observers_, 264 OnRemoteChangeQueueUpdated(metadata_db->CountDirtyTracker())); 265 } 266} 267 268void SyncEngine::ApplyLocalChange( 269 const FileChange& local_change, 270 const base::FilePath& local_path, 271 const SyncFileMetadata& local_metadata, 272 const fileapi::FileSystemURL& url, 273 const SyncStatusCallback& callback) { 274 sync_worker_->ApplyLocalChange( 275 local_change, local_path, local_metadata, url, callback); 276} 277 278SyncTaskManager* SyncEngine::GetSyncTaskManagerForTesting() { 279 return sync_worker_->GetSyncTaskManager(); 280} 281 282void SyncEngine::OnNotificationReceived() { 283 sync_worker_->OnNotificationReceived(); 284} 285 286void SyncEngine::OnPushNotificationEnabled(bool) {} 287 288void SyncEngine::OnReadyToSendRequests() { 289 sync_worker_->OnReadyToSendRequests( 290 signin_manager_ ? signin_manager_->GetAuthenticatedAccountId() : ""); 291} 292 293void SyncEngine::OnRefreshTokenInvalid() { 294 sync_worker_->OnRefreshTokenInvalid(); 295} 296 297void SyncEngine::OnNetworkChanged( 298 net::NetworkChangeNotifier::ConnectionType type) { 299 sync_worker_->OnNetworkChanged(type); 300} 301 302drive::DriveServiceInterface* SyncEngine::GetDriveService() { 303 return sync_worker_->GetDriveService(); 304} 305 306drive::DriveUploaderInterface* SyncEngine::GetDriveUploader() { 307 return sync_worker_->GetDriveUploader(); 308} 309 310MetadataDatabase* SyncEngine::GetMetadataDatabase() { 311 return sync_worker_->GetMetadataDatabase(); 312} 313 314SyncEngine::SyncEngine( 315 scoped_ptr<drive::DriveServiceInterface> drive_service, 316 scoped_ptr<drive::DriveUploaderInterface> drive_uploader, 317 drive::DriveNotificationManager* notification_manager, 318 ExtensionServiceInterface* extension_service, 319 SigninManagerBase* signin_manager) 320 : drive_service_(drive_service.Pass()), 321 drive_uploader_(drive_uploader.Pass()), 322 notification_manager_(notification_manager), 323 extension_service_(extension_service), 324 signin_manager_(signin_manager), 325 weak_ptr_factory_(this) {} 326 327void SyncEngine::DidProcessRemoteChange(RemoteToLocalSyncer* syncer) { 328 if (syncer->sync_action() != SYNC_ACTION_NONE && syncer->url().is_valid()) { 329 FOR_EACH_OBSERVER(FileStatusObserver, 330 file_status_observers_, 331 OnFileStatusChanged(syncer->url(), 332 SYNC_FILE_STATUS_SYNCED, 333 syncer->sync_action(), 334 SYNC_DIRECTION_REMOTE_TO_LOCAL)); 335 } 336} 337 338void SyncEngine::DidApplyLocalChange(LocalToRemoteSyncer* syncer, 339 SyncStatusCode status) { 340 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) && 341 syncer->url().is_valid() && 342 syncer->sync_action() != SYNC_ACTION_NONE) { 343 fileapi::FileSystemURL updated_url = syncer->url(); 344 if (!syncer->target_path().empty()) { 345 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(), 346 syncer->target_path()); 347 } 348 FOR_EACH_OBSERVER(FileStatusObserver, 349 file_status_observers_, 350 OnFileStatusChanged(updated_url, 351 SYNC_FILE_STATUS_SYNCED, 352 syncer->sync_action(), 353 SYNC_DIRECTION_LOCAL_TO_REMOTE)); 354 } 355} 356 357void SyncEngine::UpdateServiceState(const std::string& description) { 358 FOR_EACH_OBSERVER( 359 Observer, service_observers_, 360 OnRemoteServiceStateUpdated(GetCurrentState(), description)); 361} 362 363void SyncEngine::UpdateRegisteredApps() { 364 if (!extension_service_) 365 return; 366 367 MetadataDatabase* metadata_db = GetMetadataDatabase(); 368 DCHECK(metadata_db); 369 std::vector<std::string> app_ids; 370 metadata_db->GetRegisteredAppIDs(&app_ids); 371 372 // Update the status of every origin using status from ExtensionService. 373 for (std::vector<std::string>::const_iterator itr = app_ids.begin(); 374 itr != app_ids.end(); ++itr) { 375 const std::string& app_id = *itr; 376 GURL origin = 377 extensions::Extension::GetBaseURLFromExtensionId(app_id); 378 if (!extension_service_->GetInstalledExtension(app_id)) { 379 // Extension has been uninstalled. 380 // (At this stage we can't know if it was unpacked extension or not, 381 // so just purge the remote folder.) 382 UninstallOrigin(origin, 383 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE, 384 base::Bind(&EmptyStatusCallback)); 385 continue; 386 } 387 FileTracker tracker; 388 if (!metadata_db->FindAppRootTracker(app_id, &tracker)) { 389 // App will register itself on first run. 390 continue; 391 } 392 bool is_app_enabled = extension_service_->IsExtensionEnabled(app_id); 393 bool is_app_root_tracker_enabled = 394 tracker.tracker_kind() == TRACKER_KIND_APP_ROOT; 395 if (is_app_enabled && !is_app_root_tracker_enabled) 396 EnableOrigin(origin, base::Bind(&EmptyStatusCallback)); 397 else if (!is_app_enabled && is_app_root_tracker_enabled) 398 DisableOrigin(origin, base::Bind(&EmptyStatusCallback)); 399 } 400} 401 402void SyncEngine::NotifyLastOperationStatus() { 403 FOR_EACH_OBSERVER( 404 Observer, 405 service_observers_, 406 OnRemoteChangeQueueUpdated( 407 GetMetadataDatabase()->CountDirtyTracker())); 408} 409 410} // namespace drive_backend 411} // namespace sync_file_system 412