.: Enable reuse of cached main resources
authorjaphet@chromium.org <japhet@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Jan 2013 00:10:05 +0000 (00:10 +0000)
committerjaphet@chromium.org <japhet@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Jan 2013 00:10:05 +0000 (00:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=105667

Reviewed by Antti Koivisto.

* Source/autotools/symbols.filter: Expose MemoryCache::resourceForURL().

Source/WebCore: Enable reuse of cached main resources
https://bugs.webkit.org/show_bug.cgi?id=105667

Reviewed by Antti Koivisto.

Test: http/tests/cache/cached-main-resource.html

* WebCore.exp.in:
* dom/Document.cpp:
(WebCore::Document::hasManifest): Returns true if the <html> element has a non-empty manifest attribute.
* dom/Document.h:
(Document):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadedResourceFromMemoryCache): Don't send delegate callbacks for cache hit here, since
    MainResourceLoader will take care of it.
* loader/MainResourceLoader.cpp:
(WebCore::MainResourceLoader::MainResourceLoader):
(WebCore::MainResourceLoader::receivedError):
(WebCore::MainResourceLoader::willSendRequest):
(WebCore::MainResourceLoader::responseReceived): Don't try to cache loads from the application cache.
(WebCore::MainResourceLoader::didFinishLoading): Don't try to cache loads from the application cache.
(WebCore::MainResourceLoader::load): Ensure we create a resource load identifier for cache hits. Also,
    ensure we correctly popualate fragment identifiers in the ResourceRequest reported to DocumentLoader.
(WebCore::MainResourceLoader::identifier):
* loader/MainResourceLoader.h: Rename m_substituteDataLoadIdentifier to m_identifierForLoadWithoutResourceLoader
    to better describe when it is used.
* loader/cache/CachedRawResource.cpp:
(WebCore::CachedRawResource::didAddClient): Synthesize redirect notifications for cache hits if necessary.
(WebCore::CachedRawResource::willSendRequest): Note the redirects we received.
(WebCore::CachedRawResource::canReuse): Don't reuse a resource if the redirect chain included a "Cache-control: no-store".
* loader/cache/CachedRawResource.h:
(CachedRawResource):
(RedirectPair):
(WebCore::CachedRawResource::RedirectPair::RedirectPair):
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::addClientToSet):: Don't return cached data for a main resource synchronously
* loader/cache/CachedResource.h:
(WebCore::CachedResource::canReuse):
(CachedResource):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::determineRevalidationPolicy): Permit cache reuse for main resources.
* testing/Internals.cpp:
(WebCore::Internals::isLoadingFromMemoryCache):
(WebCore):
* testing/Internals.h:
(Internals):
* testing/Internals.idl:

Source/WebKit/win: Enable reuse of cached main resources
https://bugs.webkit.org/show_bug.cgi?id=105667

Reviewed by Antti Koivisto.

* WebKit.vcproj/WebKitExports.def.in: Expose some MemoryCache symbols for use in Internals.

LayoutTests: Enable reuse of cached main resources
https://bugs.webkit.org/show_bug.cgi?id=105667.

Reviewed by Antti Koivisto.

* http/tests/cache/cached-main-resource-expected.txt: Added.
* http/tests/cache/cached-main-resource.html: Added.
* http/tests/cache/resources/cacheable-iframe.php: Added.
* http/tests/inspector/resource-har-pages-expected.txt:
* http/tests/loading/redirect-methods-expected.txt:
* http/tests/misc/favicon-loads-with-images-disabled-expected.txt:
* http/tests/misc/link-rel-icon-beforeload-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@139683 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
ChangeLog
LayoutTests/ChangeLog
LayoutTests/http/tests/cache/cached-main-resource-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/cache/cached-main-resource.html [new file with mode: 0644]
LayoutTests/http/tests/cache/resources/cacheable-iframe.php [new file with mode: 0644]
LayoutTests/http/tests/inspector/resource-har-pages-expected.txt
LayoutTests/http/tests/loading/redirect-methods-expected.txt
LayoutTests/http/tests/misc/favicon-loads-with-images-disabled-expected.txt
LayoutTests/http/tests/misc/link-rel-icon-beforeload-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/MainResourceLoader.cpp
Source/WebCore/loader/MainResourceLoader.h
Source/WebCore/loader/cache/CachedRawResource.cpp
Source/WebCore/loader/cache/CachedRawResource.h
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebKit.vcproj/WebKitExports.def.in
Source/autotools/symbols.filter

index 5da00e4..3ce5544 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-01-14  Nate Chapin  <japhet@chromium.org>
+
+        Enable reuse of cached main resources
+        https://bugs.webkit.org/show_bug.cgi?id=105667
+
+        Reviewed by Antti Koivisto.
+
+        * Source/autotools/symbols.filter: Expose MemoryCache::resourceForURL().
+
 2013-01-14  Alexandre Rostovtsev  <tetromino@gentoo.org>
 
         Do not hardcode -ldl in OPENGL_LIBS
index bfda75f..c31ee11 100644 (file)
@@ -1,3 +1,18 @@
+2013-01-14  Nate Chapin  <japhet@chromium.org>
+
+        Enable reuse of cached main resources
+        https://bugs.webkit.org/show_bug.cgi?id=105667.
+
+        Reviewed by Antti Koivisto.
+
+        * http/tests/cache/cached-main-resource-expected.txt: Added.
+        * http/tests/cache/cached-main-resource.html: Added.
+        * http/tests/cache/resources/cacheable-iframe.php: Added.
+        * http/tests/inspector/resource-har-pages-expected.txt:
+        * http/tests/loading/redirect-methods-expected.txt:
+        * http/tests/misc/favicon-loads-with-images-disabled-expected.txt:
+        * http/tests/misc/link-rel-icon-beforeload-expected.txt:
+
 2013-01-14  Levi Weintraub  <leviw@chromium.org>
 
         Unreviewed gardening. Marking fast/image/zoomed-offset-size.html as slow on debug.
diff --git a/LayoutTests/http/tests/cache/cached-main-resource-expected.txt b/LayoutTests/http/tests/cache/cached-main-resource-expected.txt
new file mode 100644 (file)
index 0000000..a700cb6
--- /dev/null
@@ -0,0 +1,2 @@
+PASS
diff --git a/LayoutTests/http/tests/cache/cached-main-resource.html b/LayoutTests/http/tests/cache/cached-main-resource.html
new file mode 100644 (file)
index 0000000..a03c239
--- /dev/null
@@ -0,0 +1,24 @@
+<html>
+<body onload="setTimeout(removeAndReload, 0);">
+<div id="result"></div>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function removeAndReload()
+{
+    document.body.removeChild(document.getElementById("iframe"));
+    var newIframe = document.createElement("iframe");
+    newIframe.src = "resources/cacheable-iframe.php";
+    document.body.appendChild(newIframe);
+    var fromCache = internals.isLoadingFromMemoryCache(newIframe.src);
+    document.getElementById("result").appendChild(document.createTextNode(fromCache ? "PASS" : "FAIL"));
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+<iframe id="iframe" src="resources/cacheable-iframe.php"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/cache/resources/cacheable-iframe.php b/LayoutTests/http/tests/cache/resources/cacheable-iframe.php
new file mode 100644 (file)
index 0000000..d27ff83
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+require_once '../../resources/portabilityLayer.php';
+
+$max_age = 12 * 31 * 24 * 60 * 60; //one year
+$expires = gmdate(DATE_RFC1123, time() + $max_age);
+
+header('Cache-Control: public, max-age=' . $max_age);
+header('Expires: ' . $expires);
+header('Content-Type: text/html');
+exit();
+?>
index f46339a..0c2b568 100644 (file)
@@ -1,6 +1,5 @@
 Tests conversion of Inspector's resource representation into HAR format.
 
-Page reloaded.
 {
     0 : {
         id : <string>
@@ -28,4 +27,5 @@ page: page_1 url: http://127.0.0.1:8000/inspector/resources/har-pages-iframe.htm
 page: page_1 url: http://127.0.0.1:8000/inspector/resources/har-pages-navigation-target.html
 page: page_1 url: http://127.0.0.1:8000/inspector/resources/source1.js
 page: page_1 url: http://127.0.0.1:8000/resources/redirect.php?url=/inspector/resources/har-pages-navigation-target.html
+Page reloaded.
 
index 517fe74..cd3a591 100644 (file)
@@ -42,11 +42,11 @@ http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - willSendReq
 http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-form.html, http status code 200>
 frame "1" - didCancelClientRedirectForFrame
 frame "1" - didCommitLoadForFrame
+http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "1" - didFinishDocumentLoadForFrame
 frame "1" - willPerformClientRedirectToURL: http://127.0.0.1:8000/loading/resources/redirect-methods-result.php 
 frame "1" - didHandleOnloadEventsForFrame
 frame "1" - didFinishLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "1" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 302>
@@ -69,11 +69,11 @@ http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - willSendReq
 http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-form.html, http status code 200>
 frame "2" - didCancelClientRedirectForFrame
 frame "2" - didCommitLoadForFrame
+http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "2" - didFinishDocumentLoadForFrame
 frame "2" - willPerformClientRedirectToURL: http://127.0.0.1:8000/loading/resources/redirect-methods-result.php 
 frame "2" - didHandleOnloadEventsForFrame
 frame "2" - didFinishLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "2" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 303>
@@ -96,11 +96,11 @@ http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - willSendReq
 http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-form.html, http status code 200>
 frame "3" - didCancelClientRedirectForFrame
 frame "3" - didCommitLoadForFrame
+http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "3" - didFinishDocumentLoadForFrame
 frame "3" - willPerformClientRedirectToURL: http://127.0.0.1:8000/loading/resources/redirect-methods-result.php 
 frame "3" - didHandleOnloadEventsForFrame
 frame "3" - didFinishLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-form.html - didFinishLoading
 frame "3" - didStartProvisionalLoadForFrame
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse (null)
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> redirectResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, http status code 307>
index c6c9bc5..c23bbfc 100644 (file)
@@ -1,6 +1,7 @@
 <unknown> - didFinishLoading
 http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, main document URL http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, http method GET> redirectResponse (null)
 http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, http status code 200>
+http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html - didFinishLoading
 Radar 6973106 and https://bugs.webkit.org/show_bug.cgi?id=27896 - Favicons still load when automatic image loading is disabled.
 This test uses DRT's resource load delegate callback mode to see if the favicon is loaded even when image loading is off.
 
index 9f3ee65..b51ac55 100644 (file)
@@ -1,5 +1,6 @@
 <unknown> - didFinishLoading
 http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html, main document URL http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html, http method GET> redirectResponse (null)
 http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html, http status code 200>
+http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html - didFinishLoading
 http://127.0.0.1:8000/favicon.ico - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/favicon.ico, main document URL http://127.0.0.1:8000/misc/link-rel-icon-beforeload.html, http method GET> redirectResponse (null)
 This test should not show a request for the favicon dont-load-this.ico, since the beforeload handler on the favicon link returns false. Therefore, if the resource request list below shows a request for dont-load-this.ico, then this test has failed.
index a983409..445d2d8 100644 (file)
@@ -1,3 +1,53 @@
+2013-01-14  Nate Chapin  <japhet@chromium.org>
+
+        Enable reuse of cached main resources
+        https://bugs.webkit.org/show_bug.cgi?id=105667
+
+        Reviewed by Antti Koivisto.
+
+        Test: http/tests/cache/cached-main-resource.html
+
+        * WebCore.exp.in:
+        * dom/Document.cpp:
+        (WebCore::Document::hasManifest): Returns true if the <html> element has a non-empty manifest attribute.
+        * dom/Document.h:
+        (Document):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadedResourceFromMemoryCache): Don't send delegate callbacks for cache hit here, since
+            MainResourceLoader will take care of it.
+        * loader/MainResourceLoader.cpp:
+        (WebCore::MainResourceLoader::MainResourceLoader):
+        (WebCore::MainResourceLoader::receivedError):
+        (WebCore::MainResourceLoader::willSendRequest):
+        (WebCore::MainResourceLoader::responseReceived): Don't try to cache loads from the application cache.
+        (WebCore::MainResourceLoader::didFinishLoading): Don't try to cache loads from the application cache.
+        (WebCore::MainResourceLoader::load): Ensure we create a resource load identifier for cache hits. Also,
+            ensure we correctly popualate fragment identifiers in the ResourceRequest reported to DocumentLoader.
+        (WebCore::MainResourceLoader::identifier):
+        * loader/MainResourceLoader.h: Rename m_substituteDataLoadIdentifier to m_identifierForLoadWithoutResourceLoader
+            to better describe when it is used.
+        * loader/cache/CachedRawResource.cpp:
+        (WebCore::CachedRawResource::didAddClient): Synthesize redirect notifications for cache hits if necessary.
+        (WebCore::CachedRawResource::willSendRequest): Note the redirects we received.
+        (WebCore::CachedRawResource::canReuse): Don't reuse a resource if the redirect chain included a "Cache-control: no-store".
+        * loader/cache/CachedRawResource.h:
+        (CachedRawResource):
+        (RedirectPair):
+        (WebCore::CachedRawResource::RedirectPair::RedirectPair):
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::addClientToSet):: Don't return cached data for a main resource synchronously
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::canReuse):
+        (CachedResource):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::determineRevalidationPolicy): Permit cache reuse for main resources.
+        * testing/Internals.cpp:
+        (WebCore::Internals::isLoadingFromMemoryCache):
+        (WebCore):
+        * testing/Internals.h:
+        (Internals):
+        * testing/Internals.idl:
+
 2013-01-11  Ryosuke Niwa  <rniwa@webkit.org>
 
         Move functions from NodeRareData to ElementRareData and other classes
index 797a7f1..81c5378 100644 (file)
@@ -145,6 +145,7 @@ __ZN7WebCore11MemoryCache11setDisabledEb
 __ZN7WebCore11MemoryCache13getStatisticsEv
 __ZN7WebCore11MemoryCache13setCapacitiesEjjj
 __ZN7WebCore11MemoryCache14evictResourcesEv
+__ZN7WebCore11MemoryCache14resourceForURLERKNS_4KURLE
 __ZN7WebCore11MemoryCache19getOriginsWithCacheERN3WTF7HashSetINS1_6RefPtrINS_14SecurityOriginEEENS_18SecurityOriginHashENS1_10HashTraitsIS5_EEEE
 __ZN7WebCore11MemoryCache25removeResourcesWithOriginEPNS_14SecurityOriginE
 __ZN7WebCore11URLWithDataEP6NSDataP5NSURL
index f859dea..d8afa82 100644 (file)
@@ -845,6 +845,11 @@ DOMImplementation* Document::implementation()
     return m_implementation.get();
 }
 
+bool Document::hasManifest() const
+{
+    return documentElement() && documentElement()->hasTagName(htmlTag) && documentElement()->hasAttribute(manifestAttr);
+}
+
 void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
index a9c5986..077ec03 100644 (file)
@@ -340,6 +340,8 @@ public:
     {
         return m_documentElement.get();
     }
+
+    bool hasManifest() const;
     
     virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
     PassRefPtr<DocumentFragment> createDocumentFragment();
index b7c2dfd..054d31b 100644 (file)
@@ -2887,6 +2887,10 @@ void FrameLoader::loadedResourceFromMemoryCache(CachedResource* resource)
     if (!resource->shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
         return;
 
+    // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
+    if (resource->type() == CachedResource::MainResource)
+        return;
+
     if (!page->areMemoryCacheClientCallsEnabled()) {
         InspectorInstrumentation::didLoadResourceFromMemoryCache(page, m_documentLoader.get(), resource);
         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
index 571fc81..8db0771 100644 (file)
@@ -46,6 +46,7 @@
 #include "HTMLFormElement.h"
 #include "HistoryItem.h"
 #include "InspectorInstrumentation.h"
+#include "MemoryCache.h"
 #include "Page.h"
 #include "ProgressTracker.h"
 #include "ResourceBuffer.h"
@@ -73,7 +74,7 @@ MainResourceLoader::MainResourceLoader(DocumentLoader* documentLoader)
     , m_loadingMultipartContent(false)
     , m_waitingForContentPolicy(false)
     , m_timeOfLastDataReceived(0.0)
-    , m_substituteDataLoadIdentifier(0)
+    , m_identifierForLoadWithoutResourceLoader(0)
 #if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
     , m_filter(0)
 #endif
@@ -99,9 +100,9 @@ void MainResourceLoader::receivedError(const ResourceError& error)
     RefPtr<MainResourceLoader> protect(this);
     RefPtr<Frame> protectFrame(m_documentLoader->frame());
 
-    if (m_substituteDataLoadIdentifier) {
+    if (m_identifierForLoadWithoutResourceLoader) {
         ASSERT(!loader());
-        frameLoader()->client()->dispatchDidFailLoading(documentLoader(), m_substituteDataLoadIdentifier, error);
+        frameLoader()->client()->dispatchDidFailLoading(documentLoader(), m_identifierForLoadWithoutResourceLoader, error);
     }
 
     // It is important that we call DocumentLoader::mainReceivedError before calling 
@@ -286,7 +287,7 @@ void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const Reso
         ASSERT(!m_substituteData.isValid());
         documentLoader()->applicationCacheHost()->maybeLoadMainResourceForRedirect(newRequest, m_substituteData);
         if (m_substituteData.isValid())
-            m_substituteDataLoadIdentifier = identifier();
+            m_identifierForLoadWithoutResourceLoader = identifier();
     }
 
     // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
@@ -392,7 +393,21 @@ void MainResourceLoader::continueAfterContentPolicy(PolicyAction policy)
 void MainResourceLoader::responseReceived(CachedResource* resource, const ResourceResponse& r)
 {
     ASSERT_UNUSED(resource, m_resource == resource);
-    if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainResponse(request(), r))
+    bool willLoadFallback = documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainResponse(request(), r);
+
+    // The memory cache doesn't understand the application cache or its caching rules. So if a main resource is served
+    // from the application cache, ensure we don't save the result for future use.
+    bool shouldRemoveResourceFromCache = willLoadFallback;
+#if PLATFORM(CHROMIUM)
+    // chromium's ApplicationCacheHost implementation always returns true for maybeLoadFallbackForMainResponse(). However, all responses loaded
+    // from appcache will have a non-zero appCacheID().
+    if (r.appCacheID())
+        shouldRemoveResourceFromCache = true;
+#endif
+    if (shouldRemoveResourceFromCache)
+        memoryCache()->remove(m_resource.get());
+
+    if (willLoadFallback)
         return;
 
     DEFINE_STATIC_LOCAL(AtomicString, xFrameOptionHeader, ("x-frame-options", AtomicString::ConstructFromLiteral));
@@ -540,7 +555,7 @@ void MainResourceLoader::didFinishLoading(double finishTime)
 
     if (!loader()) {
         frameLoader()->notifier()->dispatchDidFinishLoading(documentLoader(), identifier(), finishTime);
-        m_substituteDataLoadIdentifier = 0;
+        m_identifierForLoadWithoutResourceLoader = 0;
     }
 
 #if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
@@ -562,6 +577,13 @@ void MainResourceLoader::didFinishLoading(double finishTime)
     documentLoader()->timing()->setResponseEnd(finishTime ? finishTime : (m_timeOfLastDataReceived ? m_timeOfLastDataReceived : monotonicallyIncreasingTime()));
     documentLoader()->finishedLoading();
 
+    // If the document specified an application cache manifest, it violates the author's intent if we store it in the memory cache
+    // and deny the appcache the chance to intercept it in the future, so remove from the memory cache.
+    if (Frame* frame = documentLoader()->frame()) {
+        if (m_resource && frame->document()->hasManifest())
+            memoryCache()->remove(m_resource.get());
+    }
+
     dl->applicationCacheHost()->finishedLoadingMainResource();
 }
 
@@ -671,9 +693,9 @@ void MainResourceLoader::load(const ResourceRequest& initialRequest, const Subst
     documentLoader()->applicationCacheHost()->maybeLoadMainResource(request, m_substituteData);
 
     if (m_substituteData.isValid()) {
-        m_substituteDataLoadIdentifier = m_documentLoader->frame()->page()->progress()->createUniqueIdentifier();
-        frameLoader()->notifier()->assignIdentifierToInitialRequest(m_substituteDataLoadIdentifier, documentLoader(), request);
-        frameLoader()->notifier()->dispatchWillSendRequest(documentLoader(), m_substituteDataLoadIdentifier, request, ResourceResponse());
+        m_identifierForLoadWithoutResourceLoader = m_documentLoader->frame()->page()->progress()->createUniqueIdentifier();
+        frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, documentLoader(), request);
+        frameLoader()->notifier()->dispatchWillSendRequest(documentLoader(), m_identifierForLoadWithoutResourceLoader, request, ResourceResponse());
         handleSubstituteDataLoadSoon(request);
         return;
     }
@@ -686,13 +708,20 @@ void MainResourceLoader::load(const ResourceRequest& initialRequest, const Subst
         documentLoader()->setRequest(ResourceRequest());
         return;
     }
+    if (!loader()) {
+        m_identifierForLoadWithoutResourceLoader = m_documentLoader->frame()->page()->progress()->createUniqueIdentifier();
+        frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, documentLoader(), request);
+        frameLoader()->notifier()->dispatchWillSendRequest(documentLoader(), m_identifierForLoadWithoutResourceLoader, request, ResourceResponse());
+    }
     m_resource->addClient(this);
 
-    // We need to wait until after requestMainResource() is called to setRequest(), because there are a bunch of headers set when
-    // the underlying ResourceLoader is created, and DocumentLoader::m_request needs to include those. However, the cache will
-    // strip the fragment identifier (which DocumentLoader::m_request should also include), so add that back in.
+    // A bunch of headers are set when the underlying ResourceLoader is created, and DocumentLoader::m_request needs to include those.
     if (loader())
         request = loader()->originalRequest();
+    // If there was a fragment identifier on initialRequest, the cache will have stripped it. DocumentLoader::m_request should include
+    // the fragment identifier, so add that back in.
+    if (equalIgnoringFragmentIdentifier(initialRequest.url(), request.url()))
+        request.setURL(initialRequest.url());
     documentLoader()->setRequest(request);
 }
 
@@ -720,9 +749,9 @@ ResourceLoader* MainResourceLoader::loader() const
 
 unsigned long MainResourceLoader::identifier() const
 {
-    ASSERT(!m_substituteDataLoadIdentifier || !loader() || !loader()->identifier());
-    if (m_substituteDataLoadIdentifier)
-        return m_substituteDataLoadIdentifier;
+    ASSERT(!m_identifierForLoadWithoutResourceLoader || !loader() || !loader()->identifier());
+    if (m_identifierForLoadWithoutResourceLoader)
+        return m_identifierForLoadWithoutResourceLoader;
     if (ResourceLoader* resourceLoader = loader())
         return resourceLoader->identifier();
     return 0;
index 5e7fd55..21a7e6e 100644 (file)
@@ -128,7 +128,7 @@ private:
     bool m_loadingMultipartContent;
     bool m_waitingForContentPolicy;
     double m_timeOfLastDataReceived;
-    unsigned long m_substituteDataLoadIdentifier;
+    unsigned long m_identifierForLoadWithoutResourceLoader;
 
 #if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
     WebFilterEvaluator *m_filter;
index 832d223..a6041a6 100644 (file)
@@ -80,14 +80,25 @@ void CachedRawResource::data(PassRefPtr<ResourceBuffer> data, bool allDataReceiv
 
 void CachedRawResource::didAddClient(CachedResourceClient* c)
 {
-    if (m_response.isNull() || !hasClient(c))
+    if (!hasClient(c))
         return;
     // The calls to the client can result in events running, potentially causing
     // this resource to be evicted from the cache and all clients to be removed,
     // so a protector is necessary.
     CachedResourceHandle<CachedRawResource> protect(this);
     CachedRawResourceClient* client = static_cast<CachedRawResourceClient*>(c);
-    client->responseReceived(this, m_response);
+    size_t redirectCount = m_redirectChain.size();
+    for (size_t i = 0; i < redirectCount; i++) {
+        RedirectPair redirect = m_redirectChain[i];
+        ResourceRequest request(redirect.m_request);
+        client->redirectReceived(this, request, redirect.m_redirectResponse);
+        if (!hasClient(c))
+            return;
+    }
+    ASSERT(redirectCount == m_redirectChain.size());
+
+    if (!m_response.isNull())
+        client->responseReceived(this, m_response);
     if (!hasClient(c))
         return;
     if (m_data)
@@ -110,6 +121,7 @@ void CachedRawResource::willSendRequest(ResourceRequest& request, const Resource
         CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
         while (CachedRawResourceClient* c = w.next())
             c->redirectReceived(this, request, response);
+        m_redirectChain.append(RedirectPair(request, response));
     }
     CachedResource::willSendRequest(request, response);
 }
@@ -194,6 +206,12 @@ bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const
         if (!shouldIgnoreHeaderForCacheReuse(headerName) && i->value != newHeaders.get(headerName))
             return false;
     }
+
+    for (size_t i = 0; i < m_redirectChain.size(); i++) {
+        if (m_redirectChain[i].m_redirectResponse.cacheControlContainsNoStore())
+            return false;
+    }
+
     return true;
 }
 
index cb97aba..518afc8 100644 (file)
@@ -48,7 +48,7 @@ public:
     SubresourceLoader* loader() const;
     void clear();
 
-    bool canReuse(const ResourceRequest&) const;
+    virtual bool canReuse(const ResourceRequest&) const;
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
 
@@ -67,6 +67,20 @@ private:
 #endif
 
     unsigned long m_identifier;
+
+    struct RedirectPair {
+    public:
+        explicit RedirectPair(const ResourceRequest& request, const ResourceResponse& redirectResponse)
+            : m_request(request)
+            , m_redirectResponse(redirectResponse)
+        {
+        }
+
+        const ResourceRequest m_request;
+        const ResourceResponse m_redirectResponse;
+    };
+
+    Vector<RedirectPair> m_redirectChain;
 };
 
 
index 88cf286..93f732c 100644 (file)
@@ -497,8 +497,8 @@ bool CachedResource::addClientToSet(CachedResourceClient* client)
     if (!hasClients() && inCache())
         memoryCache()->addToLiveResourcesSize(this);
 
-    if (m_type == RawResource && !m_response.isNull() && !m_proxyResource) {
-        // Certain resources (especially XHRs) do crazy things if an asynchronous load returns
+    if ((m_type == RawResource || m_type == MainResource) && !m_response.isNull() && !m_proxyResource) {
+        // Certain resources (especially XHRs and main resources) do crazy things if an asynchronous load returns
         // synchronously (e.g., scripts may not have set all the state they need to handle the load).
         // Therefore, rather than immediately sending callbacks on a cache hit like other CachedResources,
         // we schedule the callbacks and ensure we never finish synchronously.
index c7ebd54..d8d25eb 100644 (file)
@@ -258,6 +258,8 @@ public:
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const;
 
+    virtual bool canReuse(const ResourceRequest&) const { return true; }
+
 protected:
     virtual void checkNotify();
 
index 97297b1..faed908 100644 (file)
@@ -540,10 +540,7 @@ CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalida
         return Reload;
     }
 
-    if (existingResource->type() == CachedResource::MainResource)
-        return Reload;
-
-    if (existingResource->type() == CachedResource::RawResource && !static_cast<CachedRawResource*>(existingResource)->canReuse(request))
+    if (!existingResource->canReuse(request))
         return Reload;
 
     // Certain requests (e.g., XHRs) might have manually set headers that require revalidation.
index 7c51c12..333f36b 100644 (file)
@@ -65,6 +65,7 @@
 #include "IntRect.h"
 #include "Language.h"
 #include "MallocStatistics.h"
+#include "MemoryCache.h"
 #include "MockPagePopupDriver.h"
 #include "NodeRenderingContext.h"
 #include "Page.h"
@@ -293,6 +294,14 @@ bool Internals::isPreloaded(Document* document, const String& url)
     return document->cachedResourceLoader()->isPreloaded(url);
 }
 
+bool Internals::isLoadingFromMemoryCache(const String& url)
+{
+    if (!contextDocument())
+        return false;
+    CachedResource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url));
+    return resource && resource->status() == CachedResource::Cached;
+}
+
 PassRefPtr<Element> Internals::createContentElement(Document* document, ExceptionCode& ec)
 {
     if (!document) {
index 4ffd706..d7298b0 100644 (file)
@@ -72,6 +72,7 @@ public:
     String address(Node*);
 
     bool isPreloaded(Document*, const String& url);
+    bool isLoadingFromMemoryCache(const String& url);
 
     size_t numberOfScopedHTMLStyleChildren(const Node*, ExceptionCode&) const;
 
index da1e403..ed6ca66 100644 (file)
@@ -30,6 +30,7 @@
 
     DOMString elementRenderTreeAsText(in Element element) raises(DOMException);
     boolean isPreloaded(in Document document, in DOMString url);
+    boolean isLoadingFromMemoryCache(in DOMString url);
 
     unsigned long numberOfScopedHTMLStyleChildren(in Node scope) raises(DOMException);
 
index 6b53916..a5b76aa 100644 (file)
@@ -1,3 +1,12 @@
+2013-01-14  Nate Chapin  <japhet@chromium.org>
+
+        Enable reuse of cached main resources
+        https://bugs.webkit.org/show_bug.cgi?id=105667
+
+        Reviewed by Antti Koivisto.
+
+        * WebKit.vcproj/WebKitExports.def.in: Expose some MemoryCache symbols for use in Internals.
+
 2013-01-09  Hajime Morrita  <morrita@google.com>
 
         [Shadow DOM] Distribution related code on ElementShadow should be minimized.
index 462ef11..66fd384 100644 (file)
@@ -560,6 +560,7 @@ EXPORTS
         ?addSlowCase@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PAVStringImpl@2@@Z
         ?cacheDOMStructure@WebCore@@YAPAVStructure@JSC@@PAVJSDOMGlobalObject@1@PAV23@PBUClassInfo@3@@Z
         ?childItemWithTarget@HistoryItem@WebCore@@QBEPAV12@ABVString@WTF@@@Z
+        ?completeURL@Document@WebCore@@QBE?AVKURL@2@ABVString@WTF@@@Z
         ?create@Range@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@V?$PassRefPtr@VDocument@WebCore@@@4@V?$PassRefPtr@VNode@WebCore@@@4@H1H@Z
         ?create@SerializedScriptValue@WebCore@@SA?AV?$PassRefPtr@VSerializedScriptValue@WebCore@@@WTF@@ABVString@4@@Z
         ?create@SerializedScriptValue@WebCore@@SA?AV?$PassRefPtr@VSerializedScriptValue@WebCore@@@WTF@@PAVExecState@JSC@@VJSValue@6@PAV?$Vector@V?$RefPtr@VMessagePort@WebCore@@@WTF@@$00@4@PAV?$Vector@V?$RefPtr@VArrayBuffer@WTF@@@WTF@@$00@4@W4SerializationErrorMode@2@@Z
@@ -1390,6 +1391,7 @@ EXPORTS
         ?lastChangeWasUserEdit@HTMLTextFormControlElement@WebCore@@QBE_NXZ
         ?mainThreadScrollingReasonsAsText@Page@WebCore@@QAE?AVString@WTF@@XZ
         ?markersFor@DocumentMarkerController@WebCore@@QAE?AV?$Vector@PAVDocumentMarker@WebCore@@$0A@@WTF@@PAVNode@2@VMarkerTypes@DocumentMarker@2@@Z
+        ?memoryCache@WebCore@@YAPAVMemoryCache@1@XZ
         ?nextSibling@ComposedShadowTreeWalker@WebCore@@QAEXXZ
         ?firstChild@ComposedShadowTreeWalker@WebCore@@QAEXXZ
         ?lastChild@ComposedShadowTreeWalker@WebCore@@QAEXXZ
@@ -1409,6 +1411,7 @@ EXPORTS
         ?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PAVContainerNode@2@HH_N@Z
         ?remove@String@WTF@@QAEXIH@Z
         ?removedLastRef@Node@WebCore@@AAEXXZ
+        ?resourceForURL@MemoryCache@WebCore@@QAEPAVCachedResource@2@ABVKURL@2@@Z
         ?reverseFind@StringImpl@WTF@@QAEI_WI@Z
         ?saveDocumentAndScrollState@HistoryController@WebCore@@QAEXXZ
         ?scriptExecutionContext@JSDOMGlobalObject@WebCore@@QBEPAVScriptExecutionContext@2@XZ
index c59f59b..245fc94 100644 (file)
@@ -50,10 +50,12 @@ _ZN7WebCore10toDocumentEN3JSC7JSValueE;
 _ZN7WebCore10ClientRectC1Ev;
 _ZN7WebCore10ClientRectC1ERKNS_7IntRectE;
 _ZN7WebCore10ShadowRoot6createEPNS_7ElementERi;
+_ZN7WebCore11memoryCacheEv;
 _ZN7WebCore11EventTarget17toGeneratedStreamEv;
 _ZN7WebCore11EventTarget8toStreamEv;
 _ZN7WebCore11HistoryItem16setDocumentStateERKN3WTF6VectorINS1_6StringELj0EEE;
 _ZN7WebCore11HistoryItem16setDocumentStateERKN3WTF6VectorINS1_6StringELm0EEE;
+_ZN7WebCore11MemoryCache14resourceForURLERKNS_4KURLE;
 _ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_13ContainerNodeEiib;
 _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERjS6_;
 _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERmS6_;
@@ -146,6 +148,7 @@ _ZNK7WebCore26HTMLTextFormControlElement26placeholderShouldBeVisibleEv;
 _ZNK7WebCore5Frame8settingsEv;
 _ZNK7WebCore6JSNode21pushEventHandlerScopeEPN3JSC9ExecStateEPNS1_14ScopeChainNodeE;
 _ZNK7WebCore7Element6shadowEv;
+_ZNK7WebCore8Document11completeURLERKN3WTF6StringE;
 _ZNK7WebCore8Document4pageEv;
 _ZNK7WebCore8Document8settingsEv;
 _ZNK7WebCore8Document4viewEv;