// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO : Support NP_ASFILEONLY mode
// TODO : Support NP_SEEK mode
// TODO : Support SEEKABLE=true in NewStream

#include "content/child/npapi/plugin_stream.h"

#include <algorithm>

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/npapi/plugin_instance.h"
#include "net/base/mime_util.h"
#include "url/gurl.h"

namespace content {

PluginStream::PluginStream(
    PluginInstance* instance,
    const char* url,
    bool need_notify,
    void* notify_data)
    : instance_(instance),
      notify_needed_(need_notify),
      notify_data_(notify_data),
      close_on_write_data_(false),
      requested_plugin_mode_(NP_NORMAL),
      opened_(false),
      data_offset_(0),
      seekable_stream_(false) {
  memset(&stream_, 0, sizeof(stream_));
  stream_.url = base::strdup(url);
  ResetTempFileHandle();
  ResetTempFileName();
}

PluginStream::~PluginStream() {
  // always close our temporary files.
  CloseTempFile();
  free(const_cast<char*>(stream_.url));
}

bool PluginStream::Open(const std::string& mime_type,
                        const std::string& headers,
                        uint32 length,
                        uint32 last_modified,
                        bool request_is_seekable) {
  headers_ = headers;
  NPP id = instance_->npp();
  stream_.end = length;
  stream_.lastmodified = last_modified;
  stream_.pdata = 0;
  stream_.ndata = id->ndata;
  stream_.notifyData = notify_data_;
  if (!headers_.empty())
    stream_.headers = headers_.c_str();

  bool seekable_stream = false;
  if (request_is_seekable) {
    std::string headers_lc = base::StringToLowerASCII(headers);
    if (headers_lc.find("accept-ranges: bytes") != std::string::npos) {
      seekable_stream = true;
    }
  }

  const char* char_mime_type = "application/x-unknown-content-type";
  std::string temp_mime_type;
  if (!mime_type.empty()) {
    char_mime_type = mime_type.c_str();
  } else {
    GURL gurl(stream_.url);

    base::FilePath path = base::FilePath::FromUTF8Unsafe(gurl.path());
    if (net::GetMimeTypeFromFile(path, &temp_mime_type))
      char_mime_type = temp_mime_type.c_str();
  }

  // Silverlight expects a valid mime type
  DCHECK_NE(0U, strlen(char_mime_type));
  NPError err = instance_->NPP_NewStream((NPMIMEType)char_mime_type,
                                         &stream_, seekable_stream,
                                         &requested_plugin_mode_);
  if (err != NPERR_NO_ERROR) {
    Notify(err);
    return false;
  }

  opened_ = true;

  if (requested_plugin_mode_ == NP_SEEK) {
    seekable_stream_ = true;
  }
  // If the plugin has requested certain modes, then we need a copy
  // of this file on disk.  Open it and save it as we go.
  if (RequestedPluginModeIsAsFile()) {
    if (OpenTempFile() == false) {
      return false;
    }
  }

  mime_type_ = char_mime_type;
  return true;
}

int PluginStream::Write(const char* buffer, const int length,
                        int data_offset) {
  // There may be two streams to write to - the plugin and the file.
  // It is unclear what to do if we cannot write to both.  The rules of
  // this function are that the plugin must consume at least as many
  // bytes as returned by the WriteReady call.  So, we will attempt to
  // write that many to both streams.  If we can't write that many bytes
  // to each stream, we'll return failure.

  DCHECK(opened_);
  if (WriteToFile(buffer, length) &&
      WriteToPlugin(buffer, length, data_offset)) {
    return length;
  }

  return -1;
}

bool PluginStream::WriteToFile(const char* buf, size_t length) {
  // For ASFILEONLY, ASFILE, and SEEK modes, we need to write
  // to the disk
  if (TempFileIsValid() && RequestedPluginModeIsAsFile()) {
    size_t totalBytesWritten = 0, bytes;
    do {
      bytes = WriteBytes(buf, length);
      totalBytesWritten += bytes;
    } while (bytes > 0U && totalBytesWritten < length);

    if (totalBytesWritten != length) {
      return false;
    }
  }

  return true;
}

bool PluginStream::WriteToPlugin(const char* buf, const int length,
                                 const int data_offset) {
  // For NORMAL and ASFILE modes, we send the data to the plugin now
  if (requested_plugin_mode_ != NP_NORMAL &&
      requested_plugin_mode_ != NP_ASFILE &&
      requested_plugin_mode_ != NP_SEEK) {
    return true;
  }

  int written = TryWriteToPlugin(buf, length, data_offset);
  if (written == -1)
    return false;

  if (written < length) {
    // Buffer the remaining data.
    size_t remaining = length - written;
    size_t previous_size = delivery_data_.size();
    delivery_data_.resize(previous_size + remaining);
    data_offset_ = data_offset;
    memcpy(&delivery_data_[previous_size], buf + written, remaining);
    base::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(&PluginStream::OnDelayDelivery, this));
  }

  return true;
}

void PluginStream::OnDelayDelivery() {
  // It is possible that the plugin stream may have closed before the task
  // was hit.
  if (!opened_)
    return;

  int size = static_cast<int>(delivery_data_.size());
  int written = TryWriteToPlugin(&delivery_data_.front(), size, data_offset_);
  if (written > 0) {
    // Remove the data that we already wrote.
    delivery_data_.erase(delivery_data_.begin(),
                         delivery_data_.begin() + written);
  }
}

int PluginStream::TryWriteToPlugin(const char* buf, const int length,
                                   const int data_offset) {
  int byte_offset = 0;

  if (data_offset > 0)
    data_offset_ = data_offset;

  while (byte_offset < length) {
    int bytes_remaining = length - byte_offset;
    int bytes_to_write = instance_->NPP_WriteReady(&stream_);
    if (bytes_to_write > bytes_remaining)
      bytes_to_write = bytes_remaining;

    if (bytes_to_write == 0)
      return byte_offset;

    int bytes_consumed = instance_->NPP_Write(
        &stream_, data_offset_, bytes_to_write,
        const_cast<char*>(buf + byte_offset));
    if (bytes_consumed < 0) {
      // The plugin failed, which means that we need to close the stream.
      Close(NPRES_NETWORK_ERR);
      return -1;
    }
    if (bytes_consumed == 0) {
      // The plugin couldn't take all of the data now.
      return byte_offset;
    }

    // The plugin might report more that we gave it.
    bytes_consumed = std::min(bytes_consumed, bytes_to_write);

    data_offset_ += bytes_consumed;
    byte_offset += bytes_consumed;
  }

  if (close_on_write_data_)
    Close(NPRES_DONE);

  return length;
}

bool PluginStream::Close(NPReason reason) {
  if (opened_ == true) {
    opened_ = false;

    if (delivery_data_.size()) {
      if (reason == NPRES_DONE) {
        // There is more data to be streamed, don't destroy the stream now.
        close_on_write_data_ = true;
        return true;
      } else {
        // Stop any pending data from being streamed
        delivery_data_.resize(0);
      }
    }

    // If we have a temp file, be sure to close it.
    // Also, allow the plugin to access it now.
    if (TempFileIsValid()) {
      CloseTempFile();
      if (reason == NPRES_DONE)
        WriteAsFile();
    }

    if (stream_.ndata != NULL) {
      // Stream hasn't been closed yet.
      NPError err = instance_->NPP_DestroyStream(&stream_, reason);
      DCHECK(err == NPERR_NO_ERROR);
    }
  }

  Notify(reason);
  return true;
}

WebPluginResourceClient* PluginStream::AsResourceClient() {
  return NULL;
}

void PluginStream::Notify(NPReason reason) {
  if (notify_needed_) {
    instance_->NPP_URLNotify(stream_.url, reason, notify_data_);
    notify_needed_ = false;
  }
}

bool PluginStream::RequestedPluginModeIsAsFile() const {
  return (requested_plugin_mode_ == NP_ASFILE ||
          requested_plugin_mode_ == NP_ASFILEONLY);
}

}  // namespace content
