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

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: Created 7 years, 4 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 "content/child/thread_safe_sender.h"
15 #include "content/common/fileapi/file_system_messages.h"
13 #include "third_party/WebKit/public/platform/WebFileInfo.h" 16 #include "third_party/WebKit/public/platform/WebFileInfo.h"
14 #include "third_party/WebKit/public/platform/WebString.h" 17 #include "third_party/WebKit/public/platform/WebString.h"
15 #include "third_party/WebKit/public/platform/WebURL.h" 18 #include "third_party/WebKit/public/platform/WebURL.h"
19 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h"
20 #include "url/gurl.h"
21 #include "webkit/child/worker_task_runner.h"
16 #include "webkit/glue/webkit_glue.h" 22 #include "webkit/glue/webkit_glue.h"
17 23
18 using WebKit::WebFileInfo; 24 using WebKit::WebFileInfo;
19 using WebKit::WebFileSystemCallbacks; 25 using WebKit::WebFileSystemCallbacks;
20 using WebKit::WebFileSystemEntry; 26 using WebKit::WebFileSystemEntry;
21 using WebKit::WebString; 27 using WebKit::WebString;
22 using WebKit::WebURL; 28 using WebKit::WebURL;
23 using WebKit::WebVector; 29 using WebKit::WebVector;
30 using webkit_glue::WorkerTaskRunner;
24 31
25 namespace content { 32 namespace content {
26 33
27 namespace { 34 namespace {
28 35
29 void DidReadMetadataForCreateFileWriter( 36 void DidReadMetadataForCreateFileWriter(
30 const GURL& path, 37 const GURL& path,
31 WebKit::WebFileWriterClient* client, 38 WebKit::WebFileWriterClient* client,
32 WebKit::WebFileSystemCallbacks* callbacks, 39 WebKit::WebFileSystemCallbacks* callbacks,
33 const base::PlatformFileInfo& file_info) { 40 const base::PlatformFileInfo& file_info) {
34 if (file_info.is_directory || file_info.size < 0) { 41 if (file_info.is_directory || file_info.size < 0) {
35 callbacks->didFail(WebKit::WebFileErrorInvalidState); 42 callbacks->didFail(WebKit::WebFileErrorInvalidState);
36 return; 43 return;
37 } 44 }
38 callbacks->didCreateFileWriter(new WebFileWriterImpl(path, client), 45 callbacks->didCreateFileWriter(new WebFileWriterImpl(path, client),
39 file_info.size); 46 file_info.size);
40 } 47 }
41 48
49 int CurrentWorkerId() {
50 return WorkerTaskRunner::Instance()->CurrentWorkerId();
51 }
52
53 class CallbacksWrapper
54 : public WebFileSystemCallbacks,
55 public WorkerTaskRunner::Observer {
56 public:
57 CallbacksWrapper(WebFileSystemCallbacks* original_callbacks,
58 ThreadSafeSender* thread_safe_sender)
59 : callbacks_(original_callbacks),
60 thread_safe_sender_(thread_safe_sender),
61 worker_id_(CurrentWorkerId()) {
62 if (worker_id_)
63 WorkerTaskRunner::Instance()->AddStopObserver(this);
64 }
65
66 virtual ~CallbacksWrapper() {
67 if (CurrentWorkerId())
68 WorkerTaskRunner::Instance()->RemoveStopObserver(this);
69 }
70
71 // WorkerTaskRunner::Observer overrides.
72 virtual void OnWorkerRunLoopStopped() OVERRIDE {
73 callbacks_->didFail(WebKit::WebFileErrorAbort);
74 callbacks_ = NULL;
75 }
76
77 // WebFileSystemCallbacks overrides.
78 virtual void didSucceed() OVERRIDE {
79 RunCallback(base::Bind(&WebFileSystemCallbacks::didSucceed,
80 base::Unretained(callbacks_)));
81 }
82 virtual void didReadMetadata(const WebFileInfo& info) OVERRIDE {
83 RunCallback(base::Bind(&WebFileSystemCallbacks::didReadMetadata,
84 base::Unretained(callbacks_), info));
85 }
86 virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries,
87 bool hasMore) OVERRIDE {
88 RunCallback(base::Bind(&WebFileSystemCallbacks::didReadDirectory,
89 base::Unretained(callbacks_), entries, hasMore));
90 }
91 virtual void didOpenFileSystem(const WebString& name,
92 const WebURL& rootURL) OVERRIDE {
93 RunCallback(base::Bind(&WebFileSystemCallbacks::didOpenFileSystem,
94 base::Unretained(callbacks_), name, rootURL));
95 }
96 virtual void didFail(WebKit::WebFileError error) OVERRIDE {
97 RunCallback(base::Bind(&WebFileSystemCallbacks::didFail,
98 base::Unretained(callbacks_), error));
99 }
100 virtual bool shouldBlockUntilCompletion() const OVERRIDE {
101 return callbacks_->shouldBlockUntilCompletion();
102 }
103
104 void DidCreateSnapshotFile(const base::PlatformFileInfo& file_info,
105 const base::FilePath& platform_path,
106 int request_id) {
107 if (worker_id_ != CurrentWorkerId()) {
108 PostTaskToWorker(
109 base::Bind(&CallbacksWrapper::DidCreateSnapshotFile,
110 base::Unretained(this), file_info, platform_path,
111 request_id));
112 return;
113 }
114 scoped_ptr<CallbacksWrapper> deleter(this);
115 DCHECK(callbacks_);
116 WebFileInfo web_file_info;
117 webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info);
118 web_file_info.platformPath = platform_path.AsUTF16Unsafe();
119 callbacks_->didCreateSnapshotFile(web_file_info);
120
121 thread_safe_sender_->Send(
122 new FileSystemHostMsg_DidReceiveSnapshotFile(request_id));
michaeln 2013/07/24 22:21:12 Drat, I think i gave you a bum steer, very sorry :
kinuko 2013/07/25 04:32:41 Yup... I vaguely remember that's how I decided to
123 }
124
125 private:
126 void RunCallback(const base::Closure& callback) {
127 if (worker_id_ != CurrentWorkerId()) {
128 PostTaskToWorker(base::Bind(&CallbacksWrapper::RunCallback,
129 base::Unretained(this), callback));
130 return;
131 }
132 scoped_ptr<CallbacksWrapper> deleter(this);
133 DCHECK(callbacks_);
134 callback.Run();
135 }
136
137 void PostTaskToWorker(const base::Closure& closure) {
138 if (!WorkerTaskRunner::Instance()->PostTask(worker_id_, closure))
139 delete this;
michaeln 2013/07/24 22:21:12 I'm really not sure about 'delete this' correctnes
kinuko 2013/07/25 04:32:41 Right. I overlooked PostTask returns false when Wo
michaeln 2013/07/25 21:39:08 For a process shutdown leaks, who cares, but these
kinuko 2013/07/26 12:29:55 My initial implementation was exactlly following I
140 }
141
142 WebFileSystemCallbacks* callbacks_;
143 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
144 int worker_id_;
145 };
146
147 template <typename Method, typename Params>
148 void CallDispatcherOnMainThread(
149 base::MessageLoopProxy* loop,
150 Method method, const Params& params,
151 WebFileSystemCallbacks* callbacks) {
152 if (!loop->RunsTasksOnCurrentThread()) {
153 loop->PostTask(FROM_HERE,
154 base::Bind(&CallDispatcherOnMainThread<Method, Params>,
155 make_scoped_refptr(loop),
156 method, params, callbacks));
157 return;
158 }
159 if (!ChildThread::current() ||
160 !ChildThread::current()->file_system_dispatcher()) {
161 callbacks->didFail(WebKit::WebFileErrorAbort);
162 return;
163 }
164 DispatchToMethod(ChildThread::current()->file_system_dispatcher(),
165 method, params);
166 }
167
42 } // namespace 168 } // namespace
43 169
44 WebFileSystemImpl::WebFileSystemImpl() { 170 WebFileSystemImpl::WebFileSystemImpl(
45 } 171 base::MessageLoopProxy* main_thread_loop,
46 172 ThreadSafeSender* sender)
47 void WebFileSystemImpl::move(const WebURL& src_path, 173 : main_thread_loop_(main_thread_loop),
48 const WebURL& dest_path, 174 sender_(sender) {
49 WebFileSystemCallbacks* callbacks) { 175 // TODO(kinuko): Support creating and accessing WebFileSystemImpl on
50 FileSystemDispatcher* dispatcher = 176 // non-main thread. (crbug.com/257349)
51 ChildThread::current()->file_system_dispatcher(); 177 DCHECK(main_thread_loop_->RunsTasksOnCurrentThread());
52 dispatcher->Move(GURL(src_path), 178 }
53 GURL(dest_path), 179
54 base::Bind(&FileStatusCallbackAdapter, callbacks)); 180 WebFileSystemImpl::~WebFileSystemImpl() {
55 } 181 }
56 182
57 void WebFileSystemImpl::copy(const WebURL& src_path, 183 // WebFileSystem implementation.
58 const WebURL& dest_path, 184 void WebFileSystemImpl::move(
59 WebFileSystemCallbacks* callbacks) { 185 const WebKit::WebURL& src_path,
60 FileSystemDispatcher* dispatcher = 186 const WebKit::WebURL& dest_path,
61 ChildThread::current()->file_system_dispatcher(); 187 WebKit::WebFileSystemCallbacks* callbacks) {
62 dispatcher->Copy(GURL(src_path), 188 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
63 GURL(dest_path), 189 CallDispatcherOnMainThread(
64 base::Bind(&FileStatusCallbackAdapter, callbacks)); 190 main_thread_loop_.get(),
65 } 191 &FileSystemDispatcher::Move,
66 192 MakeTuple(GURL(src_path), GURL(dest_path),
67 void WebFileSystemImpl::remove(const WebURL& path, 193 base::Bind(&FileStatusCallbackAdapter, wrapper)),
68 WebFileSystemCallbacks* callbacks) { 194 wrapper);
69 FileSystemDispatcher* dispatcher = 195 }
70 ChildThread::current()->file_system_dispatcher(); 196
71 dispatcher->Remove( 197 void WebFileSystemImpl::copy(
72 GURL(path), 198 const WebKit::WebURL& src_path,
73 false /* recursive */, 199 const WebKit::WebURL& dest_path,
74 base::Bind(&FileStatusCallbackAdapter, callbacks)); 200 WebKit::WebFileSystemCallbacks* callbacks) {
75 } 201 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
76 202 CallDispatcherOnMainThread(
77 void WebFileSystemImpl::removeRecursively(const WebURL& path, 203 main_thread_loop_.get(),
78 WebFileSystemCallbacks* callbacks) { 204 &FileSystemDispatcher::Copy,
79 FileSystemDispatcher* dispatcher = 205 MakeTuple(GURL(src_path), GURL(dest_path),
80 ChildThread::current()->file_system_dispatcher(); 206 base::Bind(&FileStatusCallbackAdapter, wrapper)),
81 dispatcher->Remove( 207 wrapper);
82 GURL(path), 208 }
83 true /* recursive */, 209
84 base::Bind(&FileStatusCallbackAdapter, callbacks)); 210 void WebFileSystemImpl::remove(
85 } 211 const WebKit::WebURL& path,
86 212 WebKit::WebFileSystemCallbacks* callbacks) {
87 void WebFileSystemImpl::readMetadata(const WebURL& path, 213 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
88 WebFileSystemCallbacks* callbacks) { 214 CallDispatcherOnMainThread(
89 FileSystemDispatcher* dispatcher = 215 main_thread_loop_.get(),
90 ChildThread::current()->file_system_dispatcher(); 216 &FileSystemDispatcher::Remove,
91 dispatcher->ReadMetadata( 217 MakeTuple(GURL(path), false /* recursive */,
92 GURL(path), 218 base::Bind(&FileStatusCallbackAdapter, wrapper)),
93 base::Bind(&ReadMetadataCallbackAdapter, callbacks), 219 wrapper);
94 base::Bind(&FileStatusCallbackAdapter, callbacks)); 220 }
95 } 221
96 222 void WebFileSystemImpl::removeRecursively(
97 void WebFileSystemImpl::createFile(const WebURL& path, 223 const WebKit::WebURL& path,
98 bool exclusive, 224 WebKit::WebFileSystemCallbacks* callbacks) {
99 WebFileSystemCallbacks* callbacks) { 225 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
100 FileSystemDispatcher* dispatcher = 226 CallDispatcherOnMainThread(
101 ChildThread::current()->file_system_dispatcher(); 227 main_thread_loop_.get(),
102 dispatcher->CreateFile( 228 &FileSystemDispatcher::Remove,
103 GURL(path), exclusive, 229 MakeTuple(GURL(path), true /* recursive */,
104 base::Bind(&FileStatusCallbackAdapter, callbacks)); 230 base::Bind(&FileStatusCallbackAdapter, wrapper)),
105 } 231 wrapper);
106 232 }
107 void WebFileSystemImpl::createDirectory(const WebURL& path, 233
108 bool exclusive, 234 void WebFileSystemImpl::readMetadata(
109 WebFileSystemCallbacks* callbacks) { 235 const WebKit::WebURL& path,
110 FileSystemDispatcher* dispatcher = 236 WebKit::WebFileSystemCallbacks* callbacks) {
111 ChildThread::current()->file_system_dispatcher(); 237 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
112 dispatcher->CreateDirectory( 238 CallDispatcherOnMainThread(
113 GURL(path), exclusive, false /* recursive */, 239 main_thread_loop_.get(),
114 base::Bind(&FileStatusCallbackAdapter, callbacks)); 240 &FileSystemDispatcher::ReadMetadata,
115 } 241 MakeTuple(GURL(path),
116 242 base::Bind(&ReadMetadataCallbackAdapter, wrapper),
117 void WebFileSystemImpl::fileExists(const WebURL& path, 243 base::Bind(&FileStatusCallbackAdapter, wrapper)),
118 WebFileSystemCallbacks* callbacks) { 244 wrapper);
119 FileSystemDispatcher* dispatcher = 245 }
120 ChildThread::current()->file_system_dispatcher(); 246
121 dispatcher->Exists( 247 void WebFileSystemImpl::createFile(
122 GURL(path), false /* directory */, 248 const WebKit::WebURL& path,
123 base::Bind(&FileStatusCallbackAdapter, callbacks)); 249 bool exclusive,
124 } 250 WebKit::WebFileSystemCallbacks* callbacks) {
125 251 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
126 void WebFileSystemImpl::directoryExists(const WebURL& path, 252 CallDispatcherOnMainThread(
127 WebFileSystemCallbacks* callbacks) { 253 main_thread_loop_.get(),
128 FileSystemDispatcher* dispatcher = 254 &FileSystemDispatcher::CreateFile,
129 ChildThread::current()->file_system_dispatcher(); 255 MakeTuple(GURL(path), exclusive,
130 dispatcher->Exists( 256 base::Bind(&FileStatusCallbackAdapter, wrapper)),
131 GURL(path), true /* directory */, 257 wrapper);
132 base::Bind(&FileStatusCallbackAdapter, callbacks)); 258 }
133 } 259
134 260 void WebFileSystemImpl::createDirectory(
135 void WebFileSystemImpl::readDirectory(const WebURL& path, 261 const WebKit::WebURL& path,
136 WebFileSystemCallbacks* callbacks) { 262 bool exclusive,
137 FileSystemDispatcher* dispatcher = 263 WebKit::WebFileSystemCallbacks* callbacks) {
138 ChildThread::current()->file_system_dispatcher(); 264 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
139 dispatcher->ReadDirectory( 265 CallDispatcherOnMainThread(
140 GURL(path), 266 main_thread_loop_.get(),
141 base::Bind(&ReadDirectoryCallbackAdapater, callbacks), 267 &FileSystemDispatcher::CreateDirectory,
142 base::Bind(&FileStatusCallbackAdapter, callbacks)); 268 MakeTuple(GURL(path), exclusive, false /* recursive */,
269 base::Bind(&FileStatusCallbackAdapter, wrapper)),
270 wrapper);
271 }
272
273 void WebFileSystemImpl::fileExists(
274 const WebKit::WebURL& path,
275 WebKit::WebFileSystemCallbacks* callbacks) {
276 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
277 CallDispatcherOnMainThread(
278 main_thread_loop_.get(),
279 &FileSystemDispatcher::Exists,
280 MakeTuple(GURL(path), false /* directory */,
281 base::Bind(&FileStatusCallbackAdapter, wrapper)),
282 wrapper);
283 }
284
285 void WebFileSystemImpl::directoryExists(
286 const WebKit::WebURL& path,
287 WebKit::WebFileSystemCallbacks* callbacks) {
288 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
289 CallDispatcherOnMainThread(
290 main_thread_loop_.get(),
291 &FileSystemDispatcher::Exists,
292 MakeTuple(GURL(path), true /* directory */,
293 base::Bind(&FileStatusCallbackAdapter, wrapper)),
294 wrapper);
295 }
296
297 void WebFileSystemImpl::readDirectory(
298 const WebKit::WebURL& path,
299 WebKit::WebFileSystemCallbacks* callbacks) {
300 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
301 CallDispatcherOnMainThread(
302 main_thread_loop_.get(),
303 &FileSystemDispatcher::ReadDirectory,
304 MakeTuple(GURL(path),
305 base::Bind(&ReadDirectoryCallbackAdapater, wrapper),
306 base::Bind(&FileStatusCallbackAdapter, wrapper)),
307 wrapper);
143 } 308 }
144 309
145 WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter( 310 WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter(
146 const WebURL& path, WebKit::WebFileWriterClient* client) { 311 const WebURL& path, WebKit::WebFileWriterClient* client) {
147 return new WebFileWriterImpl(GURL(path), client); 312 return new WebFileWriterImpl(GURL(path), client);
148 } 313 }
149 314
150 void WebFileSystemImpl::createFileWriter( 315 void WebFileSystemImpl::createFileWriter(
151 const WebURL& path, 316 const WebURL& path,
152 WebKit::WebFileWriterClient* client, 317 WebKit::WebFileWriterClient* client,
153 WebKit::WebFileSystemCallbacks* callbacks) { 318 WebKit::WebFileSystemCallbacks* callbacks) {
319 // TODO(kinuko): Convert this method to use bridge model. (crbug.com/257349)
320 DCHECK(main_thread_loop_->RunsTasksOnCurrentThread());
154 FileSystemDispatcher* dispatcher = 321 FileSystemDispatcher* dispatcher =
155 ChildThread::current()->file_system_dispatcher(); 322 ChildThread::current()->file_system_dispatcher();
156 dispatcher->ReadMetadata( 323 dispatcher->ReadMetadata(
157 GURL(path), 324 GURL(path),
158 base::Bind(&DidReadMetadataForCreateFileWriter, 325 base::Bind(&DidReadMetadataForCreateFileWriter,
159 GURL(path), client, callbacks), 326 GURL(path), client, callbacks),
160 base::Bind(&FileStatusCallbackAdapter, callbacks)); 327 base::Bind(&FileStatusCallbackAdapter, callbacks));
161 } 328 }
162 329
163 void WebFileSystemImpl::createSnapshotFileAndReadMetadata( 330 void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
164 const WebKit::WebURL& path, 331 const WebKit::WebURL& path,
165 WebKit::WebFileSystemCallbacks* callbacks) { 332 WebKit::WebFileSystemCallbacks* callbacks) {
166 FileSystemDispatcher* dispatcher = 333 CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks, sender_.get());
167 ChildThread::current()->file_system_dispatcher(); 334 CallDispatcherOnMainThread(
168 dispatcher->CreateSnapshotFile( 335 main_thread_loop_.get(),
169 GURL(path), 336 &FileSystemDispatcher::CreateSnapshotFile,
170 base::Bind(&CreateSnapshotFileCallbackAdapter, callbacks), 337 MakeTuple(GURL(path),
171 base::Bind(&FileStatusCallbackAdapter, callbacks)); 338 base::Bind(&CallbacksWrapper::DidCreateSnapshotFile,
339 base::Unretained(wrapper)),
340 base::Bind(&FileStatusCallbackAdapter, wrapper)),
341 wrapper);
172 } 342 }
173 343
174 } // namespace content 344 } // namespace content
OLDNEW
« no previous file with comments | « content/child/fileapi/webfilesystem_impl.h ('k') | content/renderer/renderer_webkitplatformsupport_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698