• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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