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 "content/child/fileapi/webfilesystem_impl.h" | 5 #include "content/child/fileapi/webfilesystem_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | |
9 #include "base/message_loop/message_loop_proxy.h" | |
8 #include "content/child/child_thread.h" | 10 #include "content/child/child_thread.h" |
9 #include "content/child/fileapi/file_system_dispatcher.h" | 11 #include "content/child/fileapi/file_system_dispatcher.h" |
10 #include "content/child/fileapi/webfilesystem_callback_adapters.h" | 12 #include "content/child/fileapi/webfilesystem_callback_adapters.h" |
11 #include "content/child/fileapi/webfilewriter_impl.h" | 13 #include "content/child/fileapi/webfilewriter_impl.h" |
12 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" | 14 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" |
13 #include "third_party/WebKit/public/platform/WebFileInfo.h" | 15 #include "third_party/WebKit/public/platform/WebFileInfo.h" |
14 #include "third_party/WebKit/public/platform/WebString.h" | 16 #include "third_party/WebKit/public/platform/WebString.h" |
15 #include "third_party/WebKit/public/platform/WebURL.h" | 17 #include "third_party/WebKit/public/platform/WebURL.h" |
18 #include "url/gurl.h" | |
19 #include "webkit/child/worker_task_runner.h" | |
16 #include "webkit/glue/webkit_glue.h" | 20 #include "webkit/glue/webkit_glue.h" |
17 | 21 |
18 using WebKit::WebFileInfo; | 22 using WebKit::WebFileInfo; |
19 using WebKit::WebFileSystemCallbacks; | 23 using WebKit::WebFileSystemCallbacks; |
20 using WebKit::WebFileSystemEntry; | 24 using WebKit::WebFileSystemEntry; |
21 using WebKit::WebString; | 25 using WebKit::WebString; |
22 using WebKit::WebURL; | 26 using WebKit::WebURL; |
23 using WebKit::WebVector; | 27 using WebKit::WebVector; |
28 using webkit_glue::WorkerTaskRunner; | |
24 | 29 |
25 namespace content { | 30 namespace content { |
26 | 31 |
27 namespace { | 32 namespace { |
28 | 33 |
29 void DidReadMetadataForCreateFileWriter( | 34 void DidReadMetadataForCreateFileWriter( |
30 const GURL& path, | 35 const GURL& path, |
31 WebKit::WebFileWriterClient* client, | 36 WebKit::WebFileWriterClient* client, |
32 WebKit::WebFileSystemCallbacks* callbacks, | 37 WebKit::WebFileSystemCallbacks* callbacks, |
33 const base::PlatformFileInfo& file_info) { | 38 const base::PlatformFileInfo& file_info) { |
34 if (file_info.is_directory || file_info.size < 0) { | 39 if (file_info.is_directory || file_info.size < 0) { |
35 callbacks->didFail(WebKit::WebFileErrorInvalidState); | 40 callbacks->didFail(WebKit::WebFileErrorInvalidState); |
36 return; | 41 return; |
37 } | 42 } |
38 callbacks->didCreateFileWriter(new WebFileWriterImpl(path, client), | 43 callbacks->didCreateFileWriter(new WebFileWriterImpl(path, client), |
39 file_info.size); | 44 file_info.size); |
40 } | 45 } |
41 | 46 |
47 int CurrentWorkerId() { | |
48 return WorkerTaskRunner::Instance()->CurrentWorkerId(); | |
49 } | |
50 | |
51 class CallbacksWrapper | |
52 : public WebFileSystemCallbacks, | |
53 public WorkerTaskRunner::Observer { | |
54 public: | |
55 explicit CallbacksWrapper(WebFileSystemCallbacks* original_callbacks) | |
56 : callbacks_(original_callbacks), | |
57 thread_id_(CurrentWorkerId()) { | |
58 if (thread_id_) | |
59 WorkerTaskRunner::Instance()->AddStopObserver(this); | |
60 } | |
61 | |
62 virtual ~CallbacksWrapper() { | |
63 if (CurrentWorkerId()) | |
64 WorkerTaskRunner::Instance()->RemoveStopObserver(this); | |
65 } | |
66 | |
67 // WorkerTaskRunner::Observer overrides. | |
68 virtual void OnWorkerRunLoopStopped() OVERRIDE { | |
michaeln
2013/07/24 00:54:08
At this point the worker run loop is wound down an
michaeln
2013/07/24 01:38:58
Or i guess what i meant to say was, maybe just {
kinuko
2013/07/24 09:29:09
Current API is designed as 1. the callback is self
kinuko
2013/07/24 11:03:29
Well... on the second look the current API seems t
kinuko
2013/07/24 11:15:41
Oops, callbacks can't be deleted from outside sinc
| |
69 callbacks_->didFail(WebKit::WebFileErrorAbort); | |
70 delete this; | |
michaeln
2013/07/24 06:19:13
Oh, I have another question about this method?
Po
kinuko
2013/07/24 09:29:09
Ah, in the main thread side-- yes, good catch. Fi
| |
71 } | |
72 | |
73 // WebFileSystemCallbacks overrides. | |
74 virtual void didSucceed() OVERRIDE { | |
75 RunCallback(base::Bind(&WebFileSystemCallbacks::didSucceed, | |
76 base::Unretained(callbacks_))); | |
77 } | |
78 virtual void didReadMetadata(const WebFileInfo& info) OVERRIDE { | |
79 RunCallback(base::Bind(&WebFileSystemCallbacks::didReadMetadata, | |
80 base::Unretained(callbacks_), info)); | |
81 } | |
82 virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, | |
83 bool hasMore) OVERRIDE { | |
84 RunCallback(base::Bind(&WebFileSystemCallbacks::didReadDirectory, | |
85 base::Unretained(callbacks_), entries, hasMore)); | |
86 } | |
87 virtual void didOpenFileSystem(const WebString& name, | |
88 const WebURL& rootURL) OVERRIDE { | |
89 RunCallback(base::Bind(&WebFileSystemCallbacks::didOpenFileSystem, | |
90 base::Unretained(callbacks_), name, rootURL)); | |
91 } | |
92 virtual void didFail(WebKit::WebFileError error) OVERRIDE { | |
93 RunCallback(base::Bind(&WebFileSystemCallbacks::didFail, | |
94 base::Unretained(callbacks_), error)); | |
95 } | |
96 virtual bool shouldBlockUntilCompletion() const OVERRIDE { | |
97 return callbacks_->shouldBlockUntilCompletion(); | |
98 } | |
99 | |
100 void DidCreateSnapshotFile(const base::PlatformFileInfo& file_info, | |
101 const base::FilePath& platform_path, | |
102 const base::Closure& did_receive_snapshot) { | |
103 if (thread_id_ != CurrentWorkerId()) { | |
104 WorkerTaskRunner::Instance()->PostTask( | |
105 thread_id_, | |
106 base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, | |
107 base::Unretained(this), file_info, platform_path, | |
108 did_receive_snapshot)); | |
109 return; | |
110 } | |
111 scoped_ptr<CallbacksWrapper> deleter(this); | |
112 WebFileInfo web_file_info; | |
113 webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info); | |
114 web_file_info.platformPath = platform_path.AsUTF16Unsafe(); | |
115 callbacks_->didCreateSnapshotFile(web_file_info); | |
116 did_receive_snapshot.Run(); | |
117 } | |
118 | |
119 private: | |
120 void RunCallback(const base::Closure& callback) { | |
121 if (thread_id_ != CurrentWorkerId()) { | |
122 WorkerTaskRunner::Instance()->PostTask( | |
123 thread_id_, | |
124 base::Bind(&CallbacksWrapper::RunCallback, | |
125 base::Unretained(this), callback)); | |
126 return; | |
127 } | |
128 scoped_ptr<CallbacksWrapper> deleter(this); | |
129 callback.Run(); | |
130 } | |
131 | |
132 WebFileSystemCallbacks* callbacks_; | |
133 int thread_id_; | |
134 }; | |
135 | |
136 template <typename Method, typename Params> | |
137 void CallDispatcherOnMainThread( | |
138 base::MessageLoopProxy* loop, | |
139 Method method, const Params& params, | |
140 WebFileSystemCallbacks* callbacks) { | |
141 if (!loop->RunsTasksOnCurrentThread()) { | |
142 loop->PostTask(FROM_HERE, | |
143 base::Bind(&CallDispatcherOnMainThread<Method, Params>, | |
144 make_scoped_refptr(loop), | |
145 method, params, callbacks)); | |
146 return; | |
147 } | |
148 if (!ChildThread::current() || | |
149 !ChildThread::current()->file_system_dispatcher()) { | |
150 callbacks->didFail(WebKit::WebFileErrorAbort); | |
michaeln
2013/07/24 00:54:08
It looks like didFail() can be called on the main
kinuko
2013/07/24 09:29:09
Done.
| |
151 return; | |
152 } | |
153 DispatchToMethod(ChildThread::current()->file_system_dispatcher(), | |
154 method, params); | |
155 } | |
156 | |
42 } // namespace | 157 } // namespace |
43 | 158 |
44 WebFileSystemImpl::WebFileSystemImpl() { | 159 WebFileSystemImpl::WebFileSystemImpl( |
45 } | 160 base::MessageLoopProxy* main_thread_loop) |
46 | 161 : main_thread_loop_(main_thread_loop) { |
47 void WebFileSystemImpl::move(const WebURL& src_path, | 162 // TODO(kinuko): Support creating and accessing WebFileSystemImpl on |
48 const WebURL& dest_path, | 163 // non-main thread. (crbug.com/257349) |
49 WebFileSystemCallbacks* callbacks) { | 164 DCHECK(main_thread_loop_->RunsTasksOnCurrentThread()); |
50 FileSystemDispatcher* dispatcher = | 165 } |
51 ChildThread::current()->file_system_dispatcher(); | 166 |
52 dispatcher->Move(GURL(src_path), | 167 WebFileSystemImpl::~WebFileSystemImpl() { |
53 GURL(dest_path), | 168 } |
54 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 169 |
55 } | 170 // WebFileSystem implementation. |
56 | 171 void WebFileSystemImpl::move( |
57 void WebFileSystemImpl::copy(const WebURL& src_path, | 172 const WebKit::WebURL& src_path, |
58 const WebURL& dest_path, | 173 const WebKit::WebURL& dest_path, |
59 WebFileSystemCallbacks* callbacks) { | 174 WebKit::WebFileSystemCallbacks* callbacks) { |
60 FileSystemDispatcher* dispatcher = | 175 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
61 ChildThread::current()->file_system_dispatcher(); | 176 CallDispatcherOnMainThread( |
62 dispatcher->Copy(GURL(src_path), | 177 main_thread_loop_.get(), |
63 GURL(dest_path), | 178 &FileSystemDispatcher::Move, |
64 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 179 MakeTuple(GURL(src_path), GURL(dest_path), |
65 } | 180 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
66 | 181 wrapper); |
67 void WebFileSystemImpl::remove(const WebURL& path, | 182 } |
68 WebFileSystemCallbacks* callbacks) { | 183 |
69 FileSystemDispatcher* dispatcher = | 184 void WebFileSystemImpl::copy( |
70 ChildThread::current()->file_system_dispatcher(); | 185 const WebKit::WebURL& src_path, |
71 dispatcher->Remove( | 186 const WebKit::WebURL& dest_path, |
72 GURL(path), | 187 WebKit::WebFileSystemCallbacks* callbacks) { |
73 false /* recursive */, | 188 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
74 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 189 CallDispatcherOnMainThread( |
75 } | 190 main_thread_loop_.get(), |
76 | 191 &FileSystemDispatcher::Copy, |
77 void WebFileSystemImpl::removeRecursively(const WebURL& path, | 192 MakeTuple(GURL(src_path), GURL(dest_path), |
78 WebFileSystemCallbacks* callbacks) { | 193 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
79 FileSystemDispatcher* dispatcher = | 194 wrapper); |
80 ChildThread::current()->file_system_dispatcher(); | 195 } |
81 dispatcher->Remove( | 196 |
82 GURL(path), | 197 void WebFileSystemImpl::remove( |
83 true /* recursive */, | 198 const WebKit::WebURL& path, |
84 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 199 WebKit::WebFileSystemCallbacks* callbacks) { |
85 } | 200 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
86 | 201 CallDispatcherOnMainThread( |
87 void WebFileSystemImpl::readMetadata(const WebURL& path, | 202 main_thread_loop_.get(), |
88 WebFileSystemCallbacks* callbacks) { | 203 &FileSystemDispatcher::Remove, |
89 FileSystemDispatcher* dispatcher = | 204 MakeTuple(GURL(path), false /* recursive */, |
90 ChildThread::current()->file_system_dispatcher(); | 205 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
91 dispatcher->ReadMetadata( | 206 wrapper); |
92 GURL(path), | 207 } |
93 base::Bind(&ReadMetadataCallbackAdapter, callbacks), | 208 |
94 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 209 void WebFileSystemImpl::removeRecursively( |
95 } | 210 const WebKit::WebURL& path, |
96 | 211 WebKit::WebFileSystemCallbacks* callbacks) { |
97 void WebFileSystemImpl::createFile(const WebURL& path, | 212 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
98 bool exclusive, | 213 CallDispatcherOnMainThread( |
99 WebFileSystemCallbacks* callbacks) { | 214 main_thread_loop_.get(), |
100 FileSystemDispatcher* dispatcher = | 215 &FileSystemDispatcher::Remove, |
101 ChildThread::current()->file_system_dispatcher(); | 216 MakeTuple(GURL(path), true /* recursive */, |
102 dispatcher->CreateFile( | 217 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
103 GURL(path), exclusive, | 218 wrapper); |
104 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 219 } |
105 } | 220 |
106 | 221 void WebFileSystemImpl::readMetadata( |
107 void WebFileSystemImpl::createDirectory(const WebURL& path, | 222 const WebKit::WebURL& path, |
108 bool exclusive, | 223 WebKit::WebFileSystemCallbacks* callbacks) { |
109 WebFileSystemCallbacks* callbacks) { | 224 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
110 FileSystemDispatcher* dispatcher = | 225 CallDispatcherOnMainThread( |
111 ChildThread::current()->file_system_dispatcher(); | 226 main_thread_loop_.get(), |
112 dispatcher->CreateDirectory( | 227 &FileSystemDispatcher::ReadMetadata, |
113 GURL(path), exclusive, false /* recursive */, | 228 MakeTuple(GURL(path), |
114 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 229 base::Bind(&ReadMetadataCallbackAdapter, wrapper), |
115 } | 230 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
116 | 231 wrapper); |
117 void WebFileSystemImpl::fileExists(const WebURL& path, | 232 } |
118 WebFileSystemCallbacks* callbacks) { | 233 |
119 FileSystemDispatcher* dispatcher = | 234 void WebFileSystemImpl::createFile( |
120 ChildThread::current()->file_system_dispatcher(); | 235 const WebKit::WebURL& path, |
121 dispatcher->Exists( | 236 bool exclusive, |
122 GURL(path), false /* directory */, | 237 WebKit::WebFileSystemCallbacks* callbacks) { |
123 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 238 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
124 } | 239 CallDispatcherOnMainThread( |
125 | 240 main_thread_loop_.get(), |
126 void WebFileSystemImpl::directoryExists(const WebURL& path, | 241 &FileSystemDispatcher::CreateFile, |
127 WebFileSystemCallbacks* callbacks) { | 242 MakeTuple(GURL(path), exclusive, |
128 FileSystemDispatcher* dispatcher = | 243 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
129 ChildThread::current()->file_system_dispatcher(); | 244 wrapper); |
130 dispatcher->Exists( | 245 } |
131 GURL(path), true /* directory */, | 246 |
132 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 247 void WebFileSystemImpl::createDirectory( |
133 } | 248 const WebKit::WebURL& path, |
134 | 249 bool exclusive, |
135 void WebFileSystemImpl::readDirectory(const WebURL& path, | 250 WebKit::WebFileSystemCallbacks* callbacks) { |
136 WebFileSystemCallbacks* callbacks) { | 251 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
137 FileSystemDispatcher* dispatcher = | 252 CallDispatcherOnMainThread( |
138 ChildThread::current()->file_system_dispatcher(); | 253 main_thread_loop_.get(), |
139 dispatcher->ReadDirectory( | 254 &FileSystemDispatcher::CreateDirectory, |
140 GURL(path), | 255 MakeTuple(GURL(path), exclusive, false /* recursive */, |
141 base::Bind(&ReadDirectoryCallbackAdapater, callbacks), | 256 base::Bind(&FileStatusCallbackAdapter, wrapper)), |
142 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 257 wrapper); |
258 } | |
259 | |
260 void WebFileSystemImpl::fileExists( | |
261 const WebKit::WebURL& path, | |
262 WebKit::WebFileSystemCallbacks* callbacks) { | |
263 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); | |
264 CallDispatcherOnMainThread( | |
265 main_thread_loop_.get(), | |
266 &FileSystemDispatcher::Exists, | |
267 MakeTuple(GURL(path), false /* directory */, | |
268 base::Bind(&FileStatusCallbackAdapter, wrapper)), | |
269 wrapper); | |
270 } | |
271 | |
272 void WebFileSystemImpl::directoryExists( | |
273 const WebKit::WebURL& path, | |
274 WebKit::WebFileSystemCallbacks* callbacks) { | |
275 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); | |
276 CallDispatcherOnMainThread( | |
277 main_thread_loop_.get(), | |
278 &FileSystemDispatcher::Exists, | |
279 MakeTuple(GURL(path), true /* directory */, | |
280 base::Bind(&FileStatusCallbackAdapter, wrapper)), | |
281 wrapper); | |
282 } | |
283 | |
284 void WebFileSystemImpl::readDirectory( | |
285 const WebKit::WebURL& path, | |
286 WebKit::WebFileSystemCallbacks* callbacks) { | |
287 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); | |
288 CallDispatcherOnMainThread( | |
289 main_thread_loop_.get(), | |
290 &FileSystemDispatcher::ReadDirectory, | |
291 MakeTuple(GURL(path), | |
292 base::Bind(&ReadDirectoryCallbackAdapater, wrapper), | |
293 base::Bind(&FileStatusCallbackAdapter, wrapper)), | |
294 wrapper); | |
143 } | 295 } |
144 | 296 |
145 WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter( | 297 WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter( |
146 const WebURL& path, WebKit::WebFileWriterClient* client) { | 298 const WebURL& path, WebKit::WebFileWriterClient* client) { |
147 return new WebFileWriterImpl(GURL(path), client); | 299 return new WebFileWriterImpl(GURL(path), client); |
148 } | 300 } |
149 | 301 |
150 void WebFileSystemImpl::createFileWriter( | 302 void WebFileSystemImpl::createFileWriter( |
151 const WebURL& path, | 303 const WebURL& path, |
152 WebKit::WebFileWriterClient* client, | 304 WebKit::WebFileWriterClient* client, |
153 WebKit::WebFileSystemCallbacks* callbacks) { | 305 WebKit::WebFileSystemCallbacks* callbacks) { |
306 // TODO(kinuko): Convert this method to use bridge model. (crbug.com/257349) | |
307 DCHECK(main_thread_loop_->RunsTasksOnCurrentThread()); | |
154 FileSystemDispatcher* dispatcher = | 308 FileSystemDispatcher* dispatcher = |
155 ChildThread::current()->file_system_dispatcher(); | 309 ChildThread::current()->file_system_dispatcher(); |
156 dispatcher->ReadMetadata( | 310 dispatcher->ReadMetadata( |
157 GURL(path), | 311 GURL(path), |
158 base::Bind(&DidReadMetadataForCreateFileWriter, | 312 base::Bind(&DidReadMetadataForCreateFileWriter, |
159 GURL(path), client, callbacks), | 313 GURL(path), client, callbacks), |
160 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 314 base::Bind(&FileStatusCallbackAdapter, callbacks)); |
161 } | 315 } |
162 | 316 |
163 void WebFileSystemImpl::createSnapshotFileAndReadMetadata( | 317 void WebFileSystemImpl::createSnapshotFileAndReadMetadata( |
164 const WebKit::WebURL& path, | 318 const WebKit::WebURL& path, |
165 WebKit::WebFileSystemCallbacks* callbacks) { | 319 WebKit::WebFileSystemCallbacks* callbacks) { |
166 FileSystemDispatcher* dispatcher = | 320 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
167 ChildThread::current()->file_system_dispatcher(); | 321 CallDispatcherOnMainThread( |
168 dispatcher->CreateSnapshotFile( | 322 main_thread_loop_.get(), |
169 GURL(path), | 323 &FileSystemDispatcher::CreateSnapshotFile, |
170 base::Bind(&CreateSnapshotFileCallbackAdapter, callbacks), | 324 MakeTuple(GURL(path), |
171 base::Bind(&FileStatusCallbackAdapter, callbacks)); | 325 base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, |
326 base::Unretained(wrapper)), | |
327 base::Bind(&FileStatusCallbackAdapter, wrapper)), | |
328 wrapper); | |
172 } | 329 } |
173 | 330 |
174 } // namespace content | 331 } // namespace content |
OLD | NEW |