WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-175007-20170801154515.patch (text/plain), 150.44 KB, created by
Chris Dumez
on 2017-08-01 15:45:16 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Chris Dumez
Created:
2017-08-01 15:45:16 PDT
Size:
150.44 KB
patch
obsolete
>Subversion Revision: 220111 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3bb66ef751481d4d0d9109dfc578e2a97794471f..db4546a601022bcdb3e2ffbe8fa3488bbad1cb01 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,40 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add initial support for navigator.sendBeacon behind an experimental >+ feature runtime flag. The specification is available at: >+ - https://w3c.github.io/beacon/ >+ >+ The current implementation supports sending beacons with all types of >+ payloads except for ReadableStream. Some functionality is incomplete >+ and will be taken care of in follow-up patches: >+ - Support for CORS preflight for the cases where it is required. We currently >+ return false and do not send the beacon in such cases. >+ - Better support for redirects. >+ - Use a more power-friendly network priority for beacon requests. >+ >+ Tests: http/tests/blink/sendbeacon/* >+ http/tests/security/mixedContent/beacon/insecure-beacon-in-iframe.html >+ http/wpt/beacon/* >+ imported/blink/fast/beacon/* >+ imported/w3c/web-platform-tests/beacon/* >+ >+ * CMakeLists.txt: >+ * DerivedSources.make: >+ * Modules/beacon/NavigatorBeacon.cpp: Added. >+ (WebCore::NavigatorBeacon::sendBeacon): >+ * Modules/beacon/NavigatorBeacon.h: Added. >+ * Modules/beacon/NavigatorBeacon.idl: Added. >+ * WebCore.xcodeproj/project.pbxproj: >+ * loader/PingLoader.cpp: >+ (WebCore::PingLoader::sendBeacon): >+ * loader/PingLoader.h: >+ > 2017-07-26 Jiewen Tan <jiewen_tan@apple.com> > > Add tests to detect mistakes in backward compatibility when the structured clone algorithm is changed in the future >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 8677e308694fe3e383d87518d87f1e322c3f442f..03cb7770c4a08bb554a14c6cb3c176f937d0cce7 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,19 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add experimental feature flag for the Beacon API, disabled by default. >+ >+ * Shared/WebPreferencesDefinitions.h: >+ * WebProcess/InjectedBundle/InjectedBundle.cpp: >+ (WebKit::InjectedBundle::overrideBoolPreferenceForTestRunner): >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::updatePreferences): >+ > 2017-08-01 Brady Eidson <beidson@apple.com> > > API test URLSchemeHandler.Exceptions is Exiting out early on macOS Debug.. >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index 63a88eef15664b5395f289a81fa9bca44e96f593..c35e547cf020b57d0666906159a8db236607d4ba 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,22 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add setting to toggle support for the Beacon API (it is disabled by default). >+ >+ * WebView/WebPreferenceKeysPrivate.h: >+ * WebView/WebPreferences.mm: >+ (+[WebPreferences initialize]): >+ (-[WebPreferences beaconAPIEnabled]): >+ (-[WebPreferences setBeaconAPIEnabled:]): >+ * WebView/WebPreferencesPrivate.h: >+ * WebView/WebView.mm: >+ (-[WebView _preferencesChanged:]): >+ > 2017-07-28 Jeremy Jones <jeremyj@apple.com> > > Remove Web prefix from WebVideoFullscreen and WebPlaybackSession classes. >diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt >index 37a2aa7cc75598b5081ee5e28d80e2ca8e2c437e..74af4351f14a44d9c707971359ba61c5aa20dcb0 100644 >--- a/Source/WebCore/CMakeLists.txt >+++ b/Source/WebCore/CMakeLists.txt >@@ -15,6 +15,7 @@ set(WebCore_INCLUDE_DIRECTORIES > "${CMAKE_BINARY_DIR}" > "${WEBCORE_DIR}" > "${WEBCORE_DIR}/Modules/airplay" >+ "${WEBCORE_DIR}/Modules/beacon" > "${WEBCORE_DIR}/Modules/applepay" > "${WEBCORE_DIR}/Modules/credentials" > "${WEBCORE_DIR}/Modules/encryptedmedia" >@@ -175,6 +176,8 @@ set(WebCore_IDL_INCLUDES > set(WebCore_NON_SVG_IDL_FILES > Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.idl > >+ Modules/beacon/NavigatorBeacon.idl >+ > Modules/credentials/BasicCredential.idl > Modules/credentials/CredentialCreationOptions.idl > Modules/credentials/CredentialData.idl >@@ -870,6 +873,8 @@ endif () > set(WebCore_SOURCES > Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.cpp > >+ Modules/beacon/NavigatorBeacon.cpp >+ > Modules/credentials/BasicCredential.cpp > Modules/credentials/CredentialsContainer.cpp > Modules/credentials/FederatedCredential.cpp >diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make >index c9516b58c13f5dee6870704c8836740a51689a5c..326705a872f45c00f70b208f838c3f6bbf2e6e03 100644 >--- a/Source/WebCore/DerivedSources.make >+++ b/Source/WebCore/DerivedSources.make >@@ -30,6 +30,7 @@ VPATH = \ > $(WebCore) \ > $(WebCore)/Modules/airplay \ > $(WebCore)/Modules/applepay \ >+ $(WebCore)/Modules/beacon \ > $(WebCore)/Modules/credentials \ > $(WebCore)/Modules/encryptedmedia \ > $(WebCore)/Modules/encryptedmedia/legacy \ >@@ -97,6 +98,7 @@ JS_BINDING_IDLS = \ > $(WebCore)/Modules/applepay/ApplePayShippingMethodSelectedEvent.idl \ > $(WebCore)/Modules/applepay/ApplePayShippingMethodUpdate.idl \ > $(WebCore)/Modules/applepay/ApplePayValidateMerchantEvent.idl \ >+ $(WebCore)/Modules/beacon/NavigatorBeacon.idl \ > $(WebCore)/Modules/credentials/BasicCredential.idl \ > $(WebCore)/Modules/credentials/CredentialCreationOptions.idl \ > $(WebCore)/Modules/credentials/CredentialData.idl \ >diff --git a/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp b/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..1c8faf37f8dc0464a21ebbf0faa723c8a6fd0fcd >--- /dev/null >+++ b/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp >@@ -0,0 +1,55 @@ >+/* >+ * Copyright (C) 2017 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 "NavigatorBeacon.h" >+ >+#include "Document.h" >+#include "Navigator.h" >+#include "URL.h" >+ >+namespace WebCore { >+ >+ExceptionOr<bool> NavigatorBeacon::sendBeacon(Navigator&, Document& document, const String& url, std::optional<BodyInit>&& data) >+{ >+ URL parsedUrl = document.completeURL(url); >+ >+ // Set parsedUrl to the result of the URL parser steps with url and base. If the algorithm returns an error, or if >+ // parsedUrl's scheme is not "http" or "https", throw a " TypeError" exception and terminate these steps. >+ if (!parsedUrl.isValid()) >+ return Exception { TypeError, ASCIILiteral("This URL is invalid") }; >+ if (!parsedUrl.protocolIsInHTTPFamily()) >+ return Exception { TypeError, ASCIILiteral("Beacons can only be sent over HTTP(S)") }; >+ >+ auto* frame = document.frame(); >+ // We do not allow sending beacons from detached documents. >+ if (!frame) >+ return false; >+ >+ return PingLoader::sendBeacon(*frame, document, parsedUrl, WTFMove(data)); >+} >+ >+} >+ >diff --git a/Source/WebCore/Modules/beacon/NavigatorBeacon.h b/Source/WebCore/Modules/beacon/NavigatorBeacon.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d9cb3e5097893997df984634edada6ae83744fa1 >--- /dev/null >+++ b/Source/WebCore/Modules/beacon/NavigatorBeacon.h >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2017 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. >+ */ >+ >+#pragma once >+ >+#include "ExceptionOr.h" >+#include "PingLoader.h" >+#include <wtf/Forward.h> >+ >+namespace WebCore { >+ >+class Document; >+class Navigator; >+ >+class NavigatorBeacon { >+public: >+ static ExceptionOr<bool> sendBeacon(Navigator&, Document&, const String& url, std::optional<BodyInit>&&); >+}; >+ >+} >diff --git a/Source/WebCore/Modules/beacon/NavigatorBeacon.idl b/Source/WebCore/Modules/beacon/NavigatorBeacon.idl >new file mode 100644 >index 0000000000000000000000000000000000000000..30507619999917f1ab08def2d6d446343edd621d >--- /dev/null >+++ b/Source/WebCore/Modules/beacon/NavigatorBeacon.idl >@@ -0,0 +1,33 @@ >+/* >+ * Copyright (C) 2017 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. >+ */ >+ >+// FIXME: Should support ReadableStream too. >+typedef (Blob or BufferSource or DOMFormData or URLSearchParams or USVString) BodyInit; >+ >+[ >+ EnabledBySetting=BeaconAPI, >+] partial interface Navigator { >+ [CallWith=Document, MayThrowException] boolean sendBeacon(USVString url, optional BodyInit? data = null); >+}; >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 6bbbaa2d14499537da7061c389ef5f3518181d3a..135c6d31ea60a103715f07312453fcc4b1d6bf6c 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -3377,6 +3377,8 @@ > 830A36BD1DAC5FAD006D7D09 /* JSMouseEventInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 830A36BB1DAC5FA7006D7D09 /* JSMouseEventInit.h */; }; > 83120C701C56F3F6001CB112 /* HTMLDataElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 831D1F291C56ECA000F5F6C0 /* HTMLDataElement.cpp */; }; > 83120C711C56F3FB001CB112 /* HTMLDataElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B86A71C56E83A00F3F0E3 /* HTMLDataElement.h */; }; >+ 8321507D1F27EA180095B136 /* NavigatorBeacon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8321507A1F27EA150095B136 /* NavigatorBeacon.cpp */; }; >+ 8321507E1F27EA1B0095B136 /* NavigatorBeacon.h in Headers */ = {isa = PBXBuildFile; fileRef = 8321507B1F27EA150095B136 /* NavigatorBeacon.h */; }; > 832B843419D8E55100B26055 /* SVGAnimateElementBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 832B843319D8E55100B26055 /* SVGAnimateElementBase.h */; }; > 832B843619D8E57400B26055 /* SVGAnimateElementBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 832B843519D8E57400B26055 /* SVGAnimateElementBase.cpp */; }; > 83407FC11E8D9C1700E048D3 /* VisibilityChangeClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 83407FC01E8D9C1200E048D3 /* VisibilityChangeClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -11445,6 +11447,9 @@ > 830A36BA1DAC5FA7006D7D09 /* JSMouseEventInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMouseEventInit.cpp; sourceTree = "<group>"; }; > 830A36BB1DAC5FA7006D7D09 /* JSMouseEventInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMouseEventInit.h; sourceTree = "<group>"; }; > 831D1F291C56ECA000F5F6C0 /* HTMLDataElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLDataElement.cpp; sourceTree = "<group>"; }; >+ 8321507A1F27EA150095B136 /* NavigatorBeacon.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorBeacon.cpp; sourceTree = "<group>"; }; >+ 8321507B1F27EA150095B136 /* NavigatorBeacon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NavigatorBeacon.h; sourceTree = "<group>"; }; >+ 8321507C1F27EA150095B136 /* NavigatorBeacon.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = NavigatorBeacon.idl; sourceTree = "<group>"; }; > 8329A4171EC25B2B008ED4BE /* DocumentAndElementEventHandlers.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DocumentAndElementEventHandlers.idl; sourceTree = "<group>"; }; > 8329DCC21C7A6AE300730B33 /* HTMLHyperlinkElementUtils.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLHyperlinkElementUtils.idl; sourceTree = "<group>"; }; > 832B843319D8E55100B26055 /* SVGAnimateElementBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimateElementBase.h; sourceTree = "<group>"; }; >@@ -19822,6 +19827,16 @@ > path = cf; > sourceTree = "<group>"; > }; >+ 832150791F27E96B0095B136 /* beacon */ = { >+ isa = PBXGroup; >+ children = ( >+ 8321507A1F27EA150095B136 /* NavigatorBeacon.cpp */, >+ 8321507B1F27EA150095B136 /* NavigatorBeacon.h */, >+ 8321507C1F27EA150095B136 /* NavigatorBeacon.idl */, >+ ); >+ path = beacon; >+ sourceTree = "<group>"; >+ }; > 89878576122CA1DA003AABDA /* FileAPI */ = { > isa = PBXGroup; > children = ( >@@ -20612,6 +20627,7 @@ > 971145FE14EF006E00674FD9 /* Modules */ = { > isa = PBXGroup; > children = ( >+ 832150791F27E96B0095B136 /* beacon */, > CE26169D187E6554007955F3 /* airplay */, > 1A58E8611D19D37300C0EA73 /* applepay */, > 57C7A6881E56946D00C67D71 /* credentials */, >@@ -26492,6 +26508,7 @@ > FD31608012B026F700C1A359 /* AudioDSPKernel.h in Headers */, > FD31608212B026F700C1A359 /* AudioDSPKernelProcessor.h in Headers */, > FD31608312B026F700C1A359 /* AudioFileReader.h in Headers */, >+ 8321507E1F27EA1B0095B136 /* NavigatorBeacon.h in Headers */, > CD5596921475B678001D0BD0 /* AudioFileReaderIOS.h in Headers */, > FD3160BF12B0272A00C1A359 /* AudioFileReaderMac.h in Headers */, > CD2F4A2418D89F700063746D /* AudioHardwareListener.h in Headers */, >@@ -32042,6 +32059,7 @@ > 07277E5217D018CC0015534D /* JSMediaStreamTrack.cpp in Sources */, > 415CDAF71E6CE0DE004F11EE /* JSMediaStreamTrackCustom.cpp in Sources */, > 07277E5417D018CC0015534D /* JSMediaStreamTrackEvent.cpp in Sources */, >+ 8321507D1F27EA180095B136 /* NavigatorBeacon.cpp in Sources */, > 932CC0D41DFFD667004C0F9F /* JSMediaTrackConstraints.cpp in Sources */, > 0787C4691BFBDF6F006DCD7F /* JSMediaTrackSupportedConstraints.cpp in Sources */, > E107400D0E77BDC00033AF24 /* JSMessageChannel.cpp in Sources */, >diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >index c29a47cd07c93d9ab2f36c51bb59058fcb838364..9448cd50eb0dc2ca38057e6dca6a5964476b3b60 100644 >--- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >+++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >@@ -4086,7 +4086,7 @@ sub GenerateImplementation > push(@implContent, " if (!${runtimeEnableConditionalString}) {\n"); > push(@implContent, " auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>(\"$name\"), strlen(\"$name\"));\n"); > push(@implContent, " VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable);\n"); >- push(@implContent, " JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName);\n"); >+ push(@implContent, " JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName);\n"); > push(@implContent, " }\n"); > push(@implContent, "#endif\n") if $conditionalString; > } >@@ -4130,7 +4130,7 @@ sub GenerateImplementation > push(@implContent, " putDirect(vm, vm.propertyNames->iteratorSymbol, getDirect(vm, vm.propertyNames->builtinNames().entriesPublicName()), DontEnum);\n"); > } else { > AddToImplIncludes("<runtime/ArrayPrototype.h>"); >- push(@implContent, " putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayPrototype()->getDirect(vm, vm.propertyNames->builtinNames().valuesPrivateName()), DontEnum);\n"); >+ push(@implContent, " putDirect(vm, vm.propertyNames->iteratorSymbol, this->globalObject()->arrayPrototype()->getDirect(vm, vm.propertyNames->builtinNames().valuesPrivateName()), DontEnum);\n"); > } > } > push(@implContent, " addValueIterableMethods(*globalObject(), *this);\n") if $interface->iterable and !IsKeyValueIterableInterface($interface); >diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp >index a3770e54821c3452655dfbae453c0b730eaf722c..c808448cbceedc346a5853dda01c80c8dd8d388f 100644 >--- a/Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp >+++ b/Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp >@@ -102,7 +102,7 @@ void JSTestGenerateIsReachablePrototype::finishCreation(VM& vm) > if (!jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("aSecretAttribute"), strlen("aSecretAttribute")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > } > >diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp >index d29c6b251fc138e665df7c435a512bb88f332b96..27fbcf1732d0140c536fdcc89a58e31f4de50cc1 100644 >--- a/Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp >+++ b/Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp >@@ -147,39 +147,39 @@ void JSTestNodePrototype::finishCreation(VM& vm) > if (!jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("calculateSecretResult"), strlen("calculateSecretResult")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("getSecretBoolean"), strlen("getSecretBoolean")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #if ENABLE(TEST_FEATURE) > if (!(jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext() && RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled())) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("testFeatureGetSecretBoolean"), strlen("testFeatureGetSecretBoolean")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #endif > if (!RuntimeEnabledFeatures::sharedFeatures().domIteratorEnabled()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("entries"), strlen("entries")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!RuntimeEnabledFeatures::sharedFeatures().domIteratorEnabled()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("keys"), strlen("keys")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!RuntimeEnabledFeatures::sharedFeatures().domIteratorEnabled()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("values"), strlen("values")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!RuntimeEnabledFeatures::sharedFeatures().domIteratorEnabled()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("forEach"), strlen("forEach")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > putDirect(vm, vm.propertyNames->iteratorSymbol, getDirect(vm, vm.propertyNames->builtinNames().entriesPublicName()), DontEnum); > } >diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >index 18b69abd534b42656ba5313f195475340c662db7..64e7e359530875f2cfdd0975f9f93e5ed41e25a7 100644 >--- a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >+++ b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >@@ -1882,41 +1882,41 @@ void JSTestObjPrototype::finishCreation(VM& vm, JSDOMGlobalObject& globalObject) > if (!RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("enabledAtRuntimeOperation"), strlen("enabledAtRuntimeOperation")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #endif > if (!(worldForDOMObject(this).someWorld() && RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled())) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("enabledInSpecificWorldWhenRuntimeFeatureEnabled"), strlen("enabledInSpecificWorldWhenRuntimeFeatureEnabled")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!worldForDOMObject(this).someWorld()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("worldSpecificMethod"), strlen("worldSpecificMethod")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("calculateSecretResult"), strlen("calculateSecretResult")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > if (!jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext()) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("getSecretBoolean"), strlen("getSecretBoolean")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #if ENABLE(TEST_FEATURE) > if (!(jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext() && RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled())) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("testFeatureGetSecretBoolean"), strlen("testFeatureGetSecretBoolean")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #endif > #if ENABLE(TEST_FEATURE) > if (!(RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled() && RuntimeEnabledFeatures::sharedFeatures().testFeature1Enabled())) { > auto propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>("enabledAtRuntimeAttribute"), strlen("enabledAtRuntimeAttribute")); > VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); >- JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName); >+ JSObject::deleteProperty(this, this->globalObject()->globalExec(), propertyName); > } > #endif > auto* context = globalObject.scriptExecutionContext(); >@@ -1937,7 +1937,7 @@ void JSTestObjPrototype::finishCreation(VM& vm, JSDOMGlobalObject& globalObject) > #endif > putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().privateMethodPrivateName(), JSFunction::create(vm, globalObject(), 0, String(), jsTestObjPrototypeFunctionPrivateMethod), ReadOnly | DontEnum); > putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().publicAndPrivateMethodPrivateName(), JSFunction::create(vm, globalObject(), 0, String(), jsTestObjPrototypeFunctionPublicAndPrivateMethod), ReadOnly | DontEnum); >- putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayPrototype()->getDirect(vm, vm.propertyNames->builtinNames().valuesPrivateName()), DontEnum); >+ putDirect(vm, vm.propertyNames->iteratorSymbol, this->globalObject()->arrayPrototype()->getDirect(vm, vm.propertyNames->builtinNames().valuesPrivateName()), DontEnum); > addValueIterableMethods(*globalObject(), *this); > JSObject& unscopables = *constructEmptyObject(globalObject()->globalExec(), globalObject()->nullPrototypeObjectStructure()); > unscopables.putDirect(vm, Identifier::fromString(&vm, "voidMethod"), jsBoolean(true)); >diff --git a/Source/WebCore/loader/PingLoader.cpp b/Source/WebCore/loader/PingLoader.cpp >index d5fff791f150dc4d02d05811121813200c53edfe..3954efcd4abbebad01b8538aa1610340e6b2bc36 100644 >--- a/Source/WebCore/loader/PingLoader.cpp >+++ b/Source/WebCore/loader/PingLoader.cpp >@@ -34,16 +34,21 @@ > #include "config.h" > #include "PingLoader.h" > >+#include "Blob.h" > #include "ContentSecurityPolicy.h" >+#include "DOMFormData.h" > #include "Document.h" > #include "FormData.h" > #include "Frame.h" > #include "FrameLoader.h" > #include "FrameLoaderClient.h" > #include "HTTPHeaderNames.h" >+#include "HTTPHeaderValues.h" >+#include "HTTPParsers.h" > #include "InspectorInstrumentation.h" > #include "LoaderStrategy.h" > #include "Page.h" >+#include "ParsedContentType.h" > #include "PlatformStrategies.h" > #include "ProgressTracker.h" > #include "ResourceHandle.h" >@@ -52,7 +57,11 @@ > #include "ResourceResponse.h" > #include "SecurityOrigin.h" > #include "SecurityPolicy.h" >+#include "URLSearchParams.h" > #include "UserContentController.h" >+#include <runtime/ArrayBuffer.h> >+#include <runtime/ArrayBufferView.h> >+#include <runtime/JSCInlines.h> > #include <wtf/text/CString.h> > > namespace WebCore { >@@ -181,6 +190,89 @@ void PingLoader::sendViolationReport(Frame& frame, const URL& reportURL, Ref<For > startPingLoad(frame, request, ShouldFollowRedirects::No); > } > >+bool PingLoader::sendBeacon(Frame& frame, Document& document, const URL& url, std::optional<BodyInit>&& data) >+{ >+ ResourceRequest request(url); >+ if (processContentExtensionRulesForLoad(frame, request, ResourceType::Raw)) >+ return false; >+ >+ auto& contentSecurityPolicy = *document.contentSecurityPolicy(); >+ if (!document.shouldBypassMainWorldContentSecurityPolicy() && !contentSecurityPolicy.allowConnectToSource(url)) { >+ // We simulate a network error so we return true here. This is consistent with Blink. >+ return true; >+ } >+ >+ bool noCors = true; >+ request.setHTTPMethod(ASCIILiteral("POST")); >+ // FIXME: We should restrict the size of payloads. >+ if (data) { >+ String mimeType; >+ WTF::switchOn(data.value(), >+ [&] (RefPtr<Blob>& blob) { >+ auto& blobType = blob->type(); >+ if (!blobType.isEmpty() && isValidContentType(blobType)) >+ mimeType = blobType; >+ else >+ mimeType = ASCIILiteral("application/octet-stream"); >+ auto formData = FormData::create(); >+ formData->appendBlob(blob->url()); >+ request.setHTTPBody(WTFMove(formData)); >+ }, >+ [&] (RefPtr<JSC::ArrayBuffer>& buffer) { >+ mimeType = ASCIILiteral("application/octet-stream"); >+ request.setHTTPBody(FormData::create(buffer->data(), buffer->byteLength())); >+ }, >+ [&] (RefPtr<JSC::ArrayBufferView>& buffer) { >+ mimeType = ASCIILiteral("application/octet-stream"); >+ request.setHTTPBody(FormData::create(buffer->baseAddress(), buffer->byteLength())); >+ }, >+ [&] (RefPtr<DOMFormData>& domFormData) { >+ auto formData = FormData::createMultiPart(*domFormData, domFormData->encoding(), &document); >+ formData->generateFiles(&document); >+ mimeType = makeString("multipart/form-data; boundary=", formData->boundary().data()); >+ request.setHTTPBody(WTFMove(formData)); >+ }, >+ [&] (RefPtr<URLSearchParams>& searchParams) { >+ mimeType = HTTPHeaderValues::formURLEncodedContentType(); >+ request.setHTTPBody(FormData::create(searchParams->toString().utf8())); >+ }, >+ [&] (String& string) { >+ mimeType = HTTPHeaderValues::textPlainContentType(); >+ request.setHTTPBody(FormData::create(string.utf8())); >+ } >+ ); >+ noCors = false; >+ if (!mimeType.isEmpty()) { >+ // If mimeType value is a CORS-safelisted request-header value for the Content-Type header, set corsMode to "no-cors". >+ if (isCrossOriginSafeRequestHeader(HTTPHeaderName::ContentType, mimeType)) >+ noCors = true; >+ request.setHTTPContentType(mimeType); >+ } >+ } >+ request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0"); >+ frame.loader().addExtraFieldsToSubresourceRequest(request); >+ >+ auto& sourceOrigin = document.securityOrigin(); >+ bool isCrossOriginRequest = !sourceOrigin.canRequest(url); >+ >+ // FIXME: We are supposed to do a preflight in this case but this is not supported yet. >+ if (isCrossOriginRequest && !noCors) { >+ document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, ASCIILiteral("This requests requires a CORS preflight but this is not supported yet.")); >+ return false; >+ } >+ >+ FrameLoader::addHTTPOriginIfNeeded(request, sourceOrigin.toString()); >+ if (!SecurityPolicy::shouldHideReferrer(url, frame.loader().outgoingReferrer())) { >+ String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), url, frame.loader().outgoingReferrer()); >+ if (!referrer.isEmpty()) >+ request.setHTTPReferrer(referrer); >+ } >+ >+ request.setAllowCookies(true); // Credentials mode: include. >+ startPingLoad(frame, request, ShouldFollowRedirects::Yes); >+ return true; >+} >+ > void PingLoader::startPingLoad(Frame& frame, ResourceRequest& request, ShouldFollowRedirects shouldFollowRedirects) > { > unsigned long identifier = frame.page()->progress().createUniqueIdentifier(); >diff --git a/Source/WebCore/loader/PingLoader.h b/Source/WebCore/loader/PingLoader.h >index b29e8da8f808a7b060e50978fc2aed2ce2d8f138..6ab5ca37f277e12baa689e0269d43b01e6ac22d8 100644 >--- a/Source/WebCore/loader/PingLoader.h >+++ b/Source/WebCore/loader/PingLoader.h >@@ -32,13 +32,26 @@ > > #pragma once > >+#include <wtf/Forward.h> > #include <wtf/Ref.h> >+#include <wtf/Variant.h> >+ >+namespace JSC { >+ >+class ArrayBuffer; >+class ArrayBufferView; >+ >+} > > namespace WebCore { > >+class Blob; >+class DOMFormData; >+class Document; > class FormData; > class Frame; > class URL; >+class URLSearchParams; > class ResourceRequest; > > enum class ViolationReportType { >@@ -46,9 +59,12 @@ enum class ViolationReportType { > XSSAuditor, > }; > >+using BodyInit = Variant<RefPtr<Blob>, RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<DOMFormData>, RefPtr<URLSearchParams>, String>; >+ > class PingLoader { > public: > static void loadImage(Frame&, const URL&); >+ static bool sendBeacon(Frame&, Document&, const URL&, std::optional<BodyInit>&&); > static void sendPing(Frame&, const URL& pingURL, const URL& destinationURL); > static void sendViolationReport(Frame&, const URL& reportURL, Ref<FormData>&& report, ViolationReportType); > >diff --git a/Source/WebCore/page/Settings.in b/Source/WebCore/page/Settings.in >index 6ea25fbed666265026e78ba51ccc3aa636c5cb4c..d1a8fe39c2edfae5f8dd27a40b191f8bc82f5b09 100644 >--- a/Source/WebCore/page/Settings.in >+++ b/Source/WebCore/page/Settings.in >@@ -294,6 +294,8 @@ langAttributeAwareFormControlUIEnabled initial=false > > subresourceIntegrityEnabled initial=true > >+beaconAPIEnabled initial=false >+ > constantPropertiesEnabled initial=false > > viewportFitEnabled initial=false >diff --git a/Source/WebKit/Shared/WebPreferencesDefinitions.h b/Source/WebKit/Shared/WebPreferencesDefinitions.h >index f58ef35e5411758dfba3fcd14cbd62d015bdd3bd..72658e85d2cf15bb0ad4179555806f15754ae544 100644 >--- a/Source/WebKit/Shared/WebPreferencesDefinitions.h >+++ b/Source/WebKit/Shared/WebPreferencesDefinitions.h >@@ -359,6 +359,7 @@ > // wider testing). > > #define FOR_EACH_WEBKIT_EXPERIMENTAL_FEATURE_PREFERENCE(macro) \ >+ macro(BeaconAPIEnabled, beaconAPIEnabled, Bool, bool, false, "Beacon API", "Beacon API prototype") \ > macro(ConstantPropertiesEnabled, constantPropertiesEnabled, Bool, bool, true, "Constant Properties", "Enable CSS constant() properties") \ > macro(DisplayContentsEnabled, displayContentsEnabled, Bool, bool, false, "CSS display: contents", "Enable CSS display: contents support") \ > macro(SpringTimingFunctionEnabled, springTimingFunctionEnabled, Bool, bool, DEFAULT_EXPERIMENTAL_FEATURES_ENABLED, "CSS Spring Animations", "CSS Spring Animation prototype") \ >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index e13d2b9d688c54786c843ecfe367289108929c6b..b6352db42b170e0210b72a6d0c29ae8692bc18ab 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -3360,6 +3360,7 @@ void WebPage::updatePreferences(const WebPreferencesStore& store) > } > > settings.setSubresourceIntegrityEnabled(store.getBoolValueForKey(WebPreferencesKey::subresourceIntegrityEnabledKey())); >+ settings.setBeaconAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::beaconAPIEnabledKey())); > > platformPreferencesDidChange(store); > >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >index 5d31417db3a2f9e7bb6319ebe1fa34e2b7a58da0..571e2b24b7ada36b1e0141cf72d2c56ad338e55a 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >@@ -110,6 +110,7 @@ > #define WebKitSimpleLineLayoutDebugBordersEnabledPreferenceKey @"WebKitSimpleLineLayoutDebugBordersEnabled" > #define WebKitShowRepaintCounterPreferenceKey @"WebKitShowRepaintCounter" > #define WebKitWebAudioEnabledPreferenceKey @"WebKitWebAudioEnabled" >+#define WebKitBeaconAPIEnabledPreferenceKey @"WebKitBeaconAPIEnabled" > #define WebKitWebGLEnabledPreferenceKey @"WebKitWebGLEnabled" > #define WebKitWebGL2EnabledPreferenceKey @"WebKitWebGL2Enabled" > #define WebKitWebGPUEnabledPreferenceKey @"WebKitWebGPUEnabled" >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >index cff704374193edced2e90c0aa2ca6cd4df7de3d7..91fbed6ef5be8c8f8e6940ce30c69e0e06a4108b 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >@@ -625,6 +625,7 @@ + (void)initialize > [NSNumber numberWithBool:YES], WebKitShadowDOMEnabledPreferenceKey, > [NSNumber numberWithBool:YES], WebKitCustomElementsEnabledPreferenceKey, > [NSNumber numberWithBool:YES], WebKitModernMediaControlsEnabledPreferenceKey, >+ [NSNumber numberWithBool:NO], WebKitBeaconAPIEnabledPreferenceKey, > #if ENABLE(WEBGL2) > [NSNumber numberWithBool:NO], WebKitWebGL2EnabledPreferenceKey, > #endif >@@ -2070,6 +2071,16 @@ - (void)setWebGL2Enabled:(BOOL)enabled > [self _setBoolValue:enabled forKey:WebKitWebGL2EnabledPreferenceKey]; > } > >+- (BOOL)beaconAPIEnabled >+{ >+ return [self _boolValueForKey:WebKitBeaconAPIEnabledPreferenceKey]; >+} >+ >+- (void)setBeaconAPIEnabled:(BOOL)enabled >+{ >+ [self _setBoolValue:enabled forKey:WebKitBeaconAPIEnabledPreferenceKey]; >+} >+ > - (BOOL)forceSoftwareWebGLRendering > { > return [self _boolValueForKey:WebKitForceSoftwareWebGLRenderingPreferenceKey]; >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >index 86275af441729f90b231dea88579a716fa77f81f..9def45a3981ddc1d89cba43b8e3c55d49e82f92d 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >@@ -266,6 +266,9 @@ extern NSString *WebPreferencesCacheModelChangedInternalNotification; > - (BOOL)webGL2Enabled; > - (void)setWebGL2Enabled:(BOOL)enabled; > >+- (BOOL)beaconAPIEnabled; >+- (void)setBeaconAPIEnabled:(BOOL)enabled; >+ > - (BOOL)forceSoftwareWebGLRendering; > - (void)setForceSoftwareWebGLRendering:(BOOL)forced; > >diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm >index feacc65ee0cbffa7072008332968b8cb8e8ba505..80b2523eed80e8ad46584dd5e12f4ced01f6efb3 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebView.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm >@@ -2982,6 +2982,8 @@ - (void)_preferencesChanged:(WebPreferences *)preferences > settings.setViewportFitEnabled([preferences viewportFitEnabled]); > settings.setConstantPropertiesEnabled([preferences constantPropertiesEnabled]); > >+ settings.setBeaconAPIEnabled([preferences beaconAPIEnabled]); >+ > #if ENABLE(GAMEPAD) > RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled([preferences gamepadsEnabled]); > #endif >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 2e741dddb9e7297db27fa5215eb07c344c1f296c..abdd7eff85ac7f1912ba184f2bd610a7cceaf991 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,23 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Enable the Beacon API at runtime in the context of layout tests since the >+ feature is currently disabled by default. >+ >+ * DumpRenderTree/mac/DumpRenderTree.mm: >+ (enableExperimentalFeatures): >+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: >+ (WTR::InjectedBundle::beginTesting): >+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp: >+ (WTR::TestRunner::setModernMediaControlsEnabled): >+ (WTR::TestRunner::setBeaconAPIEnabled): >+ * WebKitTestRunner/InjectedBundle/TestRunner.h: >+ > 2017-08-01 Youenn Fablet <youenn@apple.com> > > Layout tests with 'https' suffix should be run over HTTPS >diff --git a/Tools/DumpRenderTree/mac/DumpRenderTree.mm b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >index 0db42dfab3c7926e494ed26b001e992e0dd458f1..1c6d6bc65b7f7f69823f279701427a1580e5667a 100644 >--- a/Tools/DumpRenderTree/mac/DumpRenderTree.mm >+++ b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >@@ -847,6 +847,7 @@ static void enableExperimentalFeatures(WebPreferences* preferences) > [preferences setMediaPreloadingEnabled:YES]; > // FIXME: InputEvents > [preferences setWebAnimationsEnabled:YES]; >+ [preferences setBeaconAPIEnabled:YES]; > [preferences setWebGL2Enabled:YES]; > [preferences setWebGPUEnabled:YES]; > // FIXME: AsyncFrameScrollingEnabled >diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp >index 7a58e23e1d4c5a71be75a78ecac0b72cfbfd2f18..1812257167cc55a623d458f3f235e88085d2a968 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp >+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp >@@ -346,6 +346,7 @@ void InjectedBundle::beginTesting(WKDictionaryRef settings) > m_testRunner->setUserStyleSheetEnabled(false); > m_testRunner->setXSSAuditorEnabled(false); > >+ m_testRunner->setBeaconAPIEnabled(true); > m_testRunner->setWebGL2Enabled(true); > m_testRunner->setWebGPUEnabled(true); > >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >index 0832a0eae2fcffd65aa4a0a6becb2b2f31c026ed..1ea2955b4024e7bbcdf9e605e21ad272ae6459a6 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >@@ -373,6 +373,13 @@ void TestRunner::setModernMediaControlsEnabled(bool enabled) > WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); > } > >+void TestRunner::setBeaconAPIEnabled(bool enabled) >+{ >+ WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitBeaconAPIEnabled")); >+ auto& injectedBundle = InjectedBundle::singleton(); >+ WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); >+} >+ > void TestRunner::setWebGL2Enabled(bool enabled) > { > WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGL2Enabled")); >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >index 3cbea6786ee89175fbe4471b2859ab6e1371ce84..e63c7c4e5107c0651686b71f69e5399d9ec94ea4 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >@@ -100,6 +100,7 @@ public: > void setCloseRemainingWindowsWhenComplete(bool value) { m_shouldCloseExtraWindows = value; } > void setXSSAuditorEnabled(bool); > void setModernMediaControlsEnabled(bool); >+ void setBeaconAPIEnabled(bool); > void setWebGL2Enabled(bool); > void setWebGPUEnabled(bool); > void setWritableStreamAPIEnabled(bool); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index c57a8c12afc73230b8db39cac79ba62f26cf6cd1..d8e584bb46d9ca2fee04d721fc444b64d8be7211 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,51 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/dom/navigator-detached-no-crash-expected.txt: >+ Rebaseline test now that sendBeacon is exposed on navigator. >+ >+ * http/tests/blink/sendbeacon/beacon-cookie-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-cookie.html: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob.html: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin-redirect-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin-redirect.html: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin.html: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin.https-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-cross-origin.https.html: Added. >+ * http/tests/blink/sendbeacon/beacon-detached-no-crash-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-detached-no-crash.html: Added. >+ * http/tests/blink/sendbeacon/beacon-same-origin-expected.txt: Added. >+ * http/tests/blink/sendbeacon/beacon-same-origin.html: Added. >+ * http/tests/blink/sendbeacon/connect-src-beacon-allowed-expected.txt: Added. >+ * http/tests/blink/sendbeacon/connect-src-beacon-allowed.html: Added. >+ * http/tests/blink/sendbeacon/resources/check-beacon.php: Added. >+ * http/tests/blink/sendbeacon/resources/save-beacon.php: Added. >+ Import more beacon test coverage from Blink. >+ >+ * http/wpt/beacon/connect-src-beacon-blocked.sub-expected.txt: Added. >+ * http/wpt/beacon/connect-src-beacon-blocked.sub.html: Added. >+ Improve test coverage for sendBeacon and CSP. >+ >+ * http/wpt/beacon/headers/header-content-type-same-origin-expected.txt: Added. >+ * http/wpt/beacon/headers/header-content-type-same-origin.html: Added. >+ Improve test coverage for sendBeacon with various types of payload. The test is done >+ using same origin as we do not currently support sending some of those payloads cross >+ origin yet. >+ >+ * imported/blink/fast/beacon/beacon-basic-expected.txt: Added. >+ * imported/blink/fast/beacon/beacon-basic.html: Added. >+ Import basic Beacon test coverage from Blink. >+ >+ * resources/window-postmessage-open-close.html: Added. >+ * tests-options.json: >+ > 2017-08-01 Youenn Fablet <youenn@apple.com> > > Layout tests with 'https' suffix should be run over HTTPS >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index 29eceb923956f60afd5d4c96f3a911556df8a027..a007780ec411e1d7b8afe37a597244ffea59bb9c 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,77 @@ >+2017-08-01 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for navigator.sendBeacon >+ https://bugs.webkit.org/show_bug.cgi?id=175007 >+ <rdar://problem/33547728> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Import more beacon web-platform-tests and rebaseline the one we had >+ already imported now that navigator.sendBeacon is exposed. >+ >+ * resources/import-expectations.json: >+ * resources/resource-files.json: >+ * web-platform-tests/beacon/beacon-basic-blob-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-blob.html: Added. >+ * web-platform-tests/beacon/beacon-basic-blobMax-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-blobMax.html: Added. >+ * web-platform-tests/beacon/beacon-basic-buffersource-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-buffersource.html: Added. >+ * web-platform-tests/beacon/beacon-basic-buffersourceMax-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-buffersourceMax.html: Added. >+ * web-platform-tests/beacon/beacon-basic-formdata-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-formdata.html: Added. >+ * web-platform-tests/beacon/beacon-basic-formdataMax-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-formdataMax.html: Added. >+ * web-platform-tests/beacon/beacon-basic-string-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-string.html: Added. >+ * web-platform-tests/beacon/beacon-basic-stringMax-expected.txt: Added. >+ * web-platform-tests/beacon/beacon-basic-stringMax.html: Added. >+ * web-platform-tests/beacon/beacon-common.js: Added. >+ (allTests.forEach): >+ (CreateArrayBufferFromPayload): >+ (CreateEmptyFormDataPayload): >+ (CreateFormDataFromPayload): >+ (initSession.return.add): >+ (initSession): >+ (runTests.): >+ (runTests): >+ (continueAfterSendingBeacon): >+ (waitForResults.): >+ (waitForResults): >+ (runSendInIframeAndNavigateTests.self.buildId): >+ (runSendInIframeAndNavigateTests.window.onmessage): >+ (runSendInIframeAndNavigateTests.self.sendFunc): >+ (runSendInIframeAndNavigateTests.iframe.onload): >+ * web-platform-tests/beacon/beacon-cors.window.js: Added. >+ (false.forEach.self.buildId): >+ (false.forEach.self.buildBaseUrl): >+ (false.forEach.self.buildTargetUrl): >+ (false.forEach): >+ * web-platform-tests/beacon/beacon-error.window.js: Added. >+ (test): >+ * web-platform-tests/beacon/beacon-redirect.window.js: Added. >+ (308.forEach.self.buildId): >+ (308.forEach.self.buildTargetUrl): >+ (308.forEach): >+ * web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html: Added. >+ * web-platform-tests/beacon/headers/header-content-type-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-no-referrer-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-origin-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-origin-when-cross-origin-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-same-origin-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-strict-origin.https-expected.txt: >+ * web-platform-tests/beacon/headers/header-referrer-unsafe-url.https-expected.txt: >+ * web-platform-tests/beacon/resources/beacon.py: Added. >+ (build_stash_key): >+ (main): >+ (main.wrap_key): >+ * web-platform-tests/beacon/resources/w3c-import.log: >+ * web-platform-tests/beacon/w3c-import.log: Added. >+ * web-platform-tests/url/failure-expected.txt: >+ > 2017-07-30 Sam Weinig <sam@webkit.org> > > [WebIDL] Remove JS builtin bindings for FetchRequest, DOMWindowFetch and WorkerGlobalScopeFetch >diff --git a/LayoutTests/fast/dom/navigator-detached-no-crash-expected.txt b/LayoutTests/fast/dom/navigator-detached-no-crash-expected.txt >index b3b252fde7e09653398264efd5e0c8c7088f6457..811bbf73c6682cf35ee2c6e9263a1af47a64f87d 100644 >--- a/LayoutTests/fast/dom/navigator-detached-no-crash-expected.txt >+++ b/LayoutTests/fast/dom/navigator-detached-no-crash-expected.txt >@@ -14,6 +14,7 @@ navigator.platform is OK > navigator.plugins is OK > navigator.product is OK > navigator.productSub is OK >+navigator.sendBeacon() threw err TypeError: Not enough arguments > navigator.userAgent is OK > navigator.vendor is OK > navigator.vendorSub is OK >@@ -32,6 +33,7 @@ navigator.platform is OK > navigator.plugins is OK > navigator.product is OK > navigator.productSub is OK >+navigator.sendBeacon() threw err TypeError: Not enough arguments > navigator.userAgent is OK > navigator.vendor is OK > navigator.vendorSub is OK >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..b35b4571f0f6c711d6f1dac81e41211c2b0271fa >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie-expected.txt >@@ -0,0 +1,19 @@ >+Checking transmission of Beacons involving cookies. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS navigator.sendBeacon("resources/save-beacon.php?name=cookie", "Blip"); is true >+PASS Beacon sent successfully >+PASS Content-Type: text/plain;charset=UTF-8 >+PASS Cookie: hello=world >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-cookie.html >+PASS Request-Method: POST >+PASS Length: 4 >+PASS Body: Blip >+PASS >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie.html >new file mode 100644 >index 0000000000000000000000000000000000000000..7144f53294c752c65afd8fa980aad20dddd2f325 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cookie.html >@@ -0,0 +1,50 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Checking transmission of Beacons involving cookies."); >+ >+window.jsTestIsAsync = true; >+ >+function test() { >+ if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+ //testRunner.dumpPingLoaderCallbacks(); >+ } >+ try { >+ var xhr = new XMLHttpRequest(); >+ xhr.open("GET", "../../cookies/resources/setCookies.cgi", false); >+ xhr.setRequestHeader("SET-COOKIE", "hello=world;path=/"); >+ xhr.send(null); >+ if (xhr.status != 200) { >+ testFailed("cookie not set"); >+ finishJSTest(); >+ } >+ } catch (e) { >+ testFailed("cookie not set"); >+ finishJSTest(); >+ } >+ >+ shouldBeTrue('navigator.sendBeacon("resources/save-beacon.php?name=cookie", "Blip");'); >+ var xhr = new XMLHttpRequest(); >+ xhr.open("GET", "resources/check-beacon.php?name=cookie"); >+ xhr.onload = function () { >+ var lines = xhr.responseText.split("\n"); >+ for (var i in lines) >+ testPassed(lines[i]); >+ finishJSTest(); >+ }; >+ xhr.onerror = function () { >+ testFailed("Unable to fetch beacon status"); >+ finishJSTest(); >+ }; >+ >+ xhr.send(); >+} >+</script> >+</head> >+<body onload="test();"> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..774e1a61661a27ae48f779c2fc94cca92e299a84 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-expected.txt >@@ -0,0 +1,18 @@ >+Testing navigator.sendBeacon() cross-origin. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS navigator.sendBeacon("http://localhost:8000/blink/sendbeacon/resources/save-beacon.php?name=cross-origin", "CrossOrigin"); is true >+PASS Beacon sent successfully >+PASS Content-Type: text/plain;charset=UTF-8 >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-cross-origin.html >+PASS Request-Method: POST >+PASS Length: 11 >+PASS Body: CrossOrigin >+PASS >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..0230ec3c3eb6832daea90d042f0ced0a93b1f302 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt >@@ -0,0 +1,10 @@ >+Verifying navigator.sendBeacon(Blob) non-CORS cross-origin redirect handling. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS navigator.sendBeacon("http://127.0.0.1:8080/navigation/resources/redirection-response.php?status=302&simple=true&target=/non-existent.php", blob); is true >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob.html >new file mode 100644 >index 0000000000000000000000000000000000000000..e376623a29f7cc1ae6687c4262174f83f50c294c >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-blob.html >@@ -0,0 +1,13 @@ >+<!DOCTYPE HTML> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Verifying navigator.sendBeacon(Blob) non-CORS cross-origin redirect handling."); >+ >+if (window.testRunner) { >+ //testRunner.dumpPingLoaderCallbacks(); >+} >+ >+const blob = new Blob(["Cross", "Origin"], {type: "text/plain;from-beacon=true"}); >+// The "simple" parameter is just for differentiating the URLs. >+shouldBeTrue('navigator.sendBeacon("http://127.0.0.1:8080/navigation/resources/redirection-response.php?status=302&simple=true&target=/non-existent.php", blob);'); >+</script> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..161fd8209ccc64eeca7d9f2812bb2d39dc27e2ba >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect-expected.txt >@@ -0,0 +1,10 @@ >+Verifying that navigator.sendBeacon() to non-CORS cross-origin redirect fails. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS navigator.sendBeacon("http://127.0.0.1:8080/navigation/resources/redirection-response.php?status=302&target=/non-existent.php", "CrossOrigin"); is true >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect.html >new file mode 100644 >index 0000000000000000000000000000000000000000..6fb17770b3efa2b81d63e3d33680e6c82389a192 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin-redirect.html >@@ -0,0 +1,24 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Verifying that navigator.sendBeacon() to non-CORS cross-origin redirect fails."); >+ >+window.jsTestIsAsync = true; >+ >+function test() { >+ if (window.testRunner) { >+ testRunner.dumpAsText(); >+ //testRunner.dumpPingLoaderCallbacks(); >+ } >+ >+ shouldBeTrue('navigator.sendBeacon("http://127.0.0.1:8080/navigation/resources/redirection-response.php?status=302&target=/non-existent.php", "CrossOrigin");'); >+ // Wait a while for the redirect response handling to happen before finishing up. >+ setTimeout(finishJSTest, 200); >+} >+</script> >+</head> >+<body onload="test();"> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..38de7ab782673116f7ca3aaae7902c839f2b7c30 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.html >@@ -0,0 +1,36 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Testing navigator.sendBeacon() cross-origin."); >+ >+window.jsTestIsAsync = true; >+ >+function test() { >+ if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+ //testRunner.dumpPingLoaderCallbacks(); >+ } >+ >+ shouldBeTrue('navigator.sendBeacon("http://localhost:8000/blink/sendbeacon/resources/save-beacon.php?name=cross-origin", "CrossOrigin");'); >+ var xhr = new XMLHttpRequest(); >+ xhr.open("GET", "resources/check-beacon.php?name=cross-origin"); >+ xhr.onload = function () { >+ var lines = xhr.responseText.split("\n"); >+ for (var i in lines) >+ testPassed(lines[i]); >+ finishJSTest(); >+ }; >+ xhr.onerror = function () { >+ testFailed("Unable to fetch beacon status"); >+ finishJSTest(); >+ }; >+ xhr.send(); >+} >+</script> >+</head> >+<body onload="test();"> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..dcf06b485a14c655ef9dd1b693413f8c4caef346 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https-expected.txt >@@ -0,0 +1,11 @@ >+Verify navigator.sendBeacon() mixed content checking. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+FAIL navigator.sendBeacon("http://example.test:8000/blink/sendbeacon/resources/save-beacon.php?name=cross-origin", "CrossOrigin"); should be false. Was true. >+PASS successfullyParsed is true >+Some tests failed. >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https.html >new file mode 100644 >index 0000000000000000000000000000000000000000..0c57f4fc55ae798ad4eb0cbbf1317ecddaeb213c >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-cross-origin.https.html >@@ -0,0 +1,23 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Verify navigator.sendBeacon() mixed content checking."); >+ >+window.jsTestIsAsync = true; >+ >+function test() { >+ if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+ } >+ >+ shouldBeFalse('navigator.sendBeacon("http://example.test:8000/blink/sendbeacon/resources/save-beacon.php?name=cross-origin", "CrossOrigin");'); >+ finishJSTest(); >+} >+</script> >+</head> >+<body onload="test();"> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..806092ac8f2f0d4cb667c1e7c0092776e017778c >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash-expected.txt >@@ -0,0 +1,12 @@ >+main frame - has 1 onunload handler(s) >+Accessing Navigator sendBeacon methods on a closed window. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS otherNavigator.sendBeacon() threw exception TypeError: Not enough arguments. >+PASS otherNavigator.sendBeacon('resources/blank.txt') is false >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash.html >new file mode 100644 >index 0000000000000000000000000000000000000000..34b4828708d44a1cbc1eeae756c9a9a41897aeca >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-detached-no-crash.html >@@ -0,0 +1,29 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Accessing Navigator sendBeacon methods on a closed window."); >+ >+window.jsTestIsAsync = true; >+ >+var w; >+function processMessage(event) { >+ if (event.data == "opened") { >+ otherNavigator = w.navigator; >+ w.close(); >+ } else if (event.data == "closed") { >+ shouldThrowErrorName("otherNavigator.sendBeacon()", "TypeError"); >+ shouldBeFalse("otherNavigator.sendBeacon('resources/blank.txt')"); >+ finishJSTest(); >+ } >+} >+ >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.setCanOpenWindows(); >+ testRunner.waitUntilDone(); >+} >+w = window.open('/js-test-resources/window-postmessage-open-close.html'); >+window.addEventListener("message", processMessage, false); >+</script> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..b2e1e803f29c2a082a1543a71c418d40a98a855d >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt >@@ -0,0 +1,59 @@ >+Testing navigator.sendBeacon() within same origin. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+Sending beacon with type: [object String] >+PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true >+PASS Beacon sent successfully >+PASS Content-Type: text/plain;charset=UTF-8 >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html >+PASS Request-Method: POST >+PASS Length: 10 >+PASS Body: SameOrigin >+PASS >+Sending beacon with type: [object Uint32Array] >+PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true >+PASS Beacon sent successfully >+PASS Content-Type: application/octet-stream >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html >+PASS Request-Method: POST >+PASS Length: 40 >+PASS Body: QAAAAEEAAABCAAAAQwAAAEQAAABFAAAARgAAAEcAAABIAAAASQAAAA== >+PASS >+Sending beacon with type: [object Blob] >+PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true >+PASS Beacon sent successfully >+PASS Content-Type: text/plain;from-beacon=true >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html >+PASS Request-Method: POST >+PASS Length: 11 >+PASS Body: hello world >+PASS >+Sending beacon with type: [object FormData] >+PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true >+PASS Beacon sent successfully >+PASS Content-Type: multipart/form-data; >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html >+PASS Request-Method: POST >+PASS Length: 9 >+PASS Body: key=value >+PASS >+Sending beacon with type: [object URLSearchParams] >+PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true >+PASS Beacon sent successfully >+PASS Content-Type: application/x-www-form-urlencoded;charset=UTF-8 >+PASS Origin: null >+PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html >+PASS Request-Method: POST >+PASS Length: 7 >+PASS Body: YT1iJmM9ZA== >+PASS >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin.html b/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..dec061e7c33af720512b6eb303b9b3a414190d43 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin.html >@@ -0,0 +1,63 @@ >+<!DOCTYPE HTML> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script> >+description("Testing navigator.sendBeacon() within same origin."); >+ >+window.jsTestIsAsync = true; >+ >+var binary_array = new Uint32Array(10); >+for (var i = 0; i < binary_array.length; i++) { >+ binary_array[i] = 64 + i; >+} >+ >+var blob = new Blob(["hello", " ", "world"], {type: "text/plain;from-beacon=true"}); >+var form = new FormData(); >+form.append("key", "value"); >+var searchParams = new URLSearchParams("a=b&c=d"); >+ >+var tests = [ >+ "SameOrigin", >+ binary_array, >+ blob, >+ form, >+ searchParams]; >+ >+var payload; >+function testOne() { >+ payload = tests.shift(); >+ if (!payload) { >+ finishJSTest(); >+ return; >+ } >+ debug("Sending beacon with type: " + Object.prototype.toString.call(payload)); >+ shouldBeTrue('navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload);'); >+ var xhr = new XMLHttpRequest(); >+ xhr.open("GET", "resources/check-beacon.php?name=same-origin"); >+ xhr.onload = function () { >+ var lines = xhr.responseText.split("\n"); >+ for (var i in lines) >+ testPassed(lines[i]); >+ testOne(); >+ }; >+ xhr.onerror = function () { >+ testFailed("Unable to fetch beacon status"); >+ testOne(); >+ }; >+ xhr.send(); >+} >+ >+function test() { >+ if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+ //testRunner.dumpPingLoaderCallbacks(); >+ } >+ testOne(); >+} >+</script> >+</head> >+<body onload="test();"> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed-expected.txt b/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..0533f45490c18668871b01bbf687ab9499b13c71 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed-expected.txt >@@ -0,0 +1,2 @@ >+Pass >+ >diff --git a/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed.html b/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed.html >new file mode 100644 >index 0000000000000000000000000000000000000000..832f48bd7a171bc569a79075ea2368ddda79a8c1 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/connect-src-beacon-allowed.html >@@ -0,0 +1,26 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<meta http-equiv="Content-Security-Policy" content="connect-src http://127.0.0.1:8000"> >+<script> >+if (window.testRunner) >+ testRunner.dumpAsText(); >+</script> >+</head> >+<body> >+<pre id="console"></pre> >+<script> >+function log(msg) >+{ >+ document.getElementById("console").appendChild(document.createTextNode(msg + "\n")); >+} >+ >+try { >+ var es = navigator.sendBeacon("http://127.0.0.1:8000/security/contentSecurityPolicy/resources/echo-report.php"); >+ log("Pass"); >+} catch(e) { >+ log("Fail"); >+} >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/resources/check-beacon.php b/LayoutTests/http/tests/blink/sendbeacon/resources/check-beacon.php >new file mode 100644 >index 0000000000000000000000000000000000000000..5bd3f6b2bbd71dfc46561ee6cf8e5bef2d77b944 >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/resources/check-beacon.php >@@ -0,0 +1,37 @@ >+<?php >+require_once '../../../resources/portabilityLayer.php'; >+ >+$beaconFilename = sys_get_temp_dir() . "/beacon" . (isset($_REQUEST['name']) ? $_REQUEST['name'] : "") . ".txt"; >+ >+$max_attempts = 700; >+$retries = isset($_REQUEST['retries']) ? (int)$_REQUEST['retries'] : $max_attempts; >+while (!file_exists($beaconFilename) && $retries != 0) { >+ usleep(10000); >+ # file_exists() caches results, we want to invalidate the cache. >+ clearstatcache(); >+ $retries--; >+} >+ >+header('Content-Type: text/plain'); >+header('Access-Control-Allow-Origin: *'); >+if (file_exists($beaconFilename)) { >+ $beaconFile = false; >+ if (is_readable($beaconFilename)) { >+ $beaconFile = fopen($beaconFilename, 'r'); >+ } >+ if ($beaconFile) { >+ echo "Beacon sent successfully\n"; >+ while ($line = fgets($beaconFile)) { >+ $trimmed = trim($line); >+ if ($trimmed != "") >+ echo "$trimmed\n"; >+ } >+ fclose($beaconFile); >+ unlink($beaconFilename); >+ } else { >+ echo "Beacon status not readable\n"; >+ } >+} else { >+ echo "Beacon not sent\n"; >+} >+?> >diff --git a/LayoutTests/http/tests/blink/sendbeacon/resources/save-beacon.php b/LayoutTests/http/tests/blink/sendbeacon/resources/save-beacon.php >new file mode 100644 >index 0000000000000000000000000000000000000000..ec79651eef11a6846cf63f127d9040642e3b9f4e >--- /dev/null >+++ b/LayoutTests/http/tests/blink/sendbeacon/resources/save-beacon.php >@@ -0,0 +1,40 @@ >+<?php >+require_once '../../../resources/portabilityLayer.php'; >+ >+function prettify($name) { >+ return str_replace(' ', '-', ucwords(str_replace('_', ' ', str_replace('http_', '', strtolower($name))))); >+} >+ >+$beaconFilename = sys_get_temp_dir() . "/beacon" . (isset($_REQUEST['name']) ? $_REQUEST['name'] : "") . ".txt"; >+$beaconFile = fopen($beaconFilename . ".tmp", 'w'); >+$httpHeaders = $_SERVER; >+ksort($httpHeaders, SORT_STRING); >+$contentType = ""; >+foreach ($httpHeaders as $name => $value) { >+ if ($name === "CONTENT_TYPE" || $name === "HTTP_REFERER" || $name === "REQUEST_METHOD" || $name === "HTTP_COOKIE" || $name === "HTTP_ORIGIN") { >+ if ($name === "CONTENT_TYPE") { >+ $contentType = $value; >+ $value = preg_replace('/boundary=.*$/', '', $value); >+ } >+ $headerName = prettify($name); >+ fwrite($beaconFile, "$headerName: $value\n"); >+ } >+} >+$postdata = file_get_contents("php://input"); >+if (strlen($postdata) == 0) >+ $postdata = http_build_query($_POST); >+ >+fwrite($beaconFile, "Length: " . strlen($postdata) . "\n"); >+if (strpos($contentType, "application/") !== false) { >+ $postdata = base64_encode($postdata); >+} >+ >+fwrite($beaconFile, "Body: $postdata\n"); >+fclose($beaconFile); >+rename($beaconFilename . ".tmp", $beaconFilename); >+ >+if (!array_key_exists('dontclearcookies', $_GET)) { >+ foreach ($_COOKIE as $name => $value) >+ setcookie($name, "deleted", time() - 60, "/"); >+} >+?> >diff --git a/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub-expected.txt b/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..2b73ca9189798b33af7ace96ea1f24162a18a95c >--- /dev/null >+++ b/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub-expected.txt >@@ -0,0 +1,5 @@ >+CONSOLE MESSAGE: Refused to connect to http://www.localhost:8800/common/text-plain.txt because it does not appear in the connect-src directive of the Content Security Policy. >+ >+PASS sendBeacon should not throw. >+PASS redirect case >+ >diff --git a/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub.html b/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c7f7e383d26e3bbbe7de14e4e90d57f46d505a5a >--- /dev/null >+++ b/LayoutTests/http/wpt/beacon/connect-src-beacon-blocked.sub.html >@@ -0,0 +1,27 @@ >+<!DOCTYPE html> >+<meta http-equiv="Content-Security-Policy" content="connect-src 'self'"> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script> >+ async_test(t => { >+ document.addEventListener("securitypolicyviolation", t.step_func_done(e => { >+ if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") >+ return; >+ >+ assert_equals(e.violatedDirective, "connect-src"); >+ })); >+ >+ assert_true(navigator.sendBeacon("http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt")); >+ }, "sendBeacon should not throw."); >+ >+ async_test(t => { >+ document.addEventListener("securitypolicyviolation", t.step_func_done(e => { >+ if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") >+ return; >+ >+ assert_equals(e.violatedDirective, "connect-src"); >+ })); >+ >+ assert_true(navigator.sendBeacon("common/redirect-opt-in.py?status=307&location=http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt")); >+ }, "redirect case"); >+</script> >diff --git a/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin-expected.txt b/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..60ee6e5eac9398982e63cc40a81e3f6f626c754a >--- /dev/null >+++ b/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin-expected.txt >@@ -0,0 +1,8 @@ >+ >+PASS Test content-type header for a body string >+PASS Test content-type header for a body ArrayBufferView >+PASS Test content-type header for a body ArrayBuffer >+PASS Test content-type header for a body Blob >+PASS Test content-type header for a body FormData >+PASS Test content-type header for a body URLSearchParams >+ >diff --git a/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin.html b/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..e24c2e7f17c59f6dc7b4a90bb3aa122181f58d3f >--- /dev/null >+++ b/LayoutTests/http/wpt/beacon/headers/header-content-type-same-origin.html >@@ -0,0 +1,87 @@ >+<!doctype html> >+<html> >+ <head> >+ <meta charset="utf-8"> >+ <title>SendBeacon Content-Type header</title> >+ <script src=/resources/testharness.js></script> >+ <script src=/resources/testharnessreport.js></script> >+ </head> >+ <body> >+ <script src="/common/utils.js"></script> >+ <script src="/common/get-host-info.sub.js"></script> >+ <script> >+var RESOURCES_DIR = "/beacon/resources/"; >+ >+function pollResult(test, id) { >+ var checkUrl = RESOURCES_DIR + "content-type.py?cmd=get&id=" + id; >+ >+ return new Promise(resolve => { >+ step_timeout(test.step_func(() => { >+ fetch(checkUrl).then(response => { >+ response.text().then(body => { >+ resolve(body); >+ }); >+ }); >+ }), 1000); >+ }); >+} >+ >+function testContentTypeHeader(what, contentType, title) { >+ var testBase = RESOURCES_DIR; >+ var id = self.token(); >+ var testUrl = testBase + "content-type.py?cmd=put&id=" + id; >+ >+ promise_test(function(test) { >+ assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); >+ return pollResult(test, id) .then(result => { >+ assert_true(result.startsWith(contentType), "Correct content-type header result"); >+ }); >+ }, "Test content-type header for a body " + title); >+} >+ >+function stringToArrayBufferView(input) { >+ var buffer = new ArrayBuffer(input.length * 2); >+ var view = new Uint16Array(buffer); >+ >+ // dumbly copy over the bytes >+ for (var i = 0, len = input.length; i < len; i++) { >+ view[i] = input.charCodeAt(i); >+ } >+ return view; >+} >+ >+function stringToArrayBuffer(input) { >+ var buffer = new ArrayBuffer(input.length * 2); >+ var view = new Uint16Array(buffer); >+ >+ // dumbly copy over the bytes >+ for (var i = 0, len = input.length; i < len; i++) { >+ view[i] = input.charCodeAt(i); >+ } >+ return buffer; >+} >+ >+function stringToBlob(input) { >+ return new Blob([input], {type: "text/plain"}); >+} >+ >+function stringToFormData(input) { >+ var formdata = new FormData(); >+ formdata.append(input, new Blob(['hi'])); >+ return formdata; >+} >+ >+function stringToURLSearchParams(input) >+{ >+ return new URLSearchParams(input); >+} >+ >+testContentTypeHeader("hi!", "text/plain;charset=UTF-8", "string"); >+testContentTypeHeader(stringToArrayBufferView("123"), "application/octet-stream", "ArrayBufferView"); // Specification says no content-type but browsers seem to use "application/octet-stream". >+testContentTypeHeader(stringToArrayBuffer("123"), "application/octet-stream", "ArrayBuffer"); // Specification says no content-type but browsers seem to use "application/octet-stream". >+testContentTypeHeader(stringToBlob("123"), "text/plain", "Blob"); >+testContentTypeHeader(stringToFormData("qwerty"), "multipart/form-data", "FormData"); >+testContentTypeHeader(stringToURLSearchParams("key1=value1&key2=value2"), "application/x-www-form-urlencoded;charset=UTF-8", "URLSearchParams"); >+ </script> >+ </body> >+</html> >diff --git a/LayoutTests/imported/blink/fast/beacon/beacon-basic-expected.txt b/LayoutTests/imported/blink/fast/beacon/beacon-basic-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..c6ccb4995d46c21d1ba012f620a0f10bcf35b590 >--- /dev/null >+++ b/LayoutTests/imported/blink/fast/beacon/beacon-basic-expected.txt >@@ -0,0 +1,15 @@ >+Exercising the Beacon API >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS Object.getPrototypeOf(navigator).hasOwnProperty('sendBeacon') is true >+PASS typeof navigator.sendBeacon is "function" >+PASS navigator.sendBeacon() threw exception TypeError: Not enough arguments. >+PASS navigator.sendBeacon('http://foo:-80/') threw exception TypeError: This URL is invalid. >+PASS navigator.sendBeacon('javascript:alert(1);') threw exception TypeError: Beacons can only be sent over HTTP(S). >+PASS navigator.sendBeacon('http://foo:-80/', new Uint8Array(new SharedArrayBuffer(10))) threw exception TypeError: This URL is invalid. >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/imported/blink/fast/beacon/beacon-basic.html b/LayoutTests/imported/blink/fast/beacon/beacon-basic.html >new file mode 100644 >index 0000000000000000000000000000000000000000..ef2697113330135cbaee4e2505ee57a6fd5118fd >--- /dev/null >+++ b/LayoutTests/imported/blink/fast/beacon/beacon-basic.html >@@ -0,0 +1,16 @@ >+<!DOCTYPE HTML> >+<script src="../../../../resources/js-test.js"></script> >+<script> >+description("Exercising the Beacon API"); >+ >+shouldBeTrue("Object.getPrototypeOf(navigator).hasOwnProperty('sendBeacon')"); >+shouldBeEqualToString("typeof navigator.sendBeacon", "function"); >+shouldThrow("navigator.sendBeacon()"); >+shouldThrow("navigator.sendBeacon('http://foo:-80/')"); >+shouldThrow("navigator.sendBeacon('javascript:alert(1);')"); >+ >+if (window.SharedArrayBuffer) { >+ shouldThrow("navigator.sendBeacon('http://foo:-80/', new Uint8Array(new SharedArrayBuffer(10)))"); >+} >+ >+</script> >diff --git a/LayoutTests/imported/w3c/resources/import-expectations.json b/LayoutTests/imported/w3c/resources/import-expectations.json >index e60a89595a4b845d49fd94ab5c42f3f754f05971..3ac1f72adbaad6dd2620ebb6a716fa2770911e11 100644 >--- a/LayoutTests/imported/w3c/resources/import-expectations.json >+++ b/LayoutTests/imported/w3c/resources/import-expectations.json >@@ -40,6 +40,7 @@ > "web-platform-tests/assumptions": "skip", > "web-platform-tests/auxclick": "skip", > "web-platform-tests/battery-status": "skip", >+ "web-platform-tests/beacon": "import", > "web-platform-tests/bluetooth": "skip", > "web-platform-tests/browser-payment-api": "skip", > "web-platform-tests/clear-site-data": "skip", >diff --git a/LayoutTests/imported/w3c/resources/resource-files.json b/LayoutTests/imported/w3c/resources/resource-files.json >index 931c985a91b6fc81aa11056dbae22b8a1fbfc509..7d570a03a1cdc99574b19427226061954e428083 100644 >--- a/LayoutTests/imported/w3c/resources/resource-files.json >+++ b/LayoutTests/imported/w3c/resources/resource-files.json >@@ -23,6 +23,7 @@ > "web-platform-tests/FileAPI/support/url-origin.html", > "web-platform-tests/XMLHttpRequest/xmlhttprequest-sync-block-defer-scripts-subframe.html", > "web-platform-tests/XMLHttpRequest/xmlhttprequest-sync-not-hang-scriptloader-subframe.html", >+ "web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html", > "web-platform-tests/css/css-grid-1/grid-items/ref-filled-green-100px-square-image.html", > "web-platform-tests/css/css-grid-1/test-plan/index.html", > "web-platform-tests/css/css-shapes-1/test-plan/index.html", >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..2e73a8bf56fd56df1ad74d06622c0979c4bc59a5 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob-expected.txt >@@ -0,0 +1,6 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: EmptyBlob >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: SmallBlob >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MediumBlob >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: LargeBlob >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob.html >new file mode 100644 >index 0000000000000000000000000000000000000000..b35c276592ee4be08fa01cc5ff178ff01ef95a5c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic Blob Test</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(blobTests); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..cd4763765ba2a8f0527670a9d98ae0e261df1037 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax-expected.txt >@@ -0,0 +1,3 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MaxBlob >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax.html >new file mode 100644 >index 0000000000000000000000000000000000000000..705a4ebde57bcb7a098399a1c0bd919cc03789f0 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic Blob Test - MaxSize</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(blobMaxTest); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..e55596267296fae239b918e0e9f6969efd7a2e90 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource-expected.txt >@@ -0,0 +1,6 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: EmptyBufferSource >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: SmallBufferSource >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MediumBufferSource >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: LargeBufferSource >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource.html >new file mode 100644 >index 0000000000000000000000000000000000000000..69d7f5d3303b78d88ca00f43f064169ef9954e5f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic BufferSource Test</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(bufferSourceTests); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..9b4ad2d8ad6c4d0452cd12223e0b2b49c90db3fb >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax-expected.txt >@@ -0,0 +1,3 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MaxBufferSource >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax.html >new file mode 100644 >index 0000000000000000000000000000000000000000..75251bcea36c75ff0706bebab6c05d855c8f42ec >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic BufferSource Test - MaxSize</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(bufferSourceMaxTest); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..bddbb49e7fde3d8c22eadda0c3c5c20dc88194fe >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata-expected.txt >@@ -0,0 +1,6 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: EmptyFormData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: SmallFormData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MediumFormData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: LargeFormData >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3f7703b7d7b71bd079585f9d095ff27402b406f5 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic FormData Test</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(formDataTests); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..c8d074ce9f3be9e8b041f7d5216964afa6871e90 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax-expected.txt >@@ -0,0 +1,3 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: LargeFormData >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax.html >new file mode 100644 >index 0000000000000000000000000000000000000000..27cb378c21f842c210e8322acb318dc3648b7d0f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic FormData Test</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(formDataMaxTest); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d19f887c2b3b4208bce5b3f870e912b628284faf >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string-expected.txt >@@ -0,0 +1,8 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: NoData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: NullData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: UndefinedData >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: SmallString >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MediumString >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: LargeString >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c8571e51e1e2eaae1c4e8a848b01f96afcc3e3be >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic String Test</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(stringTests); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..4bd6c67e2be2ad8a19d9221bd09d8ae95ee9dcf1 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax-expected.txt >@@ -0,0 +1,3 @@ >+ >+PASS Verify 'navigator.sendbeacon()' successfully sends for variant: MaxString >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax.html >new file mode 100644 >index 0000000000000000000000000000000000000000..8e1de948945bbb1a94c48b84da3955d77d7ab876 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax.html >@@ -0,0 +1,18 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon Basic String Test - MaxSize</title> >+ <meta name="timeout" content="long"> >+ <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+<body> >+ <script src="/common/utils.js"></script> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ runTests(stringMaxTest); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-common.js b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-common.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ce3d3311950e53da3f38968f9e26821d6c8c31a3 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-common.js >@@ -0,0 +1,353 @@ >+"use strict"; >+ >+// Different sizes of payloads to test. >+var smallPayloadSize = 10; >+var mediumPayloadSize = 10000; >+var largePayloadSize = 50000; >+var maxPayloadSize = 65536; // The maximum payload size allowed for a beacon request. >+ >+// String payloads of various sizes sent by sendbeacon. The format of the payloads is a string: >+// <numberOfCharacters>:<numberOfCharacters *'s> >+// ex. "10:**********" >+var smallPayload = smallPayloadSize + ":" + Array(smallPayloadSize).fill('*').join(""); >+var mediumPayload = mediumPayloadSize + ":" + Array(mediumPayloadSize).fill('*').join(""); >+var largePayload = largePayloadSize + ":" + Array(largePayloadSize).fill('*').join(""); >+// Subtract 6 from maxPayloadSize because 65536 is 5 digits, plus 1 more for the ':' >+var maxPayload = (maxPayloadSize - 6) + ":" + Array(maxPayloadSize - 6).fill('*').join("") >+ >+// Test case definitions. >+// id: String containing the unique name of the test case. >+// data: Payload object to send through sendbeacon. >+var noDataTest = { id: "NoData" }; >+var nullDataTest = { id: "NullData", data: null }; >+var undefinedDataTest = { id: "UndefinedData", data: undefined }; >+var smallStringTest = { id: "SmallString", data: smallPayload }; >+var mediumStringTest = { id: "MediumString", data: mediumPayload }; >+var largeStringTest = { id: "LargeString", data: largePayload }; >+var maxStringTest = { id: "MaxString", data: maxPayload }; >+var emptyBlobTest = { id: "EmptyBlob", data: new Blob() }; >+var smallBlobTest = { id: "SmallBlob", data: new Blob([smallPayload]) }; >+var mediumBlobTest = { id: "MediumBlob", data: new Blob([mediumPayload]) }; >+var largeBlobTest = { id: "LargeBlob", data: new Blob([largePayload]) }; >+var maxBlobTest = { id: "MaxBlob", data: new Blob([maxPayload]) }; >+var emptyBufferSourceTest = { id: "EmptyBufferSource", data: new Uint8Array() }; >+var smallBufferSourceTest = { id: "SmallBufferSource", data: CreateArrayBufferFromPayload(smallPayload) }; >+var mediumBufferSourceTest = { id: "MediumBufferSource", data: CreateArrayBufferFromPayload(mediumPayload) }; >+var largeBufferSourceTest = { id: "LargeBufferSource", data: CreateArrayBufferFromPayload(largePayload) }; >+var maxBufferSourceTest = { id: "MaxBufferSource", data: CreateArrayBufferFromPayload(maxPayload) }; >+var emptyFormDataTest = { id: "EmptyFormData", data: CreateEmptyFormDataPayload() }; >+var smallFormDataTest = { id: "SmallFormData", data: CreateFormDataFromPayload(smallPayload) }; >+var mediumFormDataTest = { id: "MediumFormData", data: CreateFormDataFromPayload(mediumPayload) }; >+var largeFormDataTest = { id: "LargeFormData", data: CreateFormDataFromPayload(largePayload) }; >+// We don't test maxFormData because the extra multipart separators make it difficult to >+// calculate a maxPayload. >+ >+// Test case suites. >+// Due to quota limits we split the max payload tests into their own bucket. >+var stringTests = [noDataTest, nullDataTest, undefinedDataTest, smallStringTest, mediumStringTest, largeStringTest]; >+var stringMaxTest = [maxStringTest]; >+var blobTests = [emptyBlobTest, smallBlobTest, mediumBlobTest, largeBlobTest]; >+var blobMaxTest = [maxBlobTest]; >+var bufferSourceTests = [emptyBufferSourceTest, smallBufferSourceTest, mediumBufferSourceTest, largeBufferSourceTest]; >+var bufferSourceMaxTest = [maxBufferSourceTest]; >+var formDataTests = [emptyFormDataTest, smallFormDataTest, mediumFormDataTest, largeFormDataTest]; >+var formDataMaxTest = [largeFormDataTest]; >+var allTests = [].concat(stringTests, stringMaxTest, blobTests, blobMaxTest, bufferSourceTests, bufferSourceMaxTest, formDataTests, formDataMaxTest); >+ >+// This special cross section of test cases is meant to provide a slimmer but reasonably- >+// representative set of tests for parameterization across variables (e.g. redirect codes, >+// cors modes, etc.) >+var sampleTests = [noDataTest, nullDataTest, undefinedDataTest, smallStringTest, smallBlobTest, smallBufferSourceTest, smallFormDataTest]; >+ >+// Build a test lookup table, which is useful when instructing a web worker or an iframe >+// to run a test, so that we don't have to marshal the entire test case across a process boundary. >+var testLookup = {}; >+allTests.forEach(function(testCase) { >+ testLookup[testCase.id] = testCase; >+}); >+ >+// Helper function to create an ArrayBuffer representation of a string. >+function CreateArrayBufferFromPayload(payload) { >+ var length = payload.length; >+ var buffer = new Uint8Array(length); >+ >+ for (var i = 0; i < length; i++) { >+ buffer[i] = payload.charCodeAt(i); >+ } >+ >+ return buffer; >+} >+ >+// Helper function to create an empty FormData object. >+function CreateEmptyFormDataPayload() { >+ // http://osgvsowi/8344051 - DOM: Workers: Add FormData support to Web Workers >+ if (self.document === undefined) { >+ return null; >+ } >+ >+ return new FormData(); >+} >+ >+// Helper function to create a FormData representation of a string. >+function CreateFormDataFromPayload(payload) { >+ // http://osgvsowi/8344051 - DOM: Workers: Add FormData support to Web Workers >+ if (self.document === undefined) { >+ return null; >+ } >+ >+ var formData = new FormData(); >+ formData.append("payload", payload); >+ return formData; >+} >+ >+// Initializes a session with a client-generated SID. >+// A "session" is a run of one or more tests. It is used to batch several beacon >+// tests in a way that isolates the server-side session state and makes it easy >+// to poll the results of the tests in one request. >+// testCases: The array of test cases participating in the session. >+function initSession(testCases) { >+ return { >+ // Provides a unique session identifier to prevent mixing server-side data >+ // with other sessions. >+ id: self.token(), >+ // Dictionary of test name to live testCase object. >+ testCaseLookup: {}, >+ // Array of testCase objects for iteration. >+ testCases: [], >+ // Tracks the total number of tests in the session. >+ totalCount: testCases.length, >+ // Tracks the number of tests for which we have sent the beacon. >+ // When it reaches totalCount, we will start polling for results. >+ sentCount: 0, >+ // Tracks the number of tests for which we have verified the results. >+ // When it reaches sentCount, we will stop polling for results. >+ doneCount: 0, >+ // Helper to add a testCase to the session. >+ add: function add(testCase) { >+ this.testCases.push(testCase); >+ this.testCaseLookup[testCase.id] = testCase; >+ } >+ }; >+} >+ >+// Schedules async_test's for each of the test cases, treating them as a single session, >+// and wires up the continueAfterSendingBeacon() and waitForResults() calls. >+// The method looks for several "extension" functions in the global scope: >+// - self.buildId: if present, can change the display name of a test. >+// - self.buildBaseUrl: if present, can change the base URL of a beacon target URL (this >+// is the scheme, hostname, and port). >+// - self.buildTargetUrl: if present, can modify a beacon target URL (for example wrap it). >+// Parameters: >+// testCases: An array of test cases. >+function runTests(testCases) { >+ var session = initSession(testCases); >+ >+ testCases.forEach(function(testCase, testIndex) { >+ // Make a copy of the test case as we'll be storing some metadata on it, >+ // such as which session it belongs to. >+ var testCaseCopy = Object.assign({ session: session }, testCase); >+ >+ // Extension point: generate the test id. >+ var testId = testCase.id; >+ if (self.buildId) { >+ testId = self.buildId(testId); >+ } >+ testCaseCopy.origId = testCaseCopy.id; >+ testCaseCopy.id = testId; >+ testCaseCopy.index = testIndex; >+ >+ session.add(testCaseCopy); >+ >+ // Schedule the sendbeacon in an async test. >+ async_test(function(test) { >+ // Save the testharness.js 'test' object, so that we only have one object >+ // to pass around. >+ testCaseCopy.test = test; >+ >+ // Extension point: generate the beacon URL. >+ var baseUrl = "http://{{host}}:{{ports[http][0]}}"; >+ if (self.buildBaseUrl) { >+ baseUrl = self.buildBaseUrl(baseUrl); >+ } >+ var targetUrl = `${baseUrl}/beacon/resources/beacon.py?cmd=store&sid=${session.id}&tid=${testId}&tidx=${testIndex}`; >+ if (self.buildTargetUrl) { >+ targetUrl = self.buildTargetUrl(targetUrl); >+ } >+ // Attach the URL to the test object for debugging purposes. >+ testCaseCopy.url = targetUrl; >+ >+ // Extension point: send the beacon immediately, or defer. >+ var sendFunc = test.step_func(function sendImmediately(testCase) { >+ var sendResult = sendData(testCase); >+ continueAfterSendingBeacon(sendResult, testCase); >+ }); >+ if (self.sendFunc) { >+ sendFunc = test.step_func(self.sendFunc); >+ } >+ sendFunc(testCaseCopy); >+ }, `Verify 'navigator.sendbeacon()' successfully sends for variant: ${testCaseCopy.id}`); >+ }); >+} >+ >+// Sends the beacon for a single test. This step is factored into its own function so that >+// it can be called from a web worker. It does not check for results. >+// Note: do not assert from this method, as when called from a worker, we won't have the >+// full testharness.js test context. Instead return 'false', and the main scope will fail >+// the test. >+// Returns the result of the 'sendbeacon()' function call, true or false. >+function sendData(testCase) { >+ var sent = false; >+ if (testCase.data) { >+ sent = self.navigator.sendBeacon(testCase.url, testCase.data); >+ } else { >+ sent = self.navigator.sendBeacon(testCase.url) >+ } >+ return sent; >+} >+ >+// Continues a single test after the beacon has been sent for that test. >+// Will trigger waitForResults() for the session if this is the last test >+// in the session to send its beacon. >+// Assumption: will be called on the test's step_func so that assert's do >+// not have to be wrapped. >+function continueAfterSendingBeacon(sendResult, testCase) { >+ var session = testCase.session; >+ >+ // Recaclulate the sent vs. total counts. >+ if (sendResult) { >+ session.sentCount++; >+ } else { >+ session.totalCount--; >+ } >+ >+ // If this was the last test in the session to send its beacon, start polling for results. >+ // Note that we start polling even if just one test in the session sends successfully, >+ // so that if any of the others fail, we still get results from the tests that did send. >+ if (session.sentCount == session.totalCount) { >+ // Exit the current test's execution context in order to run the poll >+ // loop from the harness context. >+ step_timeout(waitForResults.bind(this, session), 0); >+ } >+ >+ // Now fail this test if the beacon did not send. It will be excluded from the poll >+ // loop because of the calculation adjustment above. >+ assert_true(sendResult, "'sendbeacon' function call must succeed"); >+} >+ >+// Kicks off an asynchronous monitor to poll the server for test results. As we >+// verify that the server has received and validated a beacon, we will complete >+// its testharness test. >+function waitForResults(session) { >+ // Poll for status until all of the results come in. >+ fetch(`resources/beacon.py?cmd=stat&sid=${session.id}&tidx_min=0&tidx_max=${session.totalCount-1}`).then( >+ function(response) { >+ // Parse as text(), not json(), so that we can log the raw response if >+ // it's invalid. >+ response.text().then(function(rawResponse) { >+ // Check that we got a response we expect and know how to handle. >+ var results; >+ var failure; >+ try { >+ results = JSON.parse(rawResponse); >+ >+ if (results.length === undefined) { >+ failure = `bad validation response schema: rawResponse='${rawResponse}'`; >+ } >+ } catch (e) { >+ failure = `bad validation response: rawResponse='${rawResponse}', got parse error '${e}'`; >+ } >+ >+ if (failure) { >+ // At this point we can't deterministically get results for all of the >+ // tests in the session, so fail the entire session. >+ failSession(session, failure); >+ return; >+ } >+ >+ // The 'stat' call will return an array of zero or more results >+ // of sendbeacon() calls that the server has received and validated. >+ results.forEach(function(result) { >+ var testCase = session.testCaseLookup[result.id]; >+ >+ // While stash.take on the server is supposed to honor read-once, since we're >+ // polling so frequently it is possible that we will receive the same test result >+ // more than once. >+ if (!testCase.done) { >+ testCase.done = true; >+ session.doneCount++; >+ } >+ >+ // Validate that the sendbeacon() was actually sent to the server. >+ var test = testCase.test; >+ test.step(function() { >+ // null JSON values parse as null, not undefined >+ assert_equals(result.error, null, "'sendbeacon' data must not fail validation"); >+ }); >+ >+ test.done(); >+ }); >+ >+ // Continue polling until all of the results come in. >+ if (session.doneCount < session.sentCount) { >+ // testharness.js frowns upon the use of explicit timeouts, but there is no way >+ // around the need to poll for these tests, and there is no use spamming the server >+ // with requestAnimationFrame() just to avoid the use of step_timeout. >+ step_timeout(waitForResults.bind(this, session), 100); >+ } >+ }).catch(function(error) { >+ failSession(session, `unexpected error reading response, error='${error}'`); >+ }); >+ } >+ ); >+} >+ >+// Fails all of the tests in the session, meant to be called when an infrastructural >+// issue prevents us from deterministically completing the individual tests. >+function failSession(session, reason) { >+ session.testCases.forEach(function(testCase) { >+ var test = testCase.test; >+ test.unreached_func(reason)(); >+ }); >+} >+ >+// Creates an iframe on the document's body and runs the sample tests from the iframe. >+// The iframe is navigated immediately after it sends the data, and the window verifies >+// that the data is still successfully sent. >+// funcName: "beacon" to send the data via navigator.sendBeacon(), >+// "fetch" to send the data via fetch() with the keepalive flag. >+function runSendInIframeAndNavigateTests(funcName) { >+ var iframe = document.createElement("iframe"); >+ iframe.id = "iframe"; >+ iframe.onload = function() { >+ var tests = Array(); >+ >+ // Implement the self.buildId extension to identify the parameterized >+ // test in the report. >+ self.buildId = function(baseId) { >+ return `${baseId}-${funcName}-NAVIGATE`; >+ }; >+ >+ window.onmessage = function(e) { >+ // The iframe will execute sendData() for us and return the result. >+ var testCase = tests[e.data]; >+ continueAfterSendingBeacon(true /* sendResult */, testCase); >+ }; >+ >+ // Implement the self.sendFunc extension to send the beacon indirectly, >+ // from an iFrame that we can then navigate. >+ self.sendFunc = function(testCase) { >+ var iframeWindow = document.getElementById("iframe").contentWindow; >+ // We run into problems passing the testCase over the document boundary, >+ // because of structured cloning constraints. Instead we'll send over the >+ // test case id, and the iFrame can load the static test case by including >+ // beacon-common.js. >+ tests[testCase.origId] = testCase; >+ iframeWindow.postMessage([testCase.origId, testCase.url, funcName], "*"); >+ }; >+ >+ runTests(sampleTests); >+ }; >+ >+ document.body.appendChild(iframe); >+ iframe.src = "fetch-keepalive-navigate.iFrame.html"; >+} >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-cors.window.js b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-cors.window.js >new file mode 100644 >index 0000000000000000000000000000000000000000..317a7bde4507eafe009e50bf7f849678e548a71e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-cors.window.js >@@ -0,0 +1,41 @@ >+// META: script=/common/utils.js >+// META: script=beacon-common.js?pipe=sub >+ >+"use strict"; >+ >+// Execute each sample test with a cross-origin URL. If allowCors is 'true' >+// the beacon handler will return CORS headers. This test ensures that the >+// sendBeacon() succeeds in either case. >+[true, false].forEach(function(allowCors) { >+ // Implement the self.buildId extension to identify the parameterized >+ // test in the report. >+ self.buildId = function(baseId) { >+ return `${baseId}-${allowCors ? "CORS-ALLOW" : "CORS-FORBID"}`; >+ }; >+ >+ // Implement the self.buildBaseUrl and self.buildTargetUrl extensions >+ // to change the target URL to use a cross-origin domain name. >+ self.buildBaseUrl = function(baseUrl) { >+ return "http://{{domains[www]}}:{{ports[http][0]}}"; >+ }; >+ // Implement the self.buildTargetUrl extension to append a directive >+ // to the handler, that it should return CORS headers, if 'allowCors' >+ // is true. >+ self.buildTargetUrl = function(targetUrl) { >+ // Note that 'allowCors=true' is not necessary for the sendBeacon() to reach >+ // the server. Beacons use the HTTP POST method, which is a CORS-safelisted >+ // method, and thus they do not trigger preflight. If the server does not >+ // respond with Access-Control-Allow-Origin and Access-Control-Allow-Credentials >+ // headers, an error will be printed to the console, but the request will >+ // already have reached the server. Since beacons are fire-and-forget, the >+ // error will not affect any client script, either -- not even the return >+ // value of the sendBeacon() call, because the underlying fetch is asynchronous. >+ // The "Beacon CORS" tests are merely testing that sendBeacon() to a cross- >+ // origin URL *will* work regardless. >+ return allowCors ? `${targetUrl}&origin=http://{{host}}:{{ports[http][0]}}&credentials=true` : targetUrl; >+ } >+ >+ runTests(sampleTests); >+}); >+ >+done(); >\ No newline at end of file >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-error.window.js b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-error.window.js >new file mode 100644 >index 0000000000000000000000000000000000000000..be34900edc1a20f2de4f479f5eb821e569dd5cca >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-error.window.js >@@ -0,0 +1,39 @@ >+// META: script=/common/utils.js >+// META: script=beacon-common.js?pipe=sub >+ >+"use strict"; >+ >+test(function() { >+ // Payload that should cause sendBeacon to return false because it exceeds the maximum payload size. >+ var exceedPayload = Array(maxPayloadSize + 1).fill('z').join(""); >+ >+ var success = navigator.sendBeacon("http://doesnotmatter", exceedPayload); >+ assert_false(success, "calling 'navigator.sendBeacon()' with payload size exceeding the maximum size must fail"); >+}, "Verify calling 'navigator.sendBeacon()' with a large payload returns 'false'."); >+ >+test(function() { >+ var invalidUrl = "http://invalid:url"; >+ assert_throws(new TypeError(), function() { navigator.sendBeacon(invalidUrl, smallPayload); }, >+ `calling 'navigator.sendBeacon()' with an invalid URL '${invalidUrl}' must throw a TypeError`); >+}, "Verify calling 'navigator.sendBeacon()' with an invalid URL throws an exception."); >+ >+test(function() { >+ var invalidUrl = "nothttp://invalid.url"; >+ assert_throws(new TypeError(), function() { navigator.sendBeacon(invalidUrl, smallPayload); }, >+ `calling 'navigator.sendBeacon()' with a non-http(s) URL '${invalidUrl}' must throw a TypeError`); >+}, "Verify calling 'navigator.sendBeacon()' with a URL that is not a http(s) scheme throws an exception."); >+ >+// We'll validate that we can send one beacon that uses our entire Quota and then fail to send one that is just one char. >+test(function () { >+ var destinationURL = "/fetch/api/resources/trickle.py?count=1&ms=1000"; >+ >+ var firstSuccess = navigator.sendBeacon(destinationURL, maxPayload); >+ assert_true(firstSuccess, "calling 'navigator.sendBeacon()' with our max payload size should succeed."); >+ >+ // Now we'll send just one character. >+ var secondSuccess = navigator.sendBeacon(destinationURL, "1"); >+ assert_false(secondSuccess, "calling 'navigator.sendBeacon()' with just one char should fail while our Quota is used up."); >+ >+}, "Verify calling 'navigator.sendBeacon()' with a small payload fails while Quota is completely utilized."); >+ >+done(); >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-redirect.window.js b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-redirect.window.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0e263dd54299554c848a597fda7d7831253db516 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-redirect.window.js >@@ -0,0 +1,25 @@ >+// META: script=/common/utils.js >+// META: script=beacon-common.js?pipe=sub >+ >+"use strict"; >+ >+// Execute each sample test per redirect status code. >+// Note that status codes 307 and 308 are the only codes that will maintain POST data >+// through a redirect. >+[307, 308].forEach(function(status) { >+ // Implement the self.buildId extension to identify the parameterized >+ // test in the report. >+ self.buildId = function(baseId) { >+ return `${baseId}-${status}`; >+ }; >+ >+ // Implement the self.buildTargetUrl extension to inject a redirect to >+ // the sendBeacon target. >+ self.buildTargetUrl = function(targetUrl) { >+ return `/common/redirect.py?status=${status}&location=${encodeURIComponent(targetUrl)}`; >+ }; >+ >+ runTests(sampleTests); >+}); >+ >+done(); >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html b/LayoutTests/imported/w3c/web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c4e63c8f76af30af77275eb2d75b1a153f17ecb6 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html >@@ -0,0 +1,49 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>W3C Beacon As Fetch (Fetch KeepAlive) Navigate Test</title> >+</head> >+<body> >+ <script src="beacon-common.js?pipe=sub"></script> >+ <script> >+ "use strict"; >+ >+ // An array should be passed through postMessage to this iFrame, where >+ // [0] contains a test case id as defined in beacon-common.js. >+ // [1] is the URL for the keep alive fetch() or sendBeacon(). >+ // [2] string indicating the function to call - "fetch" to call fetch() or "beacon" to call sendBeacon(). >+ // The testcase id is returned back to the window through postMesage. >+ var tests = 0; >+ window.onmessage = function(e) { >+ var testCaseId = e.data[0]; >+ var url = e.data[1]; >+ var func = e.data[2]; >+ tests++; >+ >+ // Reconstruct enough of the test case to send the keep alive fetch (data and url). >+ var testCase = testLookup[testCaseId]; >+ testCase.url = url; >+ >+ if (func === "beacon") { >+ // sendData calls sendBeacon >+ sendData(testCase); >+ } >+ else if (func === "fetch") { >+ // Send the Fetch. >+ fetch(testCase.url, { "keepalive": true, "method": "POST", "body": testCase.data }); >+ } >+ else { >+ throw new Error(func + " is an invalid function"); >+ } >+ >+ // Let the main page continue the test if we don't immediately throw an exception. >+ parent.postMessage(testCaseId, "*"); >+ >+ // Now navigate ourselves. >+ if (tests == sampleTests.Length) { >+ window.location = "http://microsoft.com"; >+ } >+ } >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt >index ff4e70287fc169f720a5cdd8c4c5440de04423cc..ed48fe4d790128779c32146dbd776f62dcf87c08 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt >@@ -1,5 +1,6 @@ >+CONSOLE MESSAGE: line 35: This requests requires a CORS preflight but this is not supported yet. > >-FAIL Test content-type header for a body string navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl, what)', 'navigator.sendBeacon' is undefined) >-FAIL Test content-type header for a body ArrayBuffer navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl, what)', 'navigator.sendBeacon' is undefined) >-FAIL Test content-type header for a body FormData navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl, what)', 'navigator.sendBeacon' is undefined) >+PASS Test content-type header for a body string >+FAIL Test content-type header for a body ArrayBuffer assert_true: SendBeacon Succeeded expected true got false >+PASS Test content-type header for a body FormData > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-expected.txt >index 6f60a77a642f3163d772ccff9272107e06252ee9..492a80ef3613d0f29e8948009646f6d2cd82ec94 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-expected.txt >@@ -1,3 +1,3 @@ > >-FAIL Test referer header /beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+PASS Test referer header /beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt >index 61a249cf366a047403b0638a1d7994ada2426241..8cf681c612270589acd709c1c75cd55ade70191f 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt >@@ -1,4 +1,4 @@ > >-FAIL Test referer header https://localhost:9443/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >-FAIL Test referer header http://localhost:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+PASS Test referer header https://localhost:9443/beacon/resources/ >+PASS Test referer header http://localhost:8800/beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-expected.txt >index 01ee364f38720ed722ca3fe9f30c49ddca025a2f..663b2b190965fdcec7d645aa4f3326a13cb3b7b8 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-expected.txt >@@ -1,3 +1,3 @@ > >-FAIL Test referer header http://127.0.0.1:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+PASS Test referer header http://127.0.0.1:8800/beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-when-cross-origin-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-when-cross-origin-expected.txt >index eddf4a2e6183d2c5267776704c585ac40218bc59..e746c072e26469401af66265cf55770b69a40dc8 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-when-cross-origin-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-origin-when-cross-origin-expected.txt >@@ -1,5 +1,5 @@ > CONSOLE MESSAGE: line 8: Failed to set referrer policy: The value 'origin-when-cross-origin' is not one of 'no-referrer', 'origin', 'no-referrer-when-downgrade', or 'unsafe-url'. Defaulting to 'no-referrer'. > >-FAIL Test referer header http://localhost:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >-FAIL Test referer header http://127.0.0.1:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+FAIL Test referer header http://localhost:8800/beacon/resources/ assert_equals: Correct referrer header result expected "http://localhost:8800/beacon/headers/header-referrer-origin-when-cross-origin.html" but got "" >+FAIL Test referer header http://127.0.0.1:8800/beacon/resources/ assert_equals: Correct referrer header result expected "http://localhost:8800/" but got "" > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-same-origin-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-same-origin-expected.txt >index 185b6dff740cc51e9290da80ccb8b9ddf53fc87c..c5a70613463d8f3bad710ff4f83d4f93784e6c4c 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-same-origin-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-same-origin-expected.txt >@@ -1,5 +1,5 @@ > CONSOLE MESSAGE: line 8: Failed to set referrer policy: The value 'same-origin' is not one of 'no-referrer', 'origin', 'no-referrer-when-downgrade', or 'unsafe-url'. Defaulting to 'no-referrer'. > >-FAIL Test referer header /beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >-FAIL Test referer header http://127.0.0.1:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+FAIL Test referer header /beacon/resources/ assert_equals: Correct referrer header result expected "http://localhost:8800/beacon/headers/header-referrer-same-origin.html" but got "" >+PASS Test referer header http://127.0.0.1:8800/beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt >index f043abafaf6d22398afd200d2d1c9e5157f74a7a..ba0bb45632c2eb382ceb2d8784e6c634ac0d951b 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt >@@ -1,5 +1,5 @@ > CONSOLE MESSAGE: line 8: Failed to set referrer policy: The value 'strict-origin' is not one of 'no-referrer', 'origin', 'no-referrer-when-downgrade', or 'unsafe-url'. Defaulting to 'no-referrer'. > >-FAIL Test referer header https://localhost:9443/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >-FAIL Test referer header http://localhost:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+FAIL Test referer header https://localhost:9443/beacon/resources/ assert_equals: Correct referrer header result expected "https://localhost:9443/" but got "" >+PASS Test referer header http://localhost:8800/beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin.https-expected.txt >index f043abafaf6d22398afd200d2d1c9e5157f74a7a..ba0bb45632c2eb382ceb2d8784e6c634ac0d951b 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin.https-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-strict-origin.https-expected.txt >@@ -1,5 +1,5 @@ > CONSOLE MESSAGE: line 8: Failed to set referrer policy: The value 'strict-origin' is not one of 'no-referrer', 'origin', 'no-referrer-when-downgrade', or 'unsafe-url'. Defaulting to 'no-referrer'. > >-FAIL Test referer header https://localhost:9443/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >-FAIL Test referer header http://localhost:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+FAIL Test referer header https://localhost:9443/beacon/resources/ assert_equals: Correct referrer header result expected "https://localhost:9443/" but got "" >+PASS Test referer header http://localhost:8800/beacon/resources/ > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-unsafe-url.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-unsafe-url.https-expected.txt >index a7eff6f078c46bb334871e08f7b2c9d379ed64ba..0b41797489c672d81aa8aaaca10306f71798676f 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-unsafe-url.https-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-referrer-unsafe-url.https-expected.txt >@@ -1,3 +1,3 @@ > >-FAIL Test referer header http://localhost:8800/beacon/resources/ navigator.sendBeacon is not a function. (In 'navigator.sendBeacon(testUrl)', 'navigator.sendBeacon' is undefined) >+FAIL Test referer header http://localhost:8800/beacon/resources/ assert_equals: Correct referrer header result expected "https://localhost:9443/beacon/headers/header-referrer-unsafe-url.https.html" but got "" > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/beacon.py b/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/beacon.py >new file mode 100644 >index 0000000000000000000000000000000000000000..afa522a2a91707fcbf9dcc4845296399afb2bafa >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/beacon.py >@@ -0,0 +1,112 @@ >+import json >+ >+def build_stash_key(session_id, test_num): >+ return "%s_%s" % (session_id, test_num) >+ >+def main(request, response): >+ """Helper handler for Beacon tests. >+ >+ It handles two forms of requests: >+ >+ STORE: >+ A URL with a query string of the form 'cmd=store&sid=<token>&tidx=<test_index>&tid=<test_name>'. >+ >+ Stores the receipt of a sendBeacon() request along with its validation result, returning HTTP 200 OK. >+ >+ Parameters: >+ tidx - the integer index of the test. >+ tid - a friendly identifier or name for the test, used when returning results. >+ >+ STAT: >+ A URL with a query string of the form 'cmd=stat&sid=<token>&tidx_min=<min_test_index>&tidx_max=<max_test_index>'. >+ >+ Retrieves the results of test with indices [min_test_index, max_test_index] and returns them as >+ a JSON array and HTTP 200 OK status code. Due to the eventual read-once nature of the stash, results for a given test >+ are only guaranteed to be returned once, though they may be returned multiple times. >+ >+ Parameters: >+ tidx_min - the lower-bounding integer test index. >+ tidx_max - the upper-bounding integer test index. >+ >+ Example response body: >+ [{"id": "Test1", error: null}, {"id": "Test2", error: "some validation details"}] >+ >+ Common parameters: >+ cmd - the command, 'store' or 'stat'. >+ sid - session id used to provide isolation to a test run comprising multiple sendBeacon() >+ tests. >+ """ >+ >+ session_id = request.GET.first("sid"); >+ command = request.GET.first("cmd").lower(); >+ >+ # Workaround to circumvent the limitation that cache keys >+ # can only be UUID's. >+ def wrap_key(key, path): >+ return (str(path), str(key)) >+ request.server.stash._wrap_key = wrap_key >+ >+ # Append CORS headers if needed. >+ if "origin" in request.GET: >+ response.headers.set("Access-Control-Allow-Origin", request.GET.first("origin")) >+ if "credentials" in request.GET: >+ response.headers.set("Access-Control-Allow-Credentials", request.GET.first("credentials")) >+ >+ # Handle the 'store' and 'stat' commands. >+ if command == "store": >+ # The test id is just used to make the results more human-readable. >+ test_id = request.GET.first("tid") >+ # The test index is used to build a predictable stash key, together >+ # with the unique session id, in order to retrieve a range of results >+ # later knowing the index range. >+ test_idx = request.GET.first("tidx") >+ >+ test_data_key = build_stash_key(session_id, test_idx) >+ test_data = { "id": test_id, "error": None } >+ >+ payload = "" >+ if "Content-Type" in request.headers and \ >+ "form-data" in request.headers["Content-Type"]: >+ if "payload" in request.POST: >+ # The payload was sent as a FormData. >+ payload = request.POST.first("payload") >+ else: >+ # A FormData was sent with an empty payload. >+ pass >+ else: >+ # The payload was sent as either a string, Blob, or BufferSource. >+ payload = request.body >+ >+ payload_parts = filter(None, payload.split(":")) >+ if len(payload_parts) > 0: >+ payload_size = int(payload_parts[0]) >+ >+ # Confirm the payload size sent matches with the number of characters sent. >+ if payload_size != len(payload_parts[1]): >+ test_data["error"] = "expected %d characters but got %d" % (payload_size, len(payload_parts[1])) >+ else: >+ # Confirm the payload contains the correct characters. >+ for i in range(0, payload_size): >+ if payload_parts[1][i] != "*": >+ test_data["error"] = "expected '*' at index %d but got '%s''" % (i, payload_parts[1][i]) >+ break >+ >+ # Store the result in the stash so that it can be retrieved >+ # later with a 'stat' command. >+ request.server.stash.put(test_data_key, test_data) >+ elif command == "stat": >+ test_idx_min = int(request.GET.first("tidx_min")) >+ test_idx_max = int(request.GET.first("tidx_max")) >+ >+ # For each result that has come in, append it to the response. >+ results = [] >+ for test_idx in range(test_idx_min, test_idx_max+1): # +1 because end is exclusive >+ test_data_key = build_stash_key(session_id, test_idx) >+ test_data = request.server.stash.take(test_data_key) >+ if test_data: >+ results.append(test_data) >+ >+ response.headers.set("Content-Type", "text/plain") >+ response.content = json.dumps(results) >+ else: >+ response.status = 400 # BadRequest >\ No newline at end of file >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/w3c-import.log >index 459603fd559474c693a4772b62e4e35fa4b95c20..07880d6a915a114588280091803fe5a47fb8c8f0 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/w3c-import.log >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/w3c-import.log >@@ -14,5 +14,6 @@ Property values requiring vendor prefixes: > None > ------------------------------------------------------------------------ > List of files: >+/LayoutTests/imported/w3c/web-platform-tests/beacon/resources/beacon.py > /LayoutTests/imported/w3c/web-platform-tests/beacon/resources/content-type.py > /LayoutTests/imported/w3c/web-platform-tests/beacon/resources/inspect-header.py >diff --git a/LayoutTests/imported/w3c/web-platform-tests/beacon/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/beacon/w3c-import.log >new file mode 100644 >index 0000000000000000000000000000000000000000..a92bbdc14aad1a4e30dfdc0c29a6e54ebce2eb3c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/beacon/w3c-import.log >@@ -0,0 +1,30 @@ >+The tests in this directory were imported from the W3C repository. >+Do NOT modify these tests directly in WebKit. >+Instead, create a pull request on the WPT github: >+ https://github.com/w3c/web-platform-tests >+ >+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport >+ >+Do NOT modify or remove this file. >+ >+------------------------------------------------------------------------ >+Properties requiring vendor prefixes: >+None >+Property values requiring vendor prefixes: >+None >+------------------------------------------------------------------------ >+List of files: >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blob.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdata.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-string.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-common.js >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-cors.window.js >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-error.window.js >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-navigate.html >+/LayoutTests/imported/w3c/web-platform-tests/beacon/beacon-redirect.window.js >+/LayoutTests/imported/w3c/web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html >diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/failure-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/failure-expected.txt >index e17013ea7351783e4d679a335e925fc57d51a146..bdc52c2f071d73ea971fbe8c00cb711f28a1dc79 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/url/failure-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/url/failure-expected.txt >@@ -106,7 +106,7 @@ FAIL Location's href: http://foo:-80/ should throw assert_throws: function "() = > FAIL window.open(): http://foo:-80/ should throw assert_throws: function "() => self.open(test.input).close()" threw object "TypeError: null is not an object (evaluating 'self.open(test.input).close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12 > PASS URL's href: http:/:@/www.example.com should throw > FAIL XHR: http:/:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:/:@/www.example.com should throw >+FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:/:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:/:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http://user@/www.example.com should throw >@@ -116,12 +116,12 @@ FAIL Location's href: http://user@/www.example.com should throw assert_throws: f > FAIL window.open(): http://user@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" threw object "TypeError: null is not an object (evaluating 'self.open(test.input).close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12 > PASS URL's href: http:@/www.example.com should throw > FAIL XHR: http:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:@/www.example.com should throw >+FAIL sendBeacon(): http:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http:/@/www.example.com should throw > FAIL XHR: http:/@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:/@/www.example.com should throw >+FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:/@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:/@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http://@/www.example.com should throw >@@ -136,12 +136,12 @@ FAIL Location's href: https:@/www.example.com should throw assert_throws: functi > FAIL window.open(): https:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" threw object "TypeError: null is not an object (evaluating 'self.open(test.input).close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12 > PASS URL's href: http:a:b@/www.example.com should throw > FAIL XHR: http:a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:a:b@/www.example.com should throw >+FAIL sendBeacon(): http:a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http:/a:b@/www.example.com should throw > FAIL XHR: http:/a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:/a:b@/www.example.com should throw >+FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http://a:b@/www.example.com should throw >@@ -151,17 +151,17 @@ FAIL Location's href: http://a:b@/www.example.com should throw assert_throws: fu > FAIL window.open(): http://a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" threw object "TypeError: null is not an object (evaluating 'self.open(test.input).close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12 > PASS URL's href: http::@/www.example.com should throw > FAIL XHR: http::@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http::@/www.example.com should throw >+FAIL sendBeacon(): http::@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http::@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http::@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http:@:www.example.com should throw > FAIL XHR: http:@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:@:www.example.com should throw >+FAIL sendBeacon(): http:@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http:/@:www.example.com should throw > FAIL XHR: http:/@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw >-PASS sendBeacon(): http:/@:www.example.com should throw >+FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw > FAIL Location's href: http:/@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw > FAIL window.open(): http:/@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw > PASS URL's href: http://@:www.example.com should throw >diff --git a/LayoutTests/resources/window-postmessage-open-close.html b/LayoutTests/resources/window-postmessage-open-close.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3adb8ceecdc36eb667eb8238ca20515714c9e86f >--- /dev/null >+++ b/LayoutTests/resources/window-postmessage-open-close.html >@@ -0,0 +1,9 @@ >+<!DOCTYPE html> >+<!-- Used when testing access of a closed/detached window's properties --> >+<html> >+<body onunload="opener.postMessage('closed', '*');"> >+<script> >+opener.postMessage("opened", "*"); >+</script> >+</body> >+</html> >diff --git a/LayoutTests/tests-options.json b/LayoutTests/tests-options.json >index 360ee40c27852c49d2c17d09a73d6b3ee4393d39..053bedf141d8eb715e0299fd54b993e40cd6f2b4 100644 >--- a/LayoutTests/tests-options.json >+++ b/LayoutTests/tests-options.json >@@ -362,6 +362,33 @@ > "imported/w3c/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html": [ > "slow" > ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-blob.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-blobMax.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-buffersource.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-buffersourceMax.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-formdata.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-formdataMax.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-string.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-basic-stringMax.html": [ >+ "slow" >+ ], >+ "imported/w3c/web-platform-tests/beacon/beacon-navigate.html": [ >+ "slow" >+ ], > "imported/w3c/web-platform-tests/cors/status-async.htm": [ > "slow" > ],
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 175007
:
316828
|
316864
|
316872
|
316880
|
316903
|
316923
|
316928
|
316929