Fix infinite recursion on hiding panel when created during fullscreen mode.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / local / sync_file_system_backend.cc
blob50e5b94701800c7dd95475675e9defa8b3fe333b
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 "base/logging.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
10 #include "chrome/browser/sync_file_system/local/local_file_sync_context.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"
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"
17 #include "webkit/browser/blob/file_stream_reader.h"
18 #include "webkit/browser/fileapi/file_stream_writer.h"
19 #include "webkit/browser/fileapi/file_system_context.h"
20 #include "webkit/browser/fileapi/file_system_operation.h"
21 #include "webkit/common/fileapi/file_system_util.h"
23 using content::BrowserThread;
25 namespace sync_file_system {
27 namespace {
29 bool CalledOnUIThread() {
30 // Ensure that these methods are called on the UI thread, except for unittests
31 // where a UI thread might not have been created.
32 return BrowserThread::CurrentlyOn(BrowserThread::UI) ||
33 !BrowserThread::IsMessageLoopValid(BrowserThread::UI);
36 } // namespace
38 SyncFileSystemBackend::ProfileHolder::ProfileHolder(Profile* profile)
39 : profile_(profile) {
40 DCHECK(CalledOnUIThread());
41 registrar_.Add(this,
42 chrome::NOTIFICATION_PROFILE_DESTROYED,
43 content::Source<Profile>(profile_));
46 void SyncFileSystemBackend::ProfileHolder::Observe(
47 int type,
48 const content::NotificationSource& source,
49 const content::NotificationDetails& details) {
50 DCHECK(CalledOnUIThread());
51 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
52 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
53 profile_ = NULL;
54 registrar_.RemoveAll();
57 Profile* SyncFileSystemBackend::ProfileHolder::GetProfile() {
58 DCHECK(CalledOnUIThread());
59 return profile_;
62 SyncFileSystemBackend::SyncFileSystemBackend(Profile* profile)
63 : context_(NULL),
64 skip_initialize_syncfs_service_for_testing_(false) {
65 DCHECK(CalledOnUIThread());
66 if (profile)
67 profile_holder_.reset(new ProfileHolder(profile));
69 // Register the service name here to enable to crack an URL on SyncFileSystem
70 // even if SyncFileSystemService has not started yet.
71 RegisterSyncableFileSystem();
74 SyncFileSystemBackend::~SyncFileSystemBackend() {
75 if (change_tracker_) {
76 GetDelegate()->file_task_runner()->DeleteSoon(
77 FROM_HERE, change_tracker_.release());
80 if (profile_holder_ && !CalledOnUIThread()) {
81 BrowserThread::DeleteSoon(
82 BrowserThread::UI, FROM_HERE, profile_holder_.release());
86 // static
87 SyncFileSystemBackend* SyncFileSystemBackend::CreateForTesting() {
88 DCHECK(CalledOnUIThread());
89 SyncFileSystemBackend* backend = new SyncFileSystemBackend(NULL);
90 backend->skip_initialize_syncfs_service_for_testing_ = true;
91 return backend;
94 bool SyncFileSystemBackend::CanHandleType(
95 fileapi::FileSystemType type) const {
96 return type == fileapi::kFileSystemTypeSyncable ||
97 type == fileapi::kFileSystemTypeSyncableForInternalSync;
100 void SyncFileSystemBackend::Initialize(fileapi::FileSystemContext* context) {
101 DCHECK(context);
102 DCHECK(!context_);
103 context_ = context;
105 fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate();
106 delegate->RegisterQuotaUpdateObserver(fileapi::kFileSystemTypeSyncable);
107 delegate->RegisterQuotaUpdateObserver(
108 fileapi::kFileSystemTypeSyncableForInternalSync);
111 void SyncFileSystemBackend::ResolveURL(const fileapi::FileSystemURL& url,
112 fileapi::OpenFileSystemMode mode,
113 const OpenFileSystemCallback& callback) {
114 DCHECK(CanHandleType(url.type()));
116 if (skip_initialize_syncfs_service_for_testing_) {
117 GetDelegate()->OpenFileSystem(url.origin(),
118 url.type(),
119 mode,
120 callback,
121 GetSyncableFileSystemRootURI(url.origin()));
122 return;
125 // It is safe to pass Unretained(this) since |context_| owns it.
126 SyncStatusCallback initialize_callback =
127 base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService,
128 base::Unretained(this),
129 make_scoped_refptr(context_),
130 url.origin(),
131 url.type(),
132 mode,
133 callback);
134 InitializeSyncFileSystemService(url.origin(), initialize_callback);
137 fileapi::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil(
138 fileapi::FileSystemType type) {
139 return GetDelegate()->file_util();
142 fileapi::CopyOrMoveFileValidatorFactory*
143 SyncFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
144 fileapi::FileSystemType type,
145 base::File::Error* error_code) {
146 DCHECK(error_code);
147 *error_code = base::File::FILE_OK;
148 return NULL;
151 fileapi::FileSystemOperation*
152 SyncFileSystemBackend::CreateFileSystemOperation(
153 const fileapi::FileSystemURL& url,
154 fileapi::FileSystemContext* context,
155 base::File::Error* error_code) const {
156 DCHECK(CanHandleType(url.type()));
157 DCHECK(context);
158 DCHECK(error_code);
160 scoped_ptr<fileapi::FileSystemOperationContext> operation_context =
161 GetDelegate()->CreateFileSystemOperationContext(url, context, error_code);
162 if (!operation_context)
163 return NULL;
165 if (url.type() == fileapi::kFileSystemTypeSyncableForInternalSync) {
166 return fileapi::FileSystemOperation::Create(
167 url, context, operation_context.Pass());
170 return new SyncableFileSystemOperation(
171 url, context, operation_context.Pass());
174 bool SyncFileSystemBackend::SupportsStreaming(
175 const fileapi::FileSystemURL& url) const {
176 return false;
179 scoped_ptr<webkit_blob::FileStreamReader>
180 SyncFileSystemBackend::CreateFileStreamReader(
181 const fileapi::FileSystemURL& url,
182 int64 offset,
183 const base::Time& expected_modification_time,
184 fileapi::FileSystemContext* context) const {
185 DCHECK(CanHandleType(url.type()));
186 return GetDelegate()->CreateFileStreamReader(
187 url, offset, expected_modification_time, context);
190 scoped_ptr<fileapi::FileStreamWriter>
191 SyncFileSystemBackend::CreateFileStreamWriter(
192 const fileapi::FileSystemURL& url,
193 int64 offset,
194 fileapi::FileSystemContext* context) const {
195 DCHECK(CanHandleType(url.type()));
196 return GetDelegate()->CreateFileStreamWriter(
197 url, offset, context, fileapi::kFileSystemTypeSyncableForInternalSync);
200 fileapi::FileSystemQuotaUtil* SyncFileSystemBackend::GetQuotaUtil() {
201 return GetDelegate();
204 // static
205 SyncFileSystemBackend* SyncFileSystemBackend::GetBackend(
206 const fileapi::FileSystemContext* file_system_context) {
207 DCHECK(file_system_context);
208 return static_cast<SyncFileSystemBackend*>(
209 file_system_context->GetFileSystemBackend(
210 fileapi::kFileSystemTypeSyncable));
213 void SyncFileSystemBackend::SetLocalFileChangeTracker(
214 scoped_ptr<LocalFileChangeTracker> tracker) {
215 DCHECK(!change_tracker_);
216 DCHECK(tracker);
217 change_tracker_ = tracker.Pass();
219 fileapi::SandboxFileSystemBackendDelegate* delegate = GetDelegate();
220 delegate->AddFileUpdateObserver(
221 fileapi::kFileSystemTypeSyncable,
222 change_tracker_.get(),
223 delegate->file_task_runner());
224 delegate->AddFileChangeObserver(
225 fileapi::kFileSystemTypeSyncable,
226 change_tracker_.get(),
227 delegate->file_task_runner());
230 void SyncFileSystemBackend::set_sync_context(
231 LocalFileSyncContext* sync_context) {
232 DCHECK(!sync_context_);
233 sync_context_ = sync_context;
236 fileapi::SandboxFileSystemBackendDelegate*
237 SyncFileSystemBackend::GetDelegate() const {
238 DCHECK(context_);
239 DCHECK(context_->sandbox_delegate());
240 return context_->sandbox_delegate();
243 void SyncFileSystemBackend::InitializeSyncFileSystemService(
244 const GURL& origin_url,
245 const SyncStatusCallback& callback) {
246 // Repost to switch from IO thread to UI thread.
247 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
249 // It is safe to pass Unretained(this) (see comments in OpenFileSystem()).
250 BrowserThread::PostTask(
251 BrowserThread::UI, FROM_HERE,
252 base::Bind(&SyncFileSystemBackend::InitializeSyncFileSystemService,
253 base::Unretained(this), origin_url, callback));
254 return;
257 if (!profile_holder_->GetProfile()) {
258 // Profile was destroyed.
259 callback.Run(SYNC_FILE_ERROR_FAILED);
260 return;
263 SyncFileSystemService* service = SyncFileSystemServiceFactory::GetForProfile(
264 profile_holder_->GetProfile());
265 DCHECK(service);
266 service->InitializeForApp(context_, origin_url, callback);
269 void SyncFileSystemBackend::DidInitializeSyncFileSystemService(
270 fileapi::FileSystemContext* context,
271 const GURL& origin_url,
272 fileapi::FileSystemType type,
273 fileapi::OpenFileSystemMode mode,
274 const OpenFileSystemCallback& callback,
275 SyncStatusCode status) {
276 // Repost to switch from UI thread to IO thread.
277 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 // It is safe to pass Unretained(this) since |context| owns it.
280 BrowserThread::PostTask(
281 BrowserThread::IO, FROM_HERE,
282 base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService,
283 base::Unretained(this), make_scoped_refptr(context),
284 origin_url, type, mode, callback, status));
285 return;
288 if (status != sync_file_system::SYNC_STATUS_OK) {
289 callback.Run(GURL(), std::string(),
290 SyncStatusCodeToFileError(status));
291 return;
294 callback.Run(GetSyncableFileSystemRootURI(origin_url),
295 GetFileSystemName(origin_url, type),
296 base::File::FILE_OK);
299 } // namespace sync_file_system