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/synchronization/waitable_event.h"
9 #include "content/child/child_thread.h"
10 #include "content/child/fileapi/file_system_dispatcher.h"
11 #include "content/child/worker_task_runner.h"
17 FileSystemDispatcher
* GetFileSystemDispatcher() {
18 return ChildThread::current() ?
19 ChildThread::current()->file_system_dispatcher() : NULL
;
24 typedef FileSystemDispatcher::StatusCallback StatusCallback
;
25 typedef FileSystemDispatcher::WriteCallback WriteCallback
;
27 // This instance may be created outside main thread but runs mainly
29 class WebFileWriterImpl::WriterBridge
30 : public base::RefCountedThreadSafe
<WriterBridge
> {
32 WriterBridge(WebFileWriterImpl::Type type
)
34 thread_id_(WorkerTaskRunner::Instance()->CurrentWorkerId()),
36 if (type
== WebFileWriterImpl::TYPE_SYNC
)
37 waitable_event_
.reset(new base::WaitableEvent(false, false));
40 void Truncate(const GURL
& path
, int64 offset
,
41 const StatusCallback
& status_callback
) {
42 status_callback_
= status_callback
;
43 if (!GetFileSystemDispatcher())
45 ChildThread::current()->file_system_dispatcher()->Truncate(
46 path
, offset
, &request_id_
,
47 base::Bind(&WriterBridge::DidFinish
, this));
50 void Write(const GURL
& path
, const std::string
& id
, int64 offset
,
51 const WriteCallback
& write_callback
,
52 const StatusCallback
& error_callback
) {
53 write_callback_
= write_callback
;
54 status_callback_
= error_callback
;
55 if (!GetFileSystemDispatcher())
57 ChildThread::current()->file_system_dispatcher()->Write(
58 path
, id
, offset
, &request_id_
,
59 base::Bind(&WriterBridge::DidWrite
, this),
60 base::Bind(&WriterBridge::DidFinish
, this));
63 void Cancel(const StatusCallback
& status_callback
) {
64 status_callback_
= status_callback
;
65 if (!GetFileSystemDispatcher())
67 ChildThread::current()->file_system_dispatcher()->Cancel(
69 base::Bind(&WriterBridge::DidFinish
, this));
72 base::WaitableEvent
* waitable_event() {
73 return waitable_event_
.get();
77 waitable_event_
->Wait();
78 DCHECK(!results_closure_
.is_null());
79 results_closure_
.Run();
83 friend class base::RefCountedThreadSafe
<WriterBridge
>;
84 virtual ~WriterBridge() {}
86 void DidWrite(int64 bytes
, bool complete
) {
87 written_bytes_
+= bytes
;
88 if (waitable_event_
&& !complete
)
90 PostTaskToWorker(base::Bind(write_callback_
, written_bytes_
, complete
));
93 void DidFinish(base::File::Error status
) {
94 PostTaskToWorker(base::Bind(status_callback_
, status
));
97 void PostTaskToWorker(const base::Closure
& closure
) {
100 DCHECK(!waitable_event_
);
104 if (waitable_event_
) {
105 results_closure_
= closure
;
106 waitable_event_
->Signal();
109 WorkerTaskRunner::Instance()->PostTask(thread_id_
, closure
);
112 StatusCallback status_callback_
;
113 WriteCallback write_callback_
;
117 scoped_ptr
<base::WaitableEvent
> waitable_event_
;
118 base::Closure results_closure_
;
121 WebFileWriterImpl::WebFileWriterImpl(
122 const GURL
& path
, blink::WebFileWriterClient
* client
,
124 base::MessageLoopProxy
* main_thread_loop
)
125 : WebFileWriterBase(path
, client
),
126 main_thread_loop_(main_thread_loop
),
127 bridge_(new WriterBridge(type
)) {
130 WebFileWriterImpl::~WebFileWriterImpl() {
133 void WebFileWriterImpl::DoTruncate(const GURL
& path
, int64 offset
) {
134 RunOnMainThread(base::Bind(&WriterBridge::Truncate
, bridge_
,
136 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
139 void WebFileWriterImpl::DoWrite(
140 const GURL
& path
, const std::string
& blob_id
, int64 offset
) {
141 RunOnMainThread(base::Bind(&WriterBridge::Write
, bridge_
,
142 path
, blob_id
, offset
,
143 base::Bind(&WebFileWriterImpl::DidWrite
, AsWeakPtr()),
144 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
147 void WebFileWriterImpl::DoCancel() {
148 RunOnMainThread(base::Bind(&WriterBridge::Cancel
, bridge_
,
149 base::Bind(&WebFileWriterImpl::DidFinish
, AsWeakPtr())));
152 void WebFileWriterImpl::RunOnMainThread(const base::Closure
& closure
) {
153 if (main_thread_loop_
->RunsTasksOnCurrentThread()) {
154 DCHECK(!bridge_
->waitable_event());
158 main_thread_loop_
->PostTask(FROM_HERE
, closure
);
159 if (bridge_
->waitable_event())
160 bridge_
->WaitAndRun();
163 } // namespace content