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