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.
5 #include "ppapi/tests/test_url_loader.h"
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/c/ppb_file_io.h"
13 #include "ppapi/c/ppb_url_loader.h"
14 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
15 #include "ppapi/cpp/dev/url_util_dev.h"
16 #include "ppapi/cpp/file_io.h"
17 #include "ppapi/cpp/file_ref.h"
18 #include "ppapi/cpp/file_system.h"
19 #include "ppapi/cpp/instance.h"
20 #include "ppapi/cpp/module.h"
21 #include "ppapi/cpp/private/file_io_private.h"
22 #include "ppapi/cpp/url_loader.h"
23 #include "ppapi/cpp/url_request_info.h"
24 #include "ppapi/cpp/url_response_info.h"
25 #include "ppapi/tests/test_utils.h"
26 #include "ppapi/tests/testing_instance.h"
28 REGISTER_TEST_CASE(URLLoader
);
32 int32_t WriteEntireBuffer(PP_Instance instance
,
35 const std::string
& data
,
36 CallbackType callback_type
) {
37 TestCompletionCallback
callback(instance
, callback_type
);
38 int32_t write_offset
= offset
;
39 const char* buf
= data
.c_str();
40 int32_t size
= data
.size();
42 while (write_offset
< offset
+ size
) {
43 callback
.WaitForResult(file_io
->Write(write_offset
,
44 &buf
[write_offset
- offset
],
45 size
- write_offset
+ offset
,
46 callback
.GetCallback()));
47 if (callback
.result() < 0)
48 return callback
.result();
49 if (callback
.result() == 0)
50 return PP_ERROR_FAILED
;
51 write_offset
+= callback
.result();
59 TestURLLoader::TestURLLoader(TestingInstance
* instance
)
61 file_io_private_interface_(NULL
),
62 url_loader_trusted_interface_(NULL
) {
65 bool TestURLLoader::Init() {
66 if (!CheckTestingInterface()) {
67 instance_
->AppendError("Testing interface not available");
71 const PPB_FileIO
* file_io_interface
= static_cast<const PPB_FileIO
*>(
72 pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_INTERFACE
));
73 if (!file_io_interface
)
74 instance_
->AppendError("FileIO interface not available");
76 file_io_private_interface_
= static_cast<const PPB_FileIO_Private
*>(
77 pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_PRIVATE_INTERFACE
));
78 if (!file_io_private_interface_
)
79 instance_
->AppendError("FileIO_Private interface not available");
80 url_loader_trusted_interface_
= static_cast<const PPB_URLLoaderTrusted
*>(
81 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE
));
82 if (!testing_interface_
->IsOutOfProcess()) {
83 // Trusted interfaces are not supported under NaCl.
84 #if !(defined __native_client__)
85 if (!url_loader_trusted_interface_
)
86 instance_
->AppendError("URLLoaderTrusted interface not available");
88 if (url_loader_trusted_interface_
)
89 instance_
->AppendError("URLLoaderTrusted interface is supported by NaCl");
92 return EnsureRunningOverHTTP();
96 * The test order is important here, as running tests out of order may cause
99 * Here is the environment:
101 * 1. TestServer.py only accepts one open connection at the time.
102 * 2. HTTP socket pool keeps sockets open for several seconds after last use
103 * (hoping that there will be another request that could reuse the connection).
104 * 3. HTTP socket pool is separated by host/port and privacy mode (which is
105 * based on cookies set/get permissions). So, connections to 127.0.0.1,
106 * localhost and localhost in privacy mode cannot reuse existing socket and will
107 * try to open another connection.
109 * Here is the problem:
111 * Original test order was repeatedly accessing 127.0.0.1, localhost and
112 * localhost in privacy mode, causing new sockets to open and try to connect to
113 * testserver, which they couldn't until previous connection is closed by socket
114 * pool idle socket timeout (10 seconds).
116 * Because of this the test run was taking around 45 seconds, and test was
117 * reported as 'timed out' by trybot.
119 * Re-ordering of tests provides more sequential access to 127.0.0.1, localhost
120 * and localhost in privacy mode. It decreases the number of times when socket
121 * pool doesn't have existing connection to host and has to wait, therefore
122 * reducing total test time and ensuring its completion under 30 seconds.
124 void TestURLLoader::RunTests(const std::string
& filter
) {
125 // These tests connect to 127.0.0.1:
126 RUN_CALLBACK_TEST(TestURLLoader
, BasicGET
, filter
);
127 RUN_CALLBACK_TEST(TestURLLoader
, BasicPOST
, filter
);
128 RUN_CALLBACK_TEST(TestURLLoader
, BasicFilePOST
, filter
);
129 RUN_CALLBACK_TEST(TestURLLoader
, BasicFileRangePOST
, filter
);
130 RUN_CALLBACK_TEST(TestURLLoader
, CompoundBodyPOST
, filter
);
131 RUN_CALLBACK_TEST(TestURLLoader
, EmptyDataPOST
, filter
);
132 RUN_CALLBACK_TEST(TestURLLoader
, BinaryDataPOST
, filter
);
133 RUN_CALLBACK_TEST(TestURLLoader
, CustomRequestHeader
, filter
);
134 RUN_CALLBACK_TEST(TestURLLoader
, FailsBogusContentLength
, filter
);
135 RUN_CALLBACK_TEST(TestURLLoader
, StreamToFile
, filter
);
136 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedJavascriptURLRestriction
, filter
);
137 RUN_CALLBACK_TEST(TestURLLoader
, TrustedJavascriptURLRestriction
, filter
);
138 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedHttpRequests
, filter
);
139 RUN_CALLBACK_TEST(TestURLLoader
, TrustedHttpRequests
, filter
);
140 RUN_CALLBACK_TEST(TestURLLoader
, FollowURLRedirect
, filter
);
141 RUN_CALLBACK_TEST(TestURLLoader
, AuditURLRedirect
, filter
);
142 RUN_CALLBACK_TEST(TestURLLoader
, AbortCalls
, filter
);
143 RUN_CALLBACK_TEST(TestURLLoader
, UntendedLoad
, filter
);
144 RUN_CALLBACK_TEST(TestURLLoader
, PrefetchBufferThreshold
, filter
);
145 RUN_CALLBACK_TEST(TestURLLoader
, XRequestedWithHeader
, filter
);
146 // These tests connect to localhost with privacy mode enabled:
147 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedSameOriginRestriction
, filter
);
148 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedCrossOriginRequest
, filter
);
149 // These tests connect to localhost with privacy mode disabled:
150 RUN_CALLBACK_TEST(TestURLLoader
, TrustedSameOriginRestriction
, filter
);
151 RUN_CALLBACK_TEST(TestURLLoader
, TrustedCrossOriginRequest
, filter
);
154 std::string
TestURLLoader::ReadEntireFile(pp::FileIO
* file_io
,
156 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
161 callback
.WaitForResult(file_io
->Read(offset
, buf
, sizeof(buf
),
162 callback
.GetCallback()));
163 if (callback
.result() < 0)
164 return ReportError("FileIO::Read", callback
.result());
165 if (callback
.result() == 0)
167 offset
+= callback
.result();
168 data
->append(buf
, callback
.result());
174 std::string
TestURLLoader::ReadEntireResponseBody(pp::URLLoader
* loader
,
176 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
177 char buf
[2]; // Small so that multiple reads are needed.
180 callback
.WaitForResult(
181 loader
->ReadResponseBody(buf
, sizeof(buf
), callback
.GetCallback()));
182 if (callback
.result() < 0)
183 return ReportError("URLLoader::ReadResponseBody", callback
.result());
184 if (callback
.result() == 0)
186 body
->append(buf
, callback
.result());
192 std::string
TestURLLoader::LoadAndCompareBody(
193 const pp::URLRequestInfo
& request
,
194 const std::string
& expected_body
) {
195 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
197 pp::URLLoader
loader(instance_
);
198 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
199 CHECK_CALLBACK_BEHAVIOR(callback
);
200 ASSERT_EQ(PP_OK
, callback
.result());
202 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
203 if (response_info
.is_null())
204 return "URLLoader::GetResponseInfo returned null";
205 int32_t status_code
= response_info
.GetStatusCode();
206 if (status_code
!= 200)
207 return "Unexpected HTTP status code";
210 std::string error
= ReadEntireResponseBody(&loader
, &body
);
214 if (body
.size() != expected_body
.size())
215 return "URLLoader::ReadResponseBody returned unexpected content length";
216 if (body
!= expected_body
)
217 return "URLLoader::ReadResponseBody returned unexpected content";
222 int32_t TestURLLoader::OpenFileSystem(pp::FileSystem
* file_system
,
223 std::string
* message
) {
224 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
225 callback
.WaitForResult(file_system
->Open(1024, callback
.GetCallback()));
226 if (callback
.failed()) {
227 message
->assign(callback
.errors());
228 return callback
.result();
230 if (callback
.result() != PP_OK
) {
231 message
->assign("FileSystem::Open");
232 return callback
.result();
234 return callback
.result();
237 int32_t TestURLLoader::PrepareFileForPost(
238 const pp::FileRef
& file_ref
,
239 const std::string
& data
,
240 std::string
* message
) {
241 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
242 pp::FileIO
file_io(instance_
);
243 callback
.WaitForResult(file_io
.Open(file_ref
,
244 PP_FILEOPENFLAG_CREATE
|
245 PP_FILEOPENFLAG_TRUNCATE
|
246 PP_FILEOPENFLAG_WRITE
,
247 callback
.GetCallback()));
248 if (callback
.failed()) {
249 message
->assign(callback
.errors());
250 return callback
.result();
252 if (callback
.result() != PP_OK
) {
253 message
->assign("FileIO::Open failed.");
254 return callback
.result();
257 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0, data
,
260 message
->assign("FileIO::Write failed.");
267 std::string
TestURLLoader::GetReachableAbsoluteURL(
268 const std::string
& file_name
) {
269 // Get the absolute page URL and replace the test case file name
270 // with the given one.
271 pp::Var
document_url(
273 testing_interface_
->GetDocumentURL(instance_
->pp_instance(),
275 std::string
url(document_url
.AsString());
276 std::string
old_name("test_case.html");
277 size_t index
= url
.find(old_name
);
278 ASSERT_NE(index
, std::string::npos
);
279 url
.replace(index
, old_name
.length(), file_name
);
283 std::string
TestURLLoader::GetReachableCrossOriginURL(
284 const std::string
& file_name
) {
285 // Get an absolute URL and use it to construct a URL that will be
286 // considered cross-origin by the CORS access control code, and yet be
287 // reachable by the test server.
288 std::string url
= GetReachableAbsoluteURL(file_name
);
289 // Replace '127.0.0.1' with 'localhost'.
290 std::string
host("127.0.0.1");
291 size_t index
= url
.find(host
);
292 ASSERT_NE(index
, std::string::npos
);
293 url
.replace(index
, host
.length(), "localhost");
297 int32_t TestURLLoader::OpenUntrusted(const std::string
& method
,
298 const std::string
& header
) {
299 pp::URLRequestInfo
request(instance_
);
300 request
.SetURL("/echo");
301 request
.SetMethod(method
);
302 request
.SetHeaders(header
);
304 return OpenUntrusted(request
);
307 int32_t TestURLLoader::OpenTrusted(const std::string
& method
,
308 const std::string
& header
) {
309 pp::URLRequestInfo
request(instance_
);
310 request
.SetURL("/echo");
311 request
.SetMethod(method
);
312 request
.SetHeaders(header
);
314 return OpenTrusted(request
);
317 int32_t TestURLLoader::OpenUntrusted(const pp::URLRequestInfo
& request
) {
318 return Open(request
, false);
321 int32_t TestURLLoader::OpenTrusted(const pp::URLRequestInfo
& request
) {
322 return Open(request
, true);
325 int32_t TestURLLoader::Open(const pp::URLRequestInfo
& request
,
327 pp::URLLoader
loader(instance_
);
329 url_loader_trusted_interface_
->GrantUniversalAccess(loader
.pp_resource());
330 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
331 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
332 return callback
.result();
335 std::string
TestURLLoader::TestBasicGET() {
336 pp::URLRequestInfo
request(instance_
);
337 request
.SetURL("test_url_loader_data/hello.txt");
338 return LoadAndCompareBody(request
, "hello\n");
341 std::string
TestURLLoader::TestBasicPOST() {
342 pp::URLRequestInfo
request(instance_
);
343 request
.SetURL("/echo");
344 request
.SetMethod("POST");
345 std::string
postdata("postdata");
346 request
.AppendDataToBody(postdata
.data(), postdata
.length());
347 return LoadAndCompareBody(request
, postdata
);
350 std::string
TestURLLoader::TestBasicFilePOST() {
353 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
354 int32_t rv
= OpenFileSystem(&file_system
, &message
);
356 return ReportError(message
.c_str(), rv
);
358 pp::FileRef
file_ref(file_system
, "/file_post_test");
359 std::string
postdata("postdata");
360 rv
= PrepareFileForPost(file_ref
, postdata
, &message
);
362 return ReportError(message
.c_str(), rv
);
364 pp::URLRequestInfo
request(instance_
);
365 request
.SetURL("/echo");
366 request
.SetMethod("POST");
367 request
.AppendFileToBody(file_ref
, 0);
368 return LoadAndCompareBody(request
, postdata
);
371 std::string
TestURLLoader::TestBasicFileRangePOST() {
374 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
375 int32_t rv
= OpenFileSystem(&file_system
, &message
);
377 return ReportError(message
.c_str(), rv
);
379 pp::FileRef
file_ref(file_system
, "/file_range_post_test");
380 std::string
postdata("postdatapostdata");
381 rv
= PrepareFileForPost(file_ref
, postdata
, &message
);
383 return ReportError(message
.c_str(), rv
);
385 pp::URLRequestInfo
request(instance_
);
386 request
.SetURL("/echo");
387 request
.SetMethod("POST");
388 request
.AppendFileRangeToBody(file_ref
, 4, 12, 0);
389 return LoadAndCompareBody(request
, postdata
.substr(4, 12));
392 std::string
TestURLLoader::TestCompoundBodyPOST() {
393 pp::URLRequestInfo
request(instance_
);
394 request
.SetURL("/echo");
395 request
.SetMethod("POST");
396 std::string
postdata1("post");
397 request
.AppendDataToBody(postdata1
.data(), postdata1
.length());
398 std::string
postdata2("data");
399 request
.AppendDataToBody(postdata2
.data(), postdata2
.length());
400 return LoadAndCompareBody(request
, postdata1
+ postdata2
);
403 std::string
TestURLLoader::TestEmptyDataPOST() {
404 pp::URLRequestInfo
request(instance_
);
405 request
.SetURL("/echo");
406 request
.SetMethod("POST");
407 request
.AppendDataToBody("", 0);
408 return LoadAndCompareBody(request
, std::string());
411 std::string
TestURLLoader::TestBinaryDataPOST() {
412 pp::URLRequestInfo
request(instance_
);
413 request
.SetURL("/echo");
414 request
.SetMethod("POST");
415 const char postdata_chars
[] =
416 "\x00\x01\x02\x03\x04\x05postdata\xfa\xfb\xfc\xfd\xfe\xff";
417 std::string
postdata(postdata_chars
,
418 sizeof(postdata_chars
) / sizeof(postdata_chars
[0]));
419 request
.AppendDataToBody(postdata
.data(), postdata
.length());
420 return LoadAndCompareBody(request
, postdata
);
423 std::string
TestURLLoader::TestCustomRequestHeader() {
424 pp::URLRequestInfo
request(instance_
);
425 request
.SetURL("/echoheader?Foo");
426 request
.SetHeaders("Foo: 1");
427 return LoadAndCompareBody(request
, "1");
430 std::string
TestURLLoader::TestFailsBogusContentLength() {
431 pp::URLRequestInfo
request(instance_
);
432 request
.SetURL("/echo");
433 request
.SetMethod("POST");
434 request
.SetHeaders("Content-Length: 400");
435 std::string
postdata("postdata");
436 request
.AppendDataToBody(postdata
.data(), postdata
.length());
439 rv
= OpenUntrusted(request
);
440 if (rv
!= PP_ERROR_NOACCESS
)
442 "Untrusted request with bogus Content-Length restriction", rv
);
447 std::string
TestURLLoader::TestStreamToFile() {
448 pp::URLRequestInfo
request(instance_
);
449 request
.SetURL("test_url_loader_data/hello.txt");
450 request
.SetStreamToFile(true);
452 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
454 pp::URLLoader
loader(instance_
);
455 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
456 CHECK_CALLBACK_BEHAVIOR(callback
);
457 ASSERT_EQ(PP_OK
, callback
.result());
459 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
460 if (response_info
.is_null())
461 return "URLLoader::GetResponseInfo returned null";
462 int32_t status_code
= response_info
.GetStatusCode();
463 if (status_code
!= 200)
464 return "Unexpected HTTP status code";
466 pp::FileRef
body(response_info
.GetBodyAsFileRef());
468 return "URLResponseInfo::GetBody returned null";
470 callback
.WaitForResult(loader
.FinishStreamingToFile(callback
.GetCallback()));
471 CHECK_CALLBACK_BEHAVIOR(callback
);
472 ASSERT_EQ(PP_OK
, callback
.result());
474 pp::FileIO
reader(instance_
);
475 callback
.WaitForResult(reader
.Open(body
, PP_FILEOPENFLAG_READ
,
476 callback
.GetCallback()));
477 CHECK_CALLBACK_BEHAVIOR(callback
);
478 ASSERT_EQ(PP_OK
, callback
.result());
481 std::string error
= ReadEntireFile(&reader
, &data
);
485 std::string expected_body
= "hello\n";
486 if (data
.size() != expected_body
.size())
487 return "ReadEntireFile returned unexpected content length";
488 if (data
!= expected_body
)
489 return "ReadEntireFile returned unexpected content";
494 // Untrusted, unintended cross-origin requests should fail.
495 std::string
TestURLLoader::TestUntrustedSameOriginRestriction() {
496 pp::URLRequestInfo
request(instance_
);
497 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
498 request
.SetURL(cross_origin_url
);
500 int32_t rv
= OpenUntrusted(request
);
501 if (rv
!= PP_ERROR_NOACCESS
)
503 "Untrusted, unintended cross-origin request restriction", rv
);
508 // Trusted, unintended cross-origin requests should succeed.
509 std::string
TestURLLoader::TestTrustedSameOriginRestriction() {
510 pp::URLRequestInfo
request(instance_
);
511 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
512 request
.SetURL(cross_origin_url
);
514 int32_t rv
= OpenTrusted(request
);
516 return ReportError("Trusted cross-origin request failed", rv
);
521 // Untrusted, intended cross-origin requests should use CORS and succeed.
522 std::string
TestURLLoader::TestUntrustedCrossOriginRequest() {
523 pp::URLRequestInfo
request(instance_
);
524 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
525 request
.SetURL(cross_origin_url
);
526 request
.SetAllowCrossOriginRequests(true);
528 int32_t rv
= OpenUntrusted(request
);
531 "Untrusted, intended cross-origin request failed", rv
);
536 // Trusted, intended cross-origin requests should use CORS and succeed.
537 std::string
TestURLLoader::TestTrustedCrossOriginRequest() {
538 pp::URLRequestInfo
request(instance_
);
539 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
540 request
.SetURL(cross_origin_url
);
541 request
.SetAllowCrossOriginRequests(true);
543 int32_t rv
= OpenTrusted(request
);
545 return ReportError("Trusted cross-origin request failed", rv
);
550 // Untrusted Javascript URLs requests should fail.
551 std::string
TestURLLoader::TestUntrustedJavascriptURLRestriction() {
552 pp::URLRequestInfo
request(instance_
);
553 request
.SetURL("javascript:foo = bar");
555 int32_t rv
= OpenUntrusted(request
);
556 if (rv
!= PP_ERROR_NOACCESS
)
558 "Untrusted Javascript URL request restriction failed", rv
);
563 // Trusted Javascript URLs requests should succeed.
564 std::string
TestURLLoader::TestTrustedJavascriptURLRestriction() {
565 pp::URLRequestInfo
request(instance_
);
566 request
.SetURL("javascript:foo = bar");
568 int32_t rv
= OpenTrusted(request
);
569 if (rv
== PP_ERROR_NOACCESS
)
571 "Trusted Javascript URL request", rv
);
576 std::string
TestURLLoader::TestUntrustedHttpRequests() {
577 // HTTP methods are restricted only for untrusted loaders. Forbidden
578 // methods are CONNECT, TRACE, and TRACK, and any string that is not a
579 // valid token (containing special characters like CR, LF).
580 // http://www.w3.org/TR/XMLHttpRequest/
582 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("cOnNeCt", std::string()));
583 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("tRaCk", std::string()));
584 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("tRaCe", std::string()));
585 ASSERT_EQ(PP_ERROR_NOACCESS
,
586 OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()));
588 // HTTP methods are restricted only for untrusted loaders. Try all headers
589 // that are forbidden by http://www.w3.org/TR/XMLHttpRequest/.
591 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Accept-Charset:\n"));
592 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Accept-Encoding:\n"));
593 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Connection:\n"));
594 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Content-Length:\n"));
595 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Cookie:\n"));
596 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Cookie2:\n"));
597 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Date:\n"));
598 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Dnt:\n"));
599 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Expect:\n"));
600 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Host:\n"));
601 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Keep-Alive:\n"));
602 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Referer:\n"));
603 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "TE:\n"));
604 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Trailer:\n"));
605 ASSERT_EQ(PP_ERROR_NOACCESS
,
606 OpenUntrusted("GET", "Transfer-Encoding:\n"));
607 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Upgrade:\n"));
608 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "User-Agent:\n"));
609 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Via:\n"));
610 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted(
611 "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
612 ASSERT_EQ(PP_ERROR_NOACCESS
, OpenUntrusted("GET", "Sec-foo:\n"));
614 // Untrusted requests with custom referrer should fail.
616 pp::URLRequestInfo
request(instance_
);
617 request
.SetCustomReferrerURL("http://www.google.com/");
619 int32_t rv
= OpenUntrusted(request
);
620 if (rv
!= PP_ERROR_NOACCESS
)
622 "Untrusted request with custom referrer restriction", rv
);
624 // Untrusted requests with custom transfer encodings should fail.
626 pp::URLRequestInfo
request(instance_
);
627 request
.SetCustomContentTransferEncoding("foo");
629 int32_t rv
= OpenUntrusted(request
);
630 if (rv
!= PP_ERROR_NOACCESS
)
632 "Untrusted request with content-transfer-encoding restriction", rv
);
638 std::string
TestURLLoader::TestTrustedHttpRequests() {
639 // Trusted requests can use restricted methods.
641 ASSERT_EQ(PP_OK
, OpenTrusted("cOnNeCt", std::string()));
642 ASSERT_EQ(PP_OK
, OpenTrusted("tRaCk", std::string()));
643 ASSERT_EQ(PP_OK
, OpenTrusted("tRaCe", std::string()));
645 // Trusted requests can use restricted headers.
647 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Accept-Charset:\n"));
648 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Accept-Encoding:\n"));
649 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Connection:\n"));
650 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Content-Length:\n"));
651 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Cookie:\n"));
652 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Cookie2:\n"));
653 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Content-Transfer-Encoding:\n"));
654 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Date:\n"));
655 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Expect:\n"));
656 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Host:\n"));
657 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Keep-Alive:\n"));
658 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Referer:\n"));
659 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "TE:\n"));
660 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Trailer:\n"));
661 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Transfer-Encoding:\n"));
662 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Upgrade:\n"));
663 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "User-Agent:\n"));
664 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Via:\n"));
667 "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
668 ASSERT_EQ(PP_OK
, OpenTrusted("GET", "Sec-foo:\n"));
670 // Trusted requests with custom referrer should succeed.
672 pp::URLRequestInfo
request(instance_
);
673 request
.SetCustomReferrerURL("http://www.google.com/");
675 int32_t rv
= OpenTrusted(request
);
677 return ReportError("Trusted request with custom referrer", rv
);
679 // Trusted requests with custom transfer encodings should succeed.
681 pp::URLRequestInfo
request(instance_
);
682 request
.SetCustomContentTransferEncoding("foo");
684 int32_t rv
= OpenTrusted(request
);
687 "Trusted request with content-transfer-encoding failed", rv
);
693 // This test should cause a redirect and ensure that the loader follows it.
694 std::string
TestURLLoader::TestFollowURLRedirect() {
695 pp::URLRequestInfo
request(instance_
);
696 // This prefix causes the test server to return a 301 redirect.
697 std::string
redirect_prefix("/server-redirect?");
698 // We need an absolute path for the redirect to actually work.
699 std::string redirect_url
=
700 GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
701 request
.SetURL(redirect_prefix
.append(redirect_url
));
702 return LoadAndCompareBody(request
, "hello\n");
705 // This test should cause a redirect and ensure that the loader runs
706 // the callback, rather than following the redirect.
707 std::string
TestURLLoader::TestAuditURLRedirect() {
708 pp::URLRequestInfo
request(instance_
);
709 // This path will cause the server to return a 301 redirect.
710 // This prefix causes the test server to return a 301 redirect.
711 std::string
redirect_prefix("/server-redirect?");
712 // We need an absolute path for the redirect to actually work.
713 std::string redirect_url
=
714 GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
715 request
.SetURL(redirect_prefix
.append(redirect_url
));
716 request
.SetFollowRedirects(false);
718 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
720 pp::URLLoader
loader(instance_
);
721 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
722 CHECK_CALLBACK_BEHAVIOR(callback
);
723 ASSERT_EQ(PP_OK
, callback
.result());
725 // Checks that the response indicates a redirect, and that the URL
727 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
728 if (response_info
.is_null())
729 return "URLLoader::GetResponseInfo returned null";
730 int32_t status_code
= response_info
.GetStatusCode();
731 if (status_code
!= 301)
732 return "Response status should be 301";
734 // Test that the paused loader can be resumed.
735 callback
.WaitForResult(loader
.FollowRedirect(callback
.GetCallback()));
736 CHECK_CALLBACK_BEHAVIOR(callback
);
737 ASSERT_EQ(PP_OK
, callback
.result());
739 std::string error
= ReadEntireResponseBody(&loader
, &body
);
743 if (body
!= "hello\n")
744 return "URLLoader::FollowRedirect failed";
749 std::string
TestURLLoader::TestAbortCalls() {
750 pp::URLRequestInfo
request(instance_
);
751 request
.SetURL("test_url_loader_data/hello.txt");
753 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
758 rv
= pp::URLLoader(instance_
).Open(request
, callback
.GetCallback());
760 callback
.WaitForAbortResult(rv
);
761 CHECK_CALLBACK_BEHAVIOR(callback
);
763 // Abort |ReadResponseBody()|.
767 pp::URLLoader
loader(instance_
);
768 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
769 CHECK_CALLBACK_BEHAVIOR(callback
);
770 ASSERT_EQ(PP_OK
, callback
.result());
772 rv
= loader
.ReadResponseBody(buf
, sizeof(buf
), callback
.GetCallback());
773 } // Destroy |loader|.
774 callback
.WaitForAbortResult(rv
);
775 CHECK_CALLBACK_BEHAVIOR(callback
);
776 if (rv
== PP_OK_COMPLETIONPENDING
) {
777 if (buf
[0] || buf
[1]) {
778 return "URLLoader::ReadResponseBody wrote data after resource "
784 // TODO(viettrungluu): More abort tests (but add basic tests first).
785 // Also test that Close() aborts properly. crbug.com/69457
790 std::string
TestURLLoader::TestUntendedLoad() {
791 pp::URLRequestInfo
request(instance_
);
792 request
.SetURL("test_url_loader_data/hello.txt");
793 request
.SetRecordDownloadProgress(true);
794 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
796 pp::URLLoader
loader(instance_
);
797 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
798 CHECK_CALLBACK_BEHAVIOR(callback
);
799 ASSERT_EQ(PP_OK
, callback
.result());
801 // We received the response callback. Yield until the network code has called
802 // the loader's didReceiveData and didFinishLoading methods before we give it
803 // another callback function, to make sure the loader works with no callback.
804 int64_t bytes_received
= 0;
805 int64_t total_bytes_to_be_received
= 0;
807 loader
.GetDownloadProgress(&bytes_received
, &total_bytes_to_be_received
);
808 if (total_bytes_to_be_received
<= 0)
809 return ReportError("URLLoader::GetDownloadProgress total size",
810 total_bytes_to_be_received
);
811 if (bytes_received
== total_bytes_to_be_received
)
813 // Yield if we're on the main thread, so that URLLoader can receive more
815 if (pp::Module::Get()->core()->IsMainThread()) {
816 NestedEvent
event(instance_
->pp_instance());
817 event
.PostSignal(10);
821 // The loader should now have the data and have finished successfully.
823 std::string error
= ReadEntireResponseBody(&loader
, &body
);
826 if (body
!= "hello\n")
827 return ReportError("Couldn't read data", callback
.result());
832 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower
,
834 pp::URLRequestInfo
request(instance_
);
835 request
.SetURL("test_url_loader_data/hello.txt");
836 request
.SetPrefetchBufferLowerThreshold(lower
);
837 request
.SetPrefetchBufferUpperThreshold(upper
);
839 return OpenUntrusted(request
);
842 std::string
TestURLLoader::TestPrefetchBufferThreshold() {
843 int32_t rv
= OpenWithPrefetchBufferThreshold(-1, 1);
844 if (rv
!= PP_ERROR_FAILED
) {
845 return ReportError("The prefetch limits contained a negative value but "
846 "the URLLoader did not fail.", rv
);
849 rv
= OpenWithPrefetchBufferThreshold(0, 1);
851 return ReportError("The prefetch buffer limits were legal values but "
852 "the URLLoader failed.", rv
);
855 rv
= OpenWithPrefetchBufferThreshold(1000, 1);
856 if (rv
!= PP_ERROR_FAILED
) {
857 return ReportError("The lower buffer value was higher than the upper but "
858 "the URLLoader did not fail.", rv
);
864 // TODO(viettrungluu): This test properly belongs elsewhere. It tests that
865 // Chrome properly tags URL requests made on behalf of Pepper plugins (with an
866 // X-Requested-With header), but this isn't, strictly speaking, a PPAPI
868 std::string
TestURLLoader::TestXRequestedWithHeader() {
869 pp::URLRequestInfo
request(instance_
);
870 request
.SetURL("/echoheader?X-Requested-With");
871 // The name and version of the plugin is set from the command-line (see
872 // chrome/test/ppapi/ppapi_test.cc.
873 return LoadAndCompareBody(request
, "PPAPITests/1.2.3");
876 // TODO(viettrungluu): Add tests for Get{Upload,Download}Progress, Close
877 // (including abort tests if applicable).