chromium/ppapi/proxy/url_request_info_resource.cc

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

#include "ppapi/proxy/url_request_info_resource.h"

#include "base/strings/string_number_conversions.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_file_ref_api.h"

namespace ppapi {
namespace proxy {

URLRequestInfoResource::URLRequestInfoResource(Connection connection,
                                               PP_Instance instance,
                                               const URLRequestInfoData& data)
    : PluginResource(connection, instance),
      data_(data) {
}

URLRequestInfoResource::~URLRequestInfoResource() {
}

thunk::PPB_URLRequestInfo_API*
URLRequestInfoResource::AsPPB_URLRequestInfo_API() {
  return this;
}

PP_Bool URLRequestInfoResource::SetProperty(PP_URLRequestProperty property,
                                            PP_Var var) {
  // IMPORTANT: Do not do security validation of parameters at this level
  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. This
  // code is used both in the plugin (which we don't trust) and in the renderer
  // (which we trust more). When running out-of-process, the plugin calls this
  // function to configure the URLRequestInfoData, which is then sent to
  // the renderer and *not* run through SetProperty again.
  //
  // This means that anything in the PPB_URLRequestInfo_Data needs to be
  // validated at the time the URL is requested (which is what ValidateData
  // does). If your feature requires security checks, it should be in the
  // implementation in the renderer when the WebKit request is actually
  // constructed.
  //
  // It is legal to do some validation here if you want to report failure to
  // the plugin as a convenience, as long as you also do it in the renderer
  // later.
  PP_Bool result = PP_FALSE;
  switch (var.type) {
    case PP_VARTYPE_UNDEFINED:
      result = PP_FromBool(SetUndefinedProperty(property));
      break;
    case PP_VARTYPE_BOOL:
      result = PP_FromBool(
          SetBooleanProperty(property, PP_ToBool(var.value.as_bool)));
      break;
    case PP_VARTYPE_INT32:
      result = PP_FromBool(
          SetIntegerProperty(property, var.value.as_int));
      break;
    case PP_VARTYPE_STRING: {
      StringVar* string = StringVar::FromPPVar(var);
      if (string)
        result = PP_FromBool(SetStringProperty(property, string->value()));
      break;
    }
    default:
      break;
  }
  if (!result) {
    std::string error_msg("PPB_URLRequestInfo.SetProperty: Attempted to set a "
                          "value for PP_URLRequestProperty ");
    error_msg += base::NumberToString(property);
    error_msg += ", but either this property type is invalid or its parameter "
                 "was inappropriate (e.g., the wrong type of PP_Var).";
    Log(PP_LOGLEVEL_ERROR, error_msg);
  }
  return result;
}

PP_Bool URLRequestInfoResource::AppendDataToBody(const void* data,
                                                 uint32_t len) {
  if (len > 0) {
    data_.body.push_back(URLRequestInfoData::BodyItem(
        std::string(static_cast<const char*>(data), len)));
  }
  return PP_TRUE;
}

PP_Bool URLRequestInfoResource::AppendFileToBody(
    PP_Resource file_ref,
    int64_t start_offset,
    int64_t number_of_bytes,
    PP_Time expected_last_modified_time) {
  thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
  if (enter.failed())
    return PP_FALSE;

  // Ignore a call to append nothing.
  if (number_of_bytes == 0)
    return PP_TRUE;

  // Check for bad values.  (-1 means read until end of file.)
  if (start_offset < 0 || number_of_bytes < -1)
    return PP_FALSE;

  data_.body.push_back(URLRequestInfoData::BodyItem(
      enter.resource(),
      start_offset,
      number_of_bytes,
      expected_last_modified_time));
  return PP_TRUE;
}

const URLRequestInfoData& URLRequestInfoResource::GetData() const {
  return data_;
}

bool URLRequestInfoResource::SetUndefinedProperty(
    PP_URLRequestProperty property) {
  // IMPORTANT: Do not do security validation of parameters at this level
  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
  // SetProperty() above for why.
  switch (property) {
    case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
      data_.has_custom_referrer_url = false;
      data_.custom_referrer_url = std::string();
      return true;
    case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
      data_.has_custom_content_transfer_encoding = false;
      data_.custom_content_transfer_encoding = std::string();
      return true;
    case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
      data_.has_custom_user_agent = false;
      data_.custom_user_agent = std::string();
      return true;
    default:
      return false;
  }
}

bool URLRequestInfoResource::SetBooleanProperty(
    PP_URLRequestProperty property,
    bool value) {
  // IMPORTANT: Do not do security validation of parameters at this level
  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
  // SetProperty() above for why.
  switch (property) {
    case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
      data_.follow_redirects = value;
      return true;
    case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
      data_.record_download_progress = value;
      return true;
    case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
      data_.record_upload_progress = value;
      return true;
    case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS:
      data_.allow_cross_origin_requests = value;
      return true;
    case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS:
      data_.allow_credentials = value;
      return true;
    default:
      return false;
  }
}

bool URLRequestInfoResource::SetIntegerProperty(
    PP_URLRequestProperty property,
    int32_t value) {
  // IMPORTANT: Do not do security validation of parameters at this level
  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
  // SetProperty() above for why.
  switch (property) {
    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
      data_.prefetch_buffer_upper_threshold = value;
      return true;
    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
      data_.prefetch_buffer_lower_threshold = value;
      return true;
    default:
      return false;
  }
}

bool URLRequestInfoResource::SetStringProperty(
    PP_URLRequestProperty property,
    const std::string& value) {
  // IMPORTANT: Do not do security validation of parameters at this level
  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
  // SetProperty() above for why.
  switch (property) {
    case PP_URLREQUESTPROPERTY_URL:
      data_.url = value;  // NOTE: This may be a relative URL.
      return true;
    case PP_URLREQUESTPROPERTY_METHOD:
      data_.method = value;
      return true;
    case PP_URLREQUESTPROPERTY_HEADERS:
      data_.headers = value;
      return true;
    case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
      data_.has_custom_referrer_url = true;
      data_.custom_referrer_url = value;
      return true;
    case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
      data_.has_custom_content_transfer_encoding = true;
      data_.custom_content_transfer_encoding = value;
      return true;
    case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
      data_.has_custom_user_agent = true;
      data_.custom_user_agent = value;
      return true;
    default:
      return false;
  }
}

}  // namespace proxy
}  // namespace ppapi