From-Origin: Support for 'same' and 'same-site' response header, nested frame origin...
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2018 19:51:22 +0000 (19:51 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2018 19:51:22 +0000 (19:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184560
<rdar://problem/38901344>

Reviewed by Youenn Fablet and Daniel Bates.

LayoutTests/imported/w3c:

This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
We consume the From-Origin response header and only load the resource if:
- The header is non-existent, empty, or invalid.
- The header specifies 'same' and the resource's origin matches the originating
  document's origin and the origins up the frame tree.
- The header specifies 'same-site' and the resource's eTLD+1 matches the originating
  document's eTLD+1 and the eTLD+1 of the documents up the frame tree.

This feature is experimental and off by default.

* web-platform-tests/service-workers/service-worker/fetch-request-redirect.https-expected.txt:
    Removed console message since they are now suppressed.

Source/WebCore:

Tests: http/tests/from-origin/document-from-origin-same-accepted.html
       http/tests/from-origin/document-from-origin-same-blocked.html
       http/tests/from-origin/document-from-origin-same-site-accepted.html
       http/tests/from-origin/document-from-origin-same-site-blocked.html
       http/tests/from-origin/document-nested-from-origin-same-accepted.html
       http/tests/from-origin/document-nested-from-origin-same-blocked.html
       http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html
       http/tests/from-origin/fetch-from-origin-same-accepted.html
       http/tests/from-origin/fetch-from-origin-same-blocked.html
       http/tests/from-origin/fetch-from-origin-same-site-accepted.html
       http/tests/from-origin/fetch-from-origin-same-site-blocked.html
       http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html
       http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html
       http/tests/from-origin/image-about-blank-from-origin-same-blocked.html
       http/tests/from-origin/image-from-origin-same-accepted.html
       http/tests/from-origin/image-from-origin-same-blocked.html
       http/tests/from-origin/image-from-origin-same-site-accepted.html
       http/tests/from-origin/image-from-origin-same-site-blocked.html
       http/tests/from-origin/redirect-document-from-origin-same-blocked.html
       http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html
       http/tests/from-origin/redirect-image-from-origin-same-blocked.html
       http/tests/from-origin/redirect-script-from-origin-same-blocked.html
       http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html
       http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html
       http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html
       http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html
       http/tests/from-origin/script-from-origin-same-accepted.html
       http/tests/from-origin/script-from-origin-same-blocked.html
       http/tests/from-origin/script-from-origin-same-site-accepted.html
       http/tests/from-origin/script-from-origin-same-site-blocked.html
       http/tests/from-origin/top-frame-document-from-origin-same-accepted.php
       http/tests/from-origin/xhr-from-origin-same-accepted.html
       http/tests/from-origin/xhr-from-origin-same-blocked.html
       http/tests/from-origin/xhr-from-origin-same-site-accepted.html
       http/tests/from-origin/xhr-from-origin-same-site-blocked.html

* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::didFail):
    Outputs the error's localized description in a console message except when the destination
    is FetchOptions::Destination::Serviceworker or FetchOptions::Destination::EmptyString.
* page/RuntimeEnabledFeatures.h:
(WebCore::RuntimeEnabledFeatures::setFromOriginResponseHeaderEnabled):
(WebCore::RuntimeEnabledFeatures::fromOriginResponseHeaderEnabled const):
    Added From-Origin support as an experimental feature.
* platform/network/HTTPHeaderNames.in:
    Added From-Origin.
* platform/network/HTTPParsers.cpp:
(WebCore::parseFromOriginHeader):
    Parses the From-Origin header, currently supporting 'Same' and 'Same-Site.'
* platform/network/HTTPParsers.h:

Source/WebKit:

This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
We consume the From-Origin response header and only load the resource if:
- The header is non-existent, empty, or invalid.
- The header specifies 'same' and the resource's origin matches the originating
  document's origin and the origins up the frame tree.
- The header specifies 'same-site' and the resource's eTLD+1 matches the originating
  document's eTLD+1 and the eTLD+1 of the documents up the frame tree.

This feature is experimental and off by default.

* NetworkProcess/NetworkResourceLoadParameters.cpp:
(WebKit::NetworkResourceLoadParameters::encode const):
(WebKit::NetworkResourceLoadParameters::decode):
    Support for the two new load parameters:
    - shouldEnableFromOriginResponseHeader
    - frameAncestorOrigins
* NetworkProcess/NetworkResourceLoadParameters.h:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::areFrameAncestorsSameSite):
(WebKit::areFrameAncestorsSameOrigin):
(WebKit::shouldCancelCrossOriginLoad):
    The three functions above implement the new blocking logic.
(WebKit::fromOriginResourceError):
    Convenience function that returns an error with the From-Origin error message.
(WebKit::NetworkResourceLoader::didReceiveResponse):
    Now checks for a From-Origin response header.
(WebKit::NetworkResourceLoader::didFailLoading):
    Now checks for a From-Origin response header.
(WebKit::NetworkResourceLoader::continueWillSendRedirectedRequest):
    Now checks for a From-Origin response header.
(WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
    Now checks for a From-Origin response header.
(WebKit::NetworkResourceLoader::dispatchWillSendRequestForCacheEntry):
    Now checks for a From-Origin response header.
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::encode):
(IPC::ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::decode):
    Now encodes and decodes vectors of RefPtr<WebCore::SecurityOrigin>.
* Shared/WebCoreArgumentCoders.h:
* Shared/WebPreferences.yaml:
    Added From-Origin support as an experimental feature.
* UIProcess/API/C/WKPreferences.cpp:
(WKPreferencesSetFromOriginResponseHeaderEnabled):
(WKPreferencesGetFromOriginResponseHeaderEnabled):
* UIProcess/API/C/WKPreferencesRef.h:
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::scheduleLoadFromNetworkProcess):
    Sets the two new load parameters:
    - shouldEnableFromOriginResponseHeader
    - frameAncestorOrigins

Tools:

This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
We consume the From-Origin response header and only load the resource if:
- The header is non-existent, empty, or invalid.
- The header specifies 'same' and the resource's origin matches the originating
  document's origin and the origins up the frame tree.
- The header specifies 'same-site' and the resource's eTLD+1 matches the originating
  document's eTLD+1 and the eTLD+1 of the documents up the frame tree.

This feature is experimental and off by default.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/HTTPParsers.cpp: Added.
(TestWebKitAPI::TEST):
    Tests for From-Origin header parsing.

LayoutTests:

This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
We consume the From-Origin response header and only load the resource if:
- The header is non-existent, empty, or invalid.
- The header specifies 'same' and the resource's origin matches the originating
  document's origin and the origins up the frame tree.
- The header specifies 'same-site' and the resource's eTLD+1 matches the originating
  document's eTLD+1 and the eTLD+1 of the documents up the frame tree.

This feature is experimental and off by default.

* TestExpectations:
    The http/tests/from-origin/ directory marked as [ Skip ].
    Suppressed console output for imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html.
* http/tests/from-origin: Added.
* http/tests/from-origin/document-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/document-from-origin-same-accepted.html: Added.
* http/tests/from-origin/document-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/document-from-origin-same-blocked.html: Added.
* http/tests/from-origin/document-from-origin-same-site-accepted-expected.txt: Added.
* http/tests/from-origin/document-from-origin-same-site-accepted.html: Added.
* http/tests/from-origin/document-from-origin-same-site-blocked-expected.txt: Added.
* http/tests/from-origin/document-from-origin-same-site-blocked.html: Added.
* http/tests/from-origin/document-nested-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/document-nested-from-origin-same-accepted.html: Added.
* http/tests/from-origin/document-nested-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/document-nested-from-origin-same-blocked.html: Added.
* http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html: Added.
* http/tests/from-origin/fetch-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/fetch-from-origin-same-accepted.html: Added.
* http/tests/from-origin/fetch-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/fetch-from-origin-same-blocked.html: Added.
* http/tests/from-origin/fetch-from-origin-same-site-accepted-expected.txt: Added.
* http/tests/from-origin/fetch-from-origin-same-site-accepted.html: Added.
* http/tests/from-origin/fetch-from-origin-same-site-blocked-expected.txt: Added.
* http/tests/from-origin/fetch-from-origin-same-site-blocked.html: Added.
* http/tests/from-origin/fetch-iframe-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html: Added.
* http/tests/from-origin/fetch-iframe-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html: Added.
* http/tests/from-origin/image-about-blank-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/image-about-blank-from-origin-same-blocked.html: Added.
* http/tests/from-origin/image-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/image-from-origin-same-accepted.html: Added.
* http/tests/from-origin/image-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/image-from-origin-same-blocked.html: Added.
* http/tests/from-origin/image-from-origin-same-site-accepted-expected.txt: Added.
* http/tests/from-origin/image-from-origin-same-site-accepted.html: Added.
* http/tests/from-origin/image-from-origin-same-site-blocked-expected.txt: Added.
* http/tests/from-origin/image-from-origin-same-site-blocked.html: Added.
* http/tests/from-origin/redirect-document-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/redirect-document-from-origin-same-blocked.html: Added.
* http/tests/from-origin/redirect-fetch-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html: Added.
* http/tests/from-origin/redirect-image-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/redirect-image-from-origin-same-blocked.html: Added.
* http/tests/from-origin/redirect-script-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/redirect-script-from-origin-same-blocked.html: Added.
* http/tests/from-origin/redirect-xhr-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html: Added.
* http/tests/from-origin/resources: Added.
* http/tests/from-origin/resources/fetch.php: Added.
* http/tests/from-origin/resources/iframe.php: Added.
* http/tests/from-origin/resources/iframeIPAddressFetch.html: Added.
* http/tests/from-origin/resources/iframeLocalhostFetch.html: Added.
* http/tests/from-origin/resources/image.php: Added.
* http/tests/from-origin/resources/nestedIPAddressIframe.html: Added.
* http/tests/from-origin/resources/nestedLocalhostIframe.html: Added.
* http/tests/from-origin/resources/redirect.php: Added.
* http/tests/from-origin/resources/script.php: Added.
* http/tests/from-origin/resources/xhr.php: Added.
* http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html: Added.
* http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html: Added.
* http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html: Added.
* http/tests/from-origin/script-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/script-from-origin-same-accepted.html: Added.
* http/tests/from-origin/script-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/script-from-origin-same-blocked.html: Added.
* http/tests/from-origin/script-from-origin-same-site-accepted-expected.txt: Added.
* http/tests/from-origin/script-from-origin-same-site-accepted.html: Added.
* http/tests/from-origin/script-from-origin-same-site-blocked-expected.txt: Added.
* http/tests/from-origin/script-from-origin-same-site-blocked.html: Added.
* http/tests/from-origin/top-frame-document-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/top-frame-document-from-origin-same-accepted.php: Added.
* http/tests/from-origin/xhr-from-origin-same-accepted-expected.txt: Added.
* http/tests/from-origin/xhr-from-origin-same-accepted.html: Added.
* http/tests/from-origin/xhr-from-origin-same-blocked-expected.txt: Added.
* http/tests/from-origin/xhr-from-origin-same-blocked.html: Added.
* http/tests/from-origin/xhr-from-origin-same-site-accepted-expected.txt: Added.
* http/tests/from-origin/xhr-from-origin-same-site-accepted.html: Added.
* http/tests/from-origin/xhr-from-origin-same-site-blocked-expected.txt: Added.
* http/tests/from-origin/xhr-from-origin-same-site-blocked.html: Added.
* platform/mac-wk2/TestExpectations:
    Suppressed console output for imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html.
* platform/wk2/TestExpectations:
    The http/tests/from-origin/ directory marked as [ Pass ].

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

105 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/from-origin/document-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/fetch.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/iframe.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/iframeIPAddressFetch.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/iframeLocalhostFetch.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/image.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/nestedIPAddressIframe.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/nestedLocalhostIframe.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/redirect.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/script.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/resources/xhr.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted.php [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted.html [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked.html [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https-expected.txt
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/page/RuntimeEnabledFeatures.h
Source/WebCore/platform/network/HTTPHeaderNames.in
Source/WebCore/platform/network/HTTPParsers.cpp
Source/WebCore/platform/network/HTTPParsers.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp
Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h
Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/Shared/WebCoreArgumentCoders.h
Source/WebKit/Shared/WebPreferences.yaml
Source/WebKit/UIProcess/API/C/WKPreferences.cpp
Source/WebKit/UIProcess/API/C/WKPreferencesRef.h
Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebCore/HTTPParsers.cpp [new file with mode: 0644]

index 49f880c..0965c90 100644 (file)
@@ -1,3 +1,111 @@
+2018-04-24  John Wilander  <wilander@apple.com>
+
+        From-Origin: Support for 'same' and 'same-site' response header, nested frame origin check
+        https://bugs.webkit.org/show_bug.cgi?id=184560
+        <rdar://problem/38901344>
+
+        Reviewed by Youenn Fablet and Daniel Bates.
+
+        This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
+        We consume the From-Origin response header and only load the resource if:
+        - The header is non-existent, empty, or invalid.
+        - The header specifies 'same' and the resource's origin matches the originating
+          document's origin and the origins up the frame tree.
+        - The header specifies 'same-site' and the resource's eTLD+1 matches the originating
+          document's eTLD+1 and the eTLD+1 of the documents up the frame tree.
+
+        This feature is experimental and off by default.
+
+        * TestExpectations:
+            The http/tests/from-origin/ directory marked as [ Skip ].
+            Suppressed console output for imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html.
+        * http/tests/from-origin: Added.
+        * http/tests/from-origin/document-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/document-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/document-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/document-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/document-from-origin-same-site-accepted-expected.txt: Added.
+        * http/tests/from-origin/document-from-origin-same-site-accepted.html: Added.
+        * http/tests/from-origin/document-from-origin-same-site-blocked-expected.txt: Added.
+        * http/tests/from-origin/document-from-origin-same-site-blocked.html: Added.
+        * http/tests/from-origin/document-nested-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/document-nested-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/document-nested-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/document-nested-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/fetch-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/fetch-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/fetch-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/fetch-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/fetch-from-origin-same-site-accepted-expected.txt: Added.
+        * http/tests/from-origin/fetch-from-origin-same-site-accepted.html: Added.
+        * http/tests/from-origin/fetch-from-origin-same-site-blocked-expected.txt: Added.
+        * http/tests/from-origin/fetch-from-origin-same-site-blocked.html: Added.
+        * http/tests/from-origin/fetch-iframe-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/fetch-iframe-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/image-about-blank-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/image-about-blank-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/image-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/image-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/image-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/image-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/image-from-origin-same-site-accepted-expected.txt: Added.
+        * http/tests/from-origin/image-from-origin-same-site-accepted.html: Added.
+        * http/tests/from-origin/image-from-origin-same-site-blocked-expected.txt: Added.
+        * http/tests/from-origin/image-from-origin-same-site-blocked.html: Added.
+        * http/tests/from-origin/redirect-document-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/redirect-document-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/redirect-fetch-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/redirect-image-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/redirect-image-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/redirect-script-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/redirect-script-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/redirect-xhr-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/resources: Added.
+        * http/tests/from-origin/resources/fetch.php: Added.
+        * http/tests/from-origin/resources/iframe.php: Added.
+        * http/tests/from-origin/resources/iframeIPAddressFetch.html: Added.
+        * http/tests/from-origin/resources/iframeLocalhostFetch.html: Added.
+        * http/tests/from-origin/resources/image.php: Added.
+        * http/tests/from-origin/resources/nestedIPAddressIframe.html: Added.
+        * http/tests/from-origin/resources/nestedLocalhostIframe.html: Added.
+        * http/tests/from-origin/resources/redirect.php: Added.
+        * http/tests/from-origin/resources/script.php: Added.
+        * http/tests/from-origin/resources/xhr.php: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/script-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/script-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/script-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/script-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/script-from-origin-same-site-accepted-expected.txt: Added.
+        * http/tests/from-origin/script-from-origin-same-site-accepted.html: Added.
+        * http/tests/from-origin/script-from-origin-same-site-blocked-expected.txt: Added.
+        * http/tests/from-origin/script-from-origin-same-site-blocked.html: Added.
+        * http/tests/from-origin/top-frame-document-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/top-frame-document-from-origin-same-accepted.php: Added.
+        * http/tests/from-origin/xhr-from-origin-same-accepted-expected.txt: Added.
+        * http/tests/from-origin/xhr-from-origin-same-accepted.html: Added.
+        * http/tests/from-origin/xhr-from-origin-same-blocked-expected.txt: Added.
+        * http/tests/from-origin/xhr-from-origin-same-blocked.html: Added.
+        * http/tests/from-origin/xhr-from-origin-same-site-accepted-expected.txt: Added.
+        * http/tests/from-origin/xhr-from-origin-same-site-accepted.html: Added.
+        * http/tests/from-origin/xhr-from-origin-same-site-blocked-expected.txt: Added.
+        * http/tests/from-origin/xhr-from-origin-same-site-blocked.html: Added.
+        * platform/mac-wk2/TestExpectations:
+            Suppressed console output for imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html.
+        * platform/wk2/TestExpectations:
+            The http/tests/from-origin/ directory marked as [ Pass ].
+
 2018-04-24  Tadeu Zagallo  <tzagallo@apple.com>
 
         REGRESSION(r221839): Fix requests with FormData containing empty files
index d17e964..6ea3bc8 100644 (file)
@@ -206,7 +206,7 @@ webkit.org/b/181897 imported/w3c/web-platform-tests/service-workers/service-work
 webkit.org/b/181900 imported/w3c/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ DumpJSConsoleLogInStdErr ]
 imported/w3c/web-platform-tests/service-workers/service-worker/fetch-response-taint.https.html [ DumpJSConsoleLogInStdErr ]
 imported/w3c/web-platform-tests/service-workers/service-worker/register-closed-window.https.html [ DumpJSConsoleLogInStdErr ]
-imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html [ Slow ]
+imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html [ DumpJSConsoleLogInStdErr Slow ]
 [ Debug ] imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-order.https.html [ Slow ]
 [ Debug ] imported/w3c/web-platform-tests/service-workers/service-worker/getregistrations.https.html [ Slow ]
 [ Debug ] imported/w3c/web-platform-tests/service-workers/service-worker/interfaces-sw.https.html [ Slow ]
@@ -346,6 +346,9 @@ imported/w3c/web-platform-tests/encoding/legacy-mb-tchinese/big5/big5-encode-for
 # Content encoding sniffing is only supported by CFNetwork.
 http/tests/xmlhttprequest/gzip-content-type-no-content-encoding.html [ Skip ]
 
+# Only supported in WebKit2.
+http/tests/from-origin/ [ Skip ]
+
 #//////////////////////////////////////////////////////////////////////////////////////////
 # End platform-specific tests.
 #//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/document-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..8d70579
--- /dev/null
@@ -0,0 +1,14 @@
+Tests that a same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The iframe
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/document-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..4e6c966
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/iframe.php?fromOrigin=same"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/document-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..135e430
--- /dev/null
@@ -0,0 +1,15 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/document-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..d173ef7
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://localhost:8000/from-origin/resources/iframe.php?fromOrigin=same"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted-expected.txt b/LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted-expected.txt
new file mode 100644 (file)
index 0000000..ea7ee63
--- /dev/null
@@ -0,0 +1,14 @@
+Tests that a same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The iframe
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted.html b/LayoutTests/http/tests/from-origin/document-from-origin-same-site-accepted.html
new file mode 100644 (file)
index 0000000..2b182b3
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/iframe.php?fromOrigin=same-site"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked-expected.txt b/LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked-expected.txt
new file mode 100644 (file)
index 0000000..28b97d4
--- /dev/null
@@ -0,0 +1,15 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked.html b/LayoutTests/http/tests/from-origin/document-from-origin-same-site-blocked.html
new file mode 100644 (file)
index 0000000..a0b8467
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://localhost:8000/from-origin/resources/iframe.php?fromOrigin=same-site"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..1ac9b3b
--- /dev/null
@@ -0,0 +1,21 @@
+Tests that a nested same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The outer iframe, loading a nested 127.0.0.1 iframe.
+
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->/<!--frame0-->-->'
+--------
+The iframe
diff --git a/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..fd10aed
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a nested same-origin document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/nestedIPAddressIframe.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..6cef629
--- /dev/null
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a nested cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The outer iframe, loading a nested localhost iframe.
+
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->/<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/document-nested-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..53d77a1
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a nested cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/nestedLocalhostIframe.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..3e2d62f
--- /dev/null
@@ -0,0 +1,16 @@
+CONSOLE MESSAGE: Fetch API cannot load http://127.0.0.1:8000/from-origin/resources/fetch.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin fetch in a data: iframe load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 127.0.0.1 fetch in data: iframe blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The iframe making a 127.0.0.1 fetch call.
diff --git a/LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..25b4281
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin fetch in a data: iframe load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+        testRunner.dumpChildFramesAsText();
+
+        function receiveMessage(event) {
+            if (event.origin === "null") {
+                if (event.data.indexOf("fetchSuccess") !== -1)
+                    testFailed("127.0.0.1 fetch in data: iframe succeeded.");
+                else if (event.data.indexOf("fetchError") !== -1)
+                    testPassed("127.0.0.1 fetch in data: iframe blocked.");
+                else
+                    testFailed("Received an unrecognized message. " + event.data);
+            } else {
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            }
+            finishJSTest();
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+    </script>
+</head>
+<body>
+<!-- data url equivalent to from-origin/resources/iframeIPAddressFetch.html -->
+<iframe src="data:text/html;base64,PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KICAgIDxzY3JpcHQ+CiAgICAgICAgZnVuY3Rpb24gZmV0Y2hFcnJvcigpIHsKICAgICAgICAgICAgdG9wLnBvc3RNZXNzYWdlKCJmZXRjaEVycm9yIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODAwMCIpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gZmV0Y2hTdWNjZXNzKCkgewogICAgICAgICAgICB0b3AucG9zdE1lc3NhZ2UoImZldGNoU3VjY2VzcyIsICJodHRwOi8vMTI3LjAuMC4xOjgwMDAiKTsKICAgICAgICB9CgogICAgICAgIGZldGNoKCJodHRwOi8vMTI3LjAuMC4xOjgwMDAvZnJvbS1vcmlnaW4vcmVzb3VyY2VzL2ZldGNoLnBocD9mcm9tT3JpZ2luPXNhbWUiKS50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7CiAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7CiAgICAgICAgfSkudGhlbihmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnNlZERhdGEgPSBKU09OLnBhcnNlKGRhdGEpOwogICAgICAgICAgICBpZiAocGFyc2VkRGF0YS5GZXRjaCkKICAgICAgICAgICAgICAgIGZldGNoU3VjY2VzcygpOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBmZXRjaEVycm9yKCk7CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHsKICAgICAgICAgICAgZmV0Y2hFcnJvcigpOwogICAgICAgIH0pOwogICAgPC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHk+CiAgICA8aDM+VGhlIGlmcmFtZSBtYWtpbmcgYSAxMjcuMC4wLjEgZmV0Y2ggY2FsbC48L2gzPgo8L2JvZHk+CjwvaHRtbD4K"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..a757130
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin fetch load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Fetch succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..e0d8059
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin fetch load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        fetch("http://127.0.0.1:8000/from-origin/resources/fetch.php?fromOrigin=same").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                testPassed("Fetch succeeded.");
+            else
+                testFailed("Unknown fetch response.");
+            finishJSTest();
+        }).catch(function(error) {
+            testFailed("Fetch blocked. " + error);
+            finishJSTest();
+        });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..30a5eee
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: Fetch API cannot load http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin fetch load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Fetch blocked. TypeError: Cancelled load because it violates the resource's From-Origin response header.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..18632f8
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin fetch load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        fetch("http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                testFailed("Fetch succeeded.");
+            else
+                testFailed("Unknown fetch response.");
+            finishJSTest();
+        }).catch(function(error) {
+            testPassed("Fetch blocked. " + error);
+            finishJSTest();
+        });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted-expected.txt b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted-expected.txt
new file mode 100644 (file)
index 0000000..e6a79c6
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin fetch load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Fetch succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted.html b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-accepted.html
new file mode 100644 (file)
index 0000000..0107469
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin fetch load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        fetch("http://127.0.0.1:8000/from-origin/resources/fetch.php?fromOrigin=same-site").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                testPassed("Fetch succeeded.");
+            else
+                testFailed("Unknown fetch response.");
+            finishJSTest();
+        }).catch(function(error) {
+            testFailed("Fetch blocked. " + error);
+            finishJSTest();
+        });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked-expected.txt b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked-expected.txt
new file mode 100644 (file)
index 0000000..9b986da
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: Fetch API cannot load http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same-site. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin fetch load fails if the server blocks it with a 'From-Origin: same-site' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Fetch blocked. TypeError: Cancelled load because it violates the resource's From-Origin response header.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked.html b/LayoutTests/http/tests/from-origin/fetch-from-origin-same-site-blocked.html
new file mode 100644 (file)
index 0000000..f27df8f
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin fetch load fails if the server blocks it with a 'From-Origin: same-site' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        fetch("http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same-site").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                testFailed("Fetch succeeded.");
+            else
+                testFailed("Unknown fetch response.");
+            finishJSTest();
+        }).catch(function(error) {
+            testPassed("Fetch blocked. " + error);
+            finishJSTest();
+        });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..23c8744
--- /dev/null
@@ -0,0 +1,15 @@
+Tests that a same-origin fetch in an iframe succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 127.0.0.1 fetch in 127.0.0.1 iframe succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The iframe making a 127.0.0.1 fetch call.
diff --git a/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..d9da6f3
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin fetch in an iframe succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+        testRunner.dumpChildFramesAsText();
+
+        function receiveMessage(event) {
+            if (event.origin === "http://127.0.0.1:8000") {
+                if (event.data.indexOf("fetchSuccess") !== -1)
+                    testPassed("127.0.0.1 fetch in 127.0.0.1 iframe succeeded.");
+                else if (event.data.indexOf("fetchError") !== -1)
+                    testFailed("127.0.0.1 fetch in 127.0.0.1 iframe blocked.");
+                else
+                    testFailed("Received an unrecognized message. " + event.data);
+            } else {
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            }
+
+            finishJSTest();
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/iframeIPAddressFetch.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..2a65c6f
--- /dev/null
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: Fetch API cannot load http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Fetch API cannot load http://127.0.0.1:8000/from-origin/resources/fetch.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin fetch in an iframe load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Localhost fetch in 127.0.0.1 iframe blocked and 127.0.0.1 fetch in localhost iframe blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The iframe making a localhost fetch call.
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+The iframe making a 127.0.0.1 fetch call.
diff --git a/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..7d2beef
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin fetch in an iframe load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+        testRunner.dumpChildFramesAsText();
+
+        function addIframe (url) {
+            iframeElement = document.createElement("iframe");
+            iframeElement.src = url;
+            document.body.appendChild(iframeElement);
+        }
+
+        var ipAddressIframeDone = false;
+        var localhostIframeDone = false;
+        function receiveMessage(event) {
+            if (event.origin === "http://127.0.0.1:8000") {
+                ipAddressIframeDone = true;
+                if (event.data.indexOf("fetchSuccess") !== -1)
+                    testFailed("Localhost fetch in 127.0.0.1 iframe succeeded.");
+                else if (event.data.indexOf("fetchError") === -1)
+                    testFailed("Received an unrecognized message. " + event.data);
+                addIframe("http://localhost:8000/from-origin/resources/iframeIPAddressFetch.html");
+            } else if (event.origin === "http://localhost:8000") {
+                localhostIframeDone = true;
+                if (event.data.indexOf("fetchSuccess") !== -1)
+                    testFailed("127.0.0.1 fetch in localhost iframe succeeded.");
+                else if (event.data.indexOf("fetchError") === -1)
+                    testFailed("Received an unrecognized message. " + event.data);
+            } else {
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+                finishJSTest();
+            }
+
+            if (ipAddressIframeDone && localhostIframeDone) {
+                testPassed("Localhost fetch in 127.0.0.1 iframe blocked and 127.0.0.1 fetch in localhost iframe blocked.");
+                finishJSTest();
+            }
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function run() {
+            addIframe("http://127.0.0.1:8000/from-origin/resources/iframeLocalhostFetch.html");
+        }
+    </script>
+</head>
+<body onload="run()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..32def21
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin image load denied by Cross-Origin Resource Sharing policy.
+Tests that a cross-origin image load inside an about:blank iframe fails if the server blocks it with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/image-about-blank-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..f8be3cc
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin image load inside an about:blank iframe fails if the server blocks it with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testPassed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testFailed("Image load succeeded.");
+            finishJSTest();
+        }
+
+        function injectImageIntoIframe() {
+            var imgElement = new Image();
+            imgElement.src = "http://localhost:8000/from-origin/resources/image.php?fromOrigin=same";
+            imgElement.onload = imageLoadSuccess;
+            imgElement.onerror = imageLoadError;
+            document.getElementById("theIframe").contentDocument.body.appendChild(imgElement);
+        }
+    </script>
+</head>
+<body onload="injectImageIntoIframe()">
+<iframe src="about:blank" id="theIframe"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/image-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..73a4a36
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin image load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/image-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..4cb6214
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin image load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testFailed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testPassed("Image load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<img src="http://127.0.0.1:8000/from-origin/resources/image.php?fromOrigin=same" onerror="imageLoadError()" onload="imageLoadSuccess()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/image-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..ad23d99
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin image load denied by Cross-Origin Resource Sharing policy.
+Tests that a cross-origin image load fails if the server blocks it with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/image-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..cb0e07b
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin image load fails if the server blocks it with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testPassed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testFailed("Image load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<img src="http://localhost:8000/from-origin/resources/image.php?fromOrigin=same" onerror="imageLoadError()" onload="imageLoadSuccess()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted-expected.txt b/LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted-expected.txt
new file mode 100644 (file)
index 0000000..3d077b2
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin image load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted.html b/LayoutTests/http/tests/from-origin/image-from-origin-same-site-accepted.html
new file mode 100644 (file)
index 0000000..ef82351
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin image load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testFailed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testPassed("Image load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<img src="http://127.0.0.1:8000/from-origin/resources/image.php?fromOrigin=same-site" onerror="imageLoadError()" onload="imageLoadSuccess()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked-expected.txt b/LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked-expected.txt
new file mode 100644 (file)
index 0000000..a972c85
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin image load denied by Cross-Origin Resource Sharing policy.
+Tests that a cross-origin image load fails if the server blocks it with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked.html b/LayoutTests/http/tests/from-origin/image-from-origin-same-site-blocked.html
new file mode 100644 (file)
index 0000000..ceaf19e
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin image load fails if the server blocks it with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testPassed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testFailed("Image load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<img src="http://localhost:8000/from-origin/resources/image.php?fromOrigin=same-site" onerror="imageLoadError()" onload="imageLoadSuccess()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..051c705
--- /dev/null
@@ -0,0 +1,15 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a redirected cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/redirect-document-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..32b4c2a
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a redirected cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/redirect.php?redirectTo=http://localhost:8000/from-origin/resources/iframe.php?fromOrigin=same"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..35386c5
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: Fetch API cannot load http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a redirected cross-origin fetch load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Fetch blocked. TypeError: Cancelled load because it violates the resource's From-Origin response header.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..d3371d9
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a redirected cross-origin fetch load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        fetch("http://127.0.0.1:8000/from-origin/resources/redirect.php?redirectTo=http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                testFailed("Fetch succeeded.");
+            else
+                testFailed("Unknown fetch response.");
+            finishJSTest();
+        }).catch(function(error) {
+            testPassed("Fetch blocked. " + error);
+            finishJSTest();
+        });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..c2c6d0f
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin image load denied by Cross-Origin Resource Sharing policy.
+Tests that a redirected cross-origin image load fails if the server blocks it with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image load blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/redirect-image-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..1e0c4e3
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a redirected cross-origin image load fails if the server blocks it with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function imageLoadError() {
+            testPassed("Image load blocked.");
+            finishJSTest();
+        }
+
+        function imageLoadSuccess() {
+            testFailed("Image load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<img src="http://127.0.0.1:8000/from-origin/resources/redirect.php?redirectTo=http://localhost:8000/from-origin/resources/image.php?fromOrigin=same" onerror="imageLoadError()" onload="imageLoadSuccess()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..47ab9b1
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin script load denied by Cross-Origin Resource Sharing policy.
+Tests that a redirected cross-origin script load fails if the server blocks it with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Script load blocked.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/redirect-script-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..134464f
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a redirected cross-origin script load fails if the server blocks it with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function scriptLoadError() {
+            testPassed("Script load blocked.");
+            finishJSTest();
+        }
+
+        function scriptLoadSuccess() {
+            testFailed("Script load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<script src="http://127.0.0.1:8000/from-origin/resources/redirect.php?redirectTo=http://localhost:8000/from-origin/resources/script.php?fromOrigin=same" onload="scriptLoadSuccess()" onerror="scriptLoadError()"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..cb31428
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a redirected cross-origin xhr load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Xhr blocked. 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..dcc4742
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a redirected cross-origin xhr load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        function transferComplete() {
+            if (xhr.responseText === "xhr")
+                testFailed("Xhr succeeded.");
+            else
+                testFailed("Unknown xhr response: " + xhr.responseText);
+            finishJSTest();
+        }
+
+        function transferFailed() {
+            testPassed("Xhr blocked. " + xhr.statusText);
+            finishJSTest();
+        }
+
+        var xhr = new XMLHttpRequest();
+        xhr.addEventListener("load", transferComplete);
+        xhr.addEventListener("error", transferFailed);
+        xhr.open("GET", "http://127.0.0.1:8000/from-origin/resources/redirect.php?redirectTo=http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same");
+        xhr.send();
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/resources/fetch.php b/LayoutTests/http/tests/from-origin/resources/fetch.php
new file mode 100644 (file)
index 0000000..12829cb
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+if($_GET["fromOrigin"] == "same") {
+    header("From-Origin: Same");
+} elseif($_GET["fromOrigin"] == "same-site") {
+    header("From-Origin: Same-Site");
+}
+
+if (isset($_SERVER['HTTP_ORIGIN'])) {
+    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
+}
+$data = '{
+       "Fetch": true
+}';
+echo json_encode($data);
+?>
diff --git a/LayoutTests/http/tests/from-origin/resources/iframe.php b/LayoutTests/http/tests/from-origin/resources/iframe.php
new file mode 100644 (file)
index 0000000..dde4f0f
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+if($_GET["fromOrigin"] == "same") {
+    header("From-Origin: Same");
+} elseif($_GET["fromOrigin"] == "same-site") {
+    header("From-Origin: Same-Site");
+}
+?>
+<h3>The iframe</h3>
diff --git a/LayoutTests/http/tests/from-origin/resources/iframeIPAddressFetch.html b/LayoutTests/http/tests/from-origin/resources/iframeIPAddressFetch.html
new file mode 100644 (file)
index 0000000..5478c7f
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script>
+        function fetchError() {
+            top.postMessage("fetchError", "http://127.0.0.1:8000");
+        }
+
+        function fetchSuccess() {
+            top.postMessage("fetchSuccess", "http://127.0.0.1:8000");
+        }
+
+        fetch("http://127.0.0.1:8000/from-origin/resources/fetch.php?fromOrigin=same").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                fetchSuccess();
+            else
+                fetchError();
+        }).catch(function(error) {
+            fetchError();
+        });
+    </script>
+</head>
+<body>
+    <h3>The iframe making a 127.0.0.1 fetch call.</h3>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/resources/iframeLocalhostFetch.html b/LayoutTests/http/tests/from-origin/resources/iframeLocalhostFetch.html
new file mode 100644 (file)
index 0000000..9124439
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+        function fetchError() {
+            top.postMessage("fetchError", "http://127.0.0.1:8000");
+        }
+
+        function fetchSuccess() {
+            top.postMessage("fetchSuccess", "http://127.0.0.1:8000");
+        }
+
+        fetch("http://localhost:8000/from-origin/resources/fetch.php?fromOrigin=same").then(function(response) {
+            return response.json();
+        }).then(function(data) {
+            const parsedData = JSON.parse(data);
+            if (parsedData.Fetch)
+                fetchSuccess();
+            else
+                fetchError();
+        }).catch(function(error) {
+            fetchError();
+        });
+</script>
+</head>
+<body>
+    <h3>The iframe making a localhost fetch call.</h3>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/resources/image.php b/LayoutTests/http/tests/from-origin/resources/image.php
new file mode 100644 (file)
index 0000000..ccfe249
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+if($_GET["fromOrigin"] == "same") {
+    header("From-Origin: Same");
+} elseif($_GET["fromOrigin"] == "same-site") {
+    header("From-Origin: Same-Site");
+}
+$fp = fopen("../../resources/square20.jpg", "rb");
+header("Content-Type: image/jpeg");
+header("Content-Length: " . filesize($name));
+fpassthru($fp);
+exit;
+?>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/from-origin/resources/nestedIPAddressIframe.html b/LayoutTests/http/tests/from-origin/resources/nestedIPAddressIframe.html
new file mode 100644 (file)
index 0000000..203c14a
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+    <h3>The outer iframe, loading a nested 127.0.0.1 iframe.</h3>
+    <iframe src="http://127.0.0.1:8000/from-origin/resources/iframe.php?fromOrigin=same"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/resources/nestedLocalhostIframe.html b/LayoutTests/http/tests/from-origin/resources/nestedLocalhostIframe.html
new file mode 100644 (file)
index 0000000..b8e0530
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+    <h3>The outer iframe, loading a nested localhost iframe.</h3>
+    <iframe src="http://localhost:8000/from-origin/resources/iframe.php?fromOrigin=same"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/resources/redirect.php b/LayoutTests/http/tests/from-origin/resources/redirect.php
new file mode 100644 (file)
index 0000000..17abfd9
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+$redirectURL = $_GET["redirectTo"];
+header('Location: ' . $redirectURL);
+die();
+?>
diff --git a/LayoutTests/http/tests/from-origin/resources/script.php b/LayoutTests/http/tests/from-origin/resources/script.php
new file mode 100644 (file)
index 0000000..9c81bb8
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+if($_GET["fromOrigin"] == "same") {
+    header("From-Origin: Same");
+} elseif($_GET["fromOrigin"] == "same-site") {
+    header("From-Origin: Same-Site");
+}
+?>
+var divElement = document.createElement("div");
+divElement.textContent = "Created by JavaScript.";
+document.body.appendChild(divElement);
diff --git a/LayoutTests/http/tests/from-origin/resources/xhr.php b/LayoutTests/http/tests/from-origin/resources/xhr.php
new file mode 100644 (file)
index 0000000..997f07a
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+if($_GET["fromOrigin"] == "same") {
+    header("From-Origin: Same");
+} elseif($_GET["fromOrigin"] == "same-site") {
+    header("From-Origin: Same-Site");
+}
+
+if (isset($_SERVER['HTTP_ORIGIN'])) {
+    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
+}
+?>
+xhr
\ No newline at end of file
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..946da80
--- /dev/null
@@ -0,0 +1,16 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Timeout fired without iframe onload event fired.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..f9e125e
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.");
+        jsTestIsAsync = true;
+        testRunner.dumpChildFramesAsText();
+
+        function iframeLoadError() {
+            testPassed("Timeout fired without iframe onload event fired.");
+            finishJSTest();
+        }
+
+        function iframeLoadSuccess() {
+            testFailed("Document load succeeded.");
+            finishJSTest();
+        }
+
+        setTimeout("iframeLoadError()", 500);
+    </script>
+</head>
+<body>
+<iframe src="http://localhost:8000/from-origin/resources/iframe.php?fromOrigin=same" sandbox="" onload="iframeLoadSuccess()"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..3d989aa
--- /dev/null
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a nested cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The outer iframe, loading a nested localhost iframe.
+
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->/<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..c1cfc24
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a nested cross-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/nestedLocalhostIframe.html" sandbox=""></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..93be80a
--- /dev/null
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+Tests that a nested same-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+The outer iframe, loading a nested 127.0.0.1 iframe.
+
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->/<!--frame0-->-->'
+--------
+
diff --git a/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..acc9eae
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a nested same-origin document load fails if the server blocks cross-origin loads with a 'From-Origin: same' response header and the iframe is sandboxed.");
+        testRunner.dumpChildFramesAsText();
+    </script>
+</head>
+<body>
+<iframe src="http://127.0.0.1:8000/from-origin/resources/nestedIPAddressIframe.html" sandbox=""></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/script-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..8edf611
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin script load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Script load succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Created by JavaScript.
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/script-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..932fe40
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin script load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function scriptLoadError() {
+            testFailed("Timeout fired without script onload event fired.");
+            finishJSTest();
+        }
+
+        function scriptLoadSuccess() {
+            testPassed("Script load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<script src="http://127.0.0.1:8000/from-origin/resources/script.php?fromOrigin=same" onload="scriptLoadSuccess()" onerror="scriptLoadError()"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/script-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..f4a46e3
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin script load denied by Cross-Origin Resource Sharing policy.
+Tests that a cross-origin script load fails if the server blocks it with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Script load blocked
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/script-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..65f4385
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin script load fails if the server blocks it with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function scriptLoadError() {
+            testPassed("Script load blocked");
+            finishJSTest();
+        }
+
+        function scriptLoadSuccess() {
+            testFailed("Script load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<script src="http://localhost:8000/from-origin/resources/script.php?fromOrigin=same" onload="scriptLoadSuccess()" onerror="scriptLoadError()"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted-expected.txt b/LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted-expected.txt
new file mode 100644 (file)
index 0000000..4d5ed52
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin script load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Script load succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Created by JavaScript.
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted.html b/LayoutTests/http/tests/from-origin/script-from-origin-same-site-accepted.html
new file mode 100644 (file)
index 0000000..7b02f4f
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin script load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        function scriptLoadError() {
+            testFailed("Timeout fired without script onload event fired.");
+            finishJSTest();
+        }
+
+        function scriptLoadSuccess() {
+            testPassed("Script load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<script src="http://127.0.0.1:8000/from-origin/resources/script.php?fromOrigin=same-site" onload="scriptLoadSuccess()" onerror="scriptLoadError()"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked-expected.txt b/LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked-expected.txt
new file mode 100644 (file)
index 0000000..11e22a7
--- /dev/null
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: Cancelled load because it violates the resource's From-Origin response header.
+CONSOLE MESSAGE: Cross-origin script load denied by Cross-Origin Resource Sharing policy.
+Tests that a cross-origin script load fails if the server blocks it with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Script load blocked
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked.html b/LayoutTests/http/tests/from-origin/script-from-origin-same-site-blocked.html
new file mode 100644 (file)
index 0000000..d8d7e31
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin script load fails if the server blocks it with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        function scriptLoadError() {
+            testPassed("Script load blocked");
+            finishJSTest();
+        }
+
+        function scriptLoadSuccess() {
+            testFailed("Script load succeeded.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+<script src="http://localhost:8000/from-origin/resources/script.php?fromOrigin=same-site" onload="scriptLoadSuccess()" onerror="scriptLoadError()"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..6c235c3
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin top frame document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Onload event fired.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+The Document
diff --git a/LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted.php b/LayoutTests/http/tests/from-origin/top-frame-document-from-origin-same-accepted.php
new file mode 100644 (file)
index 0000000..bfbcac4
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+header("From-Origin: Same");
+?>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin top frame document load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+        testRunner.dumpChildFramesAsText();
+
+        function onloadFired() {
+            testPassed("Onload event fired.");
+            finishJSTest();
+        }
+    </script>
+</head>
+<body onload="onloadFired()">
+<h3>The Document</h3>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted-expected.txt b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted-expected.txt
new file mode 100644 (file)
index 0000000..703d74c
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin xhr load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Xhr succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted.html b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-accepted.html
new file mode 100644 (file)
index 0000000..74ad7ba
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin xhr load succeeds if the server blocks cross-origin loads with a 'From-Origin: same' response header.");
+        jsTestIsAsync = true;
+
+        function transferComplete() {
+            if (xhr.responseText === "xhr")
+                testPassed("Xhr succeeded.");
+            else
+                testFailed("Unknown xhr response: " + xhr.responseText);
+            finishJSTest();
+        }
+
+        function transferFailed() {
+            testFailed("Xhr blocked. " + xhr.statusText);
+            finishJSTest();
+        }
+
+        var xhr = new XMLHttpRequest();
+        xhr.addEventListener("load", transferComplete);
+        xhr.addEventListener("error", transferFailed);
+        xhr.open("GET", "http://127.0.0.1:8000/from-origin/resources/xhr.php?fromOrigin=same");
+        xhr.send();
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked-expected.txt b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked-expected.txt
new file mode 100644 (file)
index 0000000..786aafe
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin xhr load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Xhr blocked. 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked.html b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-blocked.html
new file mode 100644 (file)
index 0000000..e02e2ed
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin xhr load fails if the server blocks it with a 'From-Origin: same' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        function transferComplete() {
+            if (xhr.responseText === "xhr")
+                testFailed("Xhr succeeded.");
+            else
+                testFailed("Unknown xhr response: " + xhr.responseText);
+            finishJSTest();
+        }
+
+        function transferFailed() {
+            testPassed("Xhr blocked. " + xhr.statusText);
+            finishJSTest();
+        }
+
+        var xhr = new XMLHttpRequest();
+        xhr.addEventListener("load", transferComplete);
+        xhr.addEventListener("error", transferFailed);
+        xhr.open("GET", "http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same");
+        xhr.send();
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted-expected.txt b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted-expected.txt
new file mode 100644 (file)
index 0000000..0961b17
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that a same-origin xhr load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Xhr succeeded.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted.html b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-accepted.html
new file mode 100644 (file)
index 0000000..2adc562
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a same-origin xhr load succeeds if the server blocks cross-origin loads with a 'From-Origin: same-site' response header.");
+        jsTestIsAsync = true;
+
+        function transferComplete() {
+            if (xhr.responseText === "xhr")
+                testPassed("Xhr succeeded.");
+            else
+                testFailed("Unknown xhr response: " + xhr.responseText);
+            finishJSTest();
+        }
+
+        function transferFailed() {
+            testFailed("Xhr blocked. " + xhr.statusText);
+            finishJSTest();
+        }
+
+        var xhr = new XMLHttpRequest();
+        xhr.addEventListener("load", transferComplete);
+        xhr.addEventListener("error", transferFailed);
+        xhr.open("GET", "http://127.0.0.1:8000/from-origin/resources/xhr.php?fromOrigin=same-site");
+        xhr.send();
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked-expected.txt b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked-expected.txt
new file mode 100644 (file)
index 0000000..65e6a6a
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same-site. Cancelled load because it violates the resource's From-Origin response header.
+Tests that a cross-origin xhr load fails if the server blocks it with a 'From-Origin: same-site' response header, even though the server includes an Access-Control-Allow-Origin response header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Xhr blocked. 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked.html b/LayoutTests/http/tests/from-origin/xhr-from-origin-same-site-blocked.html
new file mode 100644 (file)
index 0000000..7287187
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script>
+        description("Tests that a cross-origin xhr load fails if the server blocks it with a 'From-Origin: same-site' response header, even though the server includes an Access-Control-Allow-Origin response header.");
+        jsTestIsAsync = true;
+
+        function transferComplete() {
+            if (xhr.responseText === "xhr")
+                testFailed("Xhr succeeded.");
+            else
+                testFailed("Unknown xhr response: " + xhr.responseText);
+            finishJSTest();
+        }
+
+        function transferFailed() {
+            testPassed("Xhr blocked. " + xhr.statusText);
+            finishJSTest();
+        }
+
+        var xhr = new XMLHttpRequest();
+        xhr.addEventListener("load", transferComplete);
+        xhr.addEventListener("error", transferFailed);
+        xhr.open("GET", "http://localhost:8000/from-origin/resources/xhr.php?fromOrigin=same-site");
+        xhr.send();
+    </script>
+</head>
+<body>
+</body>
+</html>
index 08bdc28..08115e7 100644 (file)
@@ -1,3 +1,24 @@
+2018-04-24  John Wilander  <wilander@apple.com>
+
+        From-Origin: Support for 'same' and 'same-site' response header, nested frame origin check
+        https://bugs.webkit.org/show_bug.cgi?id=184560
+        <rdar://problem/38901344>
+
+        Reviewed by Youenn Fablet and Daniel Bates.
+
+        This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
+        We consume the From-Origin response header and only load the resource if:
+        - The header is non-existent, empty, or invalid.
+        - The header specifies 'same' and the resource's origin matches the originating
+          document's origin and the origins up the frame tree.
+        - The header specifies 'same-site' and the resource's eTLD+1 matches the originating
+          document's eTLD+1 and the eTLD+1 of the documents up the frame tree.
+
+        This feature is experimental and off by default.
+
+        * web-platform-tests/service-workers/service-worker/fetch-request-redirect.https-expected.txt:
+            Removed console message since they are now suppressed.
+
 2018-04-23  Ms2ger  <Ms2ger@igalia.com>
 
         Avoid uninitialized memory read.
index c2c1912..261dc7c 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: XMLHttpRequest cannot load https://localhost:9443/service-workers/service-worker/resources/redirect.py?Redirect=%2Fservice-workers%2Fservice-worker%2Fresources%2Fsimple.txt. Response served by service worker is opaque redirect
 
 PASS Verify redirect mode of Fetch API and ServiceWorker FetchEvent. 
 PASS Verify redirected of Response(Fetch API) and ServiceWorker FetchEvent. 
index 067f73a..946cbe3 100644 (file)
@@ -854,7 +854,7 @@ webkit.org/b/172879 webrtc/video-unmute.html [ Skip ]
 
 webkit.org/b/181502 swipe/pushstate-with-manual-scrollrestoration.html [ Failure ]
 
-webkit.org/b/181750 imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html [ Pass Failure ]
+webkit.org/b/181750 imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html [ DumpJSConsoleLogInStdErr Pass Failure ]
 
 webkit.org/b/181839 [ Debug ] inspector/debugger/breakpoint-action-log.html [ Pass Timeout ]
 
index 6ed2d48..6565033 100644 (file)
@@ -710,6 +710,9 @@ http/tests/resourceLoadStatistics/strip-referrer-to-origin-for-prevalent-subreso
 # Process swapping is only implemented on WebKit2.
 http/tests/navigation/process-swap-window-open.html [ Pass ]
 
+# From-Origin response header is only implemented in WebKit2.
+http/tests/from-origin/ [ Pass ]
+
 ### END OF (5) Progressions, expected successes that are expected failures in WebKit1.
 ########################################
 
index 5debef0..bdeda74 100644 (file)
@@ -1,3 +1,62 @@
+2018-04-24  John Wilander  <wilander@apple.com>
+
+        From-Origin: Support for 'same' and 'same-site' response header, nested frame origin check
+        https://bugs.webkit.org/show_bug.cgi?id=184560
+        <rdar://problem/38901344>
+
+        Reviewed by Youenn Fablet and Daniel Bates.
+
+        Tests: http/tests/from-origin/document-from-origin-same-accepted.html
+               http/tests/from-origin/document-from-origin-same-blocked.html
+               http/tests/from-origin/document-from-origin-same-site-accepted.html
+               http/tests/from-origin/document-from-origin-same-site-blocked.html
+               http/tests/from-origin/document-nested-from-origin-same-accepted.html
+               http/tests/from-origin/document-nested-from-origin-same-blocked.html
+               http/tests/from-origin/fetch-data-iframe-from-origin-same-blocked.html
+               http/tests/from-origin/fetch-from-origin-same-accepted.html
+               http/tests/from-origin/fetch-from-origin-same-blocked.html
+               http/tests/from-origin/fetch-from-origin-same-site-accepted.html
+               http/tests/from-origin/fetch-from-origin-same-site-blocked.html
+               http/tests/from-origin/fetch-iframe-from-origin-same-accepted.html
+               http/tests/from-origin/fetch-iframe-from-origin-same-blocked.html
+               http/tests/from-origin/image-about-blank-from-origin-same-blocked.html
+               http/tests/from-origin/image-from-origin-same-accepted.html
+               http/tests/from-origin/image-from-origin-same-blocked.html
+               http/tests/from-origin/image-from-origin-same-site-accepted.html
+               http/tests/from-origin/image-from-origin-same-site-blocked.html
+               http/tests/from-origin/redirect-document-from-origin-same-blocked.html
+               http/tests/from-origin/redirect-fetch-from-origin-same-blocked.html
+               http/tests/from-origin/redirect-image-from-origin-same-blocked.html
+               http/tests/from-origin/redirect-script-from-origin-same-blocked.html
+               http/tests/from-origin/redirect-xhr-from-origin-same-blocked.html
+               http/tests/from-origin/sandboxed-sub-frame-from-origin-same-blocked.html
+               http/tests/from-origin/sandboxed-sub-frame-nested-cross-origin-from-origin-same-blocked.html
+               http/tests/from-origin/sandboxed-sub-frame-nested-same-origin-from-origin-same-blocked.html
+               http/tests/from-origin/script-from-origin-same-accepted.html
+               http/tests/from-origin/script-from-origin-same-blocked.html
+               http/tests/from-origin/script-from-origin-same-site-accepted.html
+               http/tests/from-origin/script-from-origin-same-site-blocked.html
+               http/tests/from-origin/top-frame-document-from-origin-same-accepted.php
+               http/tests/from-origin/xhr-from-origin-same-accepted.html
+               http/tests/from-origin/xhr-from-origin-same-blocked.html
+               http/tests/from-origin/xhr-from-origin-same-site-accepted.html
+               http/tests/from-origin/xhr-from-origin-same-site-blocked.html
+
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::didFail):
+            Outputs the error's localized description in a console message except when the destination
+            is FetchOptions::Destination::Serviceworker or FetchOptions::Destination::EmptyString.
+        * page/RuntimeEnabledFeatures.h:
+        (WebCore::RuntimeEnabledFeatures::setFromOriginResponseHeaderEnabled):
+        (WebCore::RuntimeEnabledFeatures::fromOriginResponseHeaderEnabled const):
+            Added From-Origin support as an experimental feature.
+        * platform/network/HTTPHeaderNames.in:
+            Added From-Origin.
+        * platform/network/HTTPParsers.cpp:
+        (WebCore::parseFromOriginHeader):
+            Parses the From-Origin header, currently supporting 'Same' and 'Same-Site.'
+        * platform/network/HTTPParsers.h:
+
 2018-04-24  Antti Koivisto  <antti@apple.com>
 
         Rename LayoutCtx.h/cpp to LayoutContext.h/cpp
index 2c3a1ee..2d127e8 100644 (file)
@@ -650,6 +650,9 @@ void SubresourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMe
 
 void SubresourceLoader::didFail(const ResourceError& error)
 {
+    if (m_frame && m_frame->document() && error.isAccessControl() && options().destination != FetchOptions::Destination::Serviceworker && options().destination != FetchOptions::Destination::EmptyString)
+        m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, error.localizedDescription());
+
 #if USE(QUICK_LOOK)
     if (auto previewLoader = m_previewLoader.get())
         previewLoader->didFail();
index c54f8ef..35a3b8f 100644 (file)
@@ -250,6 +250,9 @@ public:
     void setRestrictedHTTPResponseAccess(bool isEnabled) { m_isRestrictedHTTPResponseAccess = isEnabled; }
     bool restrictedHTTPResponseAccess() const { return m_isRestrictedHTTPResponseAccess; }
 
+    void setFromOriginResponseHeaderEnabled(bool isEnabled) { m_fromOriginResponseHeaderEnabled = isEnabled; }
+    bool fromOriginResponseHeaderEnabled() const { return m_fromOriginResponseHeaderEnabled; }
+
     WEBCORE_EXPORT static RuntimeEnabledFeatures& sharedFeatures();
 
 private:
@@ -383,7 +386,9 @@ private:
     bool m_resourceLoadStatisticsDebugMode { false };
 
     bool m_isRestrictedHTTPResponseAccess { false };
-    
+
+    bool m_fromOriginResponseHeaderEnabled { false };
+
     friend class WTF::NeverDestroyed<RuntimeEnabledFeatures>;
 };
 
index 1a2410b..c8f45e5 100644 (file)
@@ -897,4 +897,20 @@ String normalizeHTTPMethod(const String& method)
     return method;
 }
 
+FromOriginDisposition parseFromOriginHeader(const String& header)
+{
+    auto strippedHeader = stripLeadingAndTrailingHTTPSpaces(header);
+
+    if (strippedHeader.isEmpty())
+        return FromOriginDisposition::None;
+
+    if (equalLettersIgnoringASCIICase(strippedHeader, "same"))
+        return FromOriginDisposition::Same;
+
+    if (equalLettersIgnoringASCIICase(strippedHeader, "same-site"))
+        return FromOriginDisposition::SameSite;
+
+    return FromOriginDisposition::Invalid;
+}
+
 }
index ffddf34..90bcd18 100644 (file)
@@ -64,6 +64,13 @@ enum XFrameOptionsDisposition {
     XFrameOptionsConflict
 };
 
+enum class FromOriginDisposition {
+    None,
+    Same,
+    SameSite,
+    Invalid
+};
+
 bool isValidReasonPhrase(const String&);
 bool isValidHTTPHeaderValue(const String&);
 bool isValidAcceptHeaderValue(const String&);
@@ -103,6 +110,8 @@ bool isCrossOriginSafeRequestHeader(HTTPHeaderName, const String&);
 
 String normalizeHTTPMethod(const String&);
 
+WEBCORE_EXPORT FromOriginDisposition parseFromOriginHeader(const String&);
+
 inline bool isHTTPSpace(UChar character)
 {
     return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r');
index b9dfeef..e45591e 100644 (file)
@@ -1,3 +1,62 @@
+2018-04-24  John Wilander  <wilander@apple.com>
+
+        From-Origin: Support for 'same' and 'same-site' response header, nested frame origin check
+        https://bugs.webkit.org/show_bug.cgi?id=184560
+        <rdar://problem/38901344>
+
+        Reviewed by Youenn Fablet and Daniel Bates.
+
+        This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
+        We consume the From-Origin response header and only load the resource if:
+        - The header is non-existent, empty, or invalid.
+        - The header specifies 'same' and the resource's origin matches the originating
+          document's origin and the origins up the frame tree.
+        - The header specifies 'same-site' and the resource's eTLD+1 matches the originating
+          document's eTLD+1 and the eTLD+1 of the documents up the frame tree.
+
+        This feature is experimental and off by default.
+
+        * NetworkProcess/NetworkResourceLoadParameters.cpp:
+        (WebKit::NetworkResourceLoadParameters::encode const):
+        (WebKit::NetworkResourceLoadParameters::decode):
+            Support for the two new load parameters:
+            - shouldEnableFromOriginResponseHeader
+            - frameAncestorOrigins
+        * NetworkProcess/NetworkResourceLoadParameters.h:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::areFrameAncestorsSameSite):
+        (WebKit::areFrameAncestorsSameOrigin):
+        (WebKit::shouldCancelCrossOriginLoad):
+            The three functions above implement the new blocking logic.
+        (WebKit::fromOriginResourceError):
+            Convenience function that returns an error with the From-Origin error message.
+        (WebKit::NetworkResourceLoader::didReceiveResponse):
+            Now checks for a From-Origin response header.
+        (WebKit::NetworkResourceLoader::didFailLoading):
+            Now checks for a From-Origin response header.
+        (WebKit::NetworkResourceLoader::continueWillSendRedirectedRequest):
+            Now checks for a From-Origin response header.
+        (WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
+            Now checks for a From-Origin response header.
+        (WebKit::NetworkResourceLoader::dispatchWillSendRequestForCacheEntry):
+            Now checks for a From-Origin response header.
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::encode):
+        (IPC::ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::decode):
+            Now encodes and decodes vectors of RefPtr<WebCore::SecurityOrigin>.
+        * Shared/WebCoreArgumentCoders.h:
+        * Shared/WebPreferences.yaml:
+            Added From-Origin support as an experimental feature.
+        * UIProcess/API/C/WKPreferences.cpp:
+        (WKPreferencesSetFromOriginResponseHeaderEnabled):
+        (WKPreferencesGetFromOriginResponseHeaderEnabled):
+        * UIProcess/API/C/WKPreferencesRef.h:
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::scheduleLoadFromNetworkProcess):
+            Sets the two new load parameters:
+            - shouldEnableFromOriginResponseHeader
+            - frameAncestorOrigins
+
 2018-04-24  Jer Noble  <jer.noble@apple.com>
 
         Don't add system framework paths to FRAMEWORK_SEARCH_PATHS
index 6f57a04..74a48b9 100644 (file)
@@ -96,6 +96,10 @@ void NetworkResourceLoadParameters::encode(IPC::Encoder& encoder) const
 
     encoder.encodeEnum(preflightPolicy);
 
+    encoder << shouldEnableFromOriginResponseHeader;
+    if (shouldEnableFromOriginResponseHeader)
+        encoder << frameAncestorOrigins;
+
 #if ENABLE(CONTENT_EXTENSIONS)
     encoder << mainDocumentURL;
     encoder << userContentControllerIdentifier;
@@ -198,6 +202,16 @@ bool NetworkResourceLoadParameters::decode(IPC::Decoder& decoder, NetworkResourc
     if (!decoder.decodeEnum(result.preflightPolicy))
         return false;
 
+    std::optional<bool> shouldEnableFromOriginResponseHeader;
+    decoder >> shouldEnableFromOriginResponseHeader;
+    if (!shouldEnableFromOriginResponseHeader)
+        return false;
+    result.shouldEnableFromOriginResponseHeader = *shouldEnableFromOriginResponseHeader;
+    if (result.shouldEnableFromOriginResponseHeader) {
+        if (!decoder.decode(result.frameAncestorOrigins))
+            return false;
+    }
+    
 #if ENABLE(CONTENT_EXTENSIONS)
     if (!decoder.decode(result.mainDocumentURL))
         return false;
index e5e99d5..75a917e 100644 (file)
@@ -61,6 +61,8 @@ public:
     WebCore::HTTPHeaderMap originalRequestHeaders;
     bool shouldRestrictHTTPResponseAccess { false };
     WebCore::PreflightPolicy preflightPolicy { WebCore::PreflightPolicy::Consider };
+    bool shouldEnableFromOriginResponseHeader { false };
+    Vector<RefPtr<WebCore::SecurityOrigin>> frameAncestorOrigins;
 
 #if ENABLE(CONTENT_EXTENSIONS)
     WebCore::URL mainDocumentURL;
index debf13d..28ca190 100644 (file)
 #include <WebCore/CertificateInfo.h>
 #include <WebCore/DiagnosticLoggingKeys.h>
 #include <WebCore/HTTPHeaderNames.h>
+#include <WebCore/HTTPParsers.h>
 #include <WebCore/NetworkLoadMetrics.h>
 #include <WebCore/ProtectionSpace.h>
 #include <WebCore/SameSiteInfo.h>
+#include <WebCore/SecurityOrigin.h>
 #include <WebCore/SharedBuffer.h>
 #include <WebCore/SynchronousLoaderClient.h>
 #include <wtf/RunLoop.h>
@@ -360,6 +362,46 @@ void NetworkResourceLoader::abort()
     cleanup();
 }
 
+static bool areFrameAncestorsSameSite(const ResourceResponse& response, const Vector<RefPtr<SecurityOrigin>>& frameAncestorOrigins)
+{
+#if ENABLE(PUBLIC_SUFFIX_LIST)
+    auto responsePartition = ResourceRequest::partitionName(response.url().host());
+    return frameAncestorOrigins.findMatching([&](const auto& item) {
+        return item->isUnique() || ResourceRequest::partitionName(item->host()) != responsePartition;
+    }) == notFound;
+#else
+    UNUSED_PARAM(response);
+    UNUSED_PARAM(frameAncestorOrigins);
+    return false;
+#endif
+}
+
+static bool areFrameAncestorsSameOrigin(const ResourceResponse& response, const Vector<RefPtr<SecurityOrigin>>& frameAncestorOrigins)
+{
+    return frameAncestorOrigins.findMatching([responseOrigin = SecurityOrigin::create(response.url())](const auto& item) {
+        return !item->isSameOriginAs(responseOrigin);
+    }) == notFound;
+}
+
+static bool shouldCancelCrossOriginLoad(const ResourceResponse& response, const Vector<RefPtr<SecurityOrigin>>& frameAncestorOrigins)
+{
+    auto fromOriginDirective = WebCore::parseFromOriginHeader(response.httpHeaderField(WebCore::HTTPHeaderName::FromOrigin));
+    switch (fromOriginDirective) {
+    case WebCore::FromOriginDisposition::None:
+    case WebCore::FromOriginDisposition::Invalid:
+        return false;
+    case WebCore::FromOriginDisposition::Same:
+        return !areFrameAncestorsSameOrigin(response, frameAncestorOrigins);
+    case WebCore::FromOriginDisposition::SameSite:
+        return !areFrameAncestorsSameSite(response, frameAncestorOrigins);
+    }
+}
+
+static ResourceError fromOriginResourceError(const URL& url)
+{
+    return { errorDomainWebKitInternal, 0, url, ASCIILiteral { "Cancelled load because it violates the resource's From-Origin response header." }, ResourceError::Type::AccessControl };
+}
+
 auto NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedResponse) -> ShouldContinueDidReceiveResponse
 {
     RELEASE_LOG_IF_ALLOWED("didReceiveResponse: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", httpStatusCode = %d, length = %" PRId64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, receivedResponse.httpStatusCode(), receivedResponse.expectedContentLength());
@@ -390,15 +432,20 @@ auto NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedRespon
 
     bool shouldWaitContinueDidReceiveResponse = isMainResource();
     if (shouldSendDidReceiveResponse) {
-        if (m_networkLoadChecker) {
-            auto error = m_networkLoadChecker->validateResponse(m_response);
-            if (!error.isNull()) {
-                RunLoop::main().dispatch([protectedThis = makeRef(*this), error = WTFMove(error)] {
-                    if (protectedThis->m_networkLoad)
-                        protectedThis->didFailLoading(error);
-                });
-                return ShouldContinueDidReceiveResponse::No;
-            }
+
+        ResourceError error;
+        if (m_parameters.shouldEnableFromOriginResponseHeader && shouldCancelCrossOriginLoad(m_response, m_parameters.frameAncestorOrigins))
+            error = fromOriginResourceError(m_response.url());
+
+        if (error.isNull() && m_networkLoadChecker)
+            error = m_networkLoadChecker->validateResponse(m_response);
+
+        if (!error.isNull()) {
+            RunLoop::main().dispatch([protectedThis = makeRef(*this), error = WTFMove(error)] {
+                if (protectedThis->m_networkLoad)
+                    protectedThis->didFailLoading(error);
+            });
+            return ShouldContinueDidReceiveResponse::No;
         }
 
         auto response = sanitizeResponseIfPossible(ResourceResponse { m_response }, ResourceResponse::SanitizationType::CrossOriginSafe);
@@ -487,7 +534,7 @@ void NetworkResourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLo
 
 void NetworkResourceLoader::didFailLoading(const ResourceError& error)
 {
-    RELEASE_LOG_IF_ALLOWED("didFailLoading: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isTimeout = %d, isCancellation = %d, errCode = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, error.isTimeout(), error.isCancellation(), error.errorCode());
+    RELEASE_LOG_IF_ALLOWED("didFailLoading: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isTimeout = %d, isCancellation = %d, isAccessControl = %d, errCode = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, error.isTimeout(), error.isCancellation(), error.isAccessControl(), error.errorCode());
 
     if (shouldCaptureExtraNetworkLoadMetrics())
         m_connection->removeNetworkLoadInformation(identifier());
@@ -551,6 +598,11 @@ void NetworkResourceLoader::continueWillSendRedirectedRequest(WebCore::ResourceR
     if (canUseCachedRedirect(request))
         m_cache->storeRedirect(request, redirectResponse, redirectRequest);
 
+    if (m_parameters.shouldEnableFromOriginResponseHeader && shouldCancelCrossOriginLoad(redirectResponse, m_parameters.frameAncestorOrigins) && m_networkLoad) {
+        didFailLoading(fromOriginResourceError(redirectResponse.url()));
+        return;
+    }
+
     send(Messages::WebResourceLoader::WillSendRequest(redirectRequest, sanitizeResponseIfPossible(WTFMove(redirectResponse), ResourceResponse::SanitizationType::Redirection)));
 }
 
@@ -669,7 +721,13 @@ void NetworkResourceLoader::tryStoreAsCacheEntry()
 void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
 {
     auto response = entry->response();
-    auto error = m_networkLoadChecker ? m_networkLoadChecker->validateResponse(response) : ResourceError { };
+
+    ResourceError error;
+    if (m_parameters.shouldEnableFromOriginResponseHeader && shouldCancelCrossOriginLoad(response, m_parameters.frameAncestorOrigins))
+        error = fromOriginResourceError(response.url());
+
+    if (error.isNull() && m_networkLoadChecker)
+        error = m_networkLoadChecker->validateResponse(response);
 
     if (!error.isNull()) {
         didFailLoading(error);
@@ -780,8 +838,14 @@ void NetworkResourceLoader::dispatchWillSendRequestForCacheEntry(std::unique_ptr
 
     LOG(NetworkCache, "(NetworkProcess) Executing cached redirect");
 
+    auto& response = entry->response();
+    if (m_parameters.shouldEnableFromOriginResponseHeader && shouldCancelCrossOriginLoad(response, m_parameters.frameAncestorOrigins) && m_networkLoad) {
+        didFailLoading(fromOriginResourceError(response.url()));
+        return;
+    }
+
     ++m_redirectCount;
-    send(Messages::WebResourceLoader::WillSendRequest { *entry->redirectRequest(), sanitizeResponseIfPossible(ResourceResponse { entry->response() }, ResourceResponse::SanitizationType::Redirection) });
+    send(Messages::WebResourceLoader::WillSendRequest { *entry->redirectRequest(), sanitizeResponseIfPossible(ResourceResponse { response }, ResourceResponse::SanitizationType::Redirection) });
     m_isWaitingContinueWillSendRequestForCachedRedirect = true;
 }
 
index 430c33e..577c49c 100644 (file)
@@ -67,6 +67,7 @@
 #include <WebCore/ScrollingConstraints.h>
 #include <WebCore/ScrollingCoordinator.h>
 #include <WebCore/SearchPopupMenu.h>
+#include <WebCore/SecurityOrigin.h>
 #include <WebCore/ServiceWorkerClientData.h>
 #include <WebCore/ServiceWorkerClientIdentifier.h>
 #include <WebCore/ServiceWorkerData.h>
@@ -2833,4 +2834,27 @@ bool ArgumentCoder<AttachmentInfo>::decode(Decoder& decoder, AttachmentInfo& inf
 
 #endif // ENABLE(ATTACHMENT_ELEMENT)
 
+void ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::encode(Encoder& encoder, const Vector<RefPtr<SecurityOrigin>>& origins)
+{
+    encoder << static_cast<uint64_t>(origins.size());
+    for (auto& origin : origins)
+        encoder << *origin;
+}
+    
+bool ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::decode(Decoder& decoder, Vector<RefPtr<SecurityOrigin>>& origins)
+{
+    uint64_t dataSize;
+    if (!decoder.decode(dataSize))
+        return false;
+
+    origins.reserveInitialCapacity(dataSize);
+    for (uint64_t i = 0; i < dataSize; ++i) {
+        auto decodedOriginRefPtr = SecurityOrigin::decode(decoder);
+        if (!decodedOriginRefPtr)
+            return false;
+        origins.uncheckedAppend(decodedOriginRefPtr.releaseNonNull());
+    }
+    return true;
+}
+
 } // namespace IPC
index 1252d69..edabab6 100644 (file)
@@ -85,6 +85,7 @@ class Region;
 class ResourceError;
 class ResourceRequest;
 class ResourceResponse;
+class SecurityOrigin;
 class SpringTimingFunction;
 class StepsTimingFunction;
 class FramesTimingFunction;
@@ -698,6 +699,11 @@ template<> struct ArgumentCoder<WebCore::AttachmentInfo> {
 
 #endif
 
+template<> struct ArgumentCoder<Vector<RefPtr<WebCore::SecurityOrigin>>> {
+    static void encode(Encoder&, const Vector<RefPtr<WebCore::SecurityOrigin>>&);
+    static bool decode(Decoder&, Vector<RefPtr<WebCore::SecurityOrigin>>&);
+};
+
 } // namespace IPC
 
 namespace WTF {
index 7611a36..8332925 100644 (file)
@@ -1233,3 +1233,11 @@ RestrictedHTTPResponseAccess:
     humanReadableDescription: "Restricted HTTP Response Access to Web Process"
     category: experimental
     webcoreBinding: RuntimeEnabledFeatures
+
+FromOriginResponseHeaderEnabled:
+    type: bool
+    defaultValue: false
+    humanReadableName: "From-Origin Response Header"
+    humanReadableDescription: "Support for the From-Origin Response Header"
+    category: experimental
+    webcoreBinding: RuntimeEnabledFeatures
index 6474d1c..edd474f 100644 (file)
@@ -1964,6 +1964,16 @@ bool WKPreferencesGetAllowCrossOriginSubresourcesToAskForCredentials(WKPreferenc
     return toImpl(preferencesRef)->allowCrossOriginSubresourcesToAskForCredentials();
 }
 
+void WKPreferencesSetFromOriginResponseHeaderEnabled(WKPreferencesRef preferencesRef, bool flag)
+{
+    toImpl(preferencesRef)->setFromOriginResponseHeaderEnabled(flag);
+}
+
+bool WKPreferencesGetFromOriginResponseHeaderEnabled(WKPreferencesRef preferencesRef)
+{
+    return toImpl(preferencesRef)->fromOriginResponseHeaderEnabled();
+}
+
 void WKPreferencesSetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRef, bool flag)
 {
     toImpl(preferencesRef)->setRestrictedHTTPResponseAccess(flag);
index 35b92c3..a5f90f8 100644 (file)
@@ -315,6 +315,10 @@ WK_EXPORT void WKPreferencesSetMediaCapabilitiesEnabled(WKPreferencesRef prefere
 WK_EXPORT bool WKPreferencesGetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRef);
 WK_EXPORT void WKPreferencesSetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRef, bool allow);
 
+// Defaults to false.
+WK_EXPORT bool WKPreferencesGetFromOriginResponseHeaderEnabled(WKPreferencesRef preferencesRef);
+WK_EXPORT void WKPreferencesSetFromOriginResponseHeaderEnabled(WKPreferencesRef preferencesRef, bool allow);
+
 #ifdef __cplusplus
 }
 #endif
index 0d475b7..86b9509 100644 (file)
@@ -325,6 +325,20 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL
     // FIXME: We should also sanitize redirect response for navigations.
     loadParameters.shouldRestrictHTTPResponseAccess = RuntimeEnabledFeatures::sharedFeatures().restrictedHTTPResponseAccess() && resourceLoader.options().mode != FetchOptions::Mode::Navigate;
 
+    bool isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate;
+
+    loadParameters.shouldEnableFromOriginResponseHeader = RuntimeEnabledFeatures::sharedFeatures().fromOriginResponseHeaderEnabled() && !isMainFrameNavigation;
+    if (loadParameters.shouldEnableFromOriginResponseHeader) {
+        Vector<RefPtr<WebCore::SecurityOrigin>> frameAncestorOrigins;
+        for (auto* frame = resourceLoader.frame(); frame; frame = frame->tree().parent()) {
+            if (frame->document())
+                frameAncestorOrigins.append(makeRefPtr(frame->document()->securityOrigin()));
+            if (frame->isMainFrame())
+                break;
+        }
+        loadParameters.frameAncestorOrigins = WTFMove(frameAncestorOrigins);
+    }
+
     ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials);
 
     RELEASE_LOG_IF_ALLOWED(resourceLoader, "scheduleLoad: Resource is being scheduled with the NetworkProcess (frame = %p, priority = %d, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader.frame(), static_cast<int>(resourceLoader.request().priority()), loadParameters.webPageID, loadParameters.webFrameID, loadParameters.identifier);
index f9a74df..3586e6b 100644 (file)
@@ -1,3 +1,26 @@
+2018-04-24  John Wilander  <wilander@apple.com>
+
+        From-Origin: Support for 'same' and 'same-site' response header, nested frame origin check
+        https://bugs.webkit.org/show_bug.cgi?id=184560
+        <rdar://problem/38901344>
+
+        Reviewed by Youenn Fablet and Daniel Bates.
+
+        This patch implements significant parts of https://github.com/whatwg/fetch/issues/687.
+        We consume the From-Origin response header and only load the resource if:
+        - The header is non-existent, empty, or invalid.
+        - The header specifies 'same' and the resource's origin matches the originating
+          document's origin and the origins up the frame tree.
+        - The header specifies 'same-site' and the resource's eTLD+1 matches the originating
+          document's eTLD+1 and the eTLD+1 of the documents up the frame tree.
+
+        This feature is experimental and off by default.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/HTTPParsers.cpp: Added.
+        (TestWebKitAPI::TEST):
+            Tests for From-Origin header parsing.
+
 2018-04-24  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Unreviewed. Update W3C WebDriver imported tests.
index 7943fd2..e448163 100644 (file)
                636353A71E98665D0009F8AF /* GeolocationGetCurrentPositionResult.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 636353A61E9861940009F8AF /* GeolocationGetCurrentPositionResult.html */; };
                63A61B8B1FAD251100F06885 /* display-mode.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 63A61B8A1FAD204D00F06885 /* display-mode.html */; };
                63F668221F97F7F90032EE51 /* ApplicationManifest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 63F668201F97C3AA0032EE51 /* ApplicationManifest.mm */; };
+               6B9ABE122086952F00D75DE6 /* HTTPParsers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B9ABE112086952F00D75DE6 /* HTTPParsers.cpp */; };
                6BFD294C1D5E6C1D008EC968 /* HashCountedSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */; };
                751B05D61F8EAC410028A09E /* DatabaseTrackerTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 751B05D51F8EAC1A0028A09E /* DatabaseTrackerTest.mm */; };
                754CEC811F6722F200D0039A /* AutoFillAvailable.mm in Sources */ = {isa = PBXBuildFile; fileRef = 754CEC801F6722DC00D0039A /* AutoFillAvailable.mm */; };
                636353A61E9861940009F8AF /* GeolocationGetCurrentPositionResult.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = GeolocationGetCurrentPositionResult.html; sourceTree = "<group>"; };
                63A61B8A1FAD204D00F06885 /* display-mode.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "display-mode.html"; sourceTree = "<group>"; };
                63F668201F97C3AA0032EE51 /* ApplicationManifest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ApplicationManifest.mm; sourceTree = "<group>"; };
+               6B9ABE112086952F00D75DE6 /* HTTPParsers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPParsers.cpp; sourceTree = "<group>"; };
                751B05D51F8EAC1A0028A09E /* DatabaseTrackerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DatabaseTrackerTest.mm; sourceTree = "<group>"; };
                754CEC801F6722DC00D0039A /* AutoFillAvailable.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFillAvailable.mm; sourceTree = "<group>"; };
                7560917719259C59009EF06E /* MemoryCacheAddImageToCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryCacheAddImageToCacheIOS.mm; sourceTree = "<group>"; };
                                8E4A85361E1D1AA100F53B0F /* GridPosition.cpp */,
                                83B88A331C80056D00BB2418 /* HTMLParserIdioms.cpp */,
                                5CA1DEC71F71F40700E71BD3 /* HTTPHeaderField.cpp */,
+                               6B9ABE112086952F00D75DE6 /* HTTPParsers.cpp */,
                                7A909A731D877475007E10F8 /* IntPoint.cpp */,
                                7A909A741D877475007E10F8 /* IntRect.cpp */,
                                7A909A751D877475007E10F8 /* IntSize.cpp */,
                                7CCE7EC21A411A7E00447C4C /* HTMLFormCollectionNamedItem.mm in Sources */,
                                7C83E0501D0A641800FEBCF3 /* HTMLParserIdioms.cpp in Sources */,
                                5CA1DEC81F71F70100E71BD3 /* HTTPHeaderField.cpp in Sources */,
+                               6B9ABE122086952F00D75DE6 /* HTTPParsers.cpp in Sources */,
                                51AF23DF1EF1A3730072F281 /* IconLoadingDelegate.mm in Sources */,
                                510477781D29923B009747EB /* IDBDeleteRecovery.mm in Sources */,
                                5110FCFA1E01CDB8006F8D0B /* IDBIndexUpgradeToV2.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/HTTPParsers.cpp b/Tools/TestWebKitAPI/Tests/WebCore/HTTPParsers.cpp
new file mode 100644 (file)
index 0000000..9454e58
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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 "Test.h"
+#include <WebCore/HTTPParsers.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(HTTPParsers, ParseFromOriginHeader)
+{
+    EXPECT_TRUE(parseFromOriginHeader("") == FromOriginDisposition::None);
+    EXPECT_TRUE(parseFromOriginHeader(" ") == FromOriginDisposition::None);
+
+    EXPECT_TRUE(parseFromOriginHeader("same") == FromOriginDisposition::Same);
+    EXPECT_TRUE(parseFromOriginHeader("Same") == FromOriginDisposition::Same);
+    EXPECT_TRUE(parseFromOriginHeader("SAME") == FromOriginDisposition::Same);
+    EXPECT_TRUE(parseFromOriginHeader(" same ") == FromOriginDisposition::Same);
+
+    EXPECT_TRUE(parseFromOriginHeader("same-site") == FromOriginDisposition::SameSite);
+    EXPECT_TRUE(parseFromOriginHeader("Same-Site") == FromOriginDisposition::SameSite);
+    EXPECT_TRUE(parseFromOriginHeader("SAME-SITE") == FromOriginDisposition::SameSite);
+    EXPECT_TRUE(parseFromOriginHeader(" same-site ") == FromOriginDisposition::SameSite);
+
+    EXPECT_TRUE(parseFromOriginHeader("zame") == FromOriginDisposition::Invalid);
+    EXPECT_TRUE(parseFromOriginHeader("samesite") == FromOriginDisposition::Invalid);
+    EXPECT_TRUE(parseFromOriginHeader("same site") == FromOriginDisposition::Invalid);
+    EXPECT_TRUE(parseFromOriginHeader("same–site") == FromOriginDisposition::Invalid);
+    EXPECT_TRUE(parseFromOriginHeader("SAMESITE") == FromOriginDisposition::Invalid);
+    EXPECT_TRUE(parseFromOriginHeader("") == FromOriginDisposition::Invalid);
+}
+
+} // namespace TestWebKitAPI