OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "webkit/tools/test_shell/simple_file_writer.h" | 5 #include "webkit/tools/test_shell/simple_file_writer.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
9 #include "net/url_request/url_request_context.h" | 9 #include "net/url_request/url_request_context.h" |
10 #include "webkit/fileapi/file_system_callback_dispatcher.h" | 10 #include "webkit/fileapi/file_system_callback_dispatcher.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 URLRequestContext* SimpleFileWriter::request_context_ = NULL; | 22 URLRequestContext* SimpleFileWriter::request_context_ = NULL; |
23 | 23 |
24 // Helper class to proxy to write and truncate calls to the IO thread, | 24 // Helper class to proxy to write and truncate calls to the IO thread, |
25 // and to proxy the results back to the main thead. There is a one-to-one | 25 // and to proxy the results back to the main thead. There is a one-to-one |
26 // relationship between SimpleFileWriters and IOThreadBackends. | 26 // relationship between SimpleFileWriters and IOThreadBackends. |
27 class SimpleFileWriter::IOThreadProxy | 27 class SimpleFileWriter::IOThreadProxy |
28 : public base::RefCountedThreadSafe<SimpleFileWriter::IOThreadProxy> { | 28 : public base::RefCountedThreadSafe<SimpleFileWriter::IOThreadProxy> { |
29 public: | 29 public: |
30 explicit IOThreadProxy(const base::WeakPtr<SimpleFileWriter>& simple_writer) | 30 explicit IOThreadProxy(const base::WeakPtr<SimpleFileWriter>& simple_writer) |
31 : simple_writer_(simple_writer) { | 31 : simple_writer_(simple_writer), |
| 32 operation_(NULL) { |
32 // The IO thread needs to be running for this class to work. | 33 // The IO thread needs to be running for this class to work. |
33 SimpleResourceLoaderBridge::EnsureIOThread(); | 34 SimpleResourceLoaderBridge::EnsureIOThread(); |
34 io_thread_ = SimpleResourceLoaderBridge::GetIoThread(); | 35 io_thread_ = SimpleResourceLoaderBridge::GetIoThread(); |
35 main_thread_ = base::MessageLoopProxy::CreateForCurrentThread(); | 36 main_thread_ = base::MessageLoopProxy::CreateForCurrentThread(); |
36 } | 37 } |
37 | 38 |
38 virtual ~IOThreadProxy() { | 39 virtual ~IOThreadProxy() { |
39 } | 40 } |
40 | 41 |
41 void Truncate(const FilePath& path, int64 offset) { | 42 void Truncate(const FilePath& path, int64 offset) { |
42 if (!io_thread_->BelongsToCurrentThread()) { | 43 if (!io_thread_->BelongsToCurrentThread()) { |
43 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 44 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
44 this, &IOThreadProxy::Truncate, path, offset)); | 45 this, &IOThreadProxy::Truncate, path, offset)); |
45 return; | 46 return; |
46 } | 47 } |
47 DCHECK(!operation_.get()); | 48 DCHECK(!operation_); |
48 operation_.reset(GetNewOperation()); | 49 operation_ = GetNewOperation(); |
49 operation_->Truncate(path, offset); | 50 operation_->Truncate(path, offset); |
50 } | 51 } |
51 | 52 |
52 void Write(const FilePath& path, const GURL& blob_url, int64 offset) { | 53 void Write(const FilePath& path, const GURL& blob_url, int64 offset) { |
53 if (!io_thread_->BelongsToCurrentThread()) { | 54 if (!io_thread_->BelongsToCurrentThread()) { |
54 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 55 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
55 this, &IOThreadProxy::Write, path, blob_url, offset)); | 56 this, &IOThreadProxy::Write, path, blob_url, offset)); |
56 return; | 57 return; |
57 } | 58 } |
58 DCHECK(request_context_); | 59 DCHECK(request_context_); |
59 DCHECK(!operation_.get()); | 60 DCHECK(!operation_); |
60 operation_.reset(GetNewOperation()); | 61 operation_ = GetNewOperation(); |
61 operation_->Write(request_context_, path, blob_url, offset); | 62 operation_->Write(request_context_, path, blob_url, offset); |
62 } | 63 } |
63 | 64 |
64 void Cancel() { | 65 void Cancel() { |
65 if (!io_thread_->BelongsToCurrentThread()) { | 66 if (!io_thread_->BelongsToCurrentThread()) { |
66 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 67 io_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
67 this, &IOThreadProxy::Cancel)); | 68 this, &IOThreadProxy::Cancel)); |
68 return; | 69 return; |
69 } | 70 } |
70 if (!operation_.get()) { | 71 if (!operation_) { |
71 DidFail(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 72 DidFail(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); |
72 return; | 73 return; |
73 } | 74 } |
74 cancel_operation_.reset(GetNewOperation()); | 75 operation_->Cancel(GetNewOperation()); |
75 operation_->Cancel(cancel_operation_.get()); | |
76 } | 76 } |
77 | 77 |
78 private: | 78 private: |
79 // Inner class to receive callbacks from FileSystemOperation. | 79 // Inner class to receive callbacks from FileSystemOperation. |
80 class CallbackDispatcher : public FileSystemCallbackDispatcher { | 80 class CallbackDispatcher : public FileSystemCallbackDispatcher { |
81 public: | 81 public: |
82 explicit CallbackDispatcher(IOThreadProxy* proxy) : proxy_(proxy) { | 82 explicit CallbackDispatcher(IOThreadProxy* proxy) : proxy_(proxy) { |
83 } | 83 } |
84 | 84 |
| 85 ~CallbackDispatcher() { |
| 86 proxy_->ClearOperation(); |
| 87 } |
| 88 |
85 virtual void DidSucceed() { | 89 virtual void DidSucceed() { |
86 proxy_->DidSucceed(); | 90 proxy_->DidSucceed(); |
87 } | 91 } |
88 | 92 |
89 virtual void DidFail(base::PlatformFileError error_code) { | 93 virtual void DidFail(base::PlatformFileError error_code) { |
90 proxy_->DidFail(error_code); | 94 proxy_->DidFail(error_code); |
91 } | 95 } |
92 | 96 |
93 virtual void DidWrite(int64 bytes, bool complete) { | 97 virtual void DidWrite(int64 bytes, bool complete) { |
94 proxy_->DidWrite(bytes, complete); | 98 proxy_->DidWrite(bytes, complete); |
(...skipping 17 matching lines...) Expand all Loading... |
112 scoped_refptr<IOThreadProxy> proxy_; | 116 scoped_refptr<IOThreadProxy> proxy_; |
113 }; | 117 }; |
114 | 118 |
115 FileSystemOperation* GetNewOperation() { | 119 FileSystemOperation* GetNewOperation() { |
116 // The FileSystemOperation takes ownership of the CallbackDispatcher. | 120 // The FileSystemOperation takes ownership of the CallbackDispatcher. |
117 return new FileSystemOperation(new CallbackDispatcher(this), io_thread_); | 121 return new FileSystemOperation(new CallbackDispatcher(this), io_thread_); |
118 } | 122 } |
119 | 123 |
120 void DidSucceed() { | 124 void DidSucceed() { |
121 if (!main_thread_->BelongsToCurrentThread()) { | 125 if (!main_thread_->BelongsToCurrentThread()) { |
122 operation_.reset(); | |
123 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 126 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
124 this, &IOThreadProxy::DidSucceed)); | 127 this, &IOThreadProxy::DidSucceed)); |
125 return; | 128 return; |
126 } | 129 } |
127 if (simple_writer_) | 130 if (simple_writer_) |
128 simple_writer_->DidSucceed(); | 131 simple_writer_->DidSucceed(); |
129 } | 132 } |
130 | 133 |
131 void DidFail(base::PlatformFileError error_code) { | 134 void DidFail(base::PlatformFileError error_code) { |
132 if (!main_thread_->BelongsToCurrentThread()) { | 135 if (!main_thread_->BelongsToCurrentThread()) { |
133 operation_.reset(); | |
134 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 136 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
135 this, &IOThreadProxy::DidFail, error_code)); | 137 this, &IOThreadProxy::DidFail, error_code)); |
136 return; | 138 return; |
137 } | 139 } |
138 if (simple_writer_) | 140 if (simple_writer_) |
139 simple_writer_->DidFail(error_code); | 141 simple_writer_->DidFail(error_code); |
140 } | 142 } |
141 | 143 |
142 void DidWrite(int64 bytes, bool complete) { | 144 void DidWrite(int64 bytes, bool complete) { |
143 if (!main_thread_->BelongsToCurrentThread()) { | 145 if (!main_thread_->BelongsToCurrentThread()) { |
144 if (complete) | |
145 operation_.reset(); | |
146 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( | 146 main_thread_->PostTask(FROM_HERE, NewRunnableMethod( |
147 this, &IOThreadProxy::DidWrite, bytes, complete)); | 147 this, &IOThreadProxy::DidWrite, bytes, complete)); |
148 return; | 148 return; |
149 } | 149 } |
150 if (simple_writer_) | 150 if (simple_writer_) |
151 simple_writer_->DidWrite(bytes, complete); | 151 simple_writer_->DidWrite(bytes, complete); |
152 } | 152 } |
153 | 153 |
| 154 void ClearOperation() { |
| 155 operation_ = NULL; |
| 156 } |
| 157 |
154 scoped_refptr<base::MessageLoopProxy> io_thread_; | 158 scoped_refptr<base::MessageLoopProxy> io_thread_; |
155 scoped_refptr<base::MessageLoopProxy> main_thread_; | 159 scoped_refptr<base::MessageLoopProxy> main_thread_; |
156 | 160 |
157 // Only used on the main thread. | 161 // Only used on the main thread. |
158 base::WeakPtr<SimpleFileWriter> simple_writer_; | 162 base::WeakPtr<SimpleFileWriter> simple_writer_; |
159 | 163 |
160 // Only used on the io thread. | 164 // Only used on the io thread. |
161 scoped_ptr<FileSystemOperation> operation_; | 165 FileSystemOperation* operation_; |
162 scoped_ptr<FileSystemOperation> cancel_operation_; | |
163 }; | 166 }; |
164 | 167 |
165 | 168 |
166 SimpleFileWriter::SimpleFileWriter( | 169 SimpleFileWriter::SimpleFileWriter( |
167 const WebString& path, WebFileWriterClient* client) | 170 const WebString& path, WebFileWriterClient* client) |
168 : WebFileWriterBase(path, client), | 171 : WebFileWriterBase(path, client), |
169 io_thread_proxy_(new IOThreadProxy(AsWeakPtr())) { | 172 io_thread_proxy_(new IOThreadProxy(AsWeakPtr())) { |
170 } | 173 } |
171 | 174 |
172 SimpleFileWriter::~SimpleFileWriter() { | 175 SimpleFileWriter::~SimpleFileWriter() { |
173 } | 176 } |
174 | 177 |
175 void SimpleFileWriter::DoTruncate(const FilePath& path, int64 offset) { | 178 void SimpleFileWriter::DoTruncate(const FilePath& path, int64 offset) { |
176 io_thread_proxy_->Truncate(path, offset); | 179 io_thread_proxy_->Truncate(path, offset); |
177 } | 180 } |
178 | 181 |
179 void SimpleFileWriter::DoWrite( | 182 void SimpleFileWriter::DoWrite( |
180 const FilePath& path, const GURL& blob_url, int64 offset) { | 183 const FilePath& path, const GURL& blob_url, int64 offset) { |
181 io_thread_proxy_->Write(path, blob_url, offset); | 184 io_thread_proxy_->Write(path, blob_url, offset); |
182 } | 185 } |
183 | 186 |
184 void SimpleFileWriter::DoCancel() { | 187 void SimpleFileWriter::DoCancel() { |
185 io_thread_proxy_->Cancel(); | 188 io_thread_proxy_->Cancel(); |
186 } | 189 } |
OLD | NEW |