The referer header is not set after redirect
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Apr 2018 17:15:17 +0000 (17:15 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Apr 2018 17:15:17 +0000 (17:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182644
<rdar://problem/37479048>

Patch by Sihui Liu <sihui_liu@apple.com> on 2018-04-03
Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

Rebaseline some tests for fetch api as they are passing now.

* web-platform-tests/fetch/api/basic/referrer.any-expected.txt:
* web-platform-tests/fetch/api/basic/referrer.any.worker-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-referrer-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-referrer-worker-expected.txt:

Source/WebCore:

Update referrer policy and recompute referrer in redirection check, so Referer header would be set after it's removed from cross-origin request.

Add support for Referrer-Policy header, so referrer policy would be changed based on redirect response.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::processReferrerPolicy):
* loader/CrossOriginAccessControl.cpp:
(WebCore::updateRequestReferrer):
* loader/CrossOriginAccessControl.h:
* loader/ResourceLoader.h:
(WebCore::ResourceLoader::setReferrerPolicy):
(WebCore::ResourceLoader::referrerPolicy const):
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::checkRedirectionCrossOriginAccessControl):
(WebCore::SubresourceLoader::updateReferrerPolicy):
* loader/SubresourceLoader.h:
* loader/cache/CachedResourceRequest.cpp:
(WebCore::CachedResourceRequest::setAsPotentiallyCrossOrigin):
(WebCore::CachedResourceRequest::updateForAccessControl):
(WebCore::CachedResourceRequest::updateReferrerOriginAndUserAgentHeaders):
* platform/ReferrerPolicy.cpp: Added.
(WebCore::parseReferrerPolicy):
* platform/ReferrerPolicy.h:
* platform/network/HTTPHeaderNames.in:

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

18 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/referrer.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/referrer.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-referrer-expected.txt
LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-referrer-worker-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Document.cpp
Source/WebCore/loader/CrossOriginAccessControl.cpp
Source/WebCore/loader/CrossOriginAccessControl.h
Source/WebCore/loader/ResourceLoader.h
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/SubresourceLoader.h
Source/WebCore/loader/cache/CachedResourceRequest.cpp
Source/WebCore/platform/ReferrerPolicy.cpp [new file with mode: 0644]
Source/WebCore/platform/ReferrerPolicy.h
Source/WebCore/platform/network/HTTPHeaderNames.in

index 896fe44..f17a01b 100644 (file)
@@ -1,3 +1,18 @@
+2018-04-03  Sihui Liu  <sihui_liu@apple.com>
+
+        The referer header is not set after redirect
+        https://bugs.webkit.org/show_bug.cgi?id=182644
+        <rdar://problem/37479048>
+
+        Reviewed by Youenn Fablet.
+
+        Rebaseline some tests for fetch api as they are passing now.
+
+        * web-platform-tests/fetch/api/basic/referrer.any-expected.txt:
+        * web-platform-tests/fetch/api/basic/referrer.any.worker-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-referrer-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-referrer-worker-expected.txt:
+
 2018-03-30  Youenn Fablet  <youenn@apple.com>
 
         NetworkLoadChecker should upgrade redirects if needed
index e36292e..7653f94 100644 (file)
@@ -1,7 +1,7 @@
 
 PASS origin-when-cross-origin policy on a same-origin URL 
 PASS origin-when-cross-origin policy on a cross-origin URL 
-FAIL origin-when-cross-origin policy on a cross-origin URL after same-origin redirection assert_equals: Request's referrer is correct expected (string) "http://localhost:8800/" but got (object) null
+PASS origin-when-cross-origin policy on a cross-origin URL after same-origin redirection 
 PASS origin-when-cross-origin policy on a same-origin URL after cross-origin redirection 
 PASS Referrer with credentials should be stripped 
 PASS Referrer with fragment ID should be stripped 
index e36292e..7653f94 100644 (file)
@@ -1,7 +1,7 @@
 
 PASS origin-when-cross-origin policy on a same-origin URL 
 PASS origin-when-cross-origin policy on a cross-origin URL 
-FAIL origin-when-cross-origin policy on a cross-origin URL after same-origin redirection assert_equals: Request's referrer is correct expected (string) "http://localhost:8800/" but got (object) null
+PASS origin-when-cross-origin policy on a cross-origin URL after same-origin redirection 
 PASS origin-when-cross-origin policy on a same-origin URL after cross-origin redirection 
 PASS Referrer with credentials should be stripped 
 PASS Referrer with fragment ID should be stripped 
index 91b1a26..8e97d49 100644 (file)
@@ -2,10 +2,10 @@
 PASS Same origin redirection, empty init, unsafe-url redirect header  
 PASS Same origin redirection, empty init, no-referrer-when-downgrade redirect header  
 PASS Same origin redirection, empty init, same-origin redirect header  
-FAIL Same origin redirection, empty init, origin redirect header  assert_equals: Check referrer header expected "http://localhost:8800/" but got "http://localhost:8800/fetch/api/redirect/redirect-referrer.html"
+PASS Same origin redirection, empty init, origin redirect header  
 PASS Same origin redirection, empty init, origin-when-cross-origin redirect header  
-FAIL Same origin redirection, empty init, no-referrer redirect header  assert_equals: Check referrer header expected (object) null but got (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.html"
-FAIL Same origin redirection, empty init, strict-origin redirect header  assert_equals: Check referrer header expected "http://localhost:8800/" but got "http://localhost:8800/fetch/api/redirect/redirect-referrer.html"
+PASS Same origin redirection, empty init, no-referrer redirect header  
+PASS Same origin redirection, empty init, strict-origin redirect header  
 PASS Same origin redirection, empty init, strict-origin-when-cross-origin redirect header  
 PASS Same origin redirection, empty redirect header, unsafe-url init  
 PASS Same origin redirection, empty redirect header, no-referrer-when-downgrade init  
@@ -15,20 +15,20 @@ PASS Same origin redirection, empty redirect header, origin-when-cross-origin in
 PASS Same origin redirection, empty redirect header, no-referrer init  
 PASS Same origin redirection, empty redirect header, strict-origin init  
 PASS Same origin redirection, empty redirect header, strict-origin-when-cross-origin init  
-FAIL Cross origin redirection, empty init, unsafe-url redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.html" but got (object) null
-FAIL Cross origin redirection, empty init, no-referrer-when-downgrade redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.html" but got (object) null
+PASS Cross origin redirection, empty init, unsafe-url redirect header  
+PASS Cross origin redirection, empty init, no-referrer-when-downgrade redirect header  
 PASS Cross origin redirection, empty init, same-origin redirect header  
-FAIL Cross origin redirection, empty init, origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty init, origin-when-cross-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty init, origin redirect header  
+PASS Cross origin redirection, empty init, origin-when-cross-origin redirect header  
 PASS Cross origin redirection, empty init, no-referrer redirect header  
-FAIL Cross origin redirection, empty init, strict-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty init, strict-origin-when-cross-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, unsafe-url init  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.html" but got (object) null
-FAIL Cross origin redirection, empty redirect header, no-referrer-when-downgrade init  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.html" but got (object) null
+PASS Cross origin redirection, empty init, strict-origin redirect header  
+PASS Cross origin redirection, empty init, strict-origin-when-cross-origin redirect header  
+PASS Cross origin redirection, empty redirect header, unsafe-url init  
+PASS Cross origin redirection, empty redirect header, no-referrer-when-downgrade init  
 PASS Cross origin redirection, empty redirect header, same-origin init  
-FAIL Cross origin redirection, empty redirect header, origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, origin-when-cross-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty redirect header, origin init  
+PASS Cross origin redirection, empty redirect header, origin-when-cross-origin init  
 PASS Cross origin redirection, empty redirect header, no-referrer init  
-FAIL Cross origin redirection, empty redirect header, strict-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, strict-origin-when-cross-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty redirect header, strict-origin init  
+PASS Cross origin redirection, empty redirect header, strict-origin-when-cross-origin init  
 
index 0079969..8e97d49 100644 (file)
@@ -2,10 +2,10 @@
 PASS Same origin redirection, empty init, unsafe-url redirect header  
 PASS Same origin redirection, empty init, no-referrer-when-downgrade redirect header  
 PASS Same origin redirection, empty init, same-origin redirect header  
-FAIL Same origin redirection, empty init, origin redirect header  assert_equals: Check referrer header expected "http://localhost:8800/" but got "http://localhost:8800/fetch/api/redirect/redirect-referrer.js"
+PASS Same origin redirection, empty init, origin redirect header  
 PASS Same origin redirection, empty init, origin-when-cross-origin redirect header  
-FAIL Same origin redirection, empty init, no-referrer redirect header  assert_equals: Check referrer header expected (object) null but got (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.js"
-FAIL Same origin redirection, empty init, strict-origin redirect header  assert_equals: Check referrer header expected "http://localhost:8800/" but got "http://localhost:8800/fetch/api/redirect/redirect-referrer.js"
+PASS Same origin redirection, empty init, no-referrer redirect header  
+PASS Same origin redirection, empty init, strict-origin redirect header  
 PASS Same origin redirection, empty init, strict-origin-when-cross-origin redirect header  
 PASS Same origin redirection, empty redirect header, unsafe-url init  
 PASS Same origin redirection, empty redirect header, no-referrer-when-downgrade init  
@@ -15,20 +15,20 @@ PASS Same origin redirection, empty redirect header, origin-when-cross-origin in
 PASS Same origin redirection, empty redirect header, no-referrer init  
 PASS Same origin redirection, empty redirect header, strict-origin init  
 PASS Same origin redirection, empty redirect header, strict-origin-when-cross-origin init  
-FAIL Cross origin redirection, empty init, unsafe-url redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.js" but got (object) null
-FAIL Cross origin redirection, empty init, no-referrer-when-downgrade redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.js" but got (object) null
+PASS Cross origin redirection, empty init, unsafe-url redirect header  
+PASS Cross origin redirection, empty init, no-referrer-when-downgrade redirect header  
 PASS Cross origin redirection, empty init, same-origin redirect header  
-FAIL Cross origin redirection, empty init, origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty init, origin-when-cross-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty init, origin redirect header  
+PASS Cross origin redirection, empty init, origin-when-cross-origin redirect header  
 PASS Cross origin redirection, empty init, no-referrer redirect header  
-FAIL Cross origin redirection, empty init, strict-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty init, strict-origin-when-cross-origin redirect header  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, unsafe-url init  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.js" but got (object) null
-FAIL Cross origin redirection, empty redirect header, no-referrer-when-downgrade init  assert_equals: Check referrer header expected (string) "http://localhost:8800/fetch/api/redirect/redirect-referrer.js" but got (object) null
+PASS Cross origin redirection, empty init, strict-origin redirect header  
+PASS Cross origin redirection, empty init, strict-origin-when-cross-origin redirect header  
+PASS Cross origin redirection, empty redirect header, unsafe-url init  
+PASS Cross origin redirection, empty redirect header, no-referrer-when-downgrade init  
 PASS Cross origin redirection, empty redirect header, same-origin init  
-FAIL Cross origin redirection, empty redirect header, origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, origin-when-cross-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty redirect header, origin init  
+PASS Cross origin redirection, empty redirect header, origin-when-cross-origin init  
 PASS Cross origin redirection, empty redirect header, no-referrer init  
-FAIL Cross origin redirection, empty redirect header, strict-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
-FAIL Cross origin redirection, empty redirect header, strict-origin-when-cross-origin init  assert_equals: Check referrer header expected (string) "http://localhost:8800/" but got (object) null
+PASS Cross origin redirection, empty redirect header, strict-origin init  
+PASS Cross origin redirection, empty redirect header, strict-origin-when-cross-origin init  
 
index 87289ea..253904e 100644 (file)
@@ -1,3 +1,38 @@
+2018-04-03  Sihui Liu  <sihui_liu@apple.com>
+
+        The referer header is not set after redirect
+        https://bugs.webkit.org/show_bug.cgi?id=182644
+        <rdar://problem/37479048>
+
+        Reviewed by Youenn Fablet.
+
+        Update referrer policy and recompute referrer in redirection check, so Referer header would be set after it's removed from cross-origin request.
+
+        Add support for Referrer-Policy header, so referrer policy would be changed based on redirect response. 
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Document.cpp:
+        (WebCore::Document::processReferrerPolicy):
+        * loader/CrossOriginAccessControl.cpp:
+        (WebCore::updateRequestReferrer):
+        * loader/CrossOriginAccessControl.h:
+        * loader/ResourceLoader.h:
+        (WebCore::ResourceLoader::setReferrerPolicy):
+        (WebCore::ResourceLoader::referrerPolicy const):
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::checkRedirectionCrossOriginAccessControl):
+        (WebCore::SubresourceLoader::updateReferrerPolicy):
+        * loader/SubresourceLoader.h:
+        * loader/cache/CachedResourceRequest.cpp:
+        (WebCore::CachedResourceRequest::setAsPotentiallyCrossOrigin):
+        (WebCore::CachedResourceRequest::updateForAccessControl):
+        (WebCore::CachedResourceRequest::updateReferrerOriginAndUserAgentHeaders):
+        * platform/ReferrerPolicy.cpp: Added.
+        (WebCore::parseReferrerPolicy):
+        * platform/ReferrerPolicy.h:
+        * platform/network/HTTPHeaderNames.in:
+
 2018-04-03  Chris Dumez  <cdumez@apple.com>
 
         Make SecurityOrigin safe to create and use from any thread
index 02da4cb..5c49ce0 100644 (file)
@@ -1465,6 +1465,7 @@ platform/PlatformSpeechSynthesisVoice.cpp
 platform/PlatformSpeechSynthesizer.cpp
 platform/PlatformStrategies.cpp
 platform/Process.cpp
+platform/ReferrerPolicy.cpp
 platform/RemoteCommandListener.cpp
 platform/RuntimeApplicationChecks.cpp
 platform/SchemeRegistry.cpp
index f899f09..60b7b45 100644 (file)
                C9DADBC91B1D3B25001F17D8 /* JSMediaSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaSession.cpp; sourceTree = "<group>"; };
                C9DADBCA1B1D3B25001F17D8 /* JSMediaSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaSession.h; sourceTree = "<group>"; };
                C9F87CFD1B28E5F600979B83 /* MediaSessionEvents.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = MediaSessionEvents.h; sourceTree = "<group>"; };
+               CA1635DC2072E76900E7D2CE /* ReferrerPolicy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReferrerPolicy.cpp; sourceTree = "<group>"; };
                CA3BF67B10D99BAE00E6CE53 /* ScrollAnimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollAnimator.cpp; sourceTree = "<group>"; };
                CA3BF67D10D99BAE00E6CE53 /* ScrollAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollAnimator.h; sourceTree = "<group>"; };
                CAE9F90D146441F000C245B0 /* CSSAspectRatioValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSAspectRatioValue.cpp; sourceTree = "<group>"; };
                                F47A633C1FF6FD500081B3CC /* PromisedBlobInfo.h */,
                                0081FEFD16B0A244008AAA7A /* PublicSuffix.h */,
                                5C97A3361F5F7A6500105207 /* RectEdges.h */,
+                               CA1635DC2072E76900E7D2CE /* ReferrerPolicy.cpp */,
                                9831AE49154225A200FE2644 /* ReferrerPolicy.h */,
                                CDFC360318CA61C20026E56F /* RemoteCommandListener.cpp */,
                                CDFC360418CA61C20026E56F /* RemoteCommandListener.h */,
index 7fde9c1..bad457c 100644 (file)
@@ -3460,29 +3460,14 @@ void Document::processReferrerPolicy(const String& policy)
     if (shouldEnforceQuickLookSandbox())
         return;
 #endif
-
-    // "never" / "default" / "always" are legacy keywords that we will support. They were defined in:
-    // https://www.w3.org/TR/2014/WD-referrer-policy-20140807/#referrer-policy-delivery-meta
-    if (equalLettersIgnoringASCIICase(policy, "no-referrer") || equalLettersIgnoringASCIICase(policy, "never"))
-        setReferrerPolicy(ReferrerPolicy::NoReferrer);
-    else if (equalLettersIgnoringASCIICase(policy, "unsafe-url") || equalLettersIgnoringASCIICase(policy, "always"))
-        setReferrerPolicy(ReferrerPolicy::UnsafeUrl);
-    else if (equalLettersIgnoringASCIICase(policy, "origin"))
-        setReferrerPolicy(ReferrerPolicy::Origin);
-    else if (equalLettersIgnoringASCIICase(policy, "origin-when-cross-origin"))
-        setReferrerPolicy(ReferrerPolicy::OriginWhenCrossOrigin);
-    else if (equalLettersIgnoringASCIICase(policy, "same-origin"))
-        setReferrerPolicy(ReferrerPolicy::SameOrigin);
-    else if (equalLettersIgnoringASCIICase(policy, "strict-origin"))
-        setReferrerPolicy(ReferrerPolicy::StrictOrigin);
-    else if (equalLettersIgnoringASCIICase(policy, "strict-origin-when-cross-origin"))
-        setReferrerPolicy(ReferrerPolicy::StrictOriginWhenCrossOrigin);
-    else if (equalLettersIgnoringASCIICase(policy, "no-referrer-when-downgrade") || equalLettersIgnoringASCIICase(policy, "default"))
-        setReferrerPolicy(ReferrerPolicy::NoReferrerWhenDowngrade);
-    else {
+    
+    auto referrerPolicy = parseReferrerPolicy(policy, ShouldParseLegacyKeywords::Yes);
+    if (!referrerPolicy) {
         addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, "Failed to set referrer policy: The value '" + policy + "' is not one of 'no-referrer', 'no-referrer-when-downgrade', 'same-origin', 'origin', 'strict-origin', 'origin-when-cross-origin', 'strict-origin-when-cross-origin' or 'unsafe-url'. Defaulting to 'no-referrer'.");
         setReferrerPolicy(ReferrerPolicy::NoReferrer);
+        return;
     }
+    setReferrerPolicy(referrerPolicy.value());
 }
 
 MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const LayoutPoint& documentPoint, const PlatformMouseEvent& event)
index f185987..68804f2 100644 (file)
@@ -34,6 +34,7 @@
 #include "ResourceResponse.h"
 #include "SchemeRegistry.h"
 #include "SecurityOrigin.h"
+#include "SecurityPolicy.h"
 #include <mutex>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/AtomicString.h>
@@ -59,6 +60,15 @@ bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&
     return true;
 }
 
+void updateRequestReferrer(ResourceRequest& request, ReferrerPolicy referrerPolicy, const String& outgoingReferrer)
+{
+    String newOutgoingReferrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, request.url(), outgoingReferrer);
+    if (newOutgoingReferrer.isEmpty())
+        request.clearHTTPReferrer();
+    else
+        request.setHTTPReferrer(newOutgoingReferrer);
+}
+
 void updateRequestForAccessControl(ResourceRequest& request, SecurityOrigin& securityOrigin, StoredCredentialsPolicy storedCredentialsPolicy)
 {
     request.removeCredentials();
index 96832c6..8b6fb30 100644 (file)
@@ -42,6 +42,8 @@ class URL;
 WEBCORE_EXPORT bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&);
 bool isOnAccessControlSimpleRequestMethodWhitelist(const String&);
 
+void updateRequestReferrer(ResourceRequest&, ReferrerPolicy, const String&);
+    
 WEBCORE_EXPORT void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin&, StoredCredentialsPolicy);
 WEBCORE_EXPORT ResourceRequest createAccessControlPreflightRequest(const ResourceRequest&, SecurityOrigin&, const String&);
 
index 91775c7..e4d2ab2 100644 (file)
@@ -159,6 +159,9 @@ protected:
     bool wasCancelled() const { return m_cancellationStatus >= Cancelled; }
 
     void didReceiveDataOrBuffer(const char*, unsigned, RefPtr<SharedBuffer>&&, long long encodedDataLength, DataPayloadType);
+    
+    void setReferrerPolicy(ReferrerPolicy referrerPolicy) { m_options.referrerPolicy = referrerPolicy; }
+    ReferrerPolicy referrerPolicy() const { return m_options.referrerPolicy; }
 
 #if PLATFORM(COCOA)
     void willCacheResponseAsync(ResourceHandle*, NSCachedURLResponse*, CompletionHandler<void(NSCachedURLResponse *)>&&) override;
index f34ed81..45206a2 100644 (file)
@@ -38,6 +38,7 @@
 #include "DocumentLoader.h"
 #include "Frame.h"
 #include "FrameLoader.h"
+#include "HTTPParsers.h"
 #include "LinkLoader.h"
 #include "Logging.h"
 #include "MainFrame.h"
@@ -568,14 +569,34 @@ bool SubresourceLoader::checkRedirectionCrossOriginAccessControl(const ResourceR
     if (crossOriginFlag && redirectingToNewOrigin)
         m_origin = SecurityOrigin::createUnique();
 
+    updateReferrerPolicy(redirectResponse.httpHeaderField(HTTPHeaderName::ReferrerPolicy));
+    
     if (redirectingToNewOrigin) {
         cleanHTTPRequestHeadersForAccessControl(newRequest);
         updateRequestForAccessControl(newRequest, *m_origin, options().storedCredentialsPolicy);
     }
+    
+    updateRequestReferrer(newRequest, referrerPolicy(), previousRequest.httpReferrer());
 
     return true;
 }
 
+void SubresourceLoader::updateReferrerPolicy(const String& referrerPolicyValue)
+{
+    if (referrerPolicyValue.isEmpty())
+        return;
+    
+    // Implementing https://www.w3.org/TR/2017/CR-referrer-policy-20170126/#parse-referrer-policy-from-header.
+    ReferrerPolicy referrerPolicy = ReferrerPolicy::EmptyString;
+    for (auto tokenView : StringView { referrerPolicyValue }.split(',')) {
+        auto token = parseReferrerPolicy(stripLeadingAndTrailingHTTPSpaces(tokenView), ShouldParseLegacyKeywords::No);
+        if (token && token.value() != ReferrerPolicy::EmptyString)
+            referrerPolicy = token.value();
+    }
+    if (referrerPolicy != ReferrerPolicy::EmptyString)
+        setReferrerPolicy(referrerPolicy);
+}
+
 void SubresourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
 {
 #if USE(QUICK_LOOK)
index 39a5743..1959845 100644 (file)
@@ -79,6 +79,8 @@ private:
     void willCancel(const ResourceError&) override;
     void didCancel(const ResourceError&) override;
     void didRetrieveDerivedDataFromCache(const String& type, SharedBuffer&) override;
+    
+    void updateReferrerPolicy(const String&);
 
 #if PLATFORM(COCOA)
     void willCacheResponseAsync(ResourceHandle*, NSCachedURLResponse*, CompletionHandler<void(NSCachedURLResponse *)>&&) override;
index 1e3f044..0012e96 100644 (file)
@@ -35,7 +35,6 @@
 #include "HTTPHeaderValues.h"
 #include "ImageDecoder.h"
 #include "MemoryCache.h"
-#include "SecurityPolicy.h"
 #include "ServiceWorkerRegistrationData.h"
 #include <wtf/NeverDestroyed.h>
 
@@ -102,7 +101,7 @@ void CachedResourceRequest::setAsPotentiallyCrossOrigin(const String& mode, Docu
         ? FetchOptions::Credentials::Include : FetchOptions::Credentials::SameOrigin;
     m_options.credentials = credentials;
     m_options.storedCredentialsPolicy = credentials == FetchOptions::Credentials::Include ? StoredCredentialsPolicy::Use : StoredCredentialsPolicy::DoNotUse;
-    WebCore::updateRequestForAccessControl(m_resourceRequest, document.securityOrigin(), m_options.storedCredentialsPolicy);
+    updateRequestForAccessControl(m_resourceRequest, document.securityOrigin(), m_options.storedCredentialsPolicy);
 }
 
 void CachedResourceRequest::updateForAccessControl(Document& document)
@@ -110,7 +109,7 @@ void CachedResourceRequest::updateForAccessControl(Document& document)
     ASSERT(m_options.mode == FetchOptions::Mode::Cors);
 
     m_origin = &document.securityOrigin();
-    WebCore::updateRequestForAccessControl(m_resourceRequest, *m_origin, m_options.storedCredentialsPolicy);
+    updateRequestForAccessControl(m_resourceRequest, *m_origin, m_options.storedCredentialsPolicy);
 }
 
 void upgradeInsecureResourceRequestIfNeeded(ResourceRequest& request, Document& document)
@@ -231,22 +230,15 @@ void CachedResourceRequest::updateReferrerPolicy(ReferrerPolicy defaultPolicy)
 
 void CachedResourceRequest::updateReferrerOriginAndUserAgentHeaders(FrameLoader& frameLoader)
 {
-    // Implementing step 7 to 9 of https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
-
-    String outgoingOrigin;
-    String outgoingReferrer = m_resourceRequest.httpReferrer();
-    if (!outgoingReferrer.isNull())
+    // Implementing step 9 to 11 of https://fetch.spec.whatwg.org/#http-network-or-cache-fetch as of 16 March 2018
+    String outgoingReferrer = frameLoader.outgoingReferrer();
+    String outgoingOrigin = frameLoader.outgoingOrigin();
+    if (m_resourceRequest.hasHTTPReferrer()) {
+        outgoingReferrer = m_resourceRequest.httpReferrer();
         outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString();
-    else {
-        outgoingReferrer = frameLoader.outgoingReferrer();
-        outgoingOrigin = frameLoader.outgoingOrigin();
     }
+    updateRequestReferrer(m_resourceRequest, m_options.referrerPolicy, outgoingReferrer);
 
-    outgoingReferrer = SecurityPolicy::generateReferrerHeader(m_options.referrerPolicy, m_resourceRequest.url(), outgoingReferrer);
-    if (outgoingReferrer.isEmpty())
-        m_resourceRequest.clearHTTPReferrer();
-    else
-        m_resourceRequest.setHTTPReferrer(outgoingReferrer);
     FrameLoader::addHTTPOriginIfNeeded(m_resourceRequest, outgoingOrigin);
 
     frameLoader.applyUserAgentIfNeeded(m_resourceRequest);
diff --git a/Source/WebCore/platform/ReferrerPolicy.cpp b/Source/WebCore/platform/ReferrerPolicy.cpp
new file mode 100644 (file)
index 0000000..3cd7025
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */ 
+
+#include "config.h"
+#include "ReferrerPolicy.h"
+
+namespace WebCore {
+    
+std::optional<ReferrerPolicy> parseReferrerPolicy(StringView policy, ShouldParseLegacyKeywords shouldParseLegacyKeywords)
+{
+    // "never" / "default" / "always" are legacy keywords that we support. They were defined in:
+    // https://www.w3.org/TR/2014/WD-referrer-policy-20140807/#referrer-policy-delivery-meta
+    if (shouldParseLegacyKeywords == ShouldParseLegacyKeywords::Yes) {
+        if (equalLettersIgnoringASCIICase(policy, "never"))
+            return ReferrerPolicy::NoReferrer;
+        if (equalLettersIgnoringASCIICase(policy, "always"))
+            return ReferrerPolicy::UnsafeUrl;
+        if (equalLettersIgnoringASCIICase(policy, "default"))
+            return ReferrerPolicy::NoReferrerWhenDowngrade;
+    }
+    
+    if (equalLettersIgnoringASCIICase(policy, "no-referrer"))
+        return ReferrerPolicy::NoReferrer;
+    if (equalLettersIgnoringASCIICase(policy, "unsafe-url"))
+        return ReferrerPolicy::UnsafeUrl;
+    if (equalLettersIgnoringASCIICase(policy, "origin"))
+        return ReferrerPolicy::Origin;
+    if (equalLettersIgnoringASCIICase(policy, "origin-when-cross-origin"))
+        return ReferrerPolicy::OriginWhenCrossOrigin;
+    if (equalLettersIgnoringASCIICase(policy, "same-origin"))
+        return ReferrerPolicy::SameOrigin;
+    if (equalLettersIgnoringASCIICase(policy, "strict-origin"))
+        return ReferrerPolicy::StrictOrigin;
+    if (equalLettersIgnoringASCIICase(policy, "strict-origin-when-cross-origin"))
+        return ReferrerPolicy::StrictOriginWhenCrossOrigin;
+    if (equalLettersIgnoringASCIICase(policy, "no-referrer-when-downgrade"))
+        return ReferrerPolicy::NoReferrerWhenDowngrade;
+    if (!policy.isNull() && policy.isEmpty())
+        return ReferrerPolicy::EmptyString;
+    
+    return std::nullopt;
+}
+
+} // namespace WebCore
index 8959299..bbec77f 100644 (file)
@@ -33,6 +33,7 @@
 #pragma once
 
 #include <wtf/EnumTraits.h>
+#include <wtf/Forward.h>
 
 namespace WebCore {
 
@@ -48,6 +49,10 @@ enum class ReferrerPolicy {
     UnsafeUrl
 };
 
+enum class ShouldParseLegacyKeywords { No, Yes };
+    
+std::optional<ReferrerPolicy> parseReferrerPolicy(StringView, ShouldParseLegacyKeywords);
+
 }
 
 namespace WTF {
index 43fe7dd..38a79e1 100644 (file)
@@ -77,6 +77,7 @@ Pragma
 Proxy-Authorization
 Range
 Referer
+Referrer-Policy
 Refresh
 Sec-WebSocket-Accept
 Sec-WebSocket-Extensions