Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: content/child/fileapi/webfilesystem_impl.cc

Issue 19387002: Implement Worker-MainThread bridge for FileSystem API in Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase + nits fix Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698