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 "config.h" 32 #include "core/fetch/RawResource.h" 33 34 #include "core/fetch/ImageResourceClient.h" 35 #include "core/fetch/MemoryCache.h" 36 #include "core/fetch/MockImageResourceClient.h" 37 #include "core/fetch/ResourceFetcher.h" 38 #include "core/fetch/ResourcePtr.h" 39 #include "core/loader/DocumentLoader.h" 40 #include "core/testing/DummyPageHolder.h" 41 #include "core/testing/UnitTestHelpers.h" 42 #include "platform/SharedBuffer.h" 43 #include "public/platform/Platform.h" 44 #include "public/platform/WebURL.h" 45 #include "public/platform/WebURLResponse.h" 46 #include "public/platform/WebUnitTestSupport.h" 47 48 using namespace WebCore; 49 50 namespace WebCore { 51 52 TEST(RawResourceTest, DontIgnoreAcceptForCacheReuse) 53 { 54 ResourceRequest jpegRequest; 55 jpegRequest.setHTTPAccept("image/jpeg"); 56 57 RawResource jpegResource(jpegRequest, Resource::Raw); 58 59 ResourceRequest pngRequest; 60 pngRequest.setHTTPAccept("image/png"); 61 62 ASSERT_FALSE(jpegResource.canReuse(pngRequest)); 63 } 64 65 TEST(RawResourceTest, RevalidationSucceeded) 66 { 67 // Create two RawResources and set one to revalidate the other. 68 RawResource* oldResourcePointer = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); 69 RawResource* newResourcePointer = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); 70 newResourcePointer->setResourceToRevalidate(oldResourcePointer); 71 ResourcePtr<Resource> oldResource = oldResourcePointer; 72 ResourcePtr<Resource> newResource = newResourcePointer; 73 memoryCache()->add(oldResource.get()); 74 memoryCache()->remove(oldResource.get()); 75 memoryCache()->add(newResource.get()); 76 77 // Simulate a successful revalidation. 78 // The revalidated resource (oldResource) should now be in the cache, newResource 79 // should have been sliently switched to point to the revalidated resource, and 80 // we shouldn't hit any ASSERTs. 81 ResourceResponse response; 82 response.setHTTPStatusCode(304); 83 newResource->responseReceived(response); 84 EXPECT_EQ(memoryCache()->resourceForURL(KURL(ParsedURLString, "data:text/html,")), oldResource.get()); 85 EXPECT_EQ(oldResource.get(), newResource.get()); 86 EXPECT_NE(newResource.get(), newResourcePointer); 87 } 88 89 class DummyClient : public RawResourceClient { 90 public: 91 DummyClient() : m_called(false) { } 92 virtual ~DummyClient() { } 93 94 // ResourceClient implementation. 95 virtual void notifyFinished(Resource* resource) 96 { 97 m_called = true; 98 } 99 100 bool called() { return m_called; } 101 private: 102 bool m_called; 103 }; 104 105 // This client adds another client when notified. 106 class AddingClient : public RawResourceClient { 107 public: 108 AddingClient(DummyClient* client, Resource* resource) 109 : m_dummyClient(client) 110 , m_resource(resource) 111 , m_removeClientTimer(this, &AddingClient::removeClient) { } 112 113 virtual ~AddingClient() { } 114 115 // ResourceClient implementation. 116 virtual void notifyFinished(Resource* resource) 117 { 118 // First schedule an asynchronous task to remove the client. 119 // We do not expect the client to be called. 120 m_removeClientTimer.startOneShot(0, FROM_HERE); 121 resource->addClient(m_dummyClient); 122 } 123 void removeClient(Timer<AddingClient>* timer) 124 { 125 m_resource->removeClient(m_dummyClient); 126 } 127 private: 128 DummyClient* m_dummyClient; 129 Resource* m_resource; 130 Timer<AddingClient> m_removeClientTimer; 131 }; 132 133 TEST(RawResourceTest, AddClientDuringCallback) 134 { 135 ResourcePtr<Resource> raw = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); 136 raw->setLoading(false); 137 138 // Create a non-null response. 139 ResourceResponse response = raw->response(); 140 response.setURL(KURL(ParsedURLString, "http://600.613/")); 141 raw->setResponse(response); 142 EXPECT_FALSE(raw->response().isNull()); 143 144 OwnPtr<DummyClient> dummyClient = adoptPtr(new DummyClient()); 145 OwnPtr<AddingClient> addingClient = adoptPtr(new AddingClient(dummyClient.get(), raw.get())); 146 raw->addClient(addingClient.get()); 147 testing::runPendingTasks(); 148 raw->removeClient(addingClient.get()); 149 EXPECT_FALSE(dummyClient->called()); 150 EXPECT_FALSE(raw->hasClients()); 151 } 152 153 // This client removes another client when notified. 154 class RemovingClient : public RawResourceClient { 155 public: 156 RemovingClient(DummyClient* client) 157 : m_dummyClient(client) { } 158 159 virtual ~RemovingClient() { } 160 161 // ResourceClient implementation. 162 virtual void notifyFinished(Resource* resource) 163 { 164 resource->removeClient(m_dummyClient); 165 resource->removeClient(this); 166 } 167 private: 168 DummyClient* m_dummyClient; 169 }; 170 171 TEST(RawResourceTest, RemoveClientDuringCallback) 172 { 173 ResourcePtr<Resource> raw = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); 174 raw->setLoading(false); 175 176 // Create a non-null response. 177 ResourceResponse response = raw->response(); 178 response.setURL(KURL(ParsedURLString, "http://600.613/")); 179 raw->setResponse(response); 180 EXPECT_FALSE(raw->response().isNull()); 181 182 OwnPtr<DummyClient> dummyClient = adoptPtr(new DummyClient()); 183 OwnPtr<RemovingClient> removingClient = adoptPtr(new RemovingClient(dummyClient.get())); 184 raw->addClient(dummyClient.get()); 185 raw->addClient(removingClient.get()); 186 testing::runPendingTasks(); 187 EXPECT_FALSE(raw->hasClients()); 188 } 189 190 } // namespace WebCore 191