OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013, Google Inc. All rights reserved. | 2 * Copyright (c) 2013, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 20 matching lines...) Expand all Loading... |
31 #include "core/fetch/ResourceFetcher.h" | 31 #include "core/fetch/ResourceFetcher.h" |
32 | 32 |
33 #include "core/fetch/FetchInitiatorInfo.h" | 33 #include "core/fetch/FetchInitiatorInfo.h" |
34 #include "core/fetch/FetchInitiatorTypeNames.h" | 34 #include "core/fetch/FetchInitiatorTypeNames.h" |
35 #include "core/fetch/FetchRequest.h" | 35 #include "core/fetch/FetchRequest.h" |
36 #include "core/fetch/MemoryCache.h" | 36 #include "core/fetch/MemoryCache.h" |
37 #include "core/fetch/RawResource.h" | 37 #include "core/fetch/RawResource.h" |
38 #include "core/fetch/ResourceLoader.h" | 38 #include "core/fetch/ResourceLoader.h" |
39 #include "platform/exported/WrappedResourceResponse.h" | 39 #include "platform/exported/WrappedResourceResponse.h" |
40 #include "platform/heap/Handle.h" | 40 #include "platform/heap/Handle.h" |
| 41 #include "platform/heap/HeapAllocator.h" |
| 42 #include "platform/heap/Member.h" |
41 #include "platform/network/ResourceRequest.h" | 43 #include "platform/network/ResourceRequest.h" |
| 44 #include "platform/network/ResourceTimingInfo.h" |
42 #include "platform/testing/URLTestHelpers.h" | 45 #include "platform/testing/URLTestHelpers.h" |
| 46 #include "platform/testing/weburl_loader_mock.h" |
43 #include "platform/weborigin/KURL.h" | 47 #include "platform/weborigin/KURL.h" |
44 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
45 #include "public/platform/WebTaskRunner.h" | 49 #include "public/platform/WebTaskRunner.h" |
46 #include "public/platform/WebURLLoaderMockFactory.h" | 50 #include "public/platform/WebURLLoaderMockFactory.h" |
47 #include "public/platform/WebURLResponse.h" | 51 #include "public/platform/WebURLResponse.h" |
48 #include "testing/gtest/include/gtest/gtest.h" | 52 #include "testing/gtest/include/gtest/gtest.h" |
| 53 #include "wtf/Allocator.h" |
49 #include "wtf/PtrUtil.h" | 54 #include "wtf/PtrUtil.h" |
| 55 #include "wtf/Vector.h" |
50 #include <memory> | 56 #include <memory> |
51 | 57 |
52 namespace blink { | 58 namespace blink { |
53 | 59 |
54 namespace { | 60 namespace { |
55 | 61 |
| 62 const char testImageFilename[] = "white-1x1.png"; |
| 63 const int testImageSize = 103; // size of web/tests/data/white-1x1.png |
| 64 |
56 class MockTaskRunner : public blink::WebTaskRunner { | 65 class MockTaskRunner : public blink::WebTaskRunner { |
57 void postTask(const WebTraceLocation&, Task*) override { } | 66 void postTask(const WebTraceLocation&, Task*) override { } |
58 void postDelayedTask(const WebTraceLocation&, Task*, double) override { } | 67 void postDelayedTask(const WebTraceLocation&, Task*, double) override { } |
59 WebTaskRunner* clone() override { return nullptr; } | 68 WebTaskRunner* clone() override { return nullptr; } |
60 double virtualTimeSeconds() const override { return 0.0; } | 69 double virtualTimeSeconds() const override { return 0.0; } |
61 double monotonicallyIncreasingVirtualTimeSeconds() const override { return 0
.0; } | 70 double monotonicallyIncreasingVirtualTimeSeconds() const override { return 0
.0; } |
62 }; | 71 }; |
63 | 72 |
64 } | 73 } |
65 | 74 |
66 class ResourceFetcherTestMockFetchContext : public FetchContext { | 75 class ResourceFetcherTestMockFetchContext : public FetchContext { |
67 public: | 76 public: |
68 static ResourceFetcherTestMockFetchContext* create() | 77 static ResourceFetcherTestMockFetchContext* create() |
69 { | 78 { |
70 return new ResourceFetcherTestMockFetchContext; | 79 return new ResourceFetcherTestMockFetchContext; |
71 } | 80 } |
72 | 81 |
73 virtual ~ResourceFetcherTestMockFetchContext() { } | 82 virtual ~ResourceFetcherTestMockFetchContext() { } |
74 | 83 |
75 bool allowImage(bool imagesEnabled, const KURL&) const override { return tru
e; } | 84 bool allowImage(bool imagesEnabled, const KURL&) const override { return tru
e; } |
76 bool canRequest(Resource::Type, const ResourceRequest&, const KURL&, const R
esourceLoaderOptions&, bool forPreload, FetchRequest::OriginRestriction) const o
verride { return true; } | 85 bool canRequest(Resource::Type, const ResourceRequest&, const KURL&, const R
esourceLoaderOptions&, bool forPreload, FetchRequest::OriginRestriction) const o
verride { return true; } |
77 bool shouldLoadNewResource(Resource::Type) const override { return true; } | 86 bool shouldLoadNewResource(Resource::Type) const override { return true; } |
78 WebTaskRunner* loadingTaskRunner() const override { return m_runner.get(); } | 87 WebTaskRunner* loadingTaskRunner() const override { return m_runner.get(); } |
79 | 88 |
80 void setCachePolicy(CachePolicy policy) { m_policy = policy; } | 89 void setCachePolicy(CachePolicy policy) { m_policy = policy; } |
81 CachePolicy getCachePolicy() const override { return m_policy; } | 90 CachePolicy getCachePolicy() const override { return m_policy; } |
82 void setLoadComplete(bool complete) { m_complete = complete; } | 91 void setLoadComplete(bool complete) { m_complete = complete; } |
83 bool isLoadComplete() const override { return m_complete; } | 92 bool isLoadComplete() const override { return m_complete; } |
84 | 93 |
| 94 void addResourceTiming(const ResourceTimingInfo& resourceTimingInfo) overrid
e { m_transferSize = resourceTimingInfo.transferSize(); } |
| 95 long long getTransferSize() const { return m_transferSize; } |
| 96 |
85 private: | 97 private: |
86 ResourceFetcherTestMockFetchContext() | 98 ResourceFetcherTestMockFetchContext() |
87 : m_policy(CachePolicyVerify) | 99 : m_policy(CachePolicyVerify) |
88 , m_runner(wrapUnique(new MockTaskRunner)) | 100 , m_runner(wrapUnique(new MockTaskRunner)) |
89 , m_complete(false) | 101 , m_complete(false) |
| 102 , m_transferSize(-1) |
90 { } | 103 { } |
91 | 104 |
92 CachePolicy m_policy; | 105 CachePolicy m_policy; |
93 std::unique_ptr<MockTaskRunner> m_runner; | 106 std::unique_ptr<MockTaskRunner> m_runner; |
94 bool m_complete; | 107 bool m_complete; |
| 108 long long m_transferSize; |
95 }; | 109 }; |
96 | 110 |
97 class ResourceFetcherTest : public ::testing::Test { | 111 class ResourceFetcherTest : public ::testing::Test { |
98 }; | 112 }; |
99 | 113 |
100 class TestResourceFactory : public ResourceFactory { | 114 class TestResourceFactory : public ResourceFactory { |
101 public: | 115 public: |
102 TestResourceFactory(Resource::Type type = Resource::Raw) | 116 TestResourceFactory(Resource::Type type = Resource::Raw) |
103 : ResourceFactory(type) { } | 117 : ResourceFactory(type) { } |
104 | 118 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 TEST_F(ResourceFetcherTest, VaryImage) | 212 TEST_F(ResourceFetcherTest, VaryImage) |
199 { | 213 { |
200 ResourceFetcher* fetcher = ResourceFetcher::create(ResourceFetcherTestMockFe
tchContext::create()); | 214 ResourceFetcher* fetcher = ResourceFetcher::create(ResourceFetcherTestMockFe
tchContext::create()); |
201 | 215 |
202 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | 216 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); |
203 ResourceResponse response; | 217 ResourceResponse response; |
204 response.setURL(url); | 218 response.setURL(url); |
205 response.setHTTPStatusCode(200); | 219 response.setHTTPStatusCode(200); |
206 response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600"); | 220 response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600"); |
207 response.setHTTPHeaderField(HTTPNames::Vary, "*"); | 221 response.setHTTPHeaderField(HTTPNames::Vary, "*"); |
208 URLTestHelpers::registerMockedURLLoadWithCustomResponse(url, "white-1x1.png"
, WebString::fromUTF8(""), WrappedResourceResponse(response)); | 222 URLTestHelpers::registerMockedURLLoadWithCustomResponse(url, testImageFilena
me, WebString::fromUTF8(""), WrappedResourceResponse(response)); |
209 | 223 |
210 FetchRequest fetchRequestOriginal = FetchRequest(url, FetchInitiatorInfo()); | 224 FetchRequest fetchRequestOriginal = FetchRequest(url, FetchInitiatorInfo()); |
211 Resource* resource = fetcher->requestResource(fetchRequestOriginal, TestReso
urceFactory(Resource::Image)); | 225 Resource* resource = fetcher->requestResource(fetchRequestOriginal, TestReso
urceFactory(Resource::Image)); |
212 ASSERT_TRUE(resource); | 226 ASSERT_TRUE(resource); |
213 Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); | 227 Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); |
214 ASSERT_TRUE(resource->hasVaryHeader()); | 228 ASSERT_TRUE(resource->hasVaryHeader()); |
215 | 229 |
216 FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo()); | 230 FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo()); |
217 Resource* newResource = fetcher->requestResource(fetchRequest, TestResourceF
actory(Resource::Image)); | 231 Resource* newResource = fetcher->requestResource(fetchRequest, TestResourceF
actory(Resource::Image)); |
218 EXPECT_EQ(resource, newResource); | 232 EXPECT_EQ(resource, newResource); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 // This emulates a modal dialog triggering a nested run loop inside | 386 // This emulates a modal dialog triggering a nested run loop inside |
373 // ResourceLoader::cancel(). If the ResourceLoader doesn't promptly cancel its | 387 // ResourceLoader::cancel(). If the ResourceLoader doesn't promptly cancel its |
374 // WebURLLoader before notifying its clients, a nested run loop may send a | 388 // WebURLLoader before notifying its clients, a nested run loop may send a |
375 // network response, leading to an invalid state transition in ResourceLoader. | 389 // network response, leading to an invalid state transition in ResourceLoader. |
376 TEST_F(ResourceFetcherTest, ResponseOnCancel) | 390 TEST_F(ResourceFetcherTest, ResponseOnCancel) |
377 { | 391 { |
378 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | 392 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); |
379 ResourceResponse response; | 393 ResourceResponse response; |
380 response.setURL(url); | 394 response.setURL(url); |
381 response.setHTTPStatusCode(200); | 395 response.setHTTPStatusCode(200); |
382 URLTestHelpers::registerMockedURLLoadWithCustomResponse(url, "white-1x1.png"
, WebString::fromUTF8(""), WrappedResourceResponse(response)); | 396 URLTestHelpers::registerMockedURLLoadWithCustomResponse(url, testImageFilena
me, WebString::fromUTF8(""), WrappedResourceResponse(response)); |
383 | 397 |
384 ResourceFetcher* fetcher = ResourceFetcher::create(ResourceFetcherTestMockFe
tchContext::create()); | 398 ResourceFetcher* fetcher = ResourceFetcher::create(ResourceFetcherTestMockFe
tchContext::create()); |
385 FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo()); | 399 FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo()); |
386 Resource* resource = fetcher->requestResource(fetchRequest, TestResourceFact
ory(Resource::Raw)); | 400 Resource* resource = fetcher->requestResource(fetchRequest, TestResourceFact
ory(Resource::Raw)); |
387 Persistent<ServeRequestsOnCompleteClient> client = new ServeRequestsOnComple
teClient(); | 401 Persistent<ServeRequestsOnCompleteClient> client = new ServeRequestsOnComple
teClient(); |
388 resource->addClient(client); | 402 resource->addClient(client); |
389 resource->loader()->cancel(); | 403 resource->loader()->cancel(); |
390 resource->removeClient(client); | 404 resource->removeClient(client); |
391 Platform::current()->getURLLoaderMockFactory()->unregisterURL(url); | 405 Platform::current()->getURLLoaderMockFactory()->unregisterURL(url); |
392 } | 406 } |
393 | 407 |
| 408 class ScopedMockRedirectRequester { |
| 409 STACK_ALLOCATED(); |
| 410 WTF_MAKE_NONCOPYABLE(ScopedMockRedirectRequester); |
| 411 |
| 412 public: |
| 413 ScopedMockRedirectRequester() |
| 414 : m_context(nullptr) |
| 415 { |
| 416 } |
| 417 |
| 418 ~ScopedMockRedirectRequester() |
| 419 { |
| 420 cleanUp(); |
| 421 } |
| 422 |
| 423 void registerRedirect(const WebString& fromURL, const WebString& toURL) |
| 424 { |
| 425 KURL redirectURL(ParsedURLString, fromURL); |
| 426 WebURLResponse redirectResponse; |
| 427 redirectResponse.initialize(); |
| 428 redirectResponse.setURL(redirectURL); |
| 429 redirectResponse.setHTTPStatusCode(301); |
| 430 redirectResponse.setHTTPHeaderField(HTTPNames::Location, toURL); |
| 431 Platform::current()->getURLLoaderMockFactory()->registerURL(redirectURL,
redirectResponse, ""); |
| 432 m_registeredURLs.append(redirectURL); |
| 433 } |
| 434 |
| 435 void registerFinalResource(const WebString& url) |
| 436 { |
| 437 KURL finalURL(ParsedURLString, url); |
| 438 WebURLResponse finalResponse; |
| 439 finalResponse.initialize(); |
| 440 finalResponse.setURL(finalURL); |
| 441 finalResponse.setHTTPStatusCode(200); |
| 442 URLTestHelpers::registerMockedURLLoadWithCustomResponse(finalURL, testIm
ageFilename, "", finalResponse); |
| 443 m_registeredURLs.append(finalURL); |
| 444 } |
| 445 |
| 446 void request(const WebString& url) |
| 447 { |
| 448 DCHECK(!m_context); |
| 449 m_context = ResourceFetcherTestMockFetchContext::create(); |
| 450 ResourceFetcher* fetcher = ResourceFetcher::create(m_context); |
| 451 FetchRequest fetchRequest = FetchRequest(ResourceRequest(url), FetchInit
iatorInfo()); |
| 452 Resource* resource = fetcher->requestResource(fetchRequest, TestResource
Factory()); |
| 453 m_cachedResources.append(resource); |
| 454 Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequest
s(); |
| 455 } |
| 456 |
| 457 void cleanUp() |
| 458 { |
| 459 for (const KURL& url : m_registeredURLs) { |
| 460 Platform::current()->getURLLoaderMockFactory()->unregisterURL(url); |
| 461 } |
| 462 m_registeredURLs.clear(); |
| 463 for (const auto& resource : m_cachedResources) { |
| 464 memoryCache()->remove(resource); |
| 465 } |
| 466 m_cachedResources.clear(); |
| 467 } |
| 468 |
| 469 ResourceFetcherTestMockFetchContext* context() const { return m_context; } |
| 470 |
| 471 private: |
| 472 Vector<KURL> m_registeredURLs; |
| 473 HeapVector<Member<Resource>> m_cachedResources; |
| 474 Member<ResourceFetcherTestMockFetchContext> m_context; |
| 475 }; |
| 476 |
| 477 TEST_F(ResourceFetcherTest, SameOriginRedirect) |
| 478 { |
| 479 const char redirectURL[] = "http://127.0.0.1:8000/redirect.html"; |
| 480 const char finalURL[] = "http://127.0.0.1:8000/final.html"; |
| 481 ScopedMockRedirectRequester requester; |
| 482 requester.registerRedirect(redirectURL, finalURL); |
| 483 requester.registerFinalResource(finalURL); |
| 484 requester.request(redirectURL); |
| 485 |
| 486 EXPECT_EQ(kRedirectResponseOverheadBytes + testImageSize, requester.context(
)->getTransferSize()); |
| 487 } |
| 488 |
| 489 TEST_F(ResourceFetcherTest, CrossOriginRedirect) |
| 490 { |
| 491 const char redirectURL[] = "http://otherorigin.test/redirect.html"; |
| 492 const char finalURL[] = "http://127.0.0.1:8000/final.html"; |
| 493 ScopedMockRedirectRequester requester; |
| 494 requester.registerRedirect(redirectURL, finalURL); |
| 495 requester.registerFinalResource(finalURL); |
| 496 requester.request(redirectURL); |
| 497 |
| 498 EXPECT_EQ(testImageSize, requester.context()->getTransferSize()); |
| 499 } |
| 500 |
| 501 TEST_F(ResourceFetcherTest, ComplexCrossOriginRedirect) |
| 502 { |
| 503 const char redirectURL1[] = "http://127.0.0.1:8000/redirect1.html"; |
| 504 const char redirectURL2[] = "http://otherorigin.test/redirect2.html"; |
| 505 const char redirectURL3[] = "http://127.0.0.1:8000/redirect3.html"; |
| 506 const char finalURL[] = "http://127.0.0.1:8000/final.html"; |
| 507 ScopedMockRedirectRequester requester; |
| 508 requester.registerRedirect(redirectURL1, redirectURL2); |
| 509 requester.registerRedirect(redirectURL2, redirectURL3); |
| 510 requester.registerRedirect(redirectURL3, finalURL); |
| 511 requester.registerFinalResource(finalURL); |
| 512 requester.request(redirectURL1); |
| 513 |
| 514 EXPECT_EQ(testImageSize, requester.context()->getTransferSize()); |
| 515 } |
| 516 |
394 } // namespace blink | 517 } // namespace blink |
OLD | NEW |