| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2013, Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 #include "core/fetch/RawResource.h" | |
| 32 | |
| 33 #include "core/fetch/MemoryCache.h" | |
| 34 #include "core/fetch/ResourceFetcher.h" | |
| 35 #include "platform/SharedBuffer.h" | |
| 36 #include "platform/heap/Handle.h" | |
| 37 #include "platform/network/ResourceTimingInfo.h" | |
| 38 #include "platform/testing/UnitTestHelpers.h" | |
| 39 #include "public/platform/Platform.h" | |
| 40 #include "public/platform/WebScheduler.h" | |
| 41 #include "public/platform/WebThread.h" | |
| 42 #include "public/platform/WebURL.h" | |
| 43 #include "public/platform/WebURLResponse.h" | |
| 44 #include "testing/gmock/include/gmock/gmock.h" | |
| 45 #include "testing/gtest/include/gtest/gtest.h" | |
| 46 | |
| 47 namespace blink { | |
| 48 | |
| 49 using ::testing::InSequence; | |
| 50 using ::testing::_; | |
| 51 using Checkpoint = ::testing::StrictMock<::testing::MockFunction<void(int)>>; | |
| 52 | |
| 53 class MockRawResourceClient | |
| 54 : public GarbageCollectedFinalized<MockRawResourceClient>, | |
| 55 public RawResourceClient { | |
| 56 USING_GARBAGE_COLLECTED_MIXIN(MockRawResourceClient); | |
| 57 | |
| 58 public: | |
| 59 static MockRawResourceClient* create() { | |
| 60 return new ::testing::StrictMock<MockRawResourceClient>; | |
| 61 } | |
| 62 | |
| 63 MOCK_METHOD3(dataSent, | |
| 64 void(Resource*, unsigned long long, unsigned long long)); | |
| 65 MOCK_METHOD3(responseReceivedInternal, | |
| 66 void(Resource*, | |
| 67 const ResourceResponse&, | |
| 68 WebDataConsumerHandle*)); | |
| 69 MOCK_METHOD3(setSerializedCachedMetadata, | |
| 70 void(Resource*, const char*, size_t)); | |
| 71 MOCK_METHOD3(dataReceived, void(Resource*, const char*, size_t)); | |
| 72 MOCK_METHOD3(redirectReceived, | |
| 73 bool(Resource*, | |
| 74 const ResourceRequest&, | |
| 75 const ResourceResponse&)); | |
| 76 MOCK_METHOD0(redirectBlocked, void()); | |
| 77 MOCK_METHOD2(dataDownloaded, void(Resource*, int)); | |
| 78 MOCK_METHOD2(didReceiveResourceTiming, | |
| 79 void(Resource*, const ResourceTimingInfo&)); | |
| 80 | |
| 81 void responseReceived( | |
| 82 Resource* resource, | |
| 83 const ResourceResponse& response, | |
| 84 std::unique_ptr<WebDataConsumerHandle> handle) override { | |
| 85 responseReceivedInternal(resource, response, handle.get()); | |
| 86 } | |
| 87 | |
| 88 String debugName() const override { return "MockRawResourceClient"; } | |
| 89 | |
| 90 DEFINE_INLINE_VIRTUAL_TRACE() { RawResourceClient::trace(visitor); } | |
| 91 | |
| 92 protected: | |
| 93 MockRawResourceClient() = default; | |
| 94 }; | |
| 95 | |
| 96 TEST(RawResourceTest, DontIgnoreAcceptForCacheReuse) { | |
| 97 ResourceRequest jpegRequest; | |
| 98 jpegRequest.setHTTPAccept("image/jpeg"); | |
| 99 | |
| 100 RawResource* jpegResource(RawResource::create(jpegRequest, Resource::Raw)); | |
| 101 | |
| 102 ResourceRequest pngRequest; | |
| 103 pngRequest.setHTTPAccept("image/png"); | |
| 104 | |
| 105 EXPECT_FALSE(jpegResource->canReuse(pngRequest)); | |
| 106 } | |
| 107 | |
| 108 class DummyClient final : public GarbageCollectedFinalized<DummyClient>, | |
| 109 public RawResourceClient { | |
| 110 USING_GARBAGE_COLLECTED_MIXIN(DummyClient); | |
| 111 | |
| 112 public: | |
| 113 DummyClient() : m_called(false), m_numberOfRedirectsReceived(0) {} | |
| 114 ~DummyClient() override {} | |
| 115 | |
| 116 // ResourceClient implementation. | |
| 117 void notifyFinished(Resource* resource) override { m_called = true; } | |
| 118 String debugName() const override { return "DummyClient"; } | |
| 119 | |
| 120 void dataReceived(Resource*, const char* data, size_t length) override { | |
| 121 m_data.append(data, length); | |
| 122 } | |
| 123 | |
| 124 bool redirectReceived(Resource*, | |
| 125 const ResourceRequest&, | |
| 126 const ResourceResponse&) override { | |
| 127 ++m_numberOfRedirectsReceived; | |
| 128 return true; | |
| 129 } | |
| 130 | |
| 131 bool called() { return m_called; } | |
| 132 int numberOfRedirectsReceived() const { return m_numberOfRedirectsReceived; } | |
| 133 const Vector<char>& data() { return m_data; } | |
| 134 DEFINE_INLINE_TRACE() { RawResourceClient::trace(visitor); } | |
| 135 | |
| 136 private: | |
| 137 bool m_called; | |
| 138 int m_numberOfRedirectsReceived; | |
| 139 Vector<char> m_data; | |
| 140 }; | |
| 141 | |
| 142 // This client adds another client when notified. | |
| 143 class AddingClient final : public GarbageCollectedFinalized<AddingClient>, | |
| 144 public RawResourceClient { | |
| 145 USING_GARBAGE_COLLECTED_MIXIN(AddingClient); | |
| 146 | |
| 147 public: | |
| 148 AddingClient(DummyClient* client, Resource* resource) | |
| 149 : m_dummyClient(client), | |
| 150 m_resource(resource), | |
| 151 m_removeClientTimer(this, &AddingClient::removeClient) {} | |
| 152 | |
| 153 ~AddingClient() override {} | |
| 154 | |
| 155 // ResourceClient implementation. | |
| 156 void notifyFinished(Resource* resource) override { | |
| 157 // First schedule an asynchronous task to remove the client. | |
| 158 // We do not expect the client to be called. | |
| 159 m_removeClientTimer.startOneShot(0, BLINK_FROM_HERE); | |
| 160 resource->addClient(m_dummyClient); | |
| 161 } | |
| 162 String debugName() const override { return "AddingClient"; } | |
| 163 | |
| 164 void removeClient(TimerBase* timer) { | |
| 165 m_resource->removeClient(m_dummyClient); | |
| 166 } | |
| 167 | |
| 168 DEFINE_INLINE_VIRTUAL_TRACE() { | |
| 169 visitor->trace(m_dummyClient); | |
| 170 visitor->trace(m_resource); | |
| 171 RawResourceClient::trace(visitor); | |
| 172 } | |
| 173 | |
| 174 private: | |
| 175 Member<DummyClient> m_dummyClient; | |
| 176 Member<Resource> m_resource; | |
| 177 Timer<AddingClient> m_removeClientTimer; | |
| 178 }; | |
| 179 | |
| 180 TEST(RawResourceTest, RevalidationSucceeded) { | |
| 181 Resource* resource = | |
| 182 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 183 ResourceResponse response; | |
| 184 response.setHTTPStatusCode(200); | |
| 185 resource->responseReceived(response, nullptr); | |
| 186 const char data[5] = "abcd"; | |
| 187 resource->appendData(data, 4); | |
| 188 resource->finish(); | |
| 189 memoryCache()->add(resource); | |
| 190 | |
| 191 // Simulate a successful revalidation. | |
| 192 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
| 193 | |
| 194 Persistent<DummyClient> client = new DummyClient; | |
| 195 resource->addClient(client); | |
| 196 | |
| 197 ResourceResponse revalidatingResponse; | |
| 198 revalidatingResponse.setHTTPStatusCode(304); | |
| 199 resource->responseReceived(revalidatingResponse, nullptr); | |
| 200 EXPECT_FALSE(resource->isCacheValidator()); | |
| 201 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
| 202 EXPECT_EQ(4u, resource->resourceBuffer()->size()); | |
| 203 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
| 204 KURL(ParsedURLString, "data:text/html,"))); | |
| 205 memoryCache()->remove(resource); | |
| 206 | |
| 207 resource->removeClient(client); | |
| 208 EXPECT_FALSE(resource->isAlive()); | |
| 209 EXPECT_FALSE(client->called()); | |
| 210 EXPECT_EQ("abcd", String(client->data().data(), client->data().size())); | |
| 211 } | |
| 212 | |
| 213 TEST(RawResourceTest, RevalidationSucceededForResourceWithoutBody) { | |
| 214 Resource* resource = | |
| 215 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 216 ResourceResponse response; | |
| 217 response.setHTTPStatusCode(200); | |
| 218 resource->responseReceived(response, nullptr); | |
| 219 resource->finish(); | |
| 220 memoryCache()->add(resource); | |
| 221 | |
| 222 // Simulate a successful revalidation. | |
| 223 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
| 224 | |
| 225 Persistent<DummyClient> client = new DummyClient; | |
| 226 resource->addClient(client); | |
| 227 | |
| 228 ResourceResponse revalidatingResponse; | |
| 229 revalidatingResponse.setHTTPStatusCode(304); | |
| 230 resource->responseReceived(revalidatingResponse, nullptr); | |
| 231 EXPECT_FALSE(resource->isCacheValidator()); | |
| 232 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
| 233 EXPECT_FALSE(resource->resourceBuffer()); | |
| 234 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
| 235 KURL(ParsedURLString, "data:text/html,"))); | |
| 236 memoryCache()->remove(resource); | |
| 237 | |
| 238 resource->removeClient(client); | |
| 239 EXPECT_FALSE(resource->isAlive()); | |
| 240 EXPECT_FALSE(client->called()); | |
| 241 EXPECT_EQ(0u, client->data().size()); | |
| 242 } | |
| 243 | |
| 244 TEST(RawResourceTest, RevalidationSucceededUpdateHeaders) { | |
| 245 Resource* resource = | |
| 246 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 247 ResourceResponse response; | |
| 248 response.setHTTPStatusCode(200); | |
| 249 response.addHTTPHeaderField("keep-alive", "keep-alive value"); | |
| 250 response.addHTTPHeaderField("expires", "expires value"); | |
| 251 response.addHTTPHeaderField("last-modified", "last-modified value"); | |
| 252 response.addHTTPHeaderField("proxy-authenticate", "proxy-authenticate value"); | |
| 253 response.addHTTPHeaderField("proxy-connection", "proxy-connection value"); | |
| 254 response.addHTTPHeaderField("x-custom", "custom value"); | |
| 255 resource->responseReceived(response, nullptr); | |
| 256 resource->finish(); | |
| 257 memoryCache()->add(resource); | |
| 258 | |
| 259 // Simulate a successful revalidation. | |
| 260 resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); | |
| 261 | |
| 262 // Validate that these headers pre-update. | |
| 263 EXPECT_EQ("keep-alive value", | |
| 264 resource->response().httpHeaderField("keep-alive")); | |
| 265 EXPECT_EQ("expires value", resource->response().httpHeaderField("expires")); | |
| 266 EXPECT_EQ("last-modified value", | |
| 267 resource->response().httpHeaderField("last-modified")); | |
| 268 EXPECT_EQ("proxy-authenticate value", | |
| 269 resource->response().httpHeaderField("proxy-authenticate")); | |
| 270 EXPECT_EQ("proxy-authenticate value", | |
| 271 resource->response().httpHeaderField("proxy-authenticate")); | |
| 272 EXPECT_EQ("proxy-connection value", | |
| 273 resource->response().httpHeaderField("proxy-connection")); | |
| 274 EXPECT_EQ("custom value", resource->response().httpHeaderField("x-custom")); | |
| 275 | |
| 276 Persistent<DummyClient> client = new DummyClient; | |
| 277 resource->addClient(client.get()); | |
| 278 | |
| 279 // Perform a revalidation step. | |
| 280 ResourceResponse revalidatingResponse; | |
| 281 revalidatingResponse.setHTTPStatusCode(304); | |
| 282 // Headers that aren't copied with an 304 code. | |
| 283 revalidatingResponse.addHTTPHeaderField("keep-alive", "garbage"); | |
| 284 revalidatingResponse.addHTTPHeaderField("expires", "garbage"); | |
| 285 revalidatingResponse.addHTTPHeaderField("last-modified", "garbage"); | |
| 286 revalidatingResponse.addHTTPHeaderField("proxy-authenticate", "garbage"); | |
| 287 revalidatingResponse.addHTTPHeaderField("proxy-connection", "garbage"); | |
| 288 // Header that is updated with 304 code. | |
| 289 revalidatingResponse.addHTTPHeaderField("x-custom", "updated"); | |
| 290 resource->responseReceived(revalidatingResponse, nullptr); | |
| 291 | |
| 292 // Validate the original response. | |
| 293 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
| 294 | |
| 295 // Validate that these headers are not updated. | |
| 296 EXPECT_EQ("keep-alive value", | |
| 297 resource->response().httpHeaderField("keep-alive")); | |
| 298 EXPECT_EQ("expires value", resource->response().httpHeaderField("expires")); | |
| 299 EXPECT_EQ("last-modified value", | |
| 300 resource->response().httpHeaderField("last-modified")); | |
| 301 EXPECT_EQ("proxy-authenticate value", | |
| 302 resource->response().httpHeaderField("proxy-authenticate")); | |
| 303 EXPECT_EQ("proxy-authenticate value", | |
| 304 resource->response().httpHeaderField("proxy-authenticate")); | |
| 305 EXPECT_EQ("proxy-connection value", | |
| 306 resource->response().httpHeaderField("proxy-connection")); | |
| 307 EXPECT_EQ("updated", resource->response().httpHeaderField("x-custom")); | |
| 308 | |
| 309 memoryCache()->remove(resource); | |
| 310 | |
| 311 resource->removeClient(client); | |
| 312 EXPECT_FALSE(resource->isAlive()); | |
| 313 EXPECT_FALSE(client->called()); | |
| 314 EXPECT_EQ(0u, client->data().size()); | |
| 315 } | |
| 316 | |
| 317 TEST(RawResourceTest, RedirectDuringRevalidation) { | |
| 318 Resource* resource = RawResource::create( | |
| 319 ResourceRequest("https://example.com/1"), Resource::Raw); | |
| 320 ResourceResponse response; | |
| 321 response.setURL(KURL(ParsedURLString, "https://example.com/1")); | |
| 322 response.setHTTPStatusCode(200); | |
| 323 resource->responseReceived(response, nullptr); | |
| 324 const char data[5] = "abcd"; | |
| 325 resource->appendData(data, 4); | |
| 326 resource->finish(); | |
| 327 memoryCache()->add(resource); | |
| 328 | |
| 329 EXPECT_FALSE(resource->isCacheValidator()); | |
| 330 EXPECT_EQ("https://example.com/1", | |
| 331 resource->resourceRequest().url().getString()); | |
| 332 EXPECT_EQ("https://example.com/1", | |
| 333 resource->lastResourceRequest().url().getString()); | |
| 334 | |
| 335 // Simulate a revalidation. | |
| 336 resource->setRevalidatingRequest(ResourceRequest("https://example.com/1")); | |
| 337 EXPECT_TRUE(resource->isCacheValidator()); | |
| 338 EXPECT_EQ("https://example.com/1", | |
| 339 resource->resourceRequest().url().getString()); | |
| 340 EXPECT_EQ("https://example.com/1", | |
| 341 resource->lastResourceRequest().url().getString()); | |
| 342 | |
| 343 Persistent<DummyClient> client = new DummyClient; | |
| 344 resource->addClient(client); | |
| 345 | |
| 346 // The revalidating request is redirected. | |
| 347 ResourceResponse redirectResponse; | |
| 348 redirectResponse.setURL(KURL(ParsedURLString, "https://example.com/1")); | |
| 349 redirectResponse.setHTTPHeaderField("location", "https://example.com/2"); | |
| 350 redirectResponse.setHTTPStatusCode(308); | |
| 351 ResourceRequest redirectedRevalidatingRequest("https://example.com/2"); | |
| 352 resource->willFollowRedirect(redirectedRevalidatingRequest, redirectResponse); | |
| 353 EXPECT_FALSE(resource->isCacheValidator()); | |
| 354 EXPECT_EQ("https://example.com/1", | |
| 355 resource->resourceRequest().url().getString()); | |
| 356 EXPECT_EQ("https://example.com/2", | |
| 357 resource->lastResourceRequest().url().getString()); | |
| 358 | |
| 359 // The final response is received. | |
| 360 ResourceResponse revalidatingResponse; | |
| 361 revalidatingResponse.setURL(KURL(ParsedURLString, "https://example.com/2")); | |
| 362 revalidatingResponse.setHTTPStatusCode(200); | |
| 363 resource->responseReceived(revalidatingResponse, nullptr); | |
| 364 const char data2[4] = "xyz"; | |
| 365 resource->appendData(data2, 3); | |
| 366 resource->finish(); | |
| 367 EXPECT_FALSE(resource->isCacheValidator()); | |
| 368 EXPECT_EQ("https://example.com/1", | |
| 369 resource->resourceRequest().url().getString()); | |
| 370 EXPECT_EQ("https://example.com/2", | |
| 371 resource->lastResourceRequest().url().getString()); | |
| 372 EXPECT_FALSE(resource->isCacheValidator()); | |
| 373 EXPECT_EQ(200, resource->response().httpStatusCode()); | |
| 374 EXPECT_EQ(3u, resource->resourceBuffer()->size()); | |
| 375 EXPECT_EQ(resource, memoryCache()->resourceForURL( | |
| 376 KURL(ParsedURLString, "https://example.com/1"))); | |
| 377 | |
| 378 EXPECT_TRUE(client->called()); | |
| 379 EXPECT_EQ(1, client->numberOfRedirectsReceived()); | |
| 380 EXPECT_EQ("xyz", String(client->data().data(), client->data().size())); | |
| 381 | |
| 382 // Test the case where a client is added after revalidation is completed. | |
| 383 Persistent<DummyClient> client2 = new DummyClient; | |
| 384 resource->addClient(client2); | |
| 385 | |
| 386 // Because RawResourceClient is added asynchronously, | |
| 387 // |runPendingTasks()| is called to make |client2| to be notified. | |
| 388 testing::runPendingTasks(); | |
| 389 | |
| 390 EXPECT_TRUE(client2->called()); | |
| 391 EXPECT_EQ(1, client2->numberOfRedirectsReceived()); | |
| 392 EXPECT_EQ("xyz", String(client2->data().data(), client2->data().size())); | |
| 393 | |
| 394 memoryCache()->remove(resource); | |
| 395 | |
| 396 resource->removeClient(client); | |
| 397 resource->removeClient(client2); | |
| 398 EXPECT_FALSE(resource->isAlive()); | |
| 399 } | |
| 400 | |
| 401 TEST(RawResourceTest, AddClientDuringCallback) { | |
| 402 Resource* raw = | |
| 403 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 404 | |
| 405 // Create a non-null response. | |
| 406 ResourceResponse response = raw->response(); | |
| 407 response.setURL(KURL(ParsedURLString, "http://600.613/")); | |
| 408 raw->setResponse(response); | |
| 409 raw->finish(); | |
| 410 EXPECT_FALSE(raw->response().isNull()); | |
| 411 | |
| 412 Persistent<DummyClient> dummyClient = new DummyClient(); | |
| 413 Persistent<AddingClient> addingClient = | |
| 414 new AddingClient(dummyClient.get(), raw); | |
| 415 raw->addClient(addingClient); | |
| 416 testing::runPendingTasks(); | |
| 417 raw->removeClient(addingClient); | |
| 418 EXPECT_FALSE(dummyClient->called()); | |
| 419 EXPECT_FALSE(raw->isAlive()); | |
| 420 } | |
| 421 | |
| 422 // This client removes another client when notified. | |
| 423 class RemovingClient : public GarbageCollectedFinalized<RemovingClient>, | |
| 424 public RawResourceClient { | |
| 425 USING_GARBAGE_COLLECTED_MIXIN(RemovingClient); | |
| 426 | |
| 427 public: | |
| 428 explicit RemovingClient(DummyClient* client) : m_dummyClient(client) {} | |
| 429 | |
| 430 ~RemovingClient() override {} | |
| 431 | |
| 432 // ResourceClient implementation. | |
| 433 void notifyFinished(Resource* resource) override { | |
| 434 resource->removeClient(m_dummyClient); | |
| 435 resource->removeClient(this); | |
| 436 } | |
| 437 String debugName() const override { return "RemovingClient"; } | |
| 438 DEFINE_INLINE_TRACE() { | |
| 439 visitor->trace(m_dummyClient); | |
| 440 RawResourceClient::trace(visitor); | |
| 441 } | |
| 442 | |
| 443 private: | |
| 444 Member<DummyClient> m_dummyClient; | |
| 445 }; | |
| 446 | |
| 447 TEST(RawResourceTest, RemoveClientDuringCallback) { | |
| 448 Resource* raw = | |
| 449 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 450 | |
| 451 // Create a non-null response. | |
| 452 ResourceResponse response = raw->response(); | |
| 453 response.setURL(KURL(ParsedURLString, "http://600.613/")); | |
| 454 raw->setResponse(response); | |
| 455 raw->finish(); | |
| 456 EXPECT_FALSE(raw->response().isNull()); | |
| 457 | |
| 458 Persistent<DummyClient> dummyClient = new DummyClient(); | |
| 459 Persistent<RemovingClient> removingClient = | |
| 460 new RemovingClient(dummyClient.get()); | |
| 461 raw->addClient(dummyClient); | |
| 462 raw->addClient(removingClient); | |
| 463 testing::runPendingTasks(); | |
| 464 EXPECT_FALSE(raw->isAlive()); | |
| 465 } | |
| 466 | |
| 467 // ResourceClient can be added to |m_clients| asynchronously via | |
| 468 // ResourceCallback. When revalidation is started after ResourceCallback is | |
| 469 // scheduled and before it is dispatched, ResourceClient's callbacks should be | |
| 470 // called appropriately. | |
| 471 TEST(RawResourceTest, StartFailedRevalidationWhileResourceCallback) { | |
| 472 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | |
| 473 | |
| 474 ResourceResponse response; | |
| 475 response.setURL(url); | |
| 476 response.setHTTPStatusCode(200); | |
| 477 | |
| 478 ResourceResponse newResponse; | |
| 479 newResponse.setURL(url); | |
| 480 newResponse.setHTTPStatusCode(201); | |
| 481 | |
| 482 Resource* resource = | |
| 483 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 484 resource->responseReceived(response, nullptr); | |
| 485 resource->appendData("oldData", 8); | |
| 486 resource->finish(); | |
| 487 | |
| 488 InSequence s; | |
| 489 Checkpoint checkpoint; | |
| 490 | |
| 491 MockRawResourceClient* client = MockRawResourceClient::create(); | |
| 492 | |
| 493 EXPECT_CALL(checkpoint, Call(1)); | |
| 494 EXPECT_CALL(*client, responseReceivedInternal(resource, newResponse, _)); | |
| 495 EXPECT_CALL(*client, dataReceived(resource, ::testing::StrEq("newData"), 8)); | |
| 496 | |
| 497 // Add a client. No callbacks are made here because ResourceCallback is | |
| 498 // scheduled asynchronously. | |
| 499 resource->addClient(client); | |
| 500 EXPECT_FALSE(resource->isCacheValidator()); | |
| 501 | |
| 502 // Start revalidation. | |
| 503 resource->setRevalidatingRequest(ResourceRequest(url)); | |
| 504 EXPECT_TRUE(resource->isCacheValidator()); | |
| 505 | |
| 506 // Make the ResourceCallback to be dispatched. | |
| 507 testing::runPendingTasks(); | |
| 508 | |
| 509 checkpoint.Call(1); | |
| 510 | |
| 511 resource->responseReceived(newResponse, nullptr); | |
| 512 resource->appendData("newData", 8); | |
| 513 } | |
| 514 | |
| 515 TEST(RawResourceTest, StartSuccessfulRevalidationWhileResourceCallback) { | |
| 516 KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); | |
| 517 | |
| 518 ResourceResponse response; | |
| 519 response.setURL(url); | |
| 520 response.setHTTPStatusCode(200); | |
| 521 | |
| 522 ResourceResponse newResponse; | |
| 523 newResponse.setURL(url); | |
| 524 newResponse.setHTTPStatusCode(304); | |
| 525 | |
| 526 Resource* resource = | |
| 527 RawResource::create(ResourceRequest("data:text/html,"), Resource::Raw); | |
| 528 resource->responseReceived(response, nullptr); | |
| 529 resource->appendData("oldData", 8); | |
| 530 resource->finish(); | |
| 531 | |
| 532 InSequence s; | |
| 533 Checkpoint checkpoint; | |
| 534 | |
| 535 MockRawResourceClient* client = MockRawResourceClient::create(); | |
| 536 | |
| 537 EXPECT_CALL(checkpoint, Call(1)); | |
| 538 EXPECT_CALL(*client, responseReceivedInternal(resource, response, _)); | |
| 539 EXPECT_CALL(*client, dataReceived(resource, ::testing::StrEq("oldData"), 8)); | |
| 540 | |
| 541 // Add a client. No callbacks are made here because ResourceCallback is | |
| 542 // scheduled asynchronously. | |
| 543 resource->addClient(client); | |
| 544 EXPECT_FALSE(resource->isCacheValidator()); | |
| 545 | |
| 546 // Start revalidation. | |
| 547 resource->setRevalidatingRequest(ResourceRequest(url)); | |
| 548 EXPECT_TRUE(resource->isCacheValidator()); | |
| 549 | |
| 550 // Make the ResourceCallback to be dispatched. | |
| 551 testing::runPendingTasks(); | |
| 552 | |
| 553 checkpoint.Call(1); | |
| 554 | |
| 555 resource->responseReceived(newResponse, nullptr); | |
| 556 } | |
| 557 | |
| 558 TEST(RawResourceTest, CanReuseDevToolsEmulateNetworkConditionsClientIdHeader) { | |
| 559 ResourceRequest request("data:text/html,"); | |
| 560 request.setHTTPHeaderField( | |
| 561 HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id, "Foo"); | |
| 562 Resource* raw = RawResource::create(request, Resource::Raw); | |
| 563 EXPECT_TRUE(raw->canReuse(ResourceRequest("data:text/html,"))); | |
| 564 } | |
| 565 | |
| 566 } // namespace blink | |
| OLD | NEW |