cdm_file_io_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kReadSize = 4 * 1024;  // Arbitrary choice.
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call func_call and check the result. If the result is not
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// PP_OK_COMPLETIONPENDING, print out logs, call OnError() and return.
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHECK_PP_OK_COMPLETIONPENDING(func_call, error_type)            \
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  do {                                                                  \
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int32_t result = func_call;                                         \
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_DCHECK(result != PP_OK);                                         \
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result != PP_OK_COMPLETIONPENDING) {                            \
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CDM_DLOG() << #func_call << " failed with result: " << result;    \
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      OnError(error_type);                                              \
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;                                                           \
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }                                                                   \
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } while (0)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(NDEBUG)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// PPAPI calls should only be made on the main thread. In this file, main thread
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// checking is only performed in public APIs and the completion callbacks. This
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ensures all functions are running on the main thread since internal methods
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// are called either by the public APIs or by the completion callbacks.
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool IsMainThread() {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return pp::Module::Get()->core()->IsMainThread();
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(NDEBUG)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Posts a task to run |cb| on the main thread. The task is posted even if the
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// current thread is the main thread.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void PostOnMain(pp::CompletionCallback cb) {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::FileLockMap* CdmFileIOImpl::file_lock_map_ = NULL;
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::ResourceTracker::ResourceTracker() {
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Do nothing here since we lazy-initialize CdmFileIOImpl::file_lock_map_
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // in CdmFileIOImpl::AcquireFileLock().
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::ResourceTracker::~ResourceTracker() {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete CdmFileIOImpl::file_lock_map_;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::CdmFileIOImpl(cdm::FileIOClient* client, PP_Instance pp_instance)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : state_(FILE_UNOPENED),
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_(client),
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pp_instance_handle_(pp_instance),
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_(this),
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      io_offset_(0) {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(pp_instance);  // 0 indicates a "NULL handle".
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CdmFileIOImpl::~CdmFileIOImpl() {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == FILE_CLOSED);
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call sequence: Open() -> OpenFileSystem() -> OpenFile() -> FILE_OPENED.
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Open(const char* file_name, uint32_t file_name_size) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ != FILE_UNOPENED) {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Open() called in an invalid state.";
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(OPEN_ERROR);
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // File name should not contain any path separators.
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string file_name_str(file_name, file_name_size);
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (file_name_str.find('/') != std::string::npos ||
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_name_str.find('\\') != std::string::npos) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Invalid file name.";
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(OPEN_ERROR);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // pp::FileRef only accepts path that begins with a '/' character.
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_name_ = '/' + file_name_str;
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!AcquireFileLock()) {
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "File is in use by other cdm::FileIO objects.";
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(OPEN_WHILE_IN_USE);
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = OPENING_FILE_SYSTEM;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OpenFileSystem();
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call sequence:
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                                       finished
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Read() -> ReadFile() -> OnFileRead() ----------> Done.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//               ^              |
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//               | not finished |
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//               |--------------|
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Read() {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ == READING_FILE || state_ == WRITING_FILE) {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Read() called during pending read/write.";
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(READ_WHILE_IN_USE);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ != FILE_OPENED) {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Read() called in an invalid state.";
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(READ_ERROR);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(io_buffer_.empty());
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(cumulative_read_buffer_.empty());
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_buffer_.resize(kReadSize);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ = 0;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = READING_FILE;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReadFile();
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Call sequence:
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                                            finished
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Write() -> WriteFile() -> OnFileWritten() ----------> Done.
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                ^                  |
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                |                  | not finished
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                |------------------|
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Write(const uint8_t* data, uint32_t data_size) {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__;
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ == READING_FILE || state_ == WRITING_FILE) {
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Write() called during pending read/write.";
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(WRITE_WHILE_IN_USE);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ != FILE_OPENED) {
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Write() called in an invalid state.";
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(WRITE_ERROR);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(io_offset_ == 0);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(io_buffer_.empty());
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (data_size > 0)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    io_buffer_.assign(data, data + data_size);
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_DCHECK(!data);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = WRITING_FILE;
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Always SetLength() in case |data_size| is less than the file size.
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetLength(data_size);
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::Close() {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ != FILE_CLOSED);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CloseFile();
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReleaseFileLock();
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // All pending callbacks are canceled since |callback_factory_| is destroyed.
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete this;
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CdmFileIOImpl::SetFileID() {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(file_id_.empty());
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(!file_name_.empty() && file_name_[0] == '/');
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not taking ownership of |url_util_dev| (which is a singleton).
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const pp::URLUtil_Dev* url_util_dev = pp::URLUtil_Dev::Get();
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_URLComponents_Dev components;
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::Var url_var =
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      url_util_dev->GetDocumentURL(pp_instance_handle_, &components);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!url_var.is_string())
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string url = url_var.AsString();
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_.append(url, components.scheme.begin, components.scheme.len);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_ += ':';
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_.append(url, components.host.begin, components.host.len);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_ += ':';
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_.append(url, components.port.begin, components.port.len);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_id_ += file_name_;
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CdmFileIOImpl::AcquireFileLock() {
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (file_id_.empty() && !SetFileID())
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!file_lock_map_) {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    file_lock_map_ = new FileLockMap();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FileLockMap::iterator found = file_lock_map_->find(file_id_);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (found != file_lock_map_->end() && found->second)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  (*file_lock_map_)[file_id_] = true;
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::ReleaseFileLock() {
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!file_lock_map_)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileLockMap::iterator found = file_lock_map_->find(file_id_);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (found != file_lock_map_->end() && found->second)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    found->second = false;
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OpenFileSystem() {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == OPENING_FILE_SYSTEM);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallbackWithOutput<pp::FileSystem> cb =
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallbackWithOutput(
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &CdmFileIOImpl::OnFileSystemOpened);
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  isolated_file_system_ = pp::IsolatedFileSystemPrivate(
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pp_instance_handle_, PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE);
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_PP_OK_COMPLETIONPENDING(isolated_file_system_.Open(cb), OPEN_ERROR);
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileSystemOpened(int32_t result,
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       pp::FileSystem file_system) {
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == OPENING_FILE_SYSTEM);
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != PP_OK) {
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "File system open failed asynchronously.";
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ReleaseFileLock();
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(OPEN_ERROR);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_system_ = file_system;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = OPENING_FILE;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OpenFile();
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OpenFile() {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == OPENING_FILE);
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_io_ = pp::FileIO(pp_instance_handle_);
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_ref_ = pp::FileRef(file_system_, file_name_.c_str());
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32_t file_open_flag = PP_FILEOPENFLAG_READ |
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           PP_FILEOPENFLAG_WRITE |
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           PP_FILEOPENFLAG_CREATE;
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallback cb =
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallback(&CdmFileIOImpl::OnFileOpened);
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_PP_OK_COMPLETIONPENDING(file_io_.Open(file_ref_, file_open_flag, cb),
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                OPEN_ERROR);
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileOpened(int32_t result) {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == OPENING_FILE);
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != PP_OK) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "File open failed.";
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ReleaseFileLock();
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(OPEN_ERROR);
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = FILE_OPENED;
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  client_->OnOpenComplete(cdm::FileIOClient::kSuccess);
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::ReadFile() {
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == READING_FILE);
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(!io_buffer_.empty());
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallback cb =
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallback(&CdmFileIOImpl::OnFileRead);
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_PP_OK_COMPLETIONPENDING(
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_io_.Read(io_offset_, &io_buffer_[0], io_buffer_.size(), cb),
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      READ_ERROR);
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileRead(int32_t bytes_read) {
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__ << ": " << bytes_read;
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == READING_FILE);
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 0 |bytes_read| indicates end-of-file reached.
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (bytes_read < PP_OK) {
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Read file failed.";
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(READ_ERROR);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(static_cast<size_t>(bytes_read) <= io_buffer_.size());
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Append |bytes_read| in |io_buffer_| to |cumulative_read_buffer_|.
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cumulative_read_buffer_.insert(cumulative_read_buffer_.end(),
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 io_buffer_.begin(),
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 io_buffer_.begin() + bytes_read);
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ += bytes_read;
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not received end-of-file yet.
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (bytes_read > 0) {
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ReadFile();
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We hit end-of-file. Return read data to the client.
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_buffer_.clear();
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ = 0;
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clear |cumulative_read_buffer_| in case OnReadComplete() calls Read() or
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Write().
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<char> local_buffer;
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::swap(cumulative_read_buffer_, local_buffer);
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = FILE_OPENED;
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint8_t* data = local_buffer.empty() ?
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL : reinterpret_cast<const uint8_t*>(&local_buffer[0]);
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  client_->OnReadComplete(
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cdm::FileIOClient::kSuccess, data, local_buffer.size());
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::SetLength(uint32_t length) {
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == WRITING_FILE);
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallback cb =
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallback(&CdmFileIOImpl::OnLengthSet);
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_PP_OK_COMPLETIONPENDING(file_io_.SetLength(length, cb), WRITE_ERROR);
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnLengthSet(int32_t result) {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__ << ": " << result;
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == WRITING_FILE);
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != PP_OK) {
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "File SetLength failed.";
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(WRITE_ERROR);
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (io_buffer_.empty()) {
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state_ = FILE_OPENED;
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    client_->OnWriteComplete(cdm::FileIOClient::kSuccess);
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WriteFile();
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::WriteFile() {
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == WRITING_FILE);
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(io_offset_ < io_buffer_.size());
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallback cb =
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_factory_.NewCallback(&CdmFileIOImpl::OnFileWritten);
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK_PP_OK_COMPLETIONPENDING(file_io_.Write(io_offset_,
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &io_buffer_[io_offset_],
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               io_buffer_.size() - io_offset_,
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               cb),
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                WRITE_ERROR);
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnFileWritten(int32_t bytes_written) {
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CDM_DLOG() << __FUNCTION__ << ": " << bytes_written;
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(state_ == WRITING_FILE);
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (bytes_written <= PP_OK) {
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CDM_DLOG() << "Write file failed.";
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnError(READ_ERROR);
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ += bytes_written;
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(io_offset_ <= io_buffer_.size());
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (io_offset_ < io_buffer_.size()) {
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WriteFile();
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_buffer_.clear();
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ = 0;
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = FILE_OPENED;
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  client_->OnWriteComplete(cdm::FileIOClient::kSuccess);
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::CloseFile() {
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(IsMainThread());
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state_ = FILE_CLOSED;
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_io_.Close();
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_buffer_.clear();
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_offset_ = 0;
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cumulative_read_buffer_.clear();
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::OnError(ErrorType error_type) {
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For *_WHILE_IN_USE errors, do not reset these values. Otherwise, the
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // existing read/write operation will fail.
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error_type == READ_ERROR || error_type == WRITE_ERROR) {
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    io_buffer_.clear();
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    io_offset_ = 0;
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cumulative_read_buffer_.clear();
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PostOnMain(callback_factory_.NewCallback(&CdmFileIOImpl::NotifyClientOfError,
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           error_type));
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CdmFileIOImpl::NotifyClientOfError(int32_t result,
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        ErrorType error_type) {
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_DCHECK(result == PP_OK);
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (error_type) {
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case OPEN_ERROR:
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnOpenComplete(cdm::FileIOClient::kError);
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case READ_ERROR:
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnReadComplete(cdm::FileIOClient::kError, NULL, 0);
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WRITE_ERROR:
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnWriteComplete(cdm::FileIOClient::kError);
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case OPEN_WHILE_IN_USE:
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnOpenComplete(cdm::FileIOClient::kInUse);
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case READ_WHILE_IN_USE:
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnReadComplete(cdm::FileIOClient::kInUse, NULL, 0);
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WRITE_WHILE_IN_USE:
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      client_->OnWriteComplete(cdm::FileIOClient::kInUse);
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace media
458