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 "content/child/fileapi/webfilewriter_impl.h"
8 #include "base/platform_file.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "content/child/child_thread.h"
11 #include "content/child/fileapi/file_system_dispatcher.h"
12 #include "webkit/child/worker_task_runner.h"
14 using webkit_glue::WorkerTaskRunner
;
20 FileSystemDispatcher
* GetFileSystemDispatcher() {
21 return ChildThread::current() ?
22 ChildThread::current()->file_system_dispatcher() : NULL
;
27 typedef FileSystemDispatcher::StatusCallback StatusCallback
;
28 typedef FileSystemDispatcher::WriteCallback WriteCallback
;
30 // This instance may be created outside main thread but runs mainly
32 class WebFileWriterImpl::WriterBridge
33 : public base::RefCountedThreadSafe
<WriterBridge
> {
35 WriterBridge(WebFileWriterImpl::Type type
)
37 thread_id_(WorkerTaskRunner::Instance()->CurrentWorkerId()),
39 if (type
== WebFileWriterImpl::TYPE_SYNC
)
40 waitable_event_
.reset(new base::WaitableEvent(false, false));
43 void Truncate(const GURL
& path
, int64 offset
,
44 const StatusCallback
& status_callback
) {
45 status_callback_
= status_callback
;
46 if (!GetFileSystemDispatcher())
48 ChildThread::current()->file_system_dispatcher()->Truncate(
49 path
, offset
, &request_id_
,
50 base::Bind(&WriterBridge::DidFinish
, this));
53 void Write(const GURL
& path
, const std::string
& id
, int64 offset
,
54 const WriteCallback
& write_callback
,
55 const StatusCallback
& error_callback
) {
56 write_callback_
= write_callback
;
57 status_callback_
= error_callback
;
58 if (!GetFileSystemDispatcher())
60 ChildThread::current()->file_system_dispatcher()->Write(
61 path
, id
, offset
, &request_id_
,
62 base::Bind(&WriterBridge::DidWrite
, this),
63 base::Bind(&WriterBridge::DidFinish
, this));
66 void Cancel(const StatusCallback
& status_callback
) {
67 status_callback_
= status_callback
;
68 if (!GetFileSystemDispatcher())
70 ChildThread::current()->file_system_dispatcher()->Cancel(
72 base::Bind(&WriterBridge::DidFinish
, this));
75 base::WaitableEvent
* waitable_event() {
76 return waitable_event_
.get();
80 waitable_event_
->Wait();
81 DCHECK(!results_closure_
.is_null());
82 results_closure_
.Run();
86 friend class base::RefCountedThreadSafe
<WriterBridge
>;
87 virtual ~WriterBridge() {}
89 void DidWrite(int64 bytes
, bool complete
) {
90 written_bytes_
+= bytes
;
91 if (waitable_event_
&& !complete
)
93 PostTaskToWorker(base::Bind(write_callback_
, written_bytes_
, complete
));
96 void DidFinish(base::PlatformFileError status
) {
97 PostTaskToWorker(base::Bind(status_callback_
, status
));
100 void PostTaskToWorker(const base::Closure
& closure
) {
103 DCHECK(!waitable_event_
);
107 if (waitable_event_
) {
108 results_closure_
= closure
;
109 waitable_event_
->Signal();
112 WorkerTaskRunner::Instance()->PostTask(thread_id_
, closure
);
115 StatusCallback status_callback_
;
116 WriteCallback write_callback_
;
120 scoped_ptr
<base::WaitableEvent
> waitable_event_
;
121 base::Closure results_closure_
;
124 WebFileWriterImpl::WebFileWriterImpl(
125 const GURL
& path
, blink::WebFileWriterClient
* client
,
127 base::MessageLoopProxy
* main_thread_loop
)
128 : WebFileWriterBase(path
, client
),
129 main_thread_loop_(main_thread_loop
),
130 bridge_(new WriterBridge(type
)) {
133 WebFileWriterImpl::~WebFileWriterImpl() {
136 void WebFileWriterImpl::DoTruncate(const GURL
& path
, int64 offset
) {
137 RunOnMainThread(base::Bind(&WriterBridge::Truncate
, bridge_
,
139 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
142 void WebFileWriterImpl::DoWrite(
143 const GURL
& path
, const std::string
& blob_id
, int64 offset
) {
144 RunOnMainThread(base::Bind(&WriterBridge::Write
, bridge_
,
145 path
, blob_id
, offset
,
146 base::Bind(&WebFileWriterImpl::DidWrite
, AsWeakPtr()),
147 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
150 void WebFileWriterImpl::DoCancel() {
151 RunOnMainThread(base::Bind(&WriterBridge::Cancel
, bridge_
,
152 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
155 void WebFileWriterImpl::RunOnMainThread(const base::Closure
& closure
) {
156 if (main_thread_loop_
->RunsTasksOnCurrentThread()) {
157 DCHECK(!bridge_
->waitable_event());
161 main_thread_loop_
->PostTask(FROM_HERE
, closure
);
162 if (bridge_
->waitable_event())
163 bridge_
->WaitAndRun();
166 } // namespace content