cdm_file_io_impl.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/cdm/ppapi/cdm_file_io_impl.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <sstream> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/cdm/ppapi/cdm_logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/c/pp_errors.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/dev/url_util_dev.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace media { 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Arbitrary choice based on the following heuristic ideas: 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// - not too big to avoid unnecessarily large memory allocation; 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// - not too small to avoid breaking most reads into multiple read operations. 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kReadSize = 8 * 1024; 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call func_call and check the result. If the result is not 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// PP_OK_COMPLETIONPENDING, print out logs, call OnError() and return. 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHECK_PP_OK_COMPLETIONPENDING(func_call, error_type) \ 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do { \ 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t result = func_call; \ 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(result != PP_OK); \ 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != PP_OK_COMPLETIONPENDING) { \ 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << #func_call << " failed with result: " << result; \ 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; \ 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(error_type); \ 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; \ 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } \ 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } while (0) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(NDEBUG) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// PPAPI calls should only be made on the main thread. In this file, main thread 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// checking is only performed in public APIs and the completion callbacks. This 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ensures all functions are running on the main thread since internal methods 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// are called either by the public APIs or by the completion callbacks. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool IsMainThread() { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return pp::Module::Get()->core()->IsMainThread(); 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // !defined(NDEBUG) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Posts a task to run |cb| on the main thread. The task is posted even if the 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// current thread is the main thread. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void PostOnMain(pp::CompletionCallback cb) { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::FileLockMap* CdmFileIOImpl::file_lock_map_ = NULL; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::ResourceTracker::ResourceTracker() { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do nothing here since we lazy-initialize CdmFileIOImpl::file_lock_map_ 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // in CdmFileIOImpl::AcquireFileLock(). 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::ResourceTracker::~ResourceTracker() { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete CdmFileIOImpl::file_lock_map_; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciCdmFileIOImpl::CdmFileIOImpl( 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm::FileIOClient* client, 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_Instance pp_instance, 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const pp::CompletionCallback& first_file_read_cb) 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : state_(STATE_UNOPENED), 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_(client), 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp_instance_handle_(pp_instance), 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci io_offset_(0), 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci first_file_read_reported_(false), 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci first_file_read_cb_(first_file_read_cb), 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_factory_(this) { 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(pp_instance); // 0 indicates a "NULL handle". 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::~CdmFileIOImpl() { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The destructor is private. |this| can only be destructed through Close(). 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_CLOSED); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Call sequence: Open() -> OpenFileSystem() -> STATE_FILE_SYSTEM_OPENED. 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Note: This only stores file name and opens the file system. The real file 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// open is deferred to when Read() or Write() is called. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Open(const char* file_name, uint32_t file_name_size) { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ != STATE_UNOPENED) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Open() called in an invalid state."; 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(OPEN_ERROR); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // File name should not (1) be empty, (2) start with '_', or (3) contain any 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // path separators. 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string file_name_str(file_name, file_name_size); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (file_name_str.empty() || 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_name_str[0] == '_' || 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_name_str.find('/') != std::string::npos || 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_name_str.find('\\') != std::string::npos) { 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Invalid file name."; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(OPEN_ERROR); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // pp::FileRef only accepts path that begins with a '/' character. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_name_ = '/' + file_name_str; 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!AcquireFileLock()) { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "File is in use by other cdm::FileIO objects."; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(OPEN_WHILE_IN_USE); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_OPENING_FILE_SYSTEM; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OpenFileSystem(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call sequence: 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Read() -> OpenFileForRead() -> ReadFile() -> Done. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Read() { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__; 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == STATE_READING || state_ == STATE_WRITING) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Read() called during pending read/write."; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(READ_WHILE_IN_USE); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ != STATE_FILE_SYSTEM_OPENED) { 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Read() called in an invalid state."; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(READ_ERROR); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(io_offset_ == 0); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(io_buffer_.empty()); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(cumulative_read_buffer_.empty()); 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.resize(kReadSize); 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_offset_ = 0; 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_READING; 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OpenFileForRead(); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call sequence: 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Write() -> OpenTempFileForWrite() -> WriteTempFile() -> RenameTempFile(). 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The file name of the temporary file is /_<requested_file_name>. 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Write(const uint8_t* data, uint32_t data_size) { 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__; 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == STATE_READING || state_ == STATE_WRITING) { 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Write() called during pending read/write."; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(WRITE_WHILE_IN_USE); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ != STATE_FILE_SYSTEM_OPENED) { 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Write() called in an invalid state."; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(WRITE_ERROR); 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(io_offset_ == 0); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(io_buffer_.empty()); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data_size > 0) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.assign(data, data + data_size); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(!data); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_WRITING; 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OpenTempFileForWrite(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Close() { 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ != STATE_CLOSED); 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Reset(); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_CLOSED; 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReleaseFileLock(); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // All pending callbacks are canceled since |callback_factory_| is destroyed. 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete this; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CdmFileIOImpl::SetFileID() { 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(file_id_.empty()); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(!file_name_.empty() && file_name_[0] == '/'); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Not taking ownership of |url_util_dev| (which is a singleton). 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const pp::URLUtil_Dev* url_util_dev = pp::URLUtil_Dev::Get(); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_URLComponents_Dev components; 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::Var url_var = 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_util_dev->GetDocumentURL(pp_instance_handle_, &components); 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!url_var.is_string()) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string url = url_var.AsString(); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_.append(url, components.scheme.begin, components.scheme.len); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_ += ':'; 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_.append(url, components.host.begin, components.host.len); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_ += ':'; 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_.append(url, components.port.begin, components.port.len); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id_ += file_name_; 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CdmFileIOImpl::AcquireFileLock() { 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (file_id_.empty() && !SetFileID()) 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!file_lock_map_) { 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_lock_map_ = new FileLockMap(); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileLockMap::iterator found = file_lock_map_->find(file_id_); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (found != file_lock_map_->end() && found->second) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*file_lock_map_)[file_id_] = true; 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::ReleaseFileLock() { 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!file_lock_map_) 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileLockMap::iterator found = file_lock_map_->find(file_id_); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (found != file_lock_map_->end() && found->second) 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) found->second = false; 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OpenFileSystem() { 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_OPENING_FILE_SYSTEM); 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::CompletionCallbackWithOutput<pp::FileSystem> cb = 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_factory_.NewCallbackWithOutput( 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &CdmFileIOImpl::OnFileSystemOpened); 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) isolated_file_system_ = pp::IsolatedFileSystemPrivate( 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp_instance_handle_, PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_PP_OK_COMPLETIONPENDING(isolated_file_system_.Open(cb), OPEN_ERROR); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileSystemOpened(int32_t result, 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::FileSystem file_system) { 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_OPENING_FILE_SYSTEM); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != PP_OK) { 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "File system open failed asynchronously."; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReleaseFileLock(); 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(OPEN_ERROR); 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_ = file_system; 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_FILE_SYSTEM_OPENED; 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_->OnOpenComplete(cdm::FileIOClient::kSuccess); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OpenFileForRead() { 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_READING); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(file_io_.is_null()); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(file_ref_.is_null()); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_io_ = pp::FileIO(pp_instance_handle_); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_ref_ = pp::FileRef(file_system_, file_name_.c_str()); 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Open file for read. If file doesn't exist, PP_ERROR_FILENOTFOUND will be 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // returned. 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t file_open_flag = PP_FILEOPENFLAG_READ; 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::CompletionCallback cb = 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_factory_.NewCallback(&CdmFileIOImpl::OnFileOpenedForRead); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_PP_OK_COMPLETIONPENDING(file_io_.Open(file_ref_, file_open_flag, cb), 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci READ_ERROR); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OnFileOpenedForRead(int32_t result) { 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CDM_DLOG() << __FUNCTION__ << ": " << result; 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_READING); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != PP_OK && result != PP_ERROR_FILENOTFOUND) { 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "File open failed."; 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(OPEN_ERROR); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // File doesn't exist. 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result == PP_ERROR_FILENOTFOUND) { 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Reset(); 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_FILE_SYSTEM_OPENED; 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_->OnReadComplete(cdm::FileIOClient::kSuccess, NULL, 0); 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReadFile(); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Call sequence: 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// fully read 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ReadFile() ---> OnFileRead() ------------> Done. 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ^ | 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// | partially read | 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |----------------| 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::ReadFile() { 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_READING); 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(!io_buffer_.empty()); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::CompletionCallback cb = 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_factory_.NewCallback(&CdmFileIOImpl::OnFileRead); 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_PP_OK_COMPLETIONPENDING( 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_io_.Read(io_offset_, &io_buffer_[0], io_buffer_.size(), cb), 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) READ_ERROR); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileRead(int32_t bytes_read) { 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__ << ": " << bytes_read; 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_READING); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 0 |bytes_read| indicates end-of-file reached. 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bytes_read < PP_OK) { 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << "Read file failed."; 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(READ_ERROR); 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(static_cast<size_t>(bytes_read) <= io_buffer_.size()); 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Append |bytes_read| in |io_buffer_| to |cumulative_read_buffer_|. 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cumulative_read_buffer_.insert(cumulative_read_buffer_.end(), 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.begin(), 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.begin() + bytes_read); 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_offset_ += bytes_read; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Not received end-of-file yet. Keep reading. 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bytes_read > 0) { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReadFile(); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We hit end-of-file. Return read data to the client. 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Clear |cumulative_read_buffer_| in case OnReadComplete() calls Read() or 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Write(). 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<char> local_buffer; 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::swap(cumulative_read_buffer_, local_buffer); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const uint8_t* data = local_buffer.empty() ? 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL : reinterpret_cast<const uint8_t*>(&local_buffer[0]); 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Call this before OnReadComplete() so that we always have the latest file 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // size before CDM fires errors. 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!first_file_read_reported_) { 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci first_file_read_cb_.Run(local_buffer.size()); 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci first_file_read_reported_ = true; 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Reset(); 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_FILE_SYSTEM_OPENED; 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnReadComplete( 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cdm::FileIOClient::kSuccess, data, local_buffer.size()); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OpenTempFileForWrite() { 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(file_name_.size() > 1 && file_name_[0] == '/'); 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Temporary file name format: /_<requested_file_name> 3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string temp_file_name = "/_" + file_name_.substr(1); 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(file_io_.is_null()); 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(file_ref_.is_null()); 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_io_ = pp::FileIO(pp_instance_handle_); 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_ref_ = pp::FileRef(file_system_, temp_file_name.c_str()); 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create the file if it doesn't exist. Truncate the file to length 0 if it 3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // exists. 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(xhwang): Find a good way to report to UMA cases where the temporary 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // file already exists (due to previous interruption or failure). 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t file_open_flag = PP_FILEOPENFLAG_WRITE | 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_FILEOPENFLAG_TRUNCATE | 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_FILEOPENFLAG_CREATE; 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::CompletionCallback cb = 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_factory_.NewCallback(&CdmFileIOImpl::OnTempFileOpenedForWrite); 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_PP_OK_COMPLETIONPENDING( 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_io_.Open(file_ref_, file_open_flag, cb), WRITE_ERROR); 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OnTempFileOpenedForWrite(int32_t result) { 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__ << ": " << result; 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != PP_OK) { 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CDM_DLOG() << "Open temporary file failed."; 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnError(WRITE_ERROR); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We were told to write 0 bytes (to clear the file). In this case, there's 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // no need to write anything. 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (io_buffer_.empty()) { 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenameTempFile(); 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(io_offset_ == 0); 4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci io_offset_ = 0; 4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WriteTempFile(); 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Call sequence: 4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// fully written 4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// WriteTempFile() -> OnTempFileWritten() ---------------> RenameTempFile(). 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ^ | 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// | partially written | 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |---------------------| 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::WriteTempFile() { 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(io_offset_ < io_buffer_.size()); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp::CompletionCallback cb = 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_factory_.NewCallback(&CdmFileIOImpl::OnTempFileWritten); 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_PP_OK_COMPLETIONPENDING(file_io_.Write(io_offset_, 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &io_buffer_[io_offset_], 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.size() - io_offset_, 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cb), 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WRITE_ERROR); 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OnTempFileWritten(int32_t bytes_written) { 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CDM_DLOG() << __FUNCTION__ << ": " << bytes_written; 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bytes_written <= PP_OK) { 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CDM_DLOG() << "Write temporary file failed."; 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnError(WRITE_ERROR); 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_offset_ += bytes_written; 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(io_offset_ <= io_buffer_.size()); 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (io_offset_ < io_buffer_.size()) { 4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WriteTempFile(); 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // All data written. Now rename the temporary file to the real file. 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenameTempFile(); 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::RenameTempFile() { 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::CompletionCallback cb = 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_factory_.NewCallback(&CdmFileIOImpl::OnTempFileRenamed); 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_PP_OK_COMPLETIONPENDING( 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_ref_.Rename(pp::FileRef(file_system_, file_name_.c_str()), cb), 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WRITE_ERROR); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::OnTempFileRenamed(int32_t result) { 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CDM_DLOG() << __FUNCTION__ << ": " << result; 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(IsMainThread()); 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(state_ == STATE_WRITING); 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != PP_OK) { 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CDM_DLOG() << "Rename temporary file failed."; 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_ERROR; 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnError(WRITE_ERROR); 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Reset(); 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = STATE_FILE_SYSTEM_OPENED; 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_->OnWriteComplete(cdm::FileIOClient::kSuccess); 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CdmFileIOImpl::Reset() { 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PP_DCHECK(IsMainThread()); 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_buffer_.clear(); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_offset_ = 0; 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cumulative_read_buffer_.clear(); 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_io_.Close(); 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_io_ = pp::FileIO(); 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_ref_ = pp::FileRef(); 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnError(ErrorType error_type) { 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For *_WHILE_IN_USE errors, do not reset these values. Otherwise, the 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // existing read/write operation will fail. 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error_type == READ_ERROR || error_type == WRITE_ERROR) 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Reset(); 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PostOnMain(callback_factory_.NewCallback(&CdmFileIOImpl::NotifyClientOfError, 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_type)); 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::NotifyClientOfError(int32_t result, 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ErrorType error_type) { 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_DCHECK(result == PP_OK); 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (error_type) { 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case OPEN_ERROR: 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnOpenComplete(cdm::FileIOClient::kError); 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case READ_ERROR: 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnReadComplete(cdm::FileIOClient::kError, NULL, 0); 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case WRITE_ERROR: 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnWriteComplete(cdm::FileIOClient::kError); 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case OPEN_WHILE_IN_USE: 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnOpenComplete(cdm::FileIOClient::kInUse); 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case READ_WHILE_IN_USE: 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnReadComplete(cdm::FileIOClient::kInUse, NULL, 0); 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case WRITE_WHILE_IN_USE: 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_->OnWriteComplete(cdm::FileIOClient::kInUse); 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace media 548