Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / local / sync_file_system_backend.cc
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/local/sync_file_system_backend.h"
6
7 #include <string>
8
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/blob/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"
24
25 using content::BrowserThread;
26
27 namespace sync_file_system {
28
29 namespace {
30
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);
36 }
37
38 }  // namespace
39
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_));
46 }
47
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();
57 }
58
59 Profile* SyncFileSystemBackend::ProfileHolder::GetProfile() {
60   DCHECK(CalledOnUIThread());
61   return profile_;
62 }
63
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));
70
71   // Register the service name here to enable to crack an URL on SyncFileSystem
72   // even if SyncFileSystemService has not started yet.
73   RegisterSyncableFileSystem();
74 }
75
76 SyncFileSystemBackend::~SyncFileSystemBackend() {
77   if (change_tracker_) {
78     GetDelegate()->file_task_runner()->DeleteSoon(
79         FROM_HERE, change_tracker_.release());
80   }
81
82   if (profile_holder_ && !CalledOnUIThread()) {
83     BrowserThread::DeleteSoon(
84         BrowserThread::UI, FROM_HERE, profile_holder_.release());
85   }
86 }
87
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;
94 }
95
96 bool SyncFileSystemBackend::CanHandleType(storage::FileSystemType type) const {
97   return type == storage::kFileSystemTypeSyncable ||
98          type == storage::kFileSystemTypeSyncableForInternalSync;
99 }
100
101 void SyncFileSystemBackend::Initialize(storage::FileSystemContext* context) {
102   DCHECK(context);
103   DCHECK(!context_);
104   context_ = context;
105
106   storage::SandboxFileSystemBackendDelegate* delegate = GetDelegate();
107   delegate->RegisterQuotaUpdateObserver(storage::kFileSystemTypeSyncable);
108   delegate->RegisterQuotaUpdateObserver(
109       storage::kFileSystemTypeSyncableForInternalSync);
110 }
111
112 void SyncFileSystemBackend::ResolveURL(const storage::FileSystemURL& url,
113                                        storage::OpenFileSystemMode mode,
114                                        const OpenFileSystemCallback& callback) {
115   DCHECK(CanHandleType(url.type()));
116
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;
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),
130                  make_scoped_refptr(context_),
131                  url.origin(),
132                  url.type(),
133                  mode,
134                  callback);
135   InitializeSyncFileSystemService(url.origin(), initialize_callback);
136 }
137
138 storage::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil(
139     storage::FileSystemType type) {
140   return GetDelegate()->file_util();
141 }
142
143 storage::WatcherManager* SyncFileSystemBackend::GetWatcherManager(
144     storage::FileSystemType type) {
145   return nullptr;
146 }
147
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;
155 }
156
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);
164
165   scoped_ptr<storage::FileSystemOperationContext> operation_context =
166       GetDelegate()->CreateFileSystemOperationContext(url, context, error_code);
167   if (!operation_context)
168     return nullptr;
169
170   if (url.type() == storage::kFileSystemTypeSyncableForInternalSync) {
171     return storage::FileSystemOperation::Create(
172         url, context, operation_context.Pass());
173   }
174
175   return new SyncableFileSystemOperation(
176       url, context, operation_context.Pass());
177 }
178
179 bool SyncFileSystemBackend::SupportsStreaming(
180     const storage::FileSystemURL& url) const {
181   return false;
182 }
183
184 bool SyncFileSystemBackend::HasInplaceCopyImplementation(
185     storage::FileSystemType type) const {
186   return false;
187 }
188
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);
199 }
200
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);
209 }
210
211 storage::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() {
212   return GetDelegate();
213 }
214
215 const storage::UpdateObserverList* SyncFileSystemBackend::GetUpdateObservers(
216     storage::FileSystemType type) const {
217   return GetDelegate()->GetUpdateObservers(type);
218 }
219
220 const storage::ChangeObserverList* SyncFileSystemBackend::GetChangeObservers(
221     storage::FileSystemType type) const {
222   return GetDelegate()->GetChangeObservers(type);
223 }
224
225 const storage::AccessObserverList* SyncFileSystemBackend::GetAccessObservers(
226     storage::FileSystemType type) const {
227   return GetDelegate()->GetAccessObservers(type);
228 }
229
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));
237 }
238
239 void SyncFileSystemBackend::SetLocalFileChangeTracker(
240     scoped_ptr<LocalFileChangeTracker> tracker) {
241   DCHECK(!change_tracker_);
242   DCHECK(tracker);
243   change_tracker_ = tracker.Pass();
244
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());
252 }
253
254 void SyncFileSystemBackend::set_sync_context(
255     LocalFileSyncContext* sync_context) {
256   DCHECK(!sync_context_.get());
257   sync_context_ = sync_context;
258 }
259
260 storage::SandboxFileSystemBackendDelegate* SyncFileSystemBackend::GetDelegate()
261     const {
262   DCHECK(context_);
263   DCHECK(context_->sandbox_delegate());
264   return context_->sandbox_delegate();
265 }
266
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;
279   }
280
281   if (!profile_holder_->GetProfile()) {
282     // Profile was destroyed.
283     callback.Run(SYNC_FILE_ERROR_FAILED);
284     return;
285   }
286
287   SyncFileSystemService* service = SyncFileSystemServiceFactory::GetForProfile(
288           profile_holder_->GetProfile());
289   DCHECK(service);
290   service->InitializeForApp(context_, origin_url, callback);
291 }
292
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;
310   }
311
312   if (status != sync_file_system::SYNC_STATUS_OK) {
313     callback.Run(GURL(), std::string(),
314                  SyncStatusCodeToFileError(status));
315     return;
316   }
317
318   callback.Run(GetSyncableFileSystemRootURI(origin_url),
319                GetFileSystemName(origin_url, type),
320                base::File::FILE_OK);
321 }
322
323 }  // namespace sync_file_system