Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(654)

Side by Side Diff: media/cdm/ppapi/cdm_file_io_impl.cc

Issue 93243003: Add CDM FileIO tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments addressed Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "media/cdm/ppapi/cdm_file_io_impl.h"
6
7 #include <algorithm>
8 #include <sstream>
9
10 #include "base/logging.h"
11 #include "ppapi/c/pp_errors.h"
12
13 namespace media {
14
15 const int kReadSize = 1024; // Arbitrary choice.
16
17 // Call func_call and check the result. If the result is not
18 // PP_OK_COMPLETIONPENDING, print out logs, call OnError() and return.
19 #define CHECK_PP_OK_COMPLETIONPENDING(func_call, error_type) \
20 do { \
21 int32_t result = func_call; \
22 PP_DCHECK(result != PP_OK); \
23 if (result != PP_OK_COMPLETIONPENDING) { \
24 std::ostringstream error_message; \
ddorwin 2013/12/11 21:16:17 can we pipe directly to the DVLOG and eliminate th
xhwang 2013/12/13 02:51:47 Done.
25 error_message << #func_call << " failed with result: " << result; \
26 DVLOG(3) << error_message; \
27 OnError(error_type); \
28 return; \
29 } \
30 } while (0)
31
32 // PPAPI calls should only be made on the main thread. In this file, main thread
33 // checking is only performed in public APIs and the completion callbacks. This
34 // ensures all functions are running on the main thread since internal methods
35 // are called either by the public APIs or by the completion callbacks.
36 static bool IsMainThread() {
37 return pp::Module::Get()->core()->IsMainThread();
38 }
39
40 // Posts a task to run |cb| on the main thread. The task is posted even if the
41 // current thread is the main thread.
42 static void PostOnMain(pp::CompletionCallback cb) {
43 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
44 }
45
46 CdmFileIOImpl::CdmFileIOImpl(cdm::FileIOClient* client, PP_Instance pp_instance)
47 : state_(FILE_UNOPENED),
48 client_(client),
49 pp_instance_handle_(pp_instance),
50 callback_factory_(this),
51 io_offset_(0) {
52 PP_DCHECK(IsMainThread());
53 PP_DCHECK(pp_instance); // 0 indicates a "NULL handle".
54 }
55
56 CdmFileIOImpl::~CdmFileIOImpl() {
57 if (state_ != FILE_CLOSED)
58 CloseFile();
59 }
60
61 // Call sequence: Open() -> OpenFileSystem() -> OpenFile() -> FILE_OPENED.
62 void CdmFileIOImpl::Open(const char* file_name, uint32_t file_name_size) {
63 DVLOG(3) << __FUNCTION__;
64 PP_DCHECK(IsMainThread());
65
66 if (state_ != FILE_UNOPENED) {
67 DVLOG(3) << "Open() called in an invalid state.";
ddorwin 2013/12/11 21:16:17 CDM_DLOG?
xhwang 2013/12/13 02:51:47 Done.
68 OnError(OPEN_ERROR);
69 return;
70 }
71
72 state_ = OPENING_FILE_SYSTEM;
73
74 // File name should not contain any path separators.
75 std::string file_name_str(file_name, file_name_size);
76 if (file_name_str.find('/') != std::string::npos ||
77 file_name_str.find('\\') != std::string::npos) {
78 DVLOG(3) << "Invalid file name.";
79 OnError(OPEN_ERROR);
80 return;
81 }
82
83 // pp::FileRef only accepts path that begins with a '/' character.
84 file_name_ = '/' + file_name_str;
85 OpenFileSystem();
86 }
87
88 // Call sequence:
89 // finished
90 // Read() -> ReadFile() -> OnFileRead() ----------> Done.
91 // ^ |
92 // | not finished |
93 // |--------------|
94 void CdmFileIOImpl::Read() {
95 DVLOG(3) << __FUNCTION__;
96 PP_DCHECK(IsMainThread());
97
98 if (state_ != FILE_OPENED) {
99 DVLOG(3) << "Read() called in an invalid state.";
100 OnError(READ_ERROR);
101 return;
102 }
103
104 PP_DCHECK(io_buffer_.empty());
105 PP_DCHECK(cumulative_read_buffer_.empty());
106
107 io_buffer_.resize(kReadSize);
108 io_offset_ = 0;
109
110 state_ = READING_FILE;
111 ReadFile();
112 }
113
114 // Call sequence:
115 // finished
116 // Write() -> WriteFile() -> OnFileWritten() ----------> Done.
117 // ^ |
118 // | | not finished
119 // |------------------|
120 void CdmFileIOImpl::Write(const uint8_t* data, uint32_t data_size) {
121 DVLOG(3) << __FUNCTION__;
122 PP_DCHECK(IsMainThread());
123
124 if (state_ != FILE_OPENED) {
125 DVLOG(3) << "Write() called in an invalid state.";
126 OnError(WRITE_ERROR);
127 return;
128 }
129
130 // TODO(xhwang): Support NULL |data|.
131 PP_DCHECK(data);
132
133 io_buffer_.assign(data, data + data_size);
134 io_offset_ = 0;
135
136 state_ = WRITING_FILE;
137 WriteFile();
138 }
139
140 void CdmFileIOImpl::Close() {
141 PP_DCHECK(IsMainThread());
142 if (state_ != FILE_CLOSED)
143 CloseFile();
144 delete this;
145 }
146
147 void CdmFileIOImpl::OpenFileSystem() {
148 DVLOG(3) << __FUNCTION__;
149 PP_DCHECK(state_ == OPENING_FILE_SYSTEM);
150
151 pp::CompletionCallbackWithOutput<pp::FileSystem> cb =
152 callback_factory_.NewCallbackWithOutput(
153 &CdmFileIOImpl::OnFileSystemOpened);
154 isolated_file_system_ = pp::IsolatedFileSystemPrivate(
155 pp_instance_handle_, PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE);
156
157 CHECK_PP_OK_COMPLETIONPENDING(isolated_file_system_.Open(cb), OPEN_ERROR);
158 }
159
160 void CdmFileIOImpl::OnFileSystemOpened(int32_t result,
161 pp::FileSystem file_system) {
162 DVLOG(3) << __FUNCTION__;
163 PP_DCHECK(IsMainThread());
164 PP_DCHECK(state_ == OPENING_FILE_SYSTEM);
165
166 if (result != PP_OK) {
167 DVLOG(3) << "File system open failed asynchronously.";
168 OnError(OPEN_ERROR);
169 return;
170 }
171
172 file_system_ = file_system;
173 state_ = OPENING_FILE;
174 OpenFile();
175 }
176
177 void CdmFileIOImpl::OpenFile() {
178 DVLOG(3) << __FUNCTION__;
179 PP_DCHECK(state_ == OPENING_FILE);
180
181 file_io_ = pp::FileIO(pp_instance_handle_);
182 file_ref_ = pp::FileRef(file_system_, file_name_.c_str());
183 int32_t file_open_flag = PP_FILEOPENFLAG_READ |
184 PP_FILEOPENFLAG_WRITE |
185 PP_FILEOPENFLAG_CREATE;
186 pp::CompletionCallback cb =
187 callback_factory_.NewCallback(&CdmFileIOImpl::OnFileOpened);
188 CHECK_PP_OK_COMPLETIONPENDING(file_io_.Open(file_ref_, file_open_flag, cb),
189 OPEN_ERROR);
190 }
191
192 void CdmFileIOImpl::OnFileOpened(int32_t result) {
193 PP_DCHECK(IsMainThread());
194 PP_DCHECK(state_ == OPENING_FILE);
195
196 if (result != PP_OK) {
197 DVLOG(3) << "File open failed.";
198 OnError(OPEN_ERROR);
199 return;
200 }
201
202 state_ = FILE_OPENED;
203 client_->OnOpenComplete(cdm::FileIOClient::kSuccess);
204 }
205
206 void CdmFileIOImpl::ReadFile() {
207 PP_DCHECK(state_ == READING_FILE);
208 PP_DCHECK(!io_buffer_.empty());
209
210 pp::CompletionCallback cb =
211 callback_factory_.NewCallback(&CdmFileIOImpl::OnFileRead);
212 CHECK_PP_OK_COMPLETIONPENDING(
213 file_io_.Read(io_offset_, &io_buffer_[0], io_buffer_.size(), cb),
214 READ_ERROR);
215 }
216
217 void CdmFileIOImpl::OnFileRead(int32_t bytes_read) {
218 PP_DCHECK(IsMainThread());
219 PP_DCHECK(state_ == READING_FILE);
220
221 // 0 |bytes_read| indicates end-of-file reached.
222 if (bytes_read < PP_OK) {
223 DVLOG(3) << "Read file failed.";
224 OnError(READ_ERROR);
225 return;
226 }
227
228 PP_DCHECK(static_cast<size_t>(bytes_read) <= io_buffer_.size());
229 // Append |bytes_read| in |io_buffer_| to |cumulative_read_buffer_|.
230 cumulative_read_buffer_.insert(cumulative_read_buffer_.end(),
231 io_buffer_.begin(),
232 io_buffer_.begin() + bytes_read);
233 io_offset_ += bytes_read;
234
235 // Not received end-of-file yet.
236 if (bytes_read > 0) {
237 ReadFile();
238 return;
239 }
240
241 // We hit end-of-file. Return read data to the client.
242 io_buffer_.clear();
243 io_offset_ = 0;
244 // Clear |cumulative_read_buffer_| in case OnReadComplete() calls Read() or
245 // Write().
246 std::vector<char> local_buffer;
247 std::swap(cumulative_read_buffer_, local_buffer);
248
249 state_ = FILE_OPENED;
250 client_->OnReadComplete(cdm::FileIOClient::kSuccess,
251 reinterpret_cast<const uint8_t*>(&local_buffer[0]),
252 local_buffer.size());
253 }
254
255 void CdmFileIOImpl::WriteFile() {
256 PP_DCHECK(state_ == WRITING_FILE);
257 PP_DCHECK(io_offset_ < io_buffer_.size());
258
259 pp::CompletionCallback cb =
260 callback_factory_.NewCallback(&CdmFileIOImpl::OnFileWritten);
261 CHECK_PP_OK_COMPLETIONPENDING(file_io_.Write(io_offset_,
262 &io_buffer_[io_offset_],
263 io_buffer_.size() - io_offset_,
264 cb),
265 WRITE_ERROR);
266 }
267
268 void CdmFileIOImpl::OnFileWritten(int32_t bytes_written) {
269 PP_DCHECK(IsMainThread());
270 PP_DCHECK(state_ == WRITING_FILE);
271
272 if (bytes_written <= PP_OK) {
273 DVLOG(3) << "Write file failed.";
274 OnError(READ_ERROR);
275 return;
276 }
277
278 io_offset_ += bytes_written;
279 PP_DCHECK(io_offset_ <= io_buffer_.size());
280
281 if (io_offset_ < io_buffer_.size()) {
282 WriteFile();
283 return;
284 }
285
286 io_buffer_.clear();
287 io_offset_ = 0;
288 state_ = FILE_OPENED;
289 client_->OnWriteComplete(cdm::FileIOClient::kSuccess);
290 }
291
292 void CdmFileIOImpl::CloseFile() {
293 DVLOG(3) << __FUNCTION__;
294 PP_DCHECK(IsMainThread());
295
296 state_ = FILE_CLOSED;
297
298 file_io_.Close();
299 io_buffer_.clear();
300 io_offset_ = 0;
301 cumulative_read_buffer_.clear();
302 }
303
304 void CdmFileIOImpl::OnError(ErrorType error_type) {
305 io_buffer_.clear();
306 cumulative_read_buffer_.clear();
ddorwin 2013/12/11 21:16:17 reset offset too?
xhwang 2013/12/13 02:51:47 Done.
307 PostOnMain(callback_factory_.NewCallback(&CdmFileIOImpl::NotifyClientOfError,
308 error_type));
309 }
310
311 void CdmFileIOImpl::NotifyClientOfError(int32_t result,
312 ErrorType error_type) {
313 DCHECK(result == PP_OK);
ddorwin 2013/12/11 21:16:17 PP_ ?
xhwang 2013/12/13 02:51:47 Done.
314 switch (error_type) {
315 case OPEN_ERROR:
316 client_->OnOpenComplete(cdm::FileIOClient::kError);
317 break;
318 case READ_ERROR:
319 client_->OnReadComplete(cdm::FileIOClient::kError, NULL, 0);
320 break;
321 case WRITE_ERROR:
322 client_->OnWriteComplete(cdm::FileIOClient::kError);
323 break;
324 }
325 }
326
327 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698