NPError
BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
{
  PLUGIN_LOG_DEBUG_FUNCTION;

  AssertPluginThread();

  if (ALIVE != mState || kStreamOpen != mStreamStatus)
    return NPERR_GENERIC_ERROR;

  IPCByteRanges ranges;
  for (; aRangeList; aRangeList = aRangeList->next) {
    IPCByteRange br = {aRangeList->offset, aRangeList->length};
    ranges.push_back(br);
  }

  NPError result;
  CallNPN_RequestRead(ranges, &result);
  return result;
}
mozilla::ipc::IPCResult
BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
                                           NPError* result)
{
  PLUGIN_LOG_DEBUG_FUNCTION;

  switch (mState) {
  case INITIALIZING:
    NS_ERROR("Requesting a read before initialization has completed");
    *result = NPERR_GENERIC_ERROR;
    return IPC_FAIL_NO_REASON(this);

  case ALIVE:
    break;

  case DYING:
    *result = NPERR_GENERIC_ERROR;
    return IPC_OK();

  default:
    NS_ERROR("Unexpected state");
    return IPC_FAIL_NO_REASON(this);
  }

  if (!mStream)
    return IPC_FAIL_NO_REASON(this);

  if (ranges.Length() > INT32_MAX)
    return IPC_FAIL_NO_REASON(this);

  UniquePtr<NPByteRange[]> rp(new NPByteRange[ranges.Length()]);
  for (uint32_t i = 0; i < ranges.Length(); ++i) {
    rp[i].offset = ranges[i].offset;
    rp[i].length = ranges[i].length;
    rp[i].next = &rp[i + 1];
  }
  rp[ranges.Length() - 1].next = nullptr;

  *result = mNPP->mNPNIface->requestread(mStream, rp.get());
  return IPC_OK();
}
bool
BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
                                           NPError* result)
{
  PLUGIN_LOG_DEBUG_FUNCTION;

  switch (mState) {
  case INITIALIZING:
    NS_ERROR("Requesting a read before initialization has completed");
    *result = NPERR_GENERIC_ERROR;
    return false;

  case ALIVE:
    break;

  case DYING:
    *result = NPERR_GENERIC_ERROR;
    return true;

  default:
    NS_ERROR("Unexpected state");
    return false;
  }

  if (!mStream)
    return false;

  if (ranges.Length() > INT32_MAX)
    return false;

  nsAutoArrayPtr<NPByteRange> rp(new NPByteRange[ranges.Length()]);
  for (uint32_t i = 0; i < ranges.Length(); ++i) {
    rp[i].offset = ranges[i].offset;
    rp[i].length = ranges[i].length;
    rp[i].next = &rp[i + 1];
  }
  rp[ranges.Length() - 1].next = nullptr;

  *result = mNPP->mNPNIface->requestread(mStream, rp);
  return true;
}