blob: 157fc9c0ee18a318542f2a67e63a76f2222fd467 [file] [log] [blame]
[email protected]94af0572012-01-17 22:10:141// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]5826f3ea2010-06-24 19:43:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]20790a222013-07-25 02:23:055#include "content/renderer/pepper/url_request_info_util.h"
[email protected]5826f3ea2010-06-24 19:43:376
avi1023d012015-12-25 02:39:147#include <stddef.h>
8#include <stdint.h>
9
[email protected]5826f3ea2010-06-24 19:43:3710#include "base/logging.h"
[email protected]f63582d2013-06-11 22:52:5411#include "base/strings/string_util.h"
[email protected]354ce192014-03-25 21:35:0012#include "content/child/request_extra_data.h"
[email protected]4de8c3082013-07-29 23:26:5613#include "content/common/fileapi/file_system_messages.h"
[email protected]c6420f082013-09-18 22:42:4114#include "content/renderer/pepper/host_globals.h"
15#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
16#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
[email protected]20790a222013-07-25 02:23:0517#include "content/renderer/pepper/plugin_module.h"
[email protected]c6420f082013-09-18 22:42:4118#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
[email protected]4de8c3082013-07-29 23:26:5619#include "content/renderer/render_thread_impl.h"
[email protected]9731ede2010-07-15 05:56:2020#include "net/http/http_util.h"
[email protected]095162b2014-07-10 19:35:0521#include "ppapi/c/pp_bool.h"
22#include "ppapi/c/pp_var.h"
[email protected]c6420f082013-09-18 22:42:4123#include "ppapi/proxy/ppapi_messages.h"
[email protected]7b2f7292012-09-19 19:52:1224#include "ppapi/shared_impl/url_request_info_data.h"
[email protected]ce701cd2011-08-01 21:47:0425#include "ppapi/shared_impl/var.h"
[email protected]bf712f8e2011-06-17 02:10:4526#include "ppapi/thunk/enter.h"
[email protected]c10884462013-05-30 00:22:0927#include "third_party/WebKit/public/platform/WebData.h"
28#include "third_party/WebKit/public/platform/WebHTTPBody.h"
29#include "third_party/WebKit/public/platform/WebURL.h"
30#include "third_party/WebKit/public/platform/WebURLRequest.h"
[email protected]2255a9332013-06-17 05:12:3131#include "third_party/WebKit/public/web/WebDocument.h"
32#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]ad677772013-06-29 14:18:3833#include "url/gurl.h"
34#include "url/url_util.h"
[email protected]5826f3ea2010-06-24 19:43:3735
[email protected]76bf34a2013-09-05 23:36:1636using ppapi::Resource;
[email protected]c6420f082013-09-18 22:42:4137using ppapi::URLRequestInfoData;
[email protected]bf712f8e2011-06-17 02:10:4538using ppapi::thunk::EnterResourceNoLock;
[email protected]180ef242013-11-07 06:50:4639using blink::WebData;
40using blink::WebHTTPBody;
41using blink::WebString;
42using blink::WebFrame;
43using blink::WebURL;
44using blink::WebURLRequest;
[email protected]a0338652010-06-30 04:55:2945
[email protected]adab2332013-07-25 18:04:3246namespace content {
[email protected]5826f3ea2010-06-24 19:43:3747
48namespace {
49
[email protected]7b2f7292012-09-19 19:52:1250// Appends the file ref given the Resource pointer associated with it to the
51// given HTTP body, returning true on success.
[email protected]ad63b5c2014-04-11 21:12:3652bool AppendFileRefToBody(PP_Instance instance,
53 PP_Resource resource,
54 int64_t start_offset,
55 int64_t number_of_bytes,
56 PP_Time expected_last_modified_time,
57 WebHTTPBody* http_body) {
[email protected]76bf34a2013-09-05 23:36:1658 base::FilePath platform_path;
[email protected]c6420f082013-09-18 22:42:4159 PepperPluginInstanceImpl* instance_impl =
60 HostGlobals::Get()->GetInstance(instance);
61 if (!instance_impl)
62 return false;
63
64 RendererPpapiHost* renderer_ppapi_host =
65 instance_impl->module()->renderer_ppapi_host();
66 if (!renderer_ppapi_host)
67 return false;
68 ppapi::host::ResourceHost* resource_host =
69 renderer_ppapi_host->GetPpapiHost()->GetResourceHost(resource);
70 if (!resource_host || !resource_host->IsFileRefHost())
71 return false;
72 PepperFileRefRendererHost* file_ref_host =
73 static_cast<PepperFileRefRendererHost*>(resource_host);
74 switch (file_ref_host->GetFileSystemType()) {
[email protected]6f75c952011-08-26 04:51:0775 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
76 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
[email protected]2cd21072012-08-28 10:19:4577 // TODO(kinuko): remove this sync IPC when we fully support
78 // AppendURLRange for FileSystem URL.
[email protected]4de8c3082013-07-29 23:26:5679 RenderThreadImpl::current()->Send(
80 new FileSystemHostMsg_SyncGetPlatformPath(
[email protected]c6420f082013-09-18 22:42:4181 file_ref_host->GetFileSystemURL(), &platform_path));
[email protected]6f75c952011-08-26 04:51:0782 break;
83 case PP_FILESYSTEMTYPE_EXTERNAL:
[email protected]c6420f082013-09-18 22:42:4184 platform_path = file_ref_host->GetExternalFilePath();
[email protected]6f75c952011-08-26 04:51:0785 break;
86 default:
87 NOTREACHED();
88 }
[email protected]ad63b5c2014-04-11 21:12:3689 http_body->appendFileRange(platform_path.AsUTF16Unsafe(),
90 start_offset,
91 number_of_bytes,
92 expected_last_modified_time);
[email protected]6f75c952011-08-26 04:51:0793 return true;
94}
95
[email protected]7b2f7292012-09-19 19:52:1296// Checks that the request data is valid. Returns false on failure. Note that
97// method and header validation is done by the URL loader when the request is
98// opened, and any access errors are returned asynchronously.
[email protected]c6420f082013-09-18 22:42:4199bool ValidateURLRequestData(const URLRequestInfoData& data) {
[email protected]7b2f7292012-09-19 19:52:12100 if (data.prefetch_buffer_lower_threshold < 0 ||
101 data.prefetch_buffer_upper_threshold < 0 ||
102 data.prefetch_buffer_upper_threshold <=
[email protected]ad63b5c2014-04-11 21:12:36103 data.prefetch_buffer_lower_threshold) {
[email protected]7b2f7292012-09-19 19:52:12104 return false;
105 }
106 return true;
107}
108
[email protected]069c7b12014-08-20 19:23:20109std::string FilterStringForXRequestedWithValue(const std::string& s) {
110 std::string rv;
111 rv.reserve(s.length());
112 for (size_t i = 0; i < s.length(); i++) {
113 char c = s[i];
114 // Allow ASCII digits, letters, periods, commas, and underscores. (Ignore
115 // all other characters.)
116 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
117 (c >= 'a' && c <= 'z') || (c == '.') || (c == ',') || (c == '_'))
118 rv.push_back(c);
119 }
120 return rv;
121}
122
123// Returns an appropriate value for the X-Requested-With header for plugins that
124// present an X-Requested-With header. Returns a blank string for other plugins.
125// We produce a user-agent-like string (eating spaces and other undesired
126// characters) like "ShockwaveFlash/11.5.31.135" from the plugin name and
127// version.
128std::string MakeXRequestedWithValue(const std::string& name,
129 const std::string& version) {
130 std::string rv = FilterStringForXRequestedWithValue(name);
131 if (rv.empty())
132 return std::string();
133
134 // Apply to a narrow list of plugins only.
135 if (rv != "ShockwaveFlash" && rv != "PPAPITests")
136 return std::string();
137
138 std::string filtered_version = FilterStringForXRequestedWithValue(version);
139 if (!filtered_version.empty())
140 rv += "/" + filtered_version;
141
142 return rv;
143}
144
[email protected]7b2f7292012-09-19 19:52:12145} // namespace
146
[email protected]c6420f082013-09-18 22:42:41147bool CreateWebURLRequest(PP_Instance instance,
148 URLRequestInfoData* data,
[email protected]d0fef94d22013-08-05 18:26:16149 WebFrame* frame,
150 WebURLRequest* dest) {
[email protected]7b2f7292012-09-19 19:52:12151 // In the out-of-process case, we've received the URLRequestInfoData
152 // from the untrusted plugin and done no validation on it. We need to be
153 // sure it's not being malicious by checking everything for consistency.
[email protected]c6420f082013-09-18 22:42:41154 if (!ValidateURLRequestData(*data))
[email protected]d0fef94d22013-08-05 18:26:16155 return false;
[email protected]7b2f7292012-09-19 19:52:12156
[email protected]069c7b12014-08-20 19:23:20157 std::string name_version;
158
159 // Allow instance to be 0 or -1 for testing purposes.
160 if (instance && instance != -1) {
161 PepperPluginInstanceImpl* instance_impl =
162 HostGlobals::Get()->GetInstance(instance);
163 if (instance_impl) {
164 name_version = MakeXRequestedWithValue(
165 instance_impl->module()->name(),
166 instance_impl->module()->version());
167 }
168 } else {
169 name_version = "internal_testing_only";
170 }
171
[email protected]7b2f7292012-09-19 19:52:12172 dest->initialize();
[email protected]ad63b5c2014-04-11 21:12:36173 dest->setURL(frame->document().completeURL(WebString::fromUTF8(data->url)));
[email protected]7b2f7292012-09-19 19:52:12174 dest->setDownloadToFile(data->stream_to_file);
175 dest->setReportUploadProgress(data->record_upload_progress);
176
177 if (!data->method.empty())
178 dest->setHTTPMethod(WebString::fromUTF8(data->method));
179
180 dest->setFirstPartyForCookies(frame->document().firstPartyForCookies());
181
182 const std::string& headers = data->headers;
183 if (!headers.empty()) {
184 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n\r");
185 while (it.GetNext()) {
[email protected]ad63b5c2014-04-11 21:12:36186 dest->addHTTPHeaderField(WebString::fromUTF8(it.name()),
187 WebString::fromUTF8(it.values()));
[email protected]7b2f7292012-09-19 19:52:12188 }
189 }
190
191 // Append the upload data.
192 if (!data->body.empty()) {
193 WebHTTPBody http_body;
194 http_body.initialize();
[email protected]c6420f082013-09-18 22:42:41195 int file_index = 0;
[email protected]7b2f7292012-09-19 19:52:12196 for (size_t i = 0; i < data->body.size(); ++i) {
197 const URLRequestInfoData::BodyItem& item = data->body[i];
198 if (item.is_file) {
[email protected]c6420f082013-09-18 22:42:41199 if (!AppendFileRefToBody(instance,
200 item.file_ref_pp_resource,
[email protected]7b2f7292012-09-19 19:52:12201 item.start_offset,
202 item.number_of_bytes,
203 item.expected_last_modified_time,
[email protected]d0fef94d22013-08-05 18:26:16204 &http_body))
205 return false;
[email protected]c6420f082013-09-18 22:42:41206 file_index++;
[email protected]7b2f7292012-09-19 19:52:12207 } else {
208 DCHECK(!item.data.empty());
209 http_body.appendData(WebData(item.data));
210 }
211 }
212 dest->setHTTPBody(http_body);
213 }
214
215 // Add the "Referer" header if there is a custom referrer. Such requests
216 // require universal access. For all other requests, "Referer" will be set
217 // after header security checks are done in AssociatedURLLoader.
218 if (data->has_custom_referrer_url && !data->custom_referrer_url.empty())
219 frame->setReferrerForRequest(*dest, GURL(data->custom_referrer_url));
220
221 if (data->has_custom_content_transfer_encoding &&
222 !data->custom_content_transfer_encoding.empty()) {
223 dest->addHTTPHeaderField(
224 WebString::fromUTF8("Content-Transfer-Encoding"),
225 WebString::fromUTF8(data->custom_content_transfer_encoding));
226 }
227
[email protected]069c7b12014-08-20 19:23:20228 if (data->has_custom_user_agent || !name_version.empty()) {
[email protected]354ce192014-03-25 21:35:00229 RequestExtraData* extra_data = new RequestExtraData();
[email protected]069c7b12014-08-20 19:23:20230 if (data->has_custom_user_agent) {
231 extra_data->set_custom_user_agent(
232 WebString::fromUTF8(data->custom_user_agent));
233 }
234 if (!name_version.empty()) {
235 extra_data->set_requested_with(WebString::fromUTF8(name_version));
236 }
[email protected]354ce192014-03-25 21:35:00237 dest->setExtraData(extra_data);
[email protected]7b2f7292012-09-19 19:52:12238 }
[email protected]d0fef94d22013-08-05 18:26:16239
240 return true;
[email protected]7b2f7292012-09-19 19:52:12241}
242
[email protected]c6420f082013-09-18 22:42:41243bool URLRequestRequiresUniversalAccess(const URLRequestInfoData& data) {
[email protected]ad63b5c2014-04-11 21:12:36244 return data.has_custom_referrer_url ||
245 data.has_custom_content_transfer_encoding ||
246 data.has_custom_user_agent ||
sungmann.cho8a8db052014-09-24 01:59:25247 url::FindAndCompareScheme(data.url, url::kJavaScriptScheme, NULL);
[email protected]7b2f7292012-09-19 19:52:12248}
[email protected]6f75c952011-08-26 04:51:07249
[email protected]adab2332013-07-25 18:04:32250} // namespace content