Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / child / fileapi / webfilewriter_impl.cc
blobef16def19a7eab7241c6d9a15f7eeb3a2ac99f92
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"
7 #include "base/bind.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "content/child/child_thread_impl.h"
11 #include "content/child/fileapi/file_system_dispatcher.h"
12 #include "content/child/worker_task_runner.h"
14 namespace content {
16 namespace {
18 FileSystemDispatcher* GetFileSystemDispatcher() {
19 return ChildThreadImpl::current() ?
20 ChildThreadImpl::current()->file_system_dispatcher() : NULL;
23 } // namespace
25 typedef FileSystemDispatcher::StatusCallback StatusCallback;
26 typedef FileSystemDispatcher::WriteCallback WriteCallback;
28 // This instance may be created outside main thread but runs mainly
29 // on main thread.
30 class WebFileWriterImpl::WriterBridge
31 : public base::RefCountedThreadSafe<WriterBridge> {
32 public:
33 WriterBridge(WebFileWriterImpl::Type type)
34 : request_id_(0),
35 running_on_worker_(WorkerTaskRunner::Instance()->CurrentWorkerId() > 0),
36 task_runner_(running_on_worker_ ? base::ThreadTaskRunnerHandle::Get()
37 : nullptr),
38 written_bytes_(0) {
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())
47 return;
48 ChildThreadImpl::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())
59 return;
60 ChildThreadImpl::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())
69 return;
70 ChildThreadImpl::current()->file_system_dispatcher()->Cancel(
71 request_id_,
72 base::Bind(&WriterBridge::DidFinish, this));
75 base::WaitableEvent* waitable_event() {
76 return waitable_event_.get();
79 void WaitAndRun() {
80 waitable_event_->Wait();
81 DCHECK(!results_closure_.is_null());
82 results_closure_.Run();
85 private:
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)
92 return;
93 PostTaskToWorker(base::Bind(write_callback_, written_bytes_, complete));
96 void DidFinish(base::File::Error status) {
97 PostTaskToWorker(base::Bind(status_callback_, status));
100 void PostTaskToWorker(const base::Closure& closure) {
101 written_bytes_ = 0;
102 if (!running_on_worker_) {
103 DCHECK(!waitable_event_);
104 closure.Run();
105 return;
107 DCHECK(task_runner_);
108 if (waitable_event_) {
109 results_closure_ = closure;
110 waitable_event_->Signal();
111 return;
113 task_runner_->PostTask(FROM_HERE, closure);
116 StatusCallback status_callback_;
117 WriteCallback write_callback_;
118 int request_id_;
119 const bool running_on_worker_;
120 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
121 int written_bytes_;
122 scoped_ptr<base::WaitableEvent> waitable_event_;
123 base::Closure results_closure_;
126 WebFileWriterImpl::WebFileWriterImpl(
127 const GURL& path, blink::WebFileWriterClient* client,
128 Type type,
129 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner)
130 : WebFileWriterBase(path, client),
131 main_thread_task_runner_(main_thread_task_runner),
132 bridge_(new WriterBridge(type)) {
135 WebFileWriterImpl::~WebFileWriterImpl() {
138 void WebFileWriterImpl::DoTruncate(const GURL& path, int64 offset) {
139 RunOnMainThread(base::Bind(&WriterBridge::Truncate, bridge_,
140 path, offset,
141 base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
144 void WebFileWriterImpl::DoWrite(
145 const GURL& path, const std::string& blob_id, int64 offset) {
146 RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_,
147 path, blob_id, offset,
148 base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()),
149 base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
152 void WebFileWriterImpl::DoCancel() {
153 RunOnMainThread(base::Bind(&WriterBridge::Cancel, bridge_,
154 base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
157 void WebFileWriterImpl::RunOnMainThread(const base::Closure& closure) {
158 if (main_thread_task_runner_->RunsTasksOnCurrentThread()) {
159 DCHECK(!bridge_->waitable_event());
160 closure.Run();
161 return;
163 main_thread_task_runner_->PostTask(FROM_HERE, closure);
164 if (bridge_->waitable_event())
165 bridge_->WaitAndRun();
168 } // namespace content