Don't cache resources that are very unlikely to be reused
https://bugs.webkit.org/show_bug.cgi?id=143226
<rdar://problem/20347160>

Reviewed by Geoff Garen.

Source/WebCore:

Allow overriding resource load priorities via Internals for testing.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::addExtraFieldsToRequest):
(WebCore::FrameLoader::clearTestingOverrides):
* loader/FrameLoader.h:
(WebCore::FrameLoader::setOverrideResourceLoadPriorityForTesting):
(WebCore::FrameLoader::clearOverrideCachePolicyForTesting): Deleted.
* page/DiagnosticLoggingKeys.cpp:
(WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey):
* page/DiagnosticLoggingKeys.h:

    Add a key.

* testing/Internals.cpp:
(WebCore::Internals::resetToConsistentState):
(WebCore::stringToResourceLoadPriority):
(WebCore::Internals::setOverrideResourceLoadPriority):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit2:

We are writing lots of resources to the cache that are never used again.

In browse-around-randomly test this reduced number of cache entries created by ~20% and bytes written by ~5%.

* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::makeUseDecision):
(WebKit::NetworkCache::makeRetrieveDecision):

    Rename for clarity.

(WebKit::NetworkCache::makeStoreDecision):

    Store only if the resource has non-zero expiration or has validation headers.

    Very High priority resources (main resources) keep the existing policy to minimize impact
    on back navigation and tab restore.

(WebKit::NetworkCache::Cache::retrieve):
(WebKit::NetworkCache::Cache::store):
(WebKit::NetworkCache::canUse): Deleted.
(WebKit::NetworkCache::canRetrieve): Deleted.
(WebKit::NetworkCache::canStore): Deleted.
* NetworkProcess/cache/NetworkCache.h:
* NetworkProcess/cache/NetworkCacheStatistics.cpp:
(WebKit::NetworkCache::storeDecisionToDiagnosticKey):

LayoutTests:

* http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.txt:
* http/tests/cache/disk-cache/disk-cache-request-max-stale-expected.html:

    Keep max-age: 0 cacheable in this test by adding a validation header.

* http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy-expected.txt:
* http/tests/cache/disk-cache/disk-cache-validation-back-navigation-policy.html:

    Rebase and expand to cover the high priority resource case.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@182152 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 1cd0b56..e7f3dad 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,32 @@
+2015-03-30  Antti Koivisto  <antti@apple.com>
+
+        Don't cache resources that are very unlikely to be reused
+        https://bugs.webkit.org/show_bug.cgi?id=143226
+        <rdar://problem/20347160>
+
+        Reviewed by Geoff Garen.
+
+        Allow overriding resource load priorities via Internals for testing.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::addExtraFieldsToRequest):
+        (WebCore::FrameLoader::clearTestingOverrides):
+        * loader/FrameLoader.h:
+        (WebCore::FrameLoader::setOverrideResourceLoadPriorityForTesting):
+        (WebCore::FrameLoader::clearOverrideCachePolicyForTesting): Deleted.
+        * page/DiagnosticLoggingKeys.cpp:
+        (WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey):
+        * page/DiagnosticLoggingKeys.h:
+
+            Add a key.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::resetToConsistentState):
+        (WebCore::stringToResourceLoadPriority):
+        (WebCore::Internals::setOverrideResourceLoadPriority):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2015-03-30  Javier Fernandez  <jfernandez@igalia.com>
 
         [CSS Grid Layout] Upgrade align-self and align-items parsing to CSS 3
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 4e3a4f2..105c82c 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -2561,6 +2561,8 @@
 
     if (m_overrideCachePolicyForTesting)
         request.setCachePolicy(m_overrideCachePolicyForTesting.value());
+    if (m_overrideResourceLoadPriorityForTesting)
+        request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
 
     if (request.cachePolicy() == ReloadIgnoringCacheData) {
         if (loadType == FrameLoadType::Reload)
@@ -3413,6 +3415,12 @@
     m_client.forcePageTransitionIfNeeded();
 }
 
+void FrameLoader::clearTestingOverrides()
+{
+    m_overrideCachePolicyForTesting = Nullopt;
+    m_overrideResourceLoadPriorityForTesting = Nullopt;
+}
+
 bool FrameLoaderClient::hasHTMLView() const
 {
     return true;
diff --git a/Source/WebCore/loader/FrameLoader.h b/Source/WebCore/loader/FrameLoader.h
index 2c6748b..838a397 100644
--- a/Source/WebCore/loader/FrameLoader.h
+++ b/Source/WebCore/loader/FrameLoader.h
@@ -290,7 +290,8 @@
     void forcePageTransitionIfNeeded();
 
     void setOverrideCachePolicyForTesting(ResourceRequestCachePolicy policy) { m_overrideCachePolicyForTesting = policy; }
-    void clearOverrideCachePolicyForTesting() { m_overrideCachePolicyForTesting = Nullopt; }
+    void setOverrideResourceLoadPriorityForTesting(ResourceLoadPriority priority) { m_overrideResourceLoadPriorityForTesting = priority; }
+    WEBCORE_EXPORT void clearTestingOverrides();
 
 private:
     enum FormSubmissionCacheLoadPolicy {
@@ -442,6 +443,7 @@
     RefPtr<FrameNetworkingContext> m_networkingContext;
 
     Optional<ResourceRequestCachePolicy> m_overrideCachePolicyForTesting;
+    Optional<ResourceLoadPriority> m_overrideResourceLoadPriorityForTesting;
 
     URL m_previousURL;
     RefPtr<HistoryItem> m_requestedHistoryItem;
diff --git a/Source/WebCore/page/DiagnosticLoggingKeys.cpp b/Source/WebCore/page/DiagnosticLoggingKeys.cpp
index 9ddd63c..18c79bd 100644
--- a/Source/WebCore/page/DiagnosticLoggingKeys.cpp
+++ b/Source/WebCore/page/DiagnosticLoggingKeys.cpp
@@ -383,6 +383,11 @@
     return ASCIILiteral("uncacheableStatusCode");
 }
 
+String DiagnosticLoggingKeys::unlikelyToReuseKey()
+{
+    return ASCIILiteral("unlikelyToReuse");
+}
+
 String DiagnosticLoggingKeys::unsupportedHTTPMethodKey()
 {
     return ASCIILiteral("unsupportedHTTPMethod");
diff --git a/Source/WebCore/page/DiagnosticLoggingKeys.h b/Source/WebCore/page/DiagnosticLoggingKeys.h
index cb86b4e..f9bc1cc 100644
--- a/Source/WebCore/page/DiagnosticLoggingKeys.h
+++ b/Source/WebCore/page/DiagnosticLoggingKeys.h
@@ -108,6 +108,7 @@
     static String styleSheetKey();
     static String svgDocumentKey();
     WEBCORE_EXPORT static String uncacheableStatusCodeKey();
+    WEBCORE_EXPORT static String unlikelyToReuseKey();
     WEBCORE_EXPORT static String unsupportedHTTPMethodKey();
     static String unsuspendableDOMObjectKey();
     WEBCORE_EXPORT static String unusableCachedEntryKey();
diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp
index 39f2f35..99401f6 100644
--- a/Source/WebCore/testing/Internals.cpp
+++ b/Source/WebCore/testing/Internals.cpp
@@ -308,7 +308,7 @@
         page->mainFrame().editor().toggleContinuousSpellChecking();
     if (page->mainFrame().editor().isOverwriteModeEnabled())
         page->mainFrame().editor().toggleOverwriteModeEnabled();
-    page->mainFrame().loader().clearOverrideCachePolicyForTesting();
+    page->mainFrame().loader().clearTestingOverrides();
     ApplicationCacheStorage::singleton().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
 #if ENABLE(VIDEO)
     MediaSessionManager::sharedManager().resetRestrictions();
@@ -445,6 +445,27 @@
     frame()->loader().setOverrideCachePolicyForTesting(stringToResourceRequestCachePolicy(policy));
 }
 
+static ResourceLoadPriority stringToResourceLoadPriority(const String& policy)
+{
+    if (policy == "ResourceLoadPriorityVeryLow")
+        return ResourceLoadPriorityVeryLow;
+    if (policy == "ResourceLoadPriorityLow")
+        return ResourceLoadPriorityLow;
+    if (policy == "ResourceLoadPriorityMedium")
+        return ResourceLoadPriorityMedium;
+    if (policy == "ResourceLoadPriorityHigh")
+        return ResourceLoadPriorityHigh;
+    if (policy == "ResourceLoadPriorityVeryHigh")
+        return ResourceLoadPriorityVeryHigh;
+    ASSERT_NOT_REACHED();
+    return ResourceLoadPriorityLow;
+}
+
+void Internals::setOverrideResourceLoadPriority(const String& priority)
+{
+    frame()->loader().setOverrideResourceLoadPriorityForTesting(stringToResourceLoadPriority(priority));
+}
+
 void Internals::clearMemoryCache()
 {
     MemoryCache::singleton().evictResources();
diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h
index 4e5dd55..71ff42e3 100644
--- a/Source/WebCore/testing/Internals.h
+++ b/Source/WebCore/testing/Internals.h
@@ -90,6 +90,7 @@
     bool isLoadingFromMemoryCache(const String& url);
     String xhrResponseSource(XMLHttpRequest*);
     void setOverrideCachePolicy(const String&);
+    void setOverrideResourceLoadPriority(const String&);
 
     void clearMemoryCache();
     void pruneMemoryCacheToSize(unsigned size);
diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl
index 740eb2e..11884f0 100644
--- a/Source/WebCore/testing/Internals.idl
+++ b/Source/WebCore/testing/Internals.idl
@@ -37,6 +37,13 @@
     "ReturnCacheDataDontLoad"
 };
 
+enum ResourceLoadPriority {
+    "ResourceLoadPriorityVeryLow",
+    "ResourceLoadPriorityLow",
+    "ResourceLoadPriorityMedium",
+    "ResourceLoadPriorityHigh",
+    "ResourceLoadPriorityVeryHigh"
+};
 
 [
     NoInterfaceObject,
@@ -56,6 +63,7 @@
     void pruneMemoryCacheToSize(long size);
     long memoryCacheSize();
     void setOverrideCachePolicy(CachePolicy policy);
+    void setOverrideResourceLoadPriority(ResourceLoadPriority priority);
 
     void clearPageCache();
     unsigned int pageCacheSize();