Index: chrome/browser/sync_file_system/local/sync_file_system_backend.cc |
diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc |
index 4796762ecb8cef97bea36c6b3488a6606bd81e69..b777a0406fe0e5616735dbb00becf893f8e40798 100644 |
--- a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc |
+++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc |
@@ -5,10 +5,15 @@ |
#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" |
#include "base/logging.h" |
+#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" |
#include "chrome/browser/sync_file_system/local/local_file_sync_context.h" |
#include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h" |
+#include "chrome/browser/sync_file_system/sync_file_system_service.h" |
+#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h" |
#include "chrome/browser/sync_file_system/syncable_file_system_util.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/notification_service.h" |
#include "webkit/browser/fileapi/file_system_context.h" |
#include "webkit/browser/fileapi/file_system_file_stream_reader.h" |
#include "webkit/browser/fileapi/file_system_operation_impl.h" |
@@ -16,17 +21,71 @@ |
#include "webkit/browser/fileapi/sandbox_quota_observer.h" |
#include "webkit/common/fileapi/file_system_util.h" |
+using content::BrowserThread; |
+ |
namespace sync_file_system { |
-SyncFileSystemBackend::SyncFileSystemBackend() |
- : delegate_(NULL) { |
+namespace { |
+ |
+bool CalledOnUIThread() { |
+ // Ensure that these methods are called on the UI thread, except for unittests |
+ // where a UI thread might not have been created. |
+ return BrowserThread::CurrentlyOn(BrowserThread::UI) || |
+ !BrowserThread::IsMessageLoopValid(BrowserThread::UI); |
+} |
+ |
+} // namespace |
+ |
+SyncFileSystemBackend::ProfileHolder::ProfileHolder(Profile* profile) |
+ : profile_(profile) { |
+ DCHECK(CalledOnUIThread()); |
+ registrar_.Add(this, |
+ chrome::NOTIFICATION_PROFILE_DESTROYED, |
+ content::Source<Profile>(profile_)); |
+} |
+ |
+void SyncFileSystemBackend::ProfileHolder::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ DCHECK(CalledOnUIThread()); |
+ DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); |
+ DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); |
+ profile_ = NULL; |
+ registrar_.RemoveAll(); |
+} |
+ |
+Profile* SyncFileSystemBackend::ProfileHolder::GetProfile() { |
+ DCHECK(CalledOnUIThread()); |
+ return profile_; |
+} |
+ |
+SyncFileSystemBackend::SyncFileSystemBackend(Profile* profile) |
+ : context_(NULL), |
+ skip_initialize_syncfs_service_for_testing_(false) { |
+ DCHECK(CalledOnUIThread()); |
+ if (profile) |
+ profile_holder_.reset(new ProfileHolder(profile)); |
} |
SyncFileSystemBackend::~SyncFileSystemBackend() { |
if (change_tracker_) { |
- delegate_->file_task_runner()->DeleteSoon( |
+ GetDelegate()->file_task_runner()->DeleteSoon( |
FROM_HERE, change_tracker_.release()); |
} |
+ |
+ if (profile_holder_ && !CalledOnUIThread()) { |
+ BrowserThread::DeleteSoon( |
+ BrowserThread::UI, FROM_HERE, profile_holder_.release()); |
+ } |
+} |
+ |
+// static |
+SyncFileSystemBackend* SyncFileSystemBackend::CreateForTesting() { |
+ DCHECK(CalledOnUIThread()); |
+ SyncFileSystemBackend* backend = new SyncFileSystemBackend(NULL); |
+ backend->skip_initialize_syncfs_service_for_testing_ = true; |
+ return backend; |
} |
bool SyncFileSystemBackend::CanHandleType( |
@@ -37,17 +96,18 @@ bool SyncFileSystemBackend::CanHandleType( |
void SyncFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { |
DCHECK(context); |
- DCHECK(!delegate_); |
- delegate_ = context->sandbox_delegate(); |
+ DCHECK(!context_); |
+ context_ = context; |
- delegate_->AddFileUpdateObserver( |
+ fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate(); |
+ delegate->AddFileUpdateObserver( |
fileapi::kFileSystemTypeSyncable, |
- delegate_->quota_observer(), |
- delegate_->file_task_runner()); |
- delegate_->AddFileUpdateObserver( |
+ delegate->quota_observer(), |
+ delegate->file_task_runner()); |
+ delegate->AddFileUpdateObserver( |
fileapi::kFileSystemTypeSyncableForInternalSync, |
- delegate_->quota_observer(), |
- delegate_->file_task_runner()); |
+ delegate->quota_observer(), |
+ delegate->file_task_runner()); |
} |
void SyncFileSystemBackend::OpenFileSystem( |
@@ -56,15 +116,24 @@ void SyncFileSystemBackend::OpenFileSystem( |
fileapi::OpenFileSystemMode mode, |
const OpenFileSystemCallback& callback) { |
DCHECK(CanHandleType(type)); |
- DCHECK(delegate_); |
- delegate_->OpenFileSystem(origin_url, type, mode, callback, |
- GetSyncableFileSystemRootURI(origin_url)); |
+ |
+ if (skip_initialize_syncfs_service_for_testing_) { |
+ GetDelegate()->OpenFileSystem(origin_url, type, mode, callback, |
+ GetSyncableFileSystemRootURI(origin_url)); |
+ return; |
+ } |
+ |
+ // It is safe to pass Unretained(this) since |context_| owns it. |
+ SyncStatusCallback initialize_callback = |
+ base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService, |
+ base::Unretained(this), make_scoped_refptr(context_), |
+ origin_url, type, mode, callback); |
+ InitializeSyncFileSystemService(origin_url, initialize_callback); |
} |
fileapi::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil( |
fileapi::FileSystemType type) { |
- DCHECK(delegate_); |
- return delegate_->file_util(); |
+ return GetDelegate()->file_util(); |
} |
fileapi::CopyOrMoveFileValidatorFactory* |
@@ -85,9 +154,8 @@ SyncFileSystemBackend::CreateFileSystemOperation( |
DCHECK(context); |
DCHECK(error_code); |
- DCHECK(delegate_); |
scoped_ptr<fileapi::FileSystemOperationContext> operation_context = |
- delegate_->CreateFileSystemOperationContext(url, context, error_code); |
+ GetDelegate()->CreateFileSystemOperationContext(url, context, error_code); |
if (!operation_context) |
return NULL; |
@@ -107,8 +175,7 @@ SyncFileSystemBackend::CreateFileStreamReader( |
const base::Time& expected_modification_time, |
fileapi::FileSystemContext* context) const { |
DCHECK(CanHandleType(url.type())); |
- DCHECK(delegate_); |
- return delegate_->CreateFileStreamReader( |
+ return GetDelegate()->CreateFileStreamReader( |
url, offset, expected_modification_time, context); |
} |
@@ -118,13 +185,12 @@ SyncFileSystemBackend::CreateFileStreamWriter( |
int64 offset, |
fileapi::FileSystemContext* context) const { |
DCHECK(CanHandleType(url.type())); |
- DCHECK(delegate_); |
- return delegate_->CreateFileStreamWriter( |
+ return GetDelegate()->CreateFileStreamWriter( |
url, offset, context, fileapi::kFileSystemTypeSyncableForInternalSync); |
} |
fileapi::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() { |
- return delegate_; |
+ return GetDelegate(); |
} |
// static |
@@ -142,15 +208,15 @@ void SyncFileSystemBackend::SetLocalFileChangeTracker( |
DCHECK(tracker); |
change_tracker_ = tracker.Pass(); |
- DCHECK(delegate_); |
- delegate_->AddFileUpdateObserver( |
+ fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate(); |
+ delegate->AddFileUpdateObserver( |
fileapi::kFileSystemTypeSyncable, |
change_tracker_.get(), |
- delegate_->file_task_runner()); |
- delegate_->AddFileChangeObserver( |
+ delegate->file_task_runner()); |
+ delegate->AddFileChangeObserver( |
fileapi::kFileSystemTypeSyncable, |
change_tracker_.get(), |
- delegate_->file_task_runner()); |
+ delegate->file_task_runner()); |
} |
void SyncFileSystemBackend::set_sync_context( |
@@ -159,4 +225,66 @@ void SyncFileSystemBackend::set_sync_context( |
sync_context_ = sync_context; |
} |
+fileapi::SandboxFileSystemBackendDelegate* |
+SyncFileSystemBackend::GetDelegate() const { |
+ DCHECK(context_); |
+ DCHECK(context_->sandbox_delegate()); |
+ return context_->sandbox_delegate(); |
+} |
+ |
+void SyncFileSystemBackend::InitializeSyncFileSystemService( |
+ const GURL& origin_url, |
+ const SyncStatusCallback& callback) { |
+ // Repost to switch from IO thread to UI thread. |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ // It is safe to pass Unretained(this) (see comments in OpenFileSystem()). |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&SyncFileSystemBackend::InitializeSyncFileSystemService, |
+ base::Unretained(this), origin_url, callback)); |
+ return; |
+ } |
+ |
+ if (!profile_holder_->GetProfile()) { |
+ // Profile was destroyed. |
+ callback.Run(SYNC_FILE_ERROR_FAILED); |
+ return; |
+ } |
+ |
+ SyncFileSystemService* service = SyncFileSystemServiceFactory::GetForProfile( |
+ profile_holder_->GetProfile()); |
+ DCHECK(service); |
+ service->InitializeForApp(context_, origin_url, callback); |
+} |
+ |
+void SyncFileSystemBackend::DidInitializeSyncFileSystemService( |
+ fileapi::FileSystemContext* context, |
+ const GURL& origin_url, |
+ fileapi::FileSystemType type, |
+ fileapi::OpenFileSystemMode mode, |
+ const OpenFileSystemCallback& callback, |
+ SyncStatusCode status) { |
+ // Repost to switch from UI thread to IO thread. |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ // It is safe to pass Unretained(this) since |context| owns it. |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService, |
+ base::Unretained(this), make_scoped_refptr(context), |
+ origin_url, type, mode, callback, status)); |
+ return; |
+ } |
+ |
+ if (status != sync_file_system::SYNC_STATUS_OK) { |
+ callback.Run(GURL(), std::string(), |
+ SyncStatusCodeToPlatformFileError(status)); |
+ return; |
+ } |
+ |
+ GetDelegate()->OpenFileSystem(origin_url, type, mode, callback, |
+ GetSyncableFileSystemRootURI(origin_url)); |
+} |
+ |
} // namespace sync_file_system |