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/dev/ppb_testing_dev.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/ppb_file_io.h"
14 #include "ppapi/c/ppb_url_loader.h"
15 #include "ppapi/c/trusted/ppb_file_io_trusted.h"
16 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
17 #include "ppapi/cpp/dev/url_util_dev.h"
18 #include "ppapi/cpp/file_io.h"
19 #include "ppapi/cpp/file_ref.h"
20 #include "ppapi/cpp/file_system.h"
21 #include "ppapi/cpp/instance.h"
22 #include "ppapi/cpp/module.h"
23 #include "ppapi/cpp/url_loader.h"
24 #include "ppapi/cpp/url_request_info.h"
25 #include "ppapi/cpp/url_response_info.h"
26 #include "ppapi/tests/test_utils.h"
27 #include "ppapi/tests/testing_instance.h"
29 REGISTER_TEST_CASE(URLLoader
);
33 int32_t WriteEntireBuffer(PP_Instance instance
,
36 const std::string
& data
,
37 CallbackType callback_type
) {
38 TestCompletionCallback
callback(instance
, callback_type
);
39 int32_t write_offset
= offset
;
40 const char* buf
= data
.c_str();
41 int32_t size
= data
.size();
43 while (write_offset
< offset
+ size
) {
44 callback
.WaitForResult(file_io
->Write(write_offset
,
45 &buf
[write_offset
- offset
],
46 size
- write_offset
+ offset
,
47 callback
.GetCallback()));
48 if (callback
.result() < 0)
49 return callback
.result();
50 if (callback
.result() == 0)
51 return PP_ERROR_FAILED
;
52 write_offset
+= callback
.result();
60 TestURLLoader::TestURLLoader(TestingInstance
* instance
)
62 file_io_trusted_interface_(NULL
),
63 url_loader_trusted_interface_(NULL
) {
66 bool TestURLLoader::Init() {
67 if (!CheckTestingInterface()) {
68 instance_
->AppendError("Testing interface not available");
72 const PPB_FileIO
* file_io_interface
= static_cast<const PPB_FileIO
*>(
73 pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_INTERFACE
));
74 if (!file_io_interface
)
75 instance_
->AppendError("FileIO interface not available");
77 file_io_trusted_interface_
= static_cast<const PPB_FileIOTrusted
*>(
78 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE
));
79 url_loader_trusted_interface_
= static_cast<const PPB_URLLoaderTrusted
*>(
80 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE
));
81 if (!testing_interface_
->IsOutOfProcess()) {
82 // Trusted interfaces are not supported under NaCl.
83 #if !(defined __native_client__)
84 if (!file_io_trusted_interface_
)
85 instance_
->AppendError("FileIOTrusted interface not available");
86 if (!url_loader_trusted_interface_
)
87 instance_
->AppendError("URLLoaderTrusted interface not available");
89 if (file_io_trusted_interface_
)
90 instance_
->AppendError("FileIOTrusted interface is supported by NaCl");
91 if (url_loader_trusted_interface_
)
92 instance_
->AppendError("URLLoaderTrusted interface is supported by NaCl");
95 return EnsureRunningOverHTTP();
99 * The test order is important here, as running tests out of order may cause
102 * Here is the environment:
104 * 1. TestServer.py only accepts one open connection at the time.
105 * 2. HTTP socket pool keeps sockets open for several seconds after last use
106 * (hoping that there will be another request that could reuse the connection).
107 * 3. HTTP socket pool is separated by host/port and privacy mode (which is
108 * based on cookies set/get permissions). So, connections to 127.0.0.1,
109 * localhost and localhost in privacy mode cannot reuse existing socket and will
110 * try to open another connection.
112 * Here is the problem:
114 * Original test order was repeatedly accessing 127.0.0.1, localhost and
115 * localhost in privacy mode, causing new sockets to open and try to connect to
116 * testserver, which they couldn't until previous connection is closed by socket
117 * pool idle socket timeout (10 seconds).
119 * Because of this the test run was taking around 45 seconds, and test was
120 * reported as 'timed out' by trybot.
122 * Re-ordering of tests provides more sequential access to 127.0.0.1, localhost
123 * and localhost in privacy mode. It decreases the number of times when socket
124 * pool doesn't have existing connection to host and has to wait, therefore
125 * reducing total test time and ensuring its completion under 30 seconds.
127 void TestURLLoader::RunTests(const std::string
& filter
) {
128 // These tests connect to 127.0.0.1:
129 RUN_CALLBACK_TEST(TestURLLoader
, BasicGET
, filter
);
130 RUN_CALLBACK_TEST(TestURLLoader
, BasicPOST
, filter
);
131 RUN_CALLBACK_TEST(TestURLLoader
, BasicFilePOST
, filter
);
132 RUN_CALLBACK_TEST(TestURLLoader
, BasicFileRangePOST
, filter
);
133 RUN_CALLBACK_TEST(TestURLLoader
, CompoundBodyPOST
, filter
);
134 RUN_CALLBACK_TEST(TestURLLoader
, EmptyDataPOST
, filter
);
135 RUN_CALLBACK_TEST(TestURLLoader
, BinaryDataPOST
, filter
);
136 RUN_CALLBACK_TEST(TestURLLoader
, CustomRequestHeader
, filter
);
137 RUN_CALLBACK_TEST(TestURLLoader
, FailsBogusContentLength
, filter
);
138 RUN_CALLBACK_TEST(TestURLLoader
, StreamToFile
, filter
);
139 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedJavascriptURLRestriction
, filter
);
140 RUN_CALLBACK_TEST(TestURLLoader
, TrustedJavascriptURLRestriction
, filter
);
141 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedHttpRequests
, filter
);
142 RUN_CALLBACK_TEST(TestURLLoader
, TrustedHttpRequests
, filter
);
143 RUN_CALLBACK_TEST(TestURLLoader
, FollowURLRedirect
, filter
);
144 RUN_CALLBACK_TEST(TestURLLoader
, AuditURLRedirect
, filter
);
145 RUN_CALLBACK_TEST(TestURLLoader
, AbortCalls
, filter
);
146 RUN_CALLBACK_TEST(TestURLLoader
, UntendedLoad
, filter
);
147 RUN_CALLBACK_TEST(TestURLLoader
, PrefetchBufferThreshold
, filter
);
148 // These tests connect to localhost with privacy mode enabled:
149 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedSameOriginRestriction
, filter
);
150 RUN_CALLBACK_TEST(TestURLLoader
, UntrustedCrossOriginRequest
, filter
);
151 // These tests connect to localhost with privacy mode disabled:
152 RUN_CALLBACK_TEST(TestURLLoader
, TrustedSameOriginRestriction
, filter
);
153 RUN_CALLBACK_TEST(TestURLLoader
, TrustedCrossOriginRequest
, filter
);
156 std::string
TestURLLoader::ReadEntireFile(pp::FileIO
* file_io
,
158 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
163 callback
.WaitForResult(file_io
->Read(offset
, buf
, sizeof(buf
),
164 callback
.GetCallback()));
165 if (callback
.result() < 0)
166 return ReportError("FileIO::Read", callback
.result());
167 if (callback
.result() == 0)
169 offset
+= callback
.result();
170 data
->append(buf
, callback
.result());
176 std::string
TestURLLoader::ReadEntireResponseBody(pp::URLLoader
* loader
,
178 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
179 char buf
[2]; // Small so that multiple reads are needed.
182 callback
.WaitForResult(
183 loader
->ReadResponseBody(buf
, sizeof(buf
), callback
.GetCallback()));
184 if (callback
.result() < 0)
185 return ReportError("URLLoader::ReadResponseBody", callback
.result());
186 if (callback
.result() == 0)
188 body
->append(buf
, callback
.result());
194 std::string
TestURLLoader::LoadAndCompareBody(
195 const pp::URLRequestInfo
& request
,
196 const std::string
& expected_body
) {
197 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
199 pp::URLLoader
loader(instance_
);
200 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
201 CHECK_CALLBACK_BEHAVIOR(callback
);
202 ASSERT_EQ(PP_OK
, callback
.result());
204 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
205 if (response_info
.is_null())
206 return "URLLoader::GetResponseInfo returned null";
207 int32_t status_code
= response_info
.GetStatusCode();
208 if (status_code
!= 200)
209 return "Unexpected HTTP status code";
212 std::string error
= ReadEntireResponseBody(&loader
, &body
);
216 if (body
.size() != expected_body
.size())
217 return "URLLoader::ReadResponseBody returned unexpected content length";
218 if (body
!= expected_body
)
219 return "URLLoader::ReadResponseBody returned unexpected content";
224 int32_t TestURLLoader::OpenFileSystem(pp::FileSystem
* file_system
,
225 std::string
* message
) {
226 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
227 callback
.WaitForResult(file_system
->Open(1024, callback
.GetCallback()));
228 if (callback
.failed()) {
229 message
->assign(callback
.errors());
230 return callback
.result();
232 if (callback
.result() != PP_OK
) {
233 message
->assign("FileSystem::Open");
234 return callback
.result();
236 return callback
.result();
239 int32_t TestURLLoader::PrepareFileForPost(
240 const pp::FileRef
& file_ref
,
241 const std::string
& data
,
242 std::string
* message
) {
243 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
244 pp::FileIO
file_io(instance_
);
245 callback
.WaitForResult(file_io
.Open(file_ref
,
246 PP_FILEOPENFLAG_CREATE
|
247 PP_FILEOPENFLAG_TRUNCATE
|
248 PP_FILEOPENFLAG_WRITE
,
249 callback
.GetCallback()));
250 if (callback
.failed()) {
251 message
->assign(callback
.errors());
252 return callback
.result();
254 if (callback
.result() != PP_OK
) {
255 message
->assign("FileIO::Open failed.");
256 return callback
.result();
259 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0, data
,
262 message
->assign("FileIO::Write failed.");
269 std::string
TestURLLoader::GetReachableAbsoluteURL(
270 const std::string
& file_name
) {
271 // Get the absolute page URL and replace the test case file name
272 // with the given one.
273 pp::Var
document_url(
275 testing_interface_
->GetDocumentURL(instance_
->pp_instance(),
277 std::string
url(document_url
.AsString());
278 std::string
old_name("test_case.html");
279 size_t index
= url
.find(old_name
);
280 ASSERT_NE(index
, std::string::npos
);
281 url
.replace(index
, old_name
.length(), file_name
);
285 std::string
TestURLLoader::GetReachableCrossOriginURL(
286 const std::string
& file_name
) {
287 // Get an absolute URL and use it to construct a URL that will be
288 // considered cross-origin by the CORS access control code, and yet be
289 // reachable by the test server.
290 std::string url
= GetReachableAbsoluteURL(file_name
);
291 // Replace '127.0.0.1' with 'localhost'.
292 std::string
host("127.0.0.1");
293 size_t index
= url
.find(host
);
294 ASSERT_NE(index
, std::string::npos
);
295 url
.replace(index
, host
.length(), "localhost");
299 int32_t TestURLLoader::OpenUntrusted(const std::string
& method
,
300 const std::string
& header
) {
301 pp::URLRequestInfo
request(instance_
);
302 request
.SetURL("/echo");
303 request
.SetMethod(method
);
304 request
.SetHeaders(header
);
306 return OpenUntrusted(request
);
309 int32_t TestURLLoader::OpenTrusted(const std::string
& method
,
310 const std::string
& header
) {
311 pp::URLRequestInfo
request(instance_
);
312 request
.SetURL("/echo");
313 request
.SetMethod(method
);
314 request
.SetHeaders(header
);
316 return OpenTrusted(request
);
319 int32_t TestURLLoader::OpenUntrusted(const pp::URLRequestInfo
& request
) {
320 return Open(request
, false);
323 int32_t TestURLLoader::OpenTrusted(const pp::URLRequestInfo
& request
) {
324 return Open(request
, true);
327 int32_t TestURLLoader::Open(const pp::URLRequestInfo
& request
,
329 pp::URLLoader
loader(instance_
);
331 url_loader_trusted_interface_
->GrantUniversalAccess(loader
.pp_resource());
332 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
333 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
334 return callback
.result();
337 std::string
TestURLLoader::TestBasicGET() {
338 pp::URLRequestInfo
request(instance_
);
339 request
.SetURL("test_url_loader_data/hello.txt");
340 return LoadAndCompareBody(request
, "hello\n");
343 std::string
TestURLLoader::TestBasicPOST() {
344 pp::URLRequestInfo
request(instance_
);
345 request
.SetURL("/echo");
346 request
.SetMethod("POST");
347 std::string
postdata("postdata");
348 request
.AppendDataToBody(postdata
.data(), postdata
.length());
349 return LoadAndCompareBody(request
, postdata
);
352 std::string
TestURLLoader::TestBasicFilePOST() {
355 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
356 int32_t rv
= OpenFileSystem(&file_system
, &message
);
358 return ReportError(message
.c_str(), rv
);
360 pp::FileRef
file_ref(file_system
, "/file_post_test");
361 std::string
postdata("postdata");
362 rv
= PrepareFileForPost(file_ref
, postdata
, &message
);
364 return ReportError(message
.c_str(), rv
);
366 pp::URLRequestInfo
request(instance_
);
367 request
.SetURL("/echo");
368 request
.SetMethod("POST");
369 request
.AppendFileToBody(file_ref
, 0);
370 return LoadAndCompareBody(request
, postdata
);
373 std::string
TestURLLoader::TestBasicFileRangePOST() {
376 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
377 int32_t rv
= OpenFileSystem(&file_system
, &message
);
379 return ReportError(message
.c_str(), rv
);
381 pp::FileRef
file_ref(file_system
, "/file_range_post_test");
382 std::string
postdata("postdatapostdata");
383 rv
= PrepareFileForPost(file_ref
, postdata
, &message
);
385 return ReportError(message
.c_str(), rv
);
387 pp::URLRequestInfo
request(instance_
);
388 request
.SetURL("/echo");
389 request
.SetMethod("POST");
390 request
.AppendFileRangeToBody(file_ref
, 4, 12, 0);
391 return LoadAndCompareBody(request
, postdata
.substr(4, 12));
394 std::string
TestURLLoader::TestCompoundBodyPOST() {
395 pp::URLRequestInfo
request(instance_
);
396 request
.SetURL("/echo");
397 request
.SetMethod("POST");
398 std::string
postdata1("post");
399 request
.AppendDataToBody(postdata1
.data(), postdata1
.length());
400 std::string
postdata2("data");
401 request
.AppendDataToBody(postdata2
.data(), postdata2
.length());
402 return LoadAndCompareBody(request
, postdata1
+ postdata2
);
405 std::string
TestURLLoader::TestEmptyDataPOST() {
406 pp::URLRequestInfo
request(instance_
);
407 request
.SetURL("/echo");
408 request
.SetMethod("POST");
409 request
.AppendDataToBody("", 0);
410 return LoadAndCompareBody(request
, std::string());
413 std::string
TestURLLoader::TestBinaryDataPOST() {
414 pp::URLRequestInfo
request(instance_
);
415 request
.SetURL("/echo");
416 request
.SetMethod("POST");
417 const char postdata_chars
[] =
418 "\x00\x01\x02\x03\x04\x05postdata\xfa\xfb\xfc\xfd\xfe\xff";
419 std::string
postdata(postdata_chars
,
420 sizeof(postdata_chars
) / sizeof(postdata_chars
[0]));
421 request
.AppendDataToBody(postdata
.data(), postdata
.length());
422 return LoadAndCompareBody(request
, postdata
);
425 std::string
TestURLLoader::TestCustomRequestHeader() {
426 pp::URLRequestInfo
request(instance_
);
427 request
.SetURL("/echoheader?Foo");
428 request
.SetHeaders("Foo: 1");
429 return LoadAndCompareBody(request
, "1");
432 std::string
TestURLLoader::TestFailsBogusContentLength() {
433 pp::URLRequestInfo
request(instance_
);
434 request
.SetURL("/echo");
435 request
.SetMethod("POST");
436 request
.SetHeaders("Content-Length: 400");
437 std::string
postdata("postdata");
438 request
.AppendDataToBody(postdata
.data(), postdata
.length());
441 rv
= OpenUntrusted(request
);
442 if (rv
!= PP_ERROR_NOACCESS
)
444 "Untrusted request with bogus Content-Length restriction", rv
);
449 std::string
TestURLLoader::TestStreamToFile() {
450 pp::URLRequestInfo
request(instance_
);
451 request
.SetURL("test_url_loader_data/hello.txt");
452 request
.SetStreamToFile(true);
454 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
456 pp::URLLoader
loader(instance_
);
457 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
458 CHECK_CALLBACK_BEHAVIOR(callback
);
459 ASSERT_EQ(PP_OK
, callback
.result());
461 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
462 if (response_info
.is_null())
463 return "URLLoader::GetResponseInfo returned null";
464 int32_t status_code
= response_info
.GetStatusCode();
465 if (status_code
!= 200)
466 return "Unexpected HTTP status code";
468 pp::FileRef
body(response_info
.GetBodyAsFileRef());
470 return "URLResponseInfo::GetBody returned null";
472 callback
.WaitForResult(loader
.FinishStreamingToFile(callback
.GetCallback()));
473 CHECK_CALLBACK_BEHAVIOR(callback
);
474 ASSERT_EQ(PP_OK
, callback
.result());
476 pp::FileIO
reader(instance_
);
477 callback
.WaitForResult(reader
.Open(body
, PP_FILEOPENFLAG_READ
,
478 callback
.GetCallback()));
479 CHECK_CALLBACK_BEHAVIOR(callback
);
480 ASSERT_EQ(PP_OK
, callback
.result());
483 std::string error
= ReadEntireFile(&reader
, &data
);
487 std::string expected_body
= "hello\n";
488 if (data
.size() != expected_body
.size())
489 return "ReadEntireFile returned unexpected content length";
490 if (data
!= expected_body
)
491 return "ReadEntireFile returned unexpected content";
493 // FileIOTrusted is not supported by NaCl or ppapi/proxy.
494 if (!testing_interface_
->IsOutOfProcess()) {
495 #if !(defined __native_client__)
496 int32_t file_descriptor
= file_io_trusted_interface_
->GetOSFileDescriptor(
497 reader
.pp_resource());
498 if (file_descriptor
< 0)
499 return "FileIO::GetOSFileDescriptor() returned a bad file descriptor.";
505 // Untrusted, unintended cross-origin requests should fail.
506 std::string
TestURLLoader::TestUntrustedSameOriginRestriction() {
507 pp::URLRequestInfo
request(instance_
);
508 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
509 request
.SetURL(cross_origin_url
);
511 int32_t rv
= OpenUntrusted(request
);
512 if (rv
!= PP_ERROR_NOACCESS
)
514 "Untrusted, unintended cross-origin request restriction", rv
);
519 // Trusted, unintended cross-origin requests should succeed.
520 std::string
TestURLLoader::TestTrustedSameOriginRestriction() {
521 pp::URLRequestInfo
request(instance_
);
522 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
523 request
.SetURL(cross_origin_url
);
525 int32_t rv
= OpenTrusted(request
);
527 return ReportError("Trusted cross-origin request failed", rv
);
532 // Untrusted, intended cross-origin requests should use CORS and succeed.
533 std::string
TestURLLoader::TestUntrustedCrossOriginRequest() {
534 pp::URLRequestInfo
request(instance_
);
535 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
536 request
.SetURL(cross_origin_url
);
537 request
.SetAllowCrossOriginRequests(true);
539 int32_t rv
= OpenUntrusted(request
);
542 "Untrusted, intended cross-origin request failed", rv
);
547 // Trusted, intended cross-origin requests should use CORS and succeed.
548 std::string
TestURLLoader::TestTrustedCrossOriginRequest() {
549 pp::URLRequestInfo
request(instance_
);
550 std::string cross_origin_url
= GetReachableCrossOriginURL("test_case.html");
551 request
.SetURL(cross_origin_url
);
552 request
.SetAllowCrossOriginRequests(true);
554 int32_t rv
= OpenTrusted(request
);
556 return ReportError("Trusted cross-origin request failed", rv
);
561 // Untrusted Javascript URLs requests should fail.
562 std::string
TestURLLoader::TestUntrustedJavascriptURLRestriction() {
563 pp::URLRequestInfo
request(instance_
);
564 request
.SetURL("javascript:foo = bar");
566 int32_t rv
= OpenUntrusted(request
);
567 if (rv
!= PP_ERROR_NOACCESS
)
569 "Untrusted Javascript URL request restriction failed", rv
);
574 // Trusted Javascript URLs requests should succeed.
575 std::string
TestURLLoader::TestTrustedJavascriptURLRestriction() {
576 pp::URLRequestInfo
request(instance_
);
577 request
.SetURL("javascript:foo = bar");
579 int32_t rv
= OpenTrusted(request
);
580 if (rv
== PP_ERROR_NOACCESS
)
582 "Trusted Javascript URL request", rv
);
587 std::string
TestURLLoader::TestUntrustedHttpRequests() {
588 // HTTP methods are restricted only for untrusted loaders. Forbidden
589 // methods are CONNECT, TRACE, and TRACK, and any string that is not a
590 // valid token (containing special characters like CR, LF).
591 // http://www.w3.org/TR/XMLHttpRequest/
593 ASSERT_EQ(OpenUntrusted("cOnNeCt", std::string()), PP_ERROR_NOACCESS
);
594 ASSERT_EQ(OpenUntrusted("tRaCk", std::string()), PP_ERROR_NOACCESS
);
595 ASSERT_EQ(OpenUntrusted("tRaCe", std::string()), PP_ERROR_NOACCESS
);
597 OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()),
600 // HTTP methods are restricted only for untrusted loaders. Try all headers
601 // that are forbidden by http://www.w3.org/TR/XMLHttpRequest/.
603 ASSERT_EQ(OpenUntrusted("GET", "Accept-Charset:\n"), PP_ERROR_NOACCESS
);
604 ASSERT_EQ(OpenUntrusted("GET", "Accept-Encoding:\n"), PP_ERROR_NOACCESS
);
605 ASSERT_EQ(OpenUntrusted("GET", "Connection:\n"), PP_ERROR_NOACCESS
);
606 ASSERT_EQ(OpenUntrusted("GET", "Content-Length:\n"), PP_ERROR_NOACCESS
);
607 ASSERT_EQ(OpenUntrusted("GET", "Cookie:\n"), PP_ERROR_NOACCESS
);
608 ASSERT_EQ(OpenUntrusted("GET", "Cookie2:\n"), PP_ERROR_NOACCESS
);
609 ASSERT_EQ(OpenUntrusted(
610 "GET", "Content-Transfer-Encoding:\n"), PP_ERROR_NOACCESS
);
611 ASSERT_EQ(OpenUntrusted("GET", "Date:\n"), PP_ERROR_NOACCESS
);
612 ASSERT_EQ(OpenUntrusted("GET", "Expect:\n"), PP_ERROR_NOACCESS
);
613 ASSERT_EQ(OpenUntrusted("GET", "Host:\n"), PP_ERROR_NOACCESS
);
614 ASSERT_EQ(OpenUntrusted("GET", "Keep-Alive:\n"), PP_ERROR_NOACCESS
);
615 ASSERT_EQ(OpenUntrusted("GET", "Referer:\n"), PP_ERROR_NOACCESS
);
616 ASSERT_EQ(OpenUntrusted("GET", "TE:\n"), PP_ERROR_NOACCESS
);
617 ASSERT_EQ(OpenUntrusted("GET", "Trailer:\n"), PP_ERROR_NOACCESS
);
618 ASSERT_EQ(OpenUntrusted(
619 "GET", "Transfer-Encoding:\n"), PP_ERROR_NOACCESS
);
620 ASSERT_EQ(OpenUntrusted("GET", "Upgrade:\n"), PP_ERROR_NOACCESS
);
621 ASSERT_EQ(OpenUntrusted("GET", "User-Agent:\n"), PP_ERROR_NOACCESS
);
622 ASSERT_EQ(OpenUntrusted("GET", "Via:\n"), PP_ERROR_NOACCESS
);
623 ASSERT_EQ(OpenUntrusted(
624 "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"),
626 ASSERT_EQ(OpenUntrusted("GET", "Sec-foo:\n"), PP_ERROR_NOACCESS
);
628 // Untrusted requests with custom referrer should fail.
630 pp::URLRequestInfo
request(instance_
);
631 request
.SetCustomReferrerURL("http://www.google.com/");
633 int32_t rv
= OpenUntrusted(request
);
634 if (rv
!= PP_ERROR_NOACCESS
)
636 "Untrusted request with custom referrer restriction", rv
);
638 // Untrusted requests with custom transfer encodings should fail.
640 pp::URLRequestInfo
request(instance_
);
641 request
.SetCustomContentTransferEncoding("foo");
643 int32_t rv
= OpenUntrusted(request
);
644 if (rv
!= PP_ERROR_NOACCESS
)
646 "Untrusted request with content-transfer-encoding restriction", rv
);
652 std::string
TestURLLoader::TestTrustedHttpRequests() {
653 // Trusted requests can use restricted methods.
655 ASSERT_EQ(OpenTrusted("cOnNeCt", std::string()), PP_OK
);
656 ASSERT_EQ(OpenTrusted("tRaCk", std::string()), PP_OK
);
657 ASSERT_EQ(OpenTrusted("tRaCe", std::string()), PP_OK
);
659 // Trusted requests can use restricted headers.
661 ASSERT_EQ(OpenTrusted("GET", "Accept-Charset:\n"), PP_OK
);
662 ASSERT_EQ(OpenTrusted("GET", "Accept-Encoding:\n"), PP_OK
);
663 ASSERT_EQ(OpenTrusted("GET", "Connection:\n"), PP_OK
);
664 ASSERT_EQ(OpenTrusted("GET", "Content-Length:\n"), PP_OK
);
665 ASSERT_EQ(OpenTrusted("GET", "Cookie:\n"), PP_OK
);
666 ASSERT_EQ(OpenTrusted("GET", "Cookie2:\n"), PP_OK
);
667 ASSERT_EQ(OpenTrusted(
668 "GET", "Content-Transfer-Encoding:\n"), PP_OK
);
669 ASSERT_EQ(OpenTrusted("GET", "Date:\n"), PP_OK
);
670 ASSERT_EQ(OpenTrusted("GET", "Expect:\n"), PP_OK
);
671 ASSERT_EQ(OpenTrusted("GET", "Host:\n"), PP_OK
);
672 ASSERT_EQ(OpenTrusted("GET", "Keep-Alive:\n"), PP_OK
);
673 ASSERT_EQ(OpenTrusted("GET", "Referer:\n"), PP_OK
);
674 ASSERT_EQ(OpenTrusted("GET", "TE:\n"), PP_OK
);
675 ASSERT_EQ(OpenTrusted("GET", "Trailer:\n"), PP_OK
);
676 ASSERT_EQ(OpenTrusted("GET", "Transfer-Encoding:\n"), PP_OK
);
677 ASSERT_EQ(OpenTrusted("GET", "Upgrade:\n"), PP_OK
);
678 ASSERT_EQ(OpenTrusted("GET", "User-Agent:\n"), PP_OK
);
679 ASSERT_EQ(OpenTrusted("GET", "Via:\n"), PP_OK
);
680 ASSERT_EQ(OpenTrusted(
681 "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"), PP_OK
);
682 ASSERT_EQ(OpenTrusted("GET", "Sec-foo:\n"), PP_OK
);
684 // Trusted requests with custom referrer should succeed.
686 pp::URLRequestInfo
request(instance_
);
687 request
.SetCustomReferrerURL("http://www.google.com/");
689 int32_t rv
= OpenTrusted(request
);
691 return ReportError("Trusted request with custom referrer", rv
);
693 // Trusted requests with custom transfer encodings should succeed.
695 pp::URLRequestInfo
request(instance_
);
696 request
.SetCustomContentTransferEncoding("foo");
698 int32_t rv
= OpenTrusted(request
);
701 "Trusted request with content-transfer-encoding failed", rv
);
707 // This test should cause a redirect and ensure that the loader follows it.
708 std::string
TestURLLoader::TestFollowURLRedirect() {
709 pp::URLRequestInfo
request(instance_
);
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 return LoadAndCompareBody(request
, "hello\n");
719 // This test should cause a redirect and ensure that the loader runs
720 // the callback, rather than following the redirect.
721 std::string
TestURLLoader::TestAuditURLRedirect() {
722 pp::URLRequestInfo
request(instance_
);
723 // This path will cause the server to return a 301 redirect.
724 // This prefix causes the test server to return a 301 redirect.
725 std::string
redirect_prefix("/server-redirect?");
726 // We need an absolute path for the redirect to actually work.
727 std::string redirect_url
=
728 GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
729 request
.SetURL(redirect_prefix
.append(redirect_url
));
730 request
.SetFollowRedirects(false);
732 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
734 pp::URLLoader
loader(instance_
);
735 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
736 CHECK_CALLBACK_BEHAVIOR(callback
);
737 ASSERT_EQ(PP_OK
, callback
.result());
739 // Checks that the response indicates a redirect, and that the URL
741 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
742 if (response_info
.is_null())
743 return "URLLoader::GetResponseInfo returned null";
744 int32_t status_code
= response_info
.GetStatusCode();
745 if (status_code
!= 301)
746 return "Response status should be 301";
748 // Test that the paused loader can be resumed.
749 callback
.WaitForResult(loader
.FollowRedirect(callback
.GetCallback()));
750 CHECK_CALLBACK_BEHAVIOR(callback
);
751 ASSERT_EQ(PP_OK
, callback
.result());
753 std::string error
= ReadEntireResponseBody(&loader
, &body
);
757 if (body
!= "hello\n")
758 return "URLLoader::FollowRedirect failed";
763 std::string
TestURLLoader::TestAbortCalls() {
764 pp::URLRequestInfo
request(instance_
);
765 request
.SetURL("test_url_loader_data/hello.txt");
767 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
772 rv
= pp::URLLoader(instance_
).Open(request
, callback
.GetCallback());
774 callback
.WaitForAbortResult(rv
);
775 CHECK_CALLBACK_BEHAVIOR(callback
);
777 // Abort |ReadResponseBody()|.
781 pp::URLLoader
loader(instance_
);
782 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
783 CHECK_CALLBACK_BEHAVIOR(callback
);
784 ASSERT_EQ(PP_OK
, callback
.result());
786 rv
= loader
.ReadResponseBody(buf
, sizeof(buf
), callback
.GetCallback());
787 } // Destroy |loader|.
788 callback
.WaitForAbortResult(rv
);
789 CHECK_CALLBACK_BEHAVIOR(callback
);
790 if (rv
== PP_OK_COMPLETIONPENDING
) {
791 if (buf
[0] || buf
[1]) {
792 return "URLLoader::ReadResponseBody wrote data after resource "
798 // TODO(viettrungluu): More abort tests (but add basic tests first).
799 // Also test that Close() aborts properly. crbug.com/69457
804 std::string
TestURLLoader::TestUntendedLoad() {
805 pp::URLRequestInfo
request(instance_
);
806 request
.SetURL("test_url_loader_data/hello.txt");
807 request
.SetRecordDownloadProgress(true);
808 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
810 pp::URLLoader
loader(instance_
);
811 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
812 CHECK_CALLBACK_BEHAVIOR(callback
);
813 ASSERT_EQ(PP_OK
, callback
.result());
815 // We received the response callback. Yield until the network code has called
816 // the loader's didReceiveData and didFinishLoading methods before we give it
817 // another callback function, to make sure the loader works with no callback.
818 int64_t bytes_received
= 0;
819 int64_t total_bytes_to_be_received
= 0;
821 loader
.GetDownloadProgress(&bytes_received
, &total_bytes_to_be_received
);
822 if (total_bytes_to_be_received
<= 0)
823 return ReportError("URLLoader::GetDownloadProgress total size",
824 total_bytes_to_be_received
);
825 if (bytes_received
== total_bytes_to_be_received
)
827 // Yield if we're on the main thread, so that URLLoader can receive more
829 if (pp::Module::Get()->core()->IsMainThread()) {
830 NestedEvent
event(instance_
->pp_instance());
831 event
.PostSignal(10);
835 // The loader should now have the data and have finished successfully.
837 std::string error
= ReadEntireResponseBody(&loader
, &body
);
840 if (body
!= "hello\n")
841 return ReportError("Couldn't read data", callback
.result());
846 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower
,
848 pp::URLRequestInfo
request(instance_
);
849 request
.SetURL("test_url_loader_data/hello.txt");
850 request
.SetPrefetchBufferLowerThreshold(lower
);
851 request
.SetPrefetchBufferUpperThreshold(upper
);
853 return OpenUntrusted(request
);
856 std::string
TestURLLoader::TestPrefetchBufferThreshold() {
857 int32_t rv
= OpenWithPrefetchBufferThreshold(-1, 1);
858 if (rv
!= PP_ERROR_FAILED
) {
859 return ReportError("The prefetch limits contained a negative value but "
860 "the URLLoader did not fail.", rv
);
863 rv
= OpenWithPrefetchBufferThreshold(0, 1);
865 return ReportError("The prefetch buffer limits were legal values but "
866 "the URLLoader failed.", rv
);
869 rv
= OpenWithPrefetchBufferThreshold(1000, 1);
870 if (rv
!= PP_ERROR_FAILED
) {
871 return ReportError("The lower buffer value was higher than the upper but "
872 "the URLLoader did not fail.", rv
);
878 // TODO(viettrungluu): Add tests for Get{Upload,Download}Progress, Close
879 // (including abort tests if applicable).