Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / local / sync_file_system_backend.cc
blob57ba11611931f702c2ca401a081c0d3f87f3e0ec
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.
5 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
7 #include <string>
9 #include "base/logging.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
12 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
13 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
14 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
15 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
16 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h"
19 #include "storage/browser/fileapi/file_stream_reader.h"
20 #include "storage/browser/fileapi/file_stream_writer.h"
21 #include "storage/browser/fileapi/file_system_context.h"
22 #include "storage/browser/fileapi/file_system_operation.h"
23 #include "storage/common/fileapi/file_system_util.h"
25 using content::BrowserThread;
27 namespace sync_file_system {
29 namespace {
31 bool CalledOnUIThread() {
32 // Ensure that these methods are called on the UI thread, except for unittests
33 // where a UI thread might not have been created.
34 return BrowserThread::CurrentlyOn(BrowserThread::UI) ||
35 !BrowserThread::IsMessageLoopValid(BrowserThread::UI);
38 } // namespace
40 SyncFileSystemBackend::ProfileHolder::ProfileHolder(Profile* profile)
41 : profile_(profile) {
42 DCHECK(CalledOnUIThread());
43 registrar_.Add(this,
44 chrome::NOTIFICATION_PROFILE_DESTROYED,
45 content::Source<Profile>(profile_));
48 void SyncFileSystemBackend::ProfileHolder::Observe(
49 int type,
50 const content::NotificationSource& source,
51 const content::NotificationDetails& details) {
52 DCHECK(CalledOnUIThread());
53 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
54 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
55 profile_ = nullptr;
56 registrar_.RemoveAll();
59 Profile* SyncFileSystemBackend::ProfileHolder::GetProfile() {
60 DCHECK(CalledOnUIThread());
61 return profile_;
64 SyncFileSystemBackend::SyncFileSystemBackend(Profile* profile)
65 : context_(nullptr),
66 skip_initialize_syncfs_service_for_testing_(false) {
67 DCHECK(CalledOnUIThread());
68 if (profile)
69 profile_holder_.reset(new ProfileHolder(profile));
71 // Register the service name here to enable to crack an URL on SyncFileSystem
72 // even if SyncFileSystemService has not started yet.
73 RegisterSyncableFileSystem();
76 SyncFileSystemBackend::~SyncFileSystemBackend() {
77 if (change_tracker_) {
78 GetDelegate()->file_task_runner()->DeleteSoon(
79 FROM_HERE, change_tracker_.release());
82 if (profile_holder_ && !CalledOnUIThread()) {
83 BrowserThread::DeleteSoon(
84 BrowserThread::UI, FROM_HERE, profile_holder_.release());
88 // static
89 SyncFileSystemBackend* SyncFileSystemBackend::CreateForTesting() {
90 DCHECK(CalledOnUIThread());
91 SyncFileSystemBackend* backend = new SyncFileSystemBackend(nullptr);
92 backend->skip_initialize_syncfs_service_for_testing_ = true;
93 return backend;
96 bool SyncFileSystemBackend::CanHandleType(storage::FileSystemType type) const {
97 return type == storage::kFileSystemTypeSyncable ||
98 type == storage::kFileSystemTypeSyncableForInternalSync;
101 void SyncFileSystemBackend::Initialize(storage::FileSystemContext* context) {
102 DCHECK(context);
103 DCHECK(!context_);
104 context_ = context;
106 storage::SandboxFileSystemBackendDelegate* delegate = GetDelegate();
107 delegate->RegisterQuotaUpdateObserver(storage::kFileSystemTypeSyncable);
108 delegate->RegisterQuotaUpdateObserver(
109 storage::kFileSystemTypeSyncableForInternalSync);
112 void SyncFileSystemBackend::ResolveURL(const storage::FileSystemURL& url,
113 storage::OpenFileSystemMode mode,
114 const OpenFileSystemCallback& callback) {
115 DCHECK(CanHandleType(url.type()));
117 if (skip_initialize_syncfs_service_for_testing_) {
118 GetDelegate()->OpenFileSystem(url.origin(),
119 url.type(),
120 mode,
121 callback,
122 GetSyncableFileSystemRootURI(url.origin()));
123 return;
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),
130 make_scoped_refptr(context_),
131 url.origin(),
132 url.type(),
133 mode,
134 callback);
135 InitializeSyncFileSystemService(url.origin(), initialize_callback);
138 storage::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil(
139 storage::FileSystemType type) {
140 return GetDelegate()->file_util();
143 storage::WatcherManager* SyncFileSystemBackend::GetWatcherManager(
144 storage::FileSystemType type) {
145 return nullptr;
148 storage::CopyOrMoveFileValidatorFactory*
149 SyncFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
150 storage::FileSystemType type,
151 base::File::Error* error_code) {
152 DCHECK(error_code);
153 *error_code = base::File::FILE_OK;
154 return nullptr;
157 storage::FileSystemOperation* SyncFileSystemBackend::CreateFileSystemOperation(
158 const storage::FileSystemURL& url,
159 storage::FileSystemContext* context,
160 base::File::Error* error_code) const {
161 DCHECK(CanHandleType(url.type()));
162 DCHECK(context);
163 DCHECK(error_code);
165 scoped_ptr<storage::FileSystemOperationContext> operation_context =
166 GetDelegate()->CreateFileSystemOperationContext(url, context, error_code);
167 if (!operation_context)
168 return nullptr;
170 if (url.type() == storage::kFileSystemTypeSyncableForInternalSync) {
171 return storage::FileSystemOperation::Create(
172 url, context, operation_context.Pass());
175 return new SyncableFileSystemOperation(
176 url, context, operation_context.Pass());
179 bool SyncFileSystemBackend::SupportsStreaming(
180 const storage::FileSystemURL& url) const {
181 return false;
184 bool SyncFileSystemBackend::HasInplaceCopyImplementation(
185 storage::FileSystemType type) const {
186 return false;
189 scoped_ptr<storage::FileStreamReader>
190 SyncFileSystemBackend::CreateFileStreamReader(
191 const storage::FileSystemURL& url,
192 int64 offset,
193 int64 max_bytes_to_read,
194 const base::Time& expected_modification_time,
195 storage::FileSystemContext* context) const {
196 DCHECK(CanHandleType(url.type()));
197 return GetDelegate()->CreateFileStreamReader(
198 url, offset, expected_modification_time, context);
201 scoped_ptr<storage::FileStreamWriter>
202 SyncFileSystemBackend::CreateFileStreamWriter(
203 const storage::FileSystemURL& url,
204 int64 offset,
205 storage::FileSystemContext* context) const {
206 DCHECK(CanHandleType(url.type()));
207 return GetDelegate()->CreateFileStreamWriter(
208 url, offset, context, storage::kFileSystemTypeSyncableForInternalSync);
211 storage::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() {
212 return GetDelegate();
215 const storage::UpdateObserverList* SyncFileSystemBackend::GetUpdateObservers(
216 storage::FileSystemType type) const {
217 return GetDelegate()->GetUpdateObservers(type);
220 const storage::ChangeObserverList* SyncFileSystemBackend::GetChangeObservers(
221 storage::FileSystemType type) const {
222 return GetDelegate()->GetChangeObservers(type);
225 const storage::AccessObserverList* SyncFileSystemBackend::GetAccessObservers(
226 storage::FileSystemType type) const {
227 return GetDelegate()->GetAccessObservers(type);
230 // static
231 SyncFileSystemBackend* SyncFileSystemBackend::GetBackend(
232 const storage::FileSystemContext* file_system_context) {
233 DCHECK(file_system_context);
234 return static_cast<SyncFileSystemBackend*>(
235 file_system_context->GetFileSystemBackend(
236 storage::kFileSystemTypeSyncable));
239 void SyncFileSystemBackend::SetLocalFileChangeTracker(
240 scoped_ptr<LocalFileChangeTracker> tracker) {
241 DCHECK(!change_tracker_);
242 DCHECK(tracker);
243 change_tracker_ = tracker.Pass();
245 storage::SandboxFileSystemBackendDelegate* delegate = GetDelegate();
246 delegate->AddFileUpdateObserver(storage::kFileSystemTypeSyncable,
247 change_tracker_.get(),
248 delegate->file_task_runner());
249 delegate->AddFileChangeObserver(storage::kFileSystemTypeSyncable,
250 change_tracker_.get(),
251 delegate->file_task_runner());
254 void SyncFileSystemBackend::set_sync_context(
255 LocalFileSyncContext* sync_context) {
256 DCHECK(!sync_context_.get());
257 sync_context_ = sync_context;
260 storage::SandboxFileSystemBackendDelegate* SyncFileSystemBackend::GetDelegate()
261 const {
262 DCHECK(context_);
263 DCHECK(context_->sandbox_delegate());
264 return context_->sandbox_delegate();
267 void SyncFileSystemBackend::InitializeSyncFileSystemService(
268 const GURL& origin_url,
269 const SyncStatusCallback& callback) {
270 // Repost to switch from IO thread to UI thread.
271 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
273 // It is safe to pass Unretained(this) (see comments in OpenFileSystem()).
274 BrowserThread::PostTask(
275 BrowserThread::UI, FROM_HERE,
276 base::Bind(&SyncFileSystemBackend::InitializeSyncFileSystemService,
277 base::Unretained(this), origin_url, callback));
278 return;
281 if (!profile_holder_->GetProfile()) {
282 // Profile was destroyed.
283 callback.Run(SYNC_FILE_ERROR_FAILED);
284 return;
287 SyncFileSystemService* service = SyncFileSystemServiceFactory::GetForProfile(
288 profile_holder_->GetProfile());
289 DCHECK(service);
290 service->InitializeForApp(context_, origin_url, callback);
293 void SyncFileSystemBackend::DidInitializeSyncFileSystemService(
294 storage::FileSystemContext* context,
295 const GURL& origin_url,
296 storage::FileSystemType type,
297 storage::OpenFileSystemMode mode,
298 const OpenFileSystemCallback& callback,
299 SyncStatusCode status) {
300 // Repost to switch from UI thread to IO thread.
301 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
303 // It is safe to pass Unretained(this) since |context| owns it.
304 BrowserThread::PostTask(
305 BrowserThread::IO, FROM_HERE,
306 base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService,
307 base::Unretained(this), make_scoped_refptr(context),
308 origin_url, type, mode, callback, status));
309 return;
312 if (status != sync_file_system::SYNC_STATUS_OK) {
313 callback.Run(GURL(), std::string(),
314 SyncStatusCodeToFileError(status));
315 return;
318 callback.Run(GetSyncableFileSystemRootURI(origin_url),
319 GetFileSystemName(origin_url, type),
320 base::File::FILE_OK);
323 } // namespace sync_file_system