1 // Copyright (c) 2008 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "libcef/browser/stream_impl.h"
6 #include <stdlib.h>
7 #include "base/files/file_util.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
10
11 // Static functions
12
CreateForFile(const CefString & fileName)13 CefRefPtr<CefStreamReader> CefStreamReader::CreateForFile(
14 const CefString& fileName) {
15 DCHECK(!fileName.empty());
16
17 // TODO(cef): Do not allow file IO on all threads (issue #1187).
18 base::ThreadRestrictions::ScopedAllowIO allow_io;
19
20 CefRefPtr<CefStreamReader> reader;
21 FILE* file = base::OpenFile(base::FilePath(fileName), "rb");
22 if (file)
23 reader = new CefFileReader(file, true);
24 return reader;
25 }
26
CreateForData(void * data,size_t size)27 CefRefPtr<CefStreamReader> CefStreamReader::CreateForData(void* data,
28 size_t size) {
29 DCHECK(data != nullptr);
30 DCHECK(size > 0);
31 CefRefPtr<CefStreamReader> reader;
32 if (data && size > 0)
33 reader = new CefBytesReader(data, size, true);
34 return reader;
35 }
36
CreateForHandler(CefRefPtr<CefReadHandler> handler)37 CefRefPtr<CefStreamReader> CefStreamReader::CreateForHandler(
38 CefRefPtr<CefReadHandler> handler) {
39 DCHECK(handler.get());
40 CefRefPtr<CefStreamReader> reader;
41 if (handler.get())
42 reader = new CefHandlerReader(handler);
43 return reader;
44 }
45
CreateForFile(const CefString & fileName)46 CefRefPtr<CefStreamWriter> CefStreamWriter::CreateForFile(
47 const CefString& fileName) {
48 DCHECK(!fileName.empty());
49
50 // TODO(cef): Do not allow file IO on all threads (issue #1187).
51 base::ThreadRestrictions::ScopedAllowIO allow_io;
52
53 CefRefPtr<CefStreamWriter> writer;
54 FILE* file = base::OpenFile(base::FilePath(fileName), "wb");
55 if (file)
56 writer = new CefFileWriter(file, true);
57 return writer;
58 }
59
CreateForHandler(CefRefPtr<CefWriteHandler> handler)60 CefRefPtr<CefStreamWriter> CefStreamWriter::CreateForHandler(
61 CefRefPtr<CefWriteHandler> handler) {
62 DCHECK(handler.get());
63 CefRefPtr<CefStreamWriter> writer;
64 if (handler.get())
65 writer = new CefHandlerWriter(handler);
66 return writer;
67 }
68
69 // CefFileReader
70
CefFileReader(FILE * file,bool close)71 CefFileReader::CefFileReader(FILE* file, bool close)
72 : close_(close), file_(file) {}
73
~CefFileReader()74 CefFileReader::~CefFileReader() {
75 base::AutoLock lock_scope(lock_);
76 if (close_)
77 base::CloseFile(file_);
78 }
79
Read(void * ptr,size_t size,size_t n)80 size_t CefFileReader::Read(void* ptr, size_t size, size_t n) {
81 base::AutoLock lock_scope(lock_);
82 return fread(ptr, size, n, file_);
83 }
84
Seek(int64 offset,int whence)85 int CefFileReader::Seek(int64 offset, int whence) {
86 base::AutoLock lock_scope(lock_);
87 #if BUILDFLAG(IS_WIN)
88 return _fseeki64(file_, offset, whence);
89 #else
90 return fseek(file_, offset, whence);
91 #endif
92 }
93
Tell()94 int64 CefFileReader::Tell() {
95 base::AutoLock lock_scope(lock_);
96 #if BUILDFLAG(IS_WIN)
97 return _ftelli64(file_);
98 #else
99 return ftell(file_);
100 #endif
101 }
102
Eof()103 int CefFileReader::Eof() {
104 base::AutoLock lock_scope(lock_);
105 return feof(file_);
106 }
107
108 // CefFileWriter
109
CefFileWriter(FILE * file,bool close)110 CefFileWriter::CefFileWriter(FILE* file, bool close)
111 : file_(file), close_(close) {}
112
~CefFileWriter()113 CefFileWriter::~CefFileWriter() {
114 base::AutoLock lock_scope(lock_);
115 if (close_)
116 base::CloseFile(file_);
117 }
118
Write(const void * ptr,size_t size,size_t n)119 size_t CefFileWriter::Write(const void* ptr, size_t size, size_t n) {
120 base::AutoLock lock_scope(lock_);
121 return (size_t)fwrite(ptr, size, n, file_);
122 }
123
Seek(int64 offset,int whence)124 int CefFileWriter::Seek(int64 offset, int whence) {
125 base::AutoLock lock_scope(lock_);
126 return fseek(file_, offset, whence);
127 }
128
Tell()129 int64 CefFileWriter::Tell() {
130 base::AutoLock lock_scope(lock_);
131 return ftell(file_);
132 }
133
Flush()134 int CefFileWriter::Flush() {
135 base::AutoLock lock_scope(lock_);
136 return fflush(file_);
137 }
138
139 // CefBytesReader
140
CefBytesReader(void * data,int64 datasize,bool copy)141 CefBytesReader::CefBytesReader(void* data, int64 datasize, bool copy)
142 : data_(nullptr), datasize_(0), copy_(false), offset_(0) {
143 SetData(data, datasize, copy);
144 }
145
~CefBytesReader()146 CefBytesReader::~CefBytesReader() {
147 SetData(nullptr, 0, false);
148 }
149
Read(void * ptr,size_t size,size_t n)150 size_t CefBytesReader::Read(void* ptr, size_t size, size_t n) {
151 base::AutoLock lock_scope(lock_);
152 size_t s = (datasize_ - offset_) / size;
153 size_t ret = (n < s ? n : s);
154 memcpy(ptr, (reinterpret_cast<char*>(data_)) + offset_, ret * size);
155 offset_ += ret * size;
156 return ret;
157 }
158
Seek(int64 offset,int whence)159 int CefBytesReader::Seek(int64 offset, int whence) {
160 int rv = -1L;
161 base::AutoLock lock_scope(lock_);
162 switch (whence) {
163 case SEEK_CUR:
164 if (offset_ + offset > datasize_ || offset_ + offset < 0)
165 break;
166 offset_ += offset;
167 rv = 0;
168 break;
169 case SEEK_END: {
170 int64 offset_abs = std::abs(offset);
171 if (offset_abs > datasize_)
172 break;
173 offset_ = datasize_ - offset_abs;
174 rv = 0;
175 break;
176 }
177 case SEEK_SET:
178 if (offset > datasize_ || offset < 0)
179 break;
180 offset_ = offset;
181 rv = 0;
182 break;
183 }
184
185 return rv;
186 }
187
Tell()188 int64 CefBytesReader::Tell() {
189 base::AutoLock lock_scope(lock_);
190 return offset_;
191 }
192
Eof()193 int CefBytesReader::Eof() {
194 base::AutoLock lock_scope(lock_);
195 return (offset_ >= datasize_);
196 }
197
SetData(void * data,int64 datasize,bool copy)198 void CefBytesReader::SetData(void* data, int64 datasize, bool copy) {
199 base::AutoLock lock_scope(lock_);
200 if (copy_)
201 free(data_);
202
203 copy_ = copy;
204 offset_ = 0;
205 datasize_ = datasize;
206
207 if (copy) {
208 data_ = malloc(datasize);
209 DCHECK(data_ != nullptr);
210 if (data_)
211 memcpy(data_, data, datasize);
212 } else {
213 data_ = data;
214 }
215 }
216
217 // CefBytesWriter
218
CefBytesWriter(size_t grow)219 CefBytesWriter::CefBytesWriter(size_t grow)
220 : grow_(grow), datasize_(grow), offset_(0) {
221 DCHECK(grow > 0);
222 data_ = malloc(grow);
223 DCHECK(data_ != nullptr);
224 }
225
~CefBytesWriter()226 CefBytesWriter::~CefBytesWriter() {
227 base::AutoLock lock_scope(lock_);
228 if (data_)
229 free(data_);
230 }
231
Write(const void * ptr,size_t size,size_t n)232 size_t CefBytesWriter::Write(const void* ptr, size_t size, size_t n) {
233 base::AutoLock lock_scope(lock_);
234 size_t rv;
235 if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
236 Grow(size * n) == 0) {
237 rv = 0;
238 } else {
239 memcpy(reinterpret_cast<char*>(data_) + offset_, ptr, size * n);
240 offset_ += size * n;
241 rv = n;
242 }
243
244 return rv;
245 }
246
Seek(int64 offset,int whence)247 int CefBytesWriter::Seek(int64 offset, int whence) {
248 int rv = -1L;
249 base::AutoLock lock_scope(lock_);
250 switch (whence) {
251 case SEEK_CUR:
252 if (offset_ + offset > datasize_ || offset_ + offset < 0)
253 break;
254 offset_ += offset;
255 rv = 0;
256 break;
257 case SEEK_END: {
258 int64 offset_abs = std::abs(offset);
259 if (offset_abs > datasize_)
260 break;
261 offset_ = datasize_ - offset_abs;
262 rv = 0;
263 break;
264 }
265 case SEEK_SET:
266 if (offset > datasize_ || offset < 0)
267 break;
268 offset_ = offset;
269 rv = 0;
270 break;
271 }
272
273 return rv;
274 }
275
Tell()276 int64 CefBytesWriter::Tell() {
277 base::AutoLock lock_scope(lock_);
278 return offset_;
279 }
280
Flush()281 int CefBytesWriter::Flush() {
282 return 0;
283 }
284
GetDataString()285 std::string CefBytesWriter::GetDataString() {
286 base::AutoLock lock_scope(lock_);
287 std::string str(reinterpret_cast<char*>(data_), offset_);
288 return str;
289 }
290
Grow(size_t size)291 size_t CefBytesWriter::Grow(size_t size) {
292 base::AutoLock lock_scope(lock_);
293 size_t rv;
294 size_t s = (size > grow_ ? size : grow_);
295 void* tmp = realloc(data_, datasize_ + s);
296 DCHECK(tmp != nullptr);
297 if (tmp) {
298 data_ = tmp;
299 datasize_ += s;
300 rv = datasize_;
301 } else {
302 rv = 0;
303 }
304
305 return rv;
306 }
307