1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/proxy/url_request_info_resource.h"
6
7#include "ppapi/shared_impl/var.h"
8#include "ppapi/thunk/enter.h"
9#include "ppapi/thunk/ppb_file_ref_api.h"
10
11namespace ppapi {
12namespace proxy {
13
14URLRequestInfoResource::URLRequestInfoResource(Connection connection,
15                                               PP_Instance instance,
16                                               const URLRequestInfoData& data)
17    : PluginResource(connection, instance),
18      data_(data) {
19}
20
21URLRequestInfoResource::~URLRequestInfoResource() {
22}
23
24thunk::PPB_URLRequestInfo_API*
25URLRequestInfoResource::AsPPB_URLRequestInfo_API() {
26  return this;
27}
28
29PP_Bool URLRequestInfoResource::SetProperty(PP_URLRequestProperty property,
30                                            PP_Var var) {
31  // IMPORTANT: Do not do security validation of parameters at this level
32  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. This
33  // code is used both in the plugin (which we don't trust) and in the renderer
34  // (which we trust more). When running out-of-process, the plugin calls this
35  // function to configure the URLRequestInfoData, which is then sent to
36  // the renderer and *not* run through SetProperty again.
37  //
38  // This means that anything in the PPB_URLRequestInfo_Data needs to be
39  // validated at the time the URL is requested (which is what ValidateData
40  // does). If your feature requires security checks, it should be in the
41  // implementation in the renderer when the WebKit request is actually
42  // constructed.
43  //
44  // It is legal to do some validation here if you want to report failure to
45  // the plugin as a convenience, as long as you also do it in the renderer
46  // later.
47  PP_Bool result = PP_FALSE;
48  switch (var.type) {
49    case PP_VARTYPE_UNDEFINED:
50      result = PP_FromBool(SetUndefinedProperty(property));
51      break;
52    case PP_VARTYPE_BOOL:
53      result = PP_FromBool(
54          SetBooleanProperty(property, PP_ToBool(var.value.as_bool)));
55      break;
56    case PP_VARTYPE_INT32:
57      result = PP_FromBool(
58          SetIntegerProperty(property, var.value.as_int));
59      break;
60    case PP_VARTYPE_STRING: {
61      StringVar* string = StringVar::FromPPVar(var);
62      if (string)
63        result = PP_FromBool(SetStringProperty(property, string->value()));
64      break;
65    }
66    default:
67      break;
68  }
69  return result;
70}
71
72PP_Bool URLRequestInfoResource::AppendDataToBody(const void* data,
73                                                 uint32_t len) {
74  if (len > 0) {
75    data_.body.push_back(URLRequestInfoData::BodyItem(
76        std::string(static_cast<const char*>(data), len)));
77  }
78  return PP_TRUE;
79}
80
81PP_Bool URLRequestInfoResource::AppendFileToBody(
82    PP_Resource file_ref,
83    int64_t start_offset,
84    int64_t number_of_bytes,
85    PP_Time expected_last_modified_time) {
86  thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
87  if (enter.failed())
88    return PP_FALSE;
89
90  // Ignore a call to append nothing.
91  if (number_of_bytes == 0)
92    return PP_TRUE;
93
94  // Check for bad values.  (-1 means read until end of file.)
95  if (start_offset < 0 || number_of_bytes < -1)
96    return PP_FALSE;
97
98  data_.body.push_back(URLRequestInfoData::BodyItem(
99      enter.resource(),
100      start_offset,
101      number_of_bytes,
102      expected_last_modified_time));
103  return PP_TRUE;
104}
105
106const URLRequestInfoData& URLRequestInfoResource::GetData() const {
107  return data_;
108}
109
110bool URLRequestInfoResource::SetUndefinedProperty(
111    PP_URLRequestProperty property) {
112  // IMPORTANT: Do not do security validation of parameters at this level
113  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
114  // SetProperty() above for why.
115  switch (property) {
116    case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
117      data_.has_custom_referrer_url = false;
118      data_.custom_referrer_url = std::string();
119      return true;
120    case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
121      data_.has_custom_content_transfer_encoding = false;
122      data_.custom_content_transfer_encoding = std::string();
123      return true;
124    case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
125      data_.has_custom_user_agent = false;
126      data_.custom_user_agent = std::string();
127      return true;
128    default:
129      return false;
130  }
131}
132
133bool URLRequestInfoResource::SetBooleanProperty(
134    PP_URLRequestProperty property,
135    bool value) {
136  // IMPORTANT: Do not do security validation of parameters at this level
137  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
138  // SetProperty() above for why.
139  switch (property) {
140    case PP_URLREQUESTPROPERTY_STREAMTOFILE:
141      data_.stream_to_file = value;
142      return true;
143    case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
144      data_.follow_redirects = value;
145      return true;
146    case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
147      data_.record_download_progress = value;
148      return true;
149    case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
150      data_.record_upload_progress = value;
151      return true;
152    case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS:
153      data_.allow_cross_origin_requests = value;
154      return true;
155    case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS:
156      data_.allow_credentials = value;
157      return true;
158    default:
159      return false;
160  }
161}
162
163bool URLRequestInfoResource::SetIntegerProperty(
164    PP_URLRequestProperty property,
165    int32_t value) {
166  // IMPORTANT: Do not do security validation of parameters at this level
167  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
168  // SetProperty() above for why.
169  switch (property) {
170    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
171      data_.prefetch_buffer_upper_threshold = value;
172      return true;
173    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
174      data_.prefetch_buffer_lower_threshold = value;
175      return true;
176    default:
177      return false;
178  }
179}
180
181bool URLRequestInfoResource::SetStringProperty(
182    PP_URLRequestProperty property,
183    const std::string& value) {
184  // IMPORTANT: Do not do security validation of parameters at this level
185  // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
186  // SetProperty() above for why.
187  switch (property) {
188    case PP_URLREQUESTPROPERTY_URL:
189      data_.url = value;  // NOTE: This may be a relative URL.
190      return true;
191    case PP_URLREQUESTPROPERTY_METHOD:
192      data_.method = value;
193      return true;
194    case PP_URLREQUESTPROPERTY_HEADERS:
195      data_.headers = value;
196      return true;
197    case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
198      data_.has_custom_referrer_url = true;
199      data_.custom_referrer_url = value;
200      return true;
201    case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
202      data_.has_custom_content_transfer_encoding = true;
203      data_.custom_content_transfer_encoding = value;
204      return true;
205    case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
206      data_.has_custom_user_agent = true;
207      data_.custom_user_agent = value;
208      return true;
209    default:
210      return false;
211  }
212}
213
214}  // namespace proxy
215}  // namespace ppapi
216