OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" | 5 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "chrome/browser/chrome_notification_types.h" |
8 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" | 9 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" |
9 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h" | 10 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h" |
10 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h
" | 11 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h
" |
| 12 #include "chrome/browser/sync_file_system/sync_file_system_service.h" |
| 13 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h" |
11 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" | 14 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" |
| 15 #include "content/public/browser/browser_thread.h" |
| 16 #include "content/public/browser/notification_service.h" |
12 #include "webkit/browser/fileapi/file_system_context.h" | 17 #include "webkit/browser/fileapi/file_system_context.h" |
13 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" | 18 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" |
14 #include "webkit/browser/fileapi/file_system_operation_impl.h" | 19 #include "webkit/browser/fileapi/file_system_operation_impl.h" |
15 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" | 20 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" |
16 #include "webkit/browser/fileapi/sandbox_quota_observer.h" | 21 #include "webkit/browser/fileapi/sandbox_quota_observer.h" |
17 #include "webkit/common/fileapi/file_system_util.h" | 22 #include "webkit/common/fileapi/file_system_util.h" |
18 | 23 |
| 24 using content::BrowserThread; |
| 25 |
19 namespace sync_file_system { | 26 namespace sync_file_system { |
20 | 27 |
21 SyncFileSystemBackend::SyncFileSystemBackend() | 28 namespace { |
22 : delegate_(NULL) { | 29 |
| 30 bool CalledOnUIThread() { |
| 31 // Ensure that these methods are called on the UI thread, except for unittests |
| 32 // where a UI thread might not have been created. |
| 33 return BrowserThread::CurrentlyOn(BrowserThread::UI) || |
| 34 !BrowserThread::IsMessageLoopValid(BrowserThread::UI); |
| 35 } |
| 36 |
| 37 } // namespace |
| 38 |
| 39 SyncFileSystemBackend::ProfileHolder::ProfileHolder(Profile* profile) |
| 40 : profile_(profile) { |
| 41 DCHECK(CalledOnUIThread()); |
| 42 registrar_.Add(this, |
| 43 chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 44 content::Source<Profile>(profile_)); |
| 45 } |
| 46 |
| 47 void SyncFileSystemBackend::ProfileHolder::Observe( |
| 48 int type, |
| 49 const content::NotificationSource& source, |
| 50 const content::NotificationDetails& details) { |
| 51 DCHECK(CalledOnUIThread()); |
| 52 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); |
| 53 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); |
| 54 profile_ = NULL; |
| 55 registrar_.RemoveAll(); |
| 56 } |
| 57 |
| 58 Profile* SyncFileSystemBackend::ProfileHolder::GetProfile() { |
| 59 DCHECK(CalledOnUIThread()); |
| 60 return profile_; |
| 61 } |
| 62 |
| 63 SyncFileSystemBackend::SyncFileSystemBackend(Profile* profile) |
| 64 : context_(NULL), |
| 65 skip_initialize_syncfs_service_for_testing_(false) { |
| 66 DCHECK(CalledOnUIThread()); |
| 67 if (profile) |
| 68 profile_holder_.reset(new ProfileHolder(profile)); |
23 } | 69 } |
24 | 70 |
25 SyncFileSystemBackend::~SyncFileSystemBackend() { | 71 SyncFileSystemBackend::~SyncFileSystemBackend() { |
26 if (change_tracker_) { | 72 if (change_tracker_) { |
27 delegate_->file_task_runner()->DeleteSoon( | 73 GetDelegate()->file_task_runner()->DeleteSoon( |
28 FROM_HERE, change_tracker_.release()); | 74 FROM_HERE, change_tracker_.release()); |
29 } | 75 } |
| 76 |
| 77 if (profile_holder_ && !CalledOnUIThread()) { |
| 78 BrowserThread::DeleteSoon( |
| 79 BrowserThread::UI, FROM_HERE, profile_holder_.release()); |
| 80 } |
30 } | 81 } |
31 | 82 |
| 83 // static |
| 84 SyncFileSystemBackend* SyncFileSystemBackend::CreateForTesting() { |
| 85 DCHECK(CalledOnUIThread()); |
| 86 SyncFileSystemBackend* backend = new SyncFileSystemBackend(NULL); |
| 87 backend->skip_initialize_syncfs_service_for_testing_ = true; |
| 88 return backend; |
| 89 } |
| 90 |
32 bool SyncFileSystemBackend::CanHandleType( | 91 bool SyncFileSystemBackend::CanHandleType( |
33 fileapi::FileSystemType type) const { | 92 fileapi::FileSystemType type) const { |
34 return type == fileapi::kFileSystemTypeSyncable || | 93 return type == fileapi::kFileSystemTypeSyncable || |
35 type == fileapi::kFileSystemTypeSyncableForInternalSync; | 94 type == fileapi::kFileSystemTypeSyncableForInternalSync; |
36 } | 95 } |
37 | 96 |
38 void SyncFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { | 97 void SyncFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { |
39 DCHECK(context); | 98 DCHECK(context); |
40 DCHECK(!delegate_); | 99 DCHECK(!context_); |
41 delegate_ = context->sandbox_delegate(); | 100 context_ = context; |
42 | 101 |
43 delegate_->AddFileUpdateObserver( | 102 fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate(); |
| 103 delegate->AddFileUpdateObserver( |
44 fileapi::kFileSystemTypeSyncable, | 104 fileapi::kFileSystemTypeSyncable, |
45 delegate_->quota_observer(), | 105 delegate->quota_observer(), |
46 delegate_->file_task_runner()); | 106 delegate->file_task_runner()); |
47 delegate_->AddFileUpdateObserver( | 107 delegate->AddFileUpdateObserver( |
48 fileapi::kFileSystemTypeSyncableForInternalSync, | 108 fileapi::kFileSystemTypeSyncableForInternalSync, |
49 delegate_->quota_observer(), | 109 delegate->quota_observer(), |
50 delegate_->file_task_runner()); | 110 delegate->file_task_runner()); |
51 } | 111 } |
52 | 112 |
53 void SyncFileSystemBackend::OpenFileSystem( | 113 void SyncFileSystemBackend::OpenFileSystem( |
54 const GURL& origin_url, | 114 const GURL& origin_url, |
55 fileapi::FileSystemType type, | 115 fileapi::FileSystemType type, |
56 fileapi::OpenFileSystemMode mode, | 116 fileapi::OpenFileSystemMode mode, |
57 const OpenFileSystemCallback& callback) { | 117 const OpenFileSystemCallback& callback) { |
58 DCHECK(CanHandleType(type)); | 118 DCHECK(CanHandleType(type)); |
59 DCHECK(delegate_); | 119 |
60 delegate_->OpenFileSystem(origin_url, type, mode, callback, | 120 if (skip_initialize_syncfs_service_for_testing_) { |
61 GetSyncableFileSystemRootURI(origin_url)); | 121 GetDelegate()->OpenFileSystem(origin_url, type, mode, callback, |
| 122 GetSyncableFileSystemRootURI(origin_url)); |
| 123 return; |
| 124 } |
| 125 |
| 126 // It is safe to pass Unretained(this) since |context_| owns it. |
| 127 SyncStatusCallback initialize_callback = |
| 128 base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService, |
| 129 base::Unretained(this), make_scoped_refptr(context_), |
| 130 origin_url, type, mode, callback); |
| 131 InitializeSyncFileSystemService(origin_url, initialize_callback); |
62 } | 132 } |
63 | 133 |
64 fileapi::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil( | 134 fileapi::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil( |
65 fileapi::FileSystemType type) { | 135 fileapi::FileSystemType type) { |
66 DCHECK(delegate_); | 136 return GetDelegate()->file_util(); |
67 return delegate_->file_util(); | |
68 } | 137 } |
69 | 138 |
70 fileapi::CopyOrMoveFileValidatorFactory* | 139 fileapi::CopyOrMoveFileValidatorFactory* |
71 SyncFileSystemBackend::GetCopyOrMoveFileValidatorFactory( | 140 SyncFileSystemBackend::GetCopyOrMoveFileValidatorFactory( |
72 fileapi::FileSystemType type, | 141 fileapi::FileSystemType type, |
73 base::PlatformFileError* error_code) { | 142 base::PlatformFileError* error_code) { |
74 DCHECK(error_code); | 143 DCHECK(error_code); |
75 *error_code = base::PLATFORM_FILE_OK; | 144 *error_code = base::PLATFORM_FILE_OK; |
76 return NULL; | 145 return NULL; |
77 } | 146 } |
78 | 147 |
79 fileapi::FileSystemOperation* | 148 fileapi::FileSystemOperation* |
80 SyncFileSystemBackend::CreateFileSystemOperation( | 149 SyncFileSystemBackend::CreateFileSystemOperation( |
81 const fileapi::FileSystemURL& url, | 150 const fileapi::FileSystemURL& url, |
82 fileapi::FileSystemContext* context, | 151 fileapi::FileSystemContext* context, |
83 base::PlatformFileError* error_code) const { | 152 base::PlatformFileError* error_code) const { |
84 DCHECK(CanHandleType(url.type())); | 153 DCHECK(CanHandleType(url.type())); |
85 DCHECK(context); | 154 DCHECK(context); |
86 DCHECK(error_code); | 155 DCHECK(error_code); |
87 | 156 |
88 DCHECK(delegate_); | |
89 scoped_ptr<fileapi::FileSystemOperationContext> operation_context = | 157 scoped_ptr<fileapi::FileSystemOperationContext> operation_context = |
90 delegate_->CreateFileSystemOperationContext(url, context, error_code); | 158 GetDelegate()->CreateFileSystemOperationContext(url, context, error_code); |
91 if (!operation_context) | 159 if (!operation_context) |
92 return NULL; | 160 return NULL; |
93 | 161 |
94 if (url.type() == fileapi::kFileSystemTypeSyncableForInternalSync) { | 162 if (url.type() == fileapi::kFileSystemTypeSyncableForInternalSync) { |
95 return new fileapi::FileSystemOperationImpl( | 163 return new fileapi::FileSystemOperationImpl( |
96 url, context, operation_context.Pass()); | 164 url, context, operation_context.Pass()); |
97 } | 165 } |
98 | 166 |
99 return new SyncableFileSystemOperation( | 167 return new SyncableFileSystemOperation( |
100 url, context, operation_context.Pass()); | 168 url, context, operation_context.Pass()); |
101 } | 169 } |
102 | 170 |
103 scoped_ptr<webkit_blob::FileStreamReader> | 171 scoped_ptr<webkit_blob::FileStreamReader> |
104 SyncFileSystemBackend::CreateFileStreamReader( | 172 SyncFileSystemBackend::CreateFileStreamReader( |
105 const fileapi::FileSystemURL& url, | 173 const fileapi::FileSystemURL& url, |
106 int64 offset, | 174 int64 offset, |
107 const base::Time& expected_modification_time, | 175 const base::Time& expected_modification_time, |
108 fileapi::FileSystemContext* context) const { | 176 fileapi::FileSystemContext* context) const { |
109 DCHECK(CanHandleType(url.type())); | 177 DCHECK(CanHandleType(url.type())); |
110 DCHECK(delegate_); | 178 return GetDelegate()->CreateFileStreamReader( |
111 return delegate_->CreateFileStreamReader( | |
112 url, offset, expected_modification_time, context); | 179 url, offset, expected_modification_time, context); |
113 } | 180 } |
114 | 181 |
115 scoped_ptr<fileapi::FileStreamWriter> | 182 scoped_ptr<fileapi::FileStreamWriter> |
116 SyncFileSystemBackend::CreateFileStreamWriter( | 183 SyncFileSystemBackend::CreateFileStreamWriter( |
117 const fileapi::FileSystemURL& url, | 184 const fileapi::FileSystemURL& url, |
118 int64 offset, | 185 int64 offset, |
119 fileapi::FileSystemContext* context) const { | 186 fileapi::FileSystemContext* context) const { |
120 DCHECK(CanHandleType(url.type())); | 187 DCHECK(CanHandleType(url.type())); |
121 DCHECK(delegate_); | 188 return GetDelegate()->CreateFileStreamWriter( |
122 return delegate_->CreateFileStreamWriter( | |
123 url, offset, context, fileapi::kFileSystemTypeSyncableForInternalSync); | 189 url, offset, context, fileapi::kFileSystemTypeSyncableForInternalSync); |
124 } | 190 } |
125 | 191 |
126 fileapi::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() { | 192 fileapi::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() { |
127 return delegate_; | 193 return GetDelegate(); |
128 } | 194 } |
129 | 195 |
130 // static | 196 // static |
131 SyncFileSystemBackend* SyncFileSystemBackend::GetBackend( | 197 SyncFileSystemBackend* SyncFileSystemBackend::GetBackend( |
132 const fileapi::FileSystemContext* file_system_context) { | 198 const fileapi::FileSystemContext* file_system_context) { |
133 DCHECK(file_system_context); | 199 DCHECK(file_system_context); |
134 return static_cast<SyncFileSystemBackend*>( | 200 return static_cast<SyncFileSystemBackend*>( |
135 file_system_context->GetFileSystemBackend( | 201 file_system_context->GetFileSystemBackend( |
136 fileapi::kFileSystemTypeSyncable)); | 202 fileapi::kFileSystemTypeSyncable)); |
137 } | 203 } |
138 | 204 |
139 void SyncFileSystemBackend::SetLocalFileChangeTracker( | 205 void SyncFileSystemBackend::SetLocalFileChangeTracker( |
140 scoped_ptr<LocalFileChangeTracker> tracker) { | 206 scoped_ptr<LocalFileChangeTracker> tracker) { |
141 DCHECK(!change_tracker_); | 207 DCHECK(!change_tracker_); |
142 DCHECK(tracker); | 208 DCHECK(tracker); |
143 change_tracker_ = tracker.Pass(); | 209 change_tracker_ = tracker.Pass(); |
144 | 210 |
145 DCHECK(delegate_); | 211 fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate(); |
146 delegate_->AddFileUpdateObserver( | 212 delegate->AddFileUpdateObserver( |
147 fileapi::kFileSystemTypeSyncable, | 213 fileapi::kFileSystemTypeSyncable, |
148 change_tracker_.get(), | 214 change_tracker_.get(), |
149 delegate_->file_task_runner()); | 215 delegate->file_task_runner()); |
150 delegate_->AddFileChangeObserver( | 216 delegate->AddFileChangeObserver( |
151 fileapi::kFileSystemTypeSyncable, | 217 fileapi::kFileSystemTypeSyncable, |
152 change_tracker_.get(), | 218 change_tracker_.get(), |
153 delegate_->file_task_runner()); | 219 delegate->file_task_runner()); |
154 } | 220 } |
155 | 221 |
156 void SyncFileSystemBackend::set_sync_context( | 222 void SyncFileSystemBackend::set_sync_context( |
157 LocalFileSyncContext* sync_context) { | 223 LocalFileSyncContext* sync_context) { |
158 DCHECK(!sync_context_); | 224 DCHECK(!sync_context_); |
159 sync_context_ = sync_context; | 225 sync_context_ = sync_context; |
160 } | 226 } |
161 | 227 |
| 228 fileapi::SandboxFileSystemBackendDelegate* |
| 229 SyncFileSystemBackend::GetDelegate() const { |
| 230 DCHECK(context_); |
| 231 DCHECK(context_->sandbox_delegate()); |
| 232 return context_->sandbox_delegate(); |
| 233 } |
| 234 |
| 235 void SyncFileSystemBackend::InitializeSyncFileSystemService( |
| 236 const GURL& origin_url, |
| 237 const SyncStatusCallback& callback) { |
| 238 // Repost to switch from IO thread to UI thread. |
| 239 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 241 // It is safe to pass Unretained(this) (see comments in OpenFileSystem()). |
| 242 BrowserThread::PostTask( |
| 243 BrowserThread::UI, FROM_HERE, |
| 244 base::Bind(&SyncFileSystemBackend::InitializeSyncFileSystemService, |
| 245 base::Unretained(this), origin_url, callback)); |
| 246 return; |
| 247 } |
| 248 |
| 249 if (!profile_holder_->GetProfile()) { |
| 250 // Profile was destroyed. |
| 251 callback.Run(SYNC_FILE_ERROR_FAILED); |
| 252 return; |
| 253 } |
| 254 |
| 255 SyncFileSystemService* service = SyncFileSystemServiceFactory::GetForProfile( |
| 256 profile_holder_->GetProfile()); |
| 257 DCHECK(service); |
| 258 service->InitializeForApp(context_, origin_url, callback); |
| 259 } |
| 260 |
| 261 void SyncFileSystemBackend::DidInitializeSyncFileSystemService( |
| 262 fileapi::FileSystemContext* context, |
| 263 const GURL& origin_url, |
| 264 fileapi::FileSystemType type, |
| 265 fileapi::OpenFileSystemMode mode, |
| 266 const OpenFileSystemCallback& callback, |
| 267 SyncStatusCode status) { |
| 268 // Repost to switch from UI thread to IO thread. |
| 269 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 271 // It is safe to pass Unretained(this) since |context| owns it. |
| 272 BrowserThread::PostTask( |
| 273 BrowserThread::IO, FROM_HERE, |
| 274 base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService, |
| 275 base::Unretained(this), make_scoped_refptr(context), |
| 276 origin_url, type, mode, callback, status)); |
| 277 return; |
| 278 } |
| 279 |
| 280 if (status != sync_file_system::SYNC_STATUS_OK) { |
| 281 callback.Run(GURL(), std::string(), |
| 282 SyncStatusCodeToPlatformFileError(status)); |
| 283 return; |
| 284 } |
| 285 |
| 286 GetDelegate()->OpenFileSystem(origin_url, type, mode, callback, |
| 287 GetSyncableFileSystemRootURI(origin_url)); |
| 288 } |
| 289 |
162 } // namespace sync_file_system | 290 } // namespace sync_file_system |
OLD | NEW |