<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[245314] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/245314">245314</a></dd>
<dt>Author</dt> <dd>aestes@apple.com</dd>
<dt>Date</dt> <dd>2019-05-14 15:50:21 -0700 (Tue, 14 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Apple Pay] Payment APIs should be completely disabled in web views into which clients have injected user scripts
https://bugs.webkit.org/show_bug.cgi?id=197751
<rdar://problem/50631563>

Reviewed by Alex Christensen.

Source/WebCore:

In <a href="http://trac.webkit.org/projects/webkit/changeset/243324">r243324</a>, when a document has had user agent scripts injected into it, payment APIs were
disabled at runtime by having all entry points return falsy values or throw exceptions
(e.g., ApplePaySession.canMakePayments() returns false).

In the case of user scripts in particular (e.g., WKUserScript), since we know whether these
exist at the time we create a document's DOMWindow, we can do better than <a href="http://trac.webkit.org/projects/webkit/changeset/243324">r243324</a> by
completely disabling the payment APIs in the presence of user scripts.

To achieve this, this change introduces the 'EnabledByContext' extended attribute for
interfaces, which instructs the bindings generator to add a conjunct to the payment API
constructors that asks the interface's implementation class whether it should be enabled for
a given ScriptExecutionContext. The PaymentRequest and ApplePaySession interfaces adopt this
new extended attribute to implement the new user script check.

Added new API tests.

* Modules/applepay/ApplePaySession.idl:
* Modules/applepay/PaymentCoordinator.cpp:
(WebCore::PaymentCoordinator::shouldEnableApplePayAPIs const):
* Modules/applepay/PaymentCoordinator.h:
* Modules/applepay/PaymentSession.cpp:
(WebCore::PaymentSession::enabledForContext):
* Modules/applepay/PaymentSession.h:
* Modules/paymentrequest/PaymentHandler.cpp:
(WebCore::PaymentHandler::enabledForContext):
* Modules/paymentrequest/PaymentHandler.h:
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::enabledForContext):
* Modules/paymentrequest/PaymentRequest.h:
* Modules/paymentrequest/PaymentRequest.idl:
* bindings/scripts/CodeGeneratorJS.pm:
(NeedsRuntimeCheck):
(GenerateRuntimeEnableConditionalString):
* bindings/scripts/IDLAttributes.json:
* bindings/scripts/preprocess-idls.pl:
(GenerateConstructorAttributes):
* bindings/scripts/test/JS/JSTestEnabledForContext.cpp: Added.
* bindings/scripts/test/JS/JSTestEnabledForContext.h: Added.
* bindings/scripts/test/JS/JSTestGlobalObject.cpp:
(WebCore::JSTestGlobalObject::finishCreation):
(WebCore::jsTestGlobalObjectTestEnabledForContextConstructorGetter):
(WebCore::jsTestGlobalObjectTestEnabledForContextConstructor):
(WebCore::setJSTestGlobalObjectTestEnabledForContextConstructorSetter):
(WebCore::setJSTestGlobalObjectTestEnabledForContextConstructor):
* bindings/scripts/test/TestEnabledForContext.idl: Added.

Tools:

Added new API tests.

* TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm:
(-[TestApplePayScriptMessageHandler initWithAPIsAvailableExpectation:canMakePaymentsExpectation:]):
(-[TestApplePayScriptMessageHandler userContentController:didReceiveScriptMessage:]):
(TestWebKitAPI::TEST):
(-[TestApplePayScriptMessageHandler initWithExpectation:]): Deleted.
* TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesapplepayApplePaySessionidl">trunk/Source/WebCore/Modules/applepay/ApplePaySession.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesapplepayPaymentCoordinatorcpp">trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesapplepayPaymentCoordinatorh">trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.h</a></li>
<li><a href="#trunkSourceWebCoreModulesapplepayPaymentSessioncpp">trunk/Source/WebCore/Modules/applepay/PaymentSession.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesapplepayPaymentSessionh">trunk/Source/WebCore/Modules/applepay/PaymentSession.h</a></li>
<li><a href="#trunkSourceWebCoreModulespaymentrequestPaymentHandlercpp">trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulespaymentrequestPaymentHandlerh">trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h</a></li>
<li><a href="#trunkSourceWebCoreModulespaymentrequestPaymentRequestcpp">trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulespaymentrequestPaymentRequesth">trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h</a></li>
<li><a href="#trunkSourceWebCoreModulespaymentrequestPaymentRequestidl">trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsIDLAttributesjson">trunk/Source/WebCore/bindings/scripts/IDLAttributes.json</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptspreprocessidlspl">trunk/Source/WebCore/bindings/scripts/preprocess-idls.pl</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestGlobalObjectcpp">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaApplePaymm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaapplepayavailabilityhtml">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestEnabledForContextcpp">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestEnabledForContexth">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestTestEnabledForContextidl">trunk/Source/WebCore/bindings/scripts/test/TestEnabledForContext.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/ChangeLog      2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2019-05-14  Andy Estes  <aestes@apple.com>
+
+        [Apple Pay] Payment APIs should be completely disabled in web views into which clients have injected user scripts
+        https://bugs.webkit.org/show_bug.cgi?id=197751
+        <rdar://problem/50631563>
+
+        Reviewed by Alex Christensen.
+
+        In r243324, when a document has had user agent scripts injected into it, payment APIs were
+        disabled at runtime by having all entry points return falsy values or throw exceptions
+        (e.g., ApplePaySession.canMakePayments() returns false).
+
+        In the case of user scripts in particular (e.g., WKUserScript), since we know whether these
+        exist at the time we create a document's DOMWindow, we can do better than r243324 by
+        completely disabling the payment APIs in the presence of user scripts.
+
+        To achieve this, this change introduces the 'EnabledByContext' extended attribute for
+        interfaces, which instructs the bindings generator to add a conjunct to the payment API
+        constructors that asks the interface's implementation class whether it should be enabled for
+        a given ScriptExecutionContext. The PaymentRequest and ApplePaySession interfaces adopt this
+        new extended attribute to implement the new user script check.
+
+        Added new API tests.
+
+        * Modules/applepay/ApplePaySession.idl:
+        * Modules/applepay/PaymentCoordinator.cpp:
+        (WebCore::PaymentCoordinator::shouldEnableApplePayAPIs const):
+        * Modules/applepay/PaymentCoordinator.h:
+        * Modules/applepay/PaymentSession.cpp:
+        (WebCore::PaymentSession::enabledForContext):
+        * Modules/applepay/PaymentSession.h:
+        * Modules/paymentrequest/PaymentHandler.cpp:
+        (WebCore::PaymentHandler::enabledForContext):
+        * Modules/paymentrequest/PaymentHandler.h:
+        * Modules/paymentrequest/PaymentRequest.cpp:
+        (WebCore::PaymentRequest::enabledForContext):
+        * Modules/paymentrequest/PaymentRequest.h:
+        * Modules/paymentrequest/PaymentRequest.idl:
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (NeedsRuntimeCheck):
+        (GenerateRuntimeEnableConditionalString):
+        * bindings/scripts/IDLAttributes.json:
+        * bindings/scripts/preprocess-idls.pl:
+        (GenerateConstructorAttributes):
+        * bindings/scripts/test/JS/JSTestEnabledForContext.cpp: Added.
+        * bindings/scripts/test/JS/JSTestEnabledForContext.h: Added.
+        * bindings/scripts/test/JS/JSTestGlobalObject.cpp:
+        (WebCore::JSTestGlobalObject::finishCreation):
+        (WebCore::jsTestGlobalObjectTestEnabledForContextConstructorGetter):
+        (WebCore::jsTestGlobalObjectTestEnabledForContextConstructor):
+        (WebCore::setJSTestGlobalObjectTestEnabledForContextConstructorSetter):
+        (WebCore::setJSTestGlobalObjectTestEnabledForContextConstructor):
+        * bindings/scripts/test/TestEnabledForContext.idl: Added.
+
</ins><span class="cx"> 2019-05-14  Robin Morisset  <rmorisset@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [WHLSL] parseEffectfulSuffix() is never called
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesapplepayApplePaySessionidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/applepay/ApplePaySession.idl (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/applepay/ApplePaySession.idl        2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/applepay/ApplePaySession.idl   2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">     ConstructorCallWith=Document,
</span><span class="cx">     ConstructorMayThrowException,
</span><span class="cx">     EnabledBySetting=ApplePay,
</span><ins>+    EnabledForContext,
</ins><span class="cx"> ] interface ApplePaySession : EventTarget {
</span><span class="cx">     const unsigned short STATUS_SUCCESS = 0;
</span><span class="cx">     const unsigned short STATUS_FAILURE = 1;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesapplepayPaymentCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.cpp (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.cpp     2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.cpp        2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -31,9 +31,11 @@
</span><span class="cx"> #include "Document.h"
</span><span class="cx"> #include "LinkIconCollector.h"
</span><span class="cx"> #include "Logging.h"
</span><ins>+#include "Page.h"
</ins><span class="cx"> #include "PaymentAuthorizationStatus.h"
</span><span class="cx"> #include "PaymentCoordinatorClient.h"
</span><span class="cx"> #include "PaymentSession.h"
</span><ins>+#include "UserContentProvider.h"
</ins><span class="cx"> #include <wtf/CompletionHandler.h>
</span><span class="cx"> #include <wtf/URL.h>
</span><span class="cx"> 
</span><span class="lines">@@ -251,6 +253,22 @@
</span><span class="cx">     return m_client.validatedPaymentNetwork(paymentNetwork);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool PaymentCoordinator::shouldEnableApplePayAPIs(Document& document) const
+{
+    if (m_client.supportsUnrestrictedApplePay()) {
+        RELEASE_LOG_IF_ALLOWED("shouldEnableApplePayAPIs() -> true (unrestricted client)");
+        return true;
+    }
+
+    bool shouldEnableAPIs = true;
+    document.page()->userContentProvider().forEachUserScript([&](DOMWrapperWorld&, const UserScript&) {
+        shouldEnableAPIs = false;
+    });
+
+    RELEASE_LOG_IF_ALLOWED("shouldEnableApplePayAPIs() -> %d", shouldEnableAPIs);
+    return shouldEnableAPIs;
+}
+
</ins><span class="cx"> bool PaymentCoordinator::shouldAllowApplePay(Document& document) const
</span><span class="cx"> {
</span><span class="cx">     if (m_client.supportsUnrestrictedApplePay()) {
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesapplepayPaymentCoordinatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.h (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.h       2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/applepay/PaymentCoordinator.h  2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -78,6 +78,7 @@
</span><span class="cx"> 
</span><span class="cx">     Optional<String> validatedPaymentNetwork(Document&, unsigned version, const String&) const;
</span><span class="cx"> 
</span><ins>+    bool shouldEnableApplePayAPIs(Document&) const;
</ins><span class="cx">     WEBCORE_EXPORT bool shouldAllowApplePay(Document&) const;
</span><span class="cx">     WEBCORE_EXPORT bool shouldAllowUserAgentScripts(Document&) const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesapplepayPaymentSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/applepay/PaymentSession.cpp (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/applepay/PaymentSession.cpp 2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/applepay/PaymentSession.cpp    2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "Document.h"
</span><span class="cx"> #include "DocumentLoader.h"
</span><ins>+#include "Page.h"
</ins><span class="cx"> #include "SecurityOrigin.h"
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -72,6 +73,15 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool PaymentSession::enabledForContext(ScriptExecutionContext& context)
+{
+    auto& document = downcast<Document>(context);
+    if (auto page = document.page())
+        return page->paymentCoordinator().shouldEnableApplePayAPIs(document);
+
+    return false;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(APPLE_PAY)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesapplepayPaymentSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/applepay/PaymentSession.h (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/applepay/PaymentSession.h   2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/applepay/PaymentSession.h      2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> class PaymentSession : public virtual PaymentSessionBase {
</span><span class="cx"> public:
</span><span class="cx">     static ExceptionOr<void> canCreateSession(Document&);
</span><ins>+    static bool enabledForContext(ScriptExecutionContext&);
</ins><span class="cx"> 
</span><span class="cx">     virtual unsigned version() const = 0;
</span><span class="cx">     virtual void validateMerchant(URL&&) = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulespaymentrequestPaymentHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.cpp (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.cpp   2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.cpp      2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -61,6 +61,16 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool PaymentHandler::enabledForContext(ScriptExecutionContext& context)
+{
+#if ENABLE(APPLE_PAY)
+    return PaymentSession::enabledForContext(context);
+#else
+    UNUSED_PARAM(context);
+    return false;
+#endif
+}
+
</ins><span class="cx"> bool PaymentHandler::hasActiveSession(Document& document)
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(APPLE_PAY)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulespaymentrequestPaymentHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h     2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h        2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> public:
</span><span class="cx">     static RefPtr<PaymentHandler> create(Document&, PaymentRequest&, const PaymentRequest::MethodIdentifier&);
</span><span class="cx">     static ExceptionOr<void> canCreateSession(Document&);
</span><ins>+    static bool enabledForContext(ScriptExecutionContext&);
</ins><span class="cx">     static bool hasActiveSession(Document&);
</span><span class="cx"> 
</span><span class="cx">     virtual ExceptionOr<void> convertData(JSC::JSValue&&) = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulespaymentrequestPaymentRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp   2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp      2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -34,7 +34,9 @@
</span><span class="cx"> #include "JSDOMPromise.h"
</span><span class="cx"> #include "JSPaymentDetailsUpdate.h"
</span><span class="cx"> #include "JSPaymentResponse.h"
</span><ins>+#include "Page.h"
</ins><span class="cx"> #include "PaymentAddress.h"
</span><ins>+#include "PaymentCoordinator.h"
</ins><span class="cx"> #include "PaymentCurrencyAmount.h"
</span><span class="cx"> #include "PaymentDetailsInit.h"
</span><span class="cx"> #include "PaymentHandler.h"
</span><span class="lines">@@ -351,6 +353,11 @@
</span><span class="cx">     return adoptRef(*new PaymentRequest(document, WTFMove(options), WTFMove(details), WTFMove(std::get<1>(shippingOptionAndModifierData)), WTFMove(serializedMethodData), WTFMove(std::get<0>(shippingOptionAndModifierData))));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool PaymentRequest::enabledForContext(ScriptExecutionContext& context)
+{
+    return PaymentHandler::enabledForContext(context);
+}
+
</ins><span class="cx"> PaymentRequest::PaymentRequest(Document& document, PaymentOptions&& options, PaymentDetailsInit&& details, Vector<String>&& serializedModifierData, Vector<Method>&& serializedMethodData, String&& selectedShippingOption)
</span><span class="cx">     : ActiveDOMObject { document }
</span><span class="cx">     , m_options { WTFMove(options) }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulespaymentrequestPaymentRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h     2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h        2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     using ShowPromise = DOMPromiseDeferred<IDLInterface<PaymentResponse>>;
</span><span class="cx"> 
</span><span class="cx">     static ExceptionOr<Ref<PaymentRequest>> create(Document&, Vector<PaymentMethodData>&&, PaymentDetailsInit&&, PaymentOptions&&);
</span><ins>+    static bool enabledForContext(ScriptExecutionContext&);
</ins><span class="cx">     ~PaymentRequest();
</span><span class="cx"> 
</span><span class="cx">     void show(Document&, RefPtr<DOMPromise>&& detailsPromise, ShowPromise&&);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulespaymentrequestPaymentRequestidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl   2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.idl      2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">     ConstructorCallWith=Document,
</span><span class="cx">     ConstructorMayThrowException,
</span><span class="cx">     EnabledBySetting=PaymentRequest,
</span><ins>+    EnabledForContext,
</ins><span class="cx">     SecureContext,
</span><span class="cx"> ] interface PaymentRequest : EventTarget {
</span><span class="cx">     [CallWith=Document] Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm    2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -1705,6 +1705,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return $context->extendedAttributes->{EnabledAtRuntime}
</span><ins>+        || $context->extendedAttributes->{EnabledForContext}
</ins><span class="cx">         || $context->extendedAttributes->{EnabledForWorld}
</span><span class="cx">         || $context->extendedAttributes->{EnabledBySetting}
</span><span class="cx">         || $context->extendedAttributes->{DisabledByQuirk}
</span><span class="lines">@@ -3788,6 +3789,15 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if ($context->extendedAttributes->{EnabledForContext}) {
+        assert("Must not specify value for EnabledForContext.") unless $context->extendedAttributes->{EnabledForContext} eq "VALUE_IS_MISSING";
+        assert("EnabledForContext must be an interface or constructor attribute.") unless $codeGenerator->IsConstructorType($context->type);
+
+        my $contextRef = "*jsCast<JSDOMGlobalObject*>(" . $globalObjectPtr . ")->scriptExecutionContext()";
+        my $name = $context->name;
+        push(@conjuncts,  "${name}::enabledForContext(" . $contextRef . ")");
+    }
+
</ins><span class="cx">     my $result = join(" && ", @conjuncts);
</span><span class="cx">     $result = "($result)" if @conjuncts > 1;
</span><span class="cx">     return $result;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsIDLAttributesjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.json (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.json 2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.json    2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -192,6 +192,9 @@
</span><span class="cx">             "contextsAllowed": ["interface", "dictionary", "enum", "attribute", "operation", "constant"],
</span><span class="cx">             "values": ["*"]
</span><span class="cx">         },
</span><ins>+        "EnabledForContext": {
+            "contextsAllowed": ["attribute", "interface"]
+        },
</ins><span class="cx">         "EnabledForWorld": {
</span><span class="cx">             "contextsAllowed": ["attribute", "operation"],
</span><span class="cx">             "values": ["*"]
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptspreprocessidlspl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/preprocess-idls.pl (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/preprocess-idls.pl 2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/bindings/scripts/preprocess-idls.pl    2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -283,7 +283,7 @@
</span><span class="cx">     foreach my $attributeName (sort keys %{$extendedAttributes}) {
</span><span class="cx">       next unless ($attributeName eq "Conditional" || $attributeName eq "EnabledAtRuntime" || $attributeName eq "EnabledForWorld"
</span><span class="cx">         || $attributeName eq "EnabledBySetting" || $attributeName eq "SecureContext" || $attributeName eq "PrivateIdentifier"
</span><del>-        || $attributeName eq "PublicIdentifier" || $attributeName eq "DisabledByQuirk" || $attributeName eq "EnabledByQuirk");
</del><ins>+        || $attributeName eq "PublicIdentifier" || $attributeName eq "DisabledByQuirk" || $attributeName eq "EnabledByQuirk" || $attributeName eq "EnabledForContext");
</ins><span class="cx">       my $extendedAttribute = $attributeName;
</span><span class="cx">       $extendedAttribute .= "=" . $extendedAttributes->{$attributeName} unless $extendedAttributes->{$attributeName} eq "VALUE_IS_MISSING";
</span><span class="cx">       push(@extendedAttributesList, $extendedAttribute);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestEnabledForContextcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.cpp (0 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.cpp                                (rev 0)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.cpp   2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -0,0 +1,267 @@
</span><ins>+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestEnabledForContext.h"
+
+#include "Document.h"
+#include "JSDOMAttribute.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructorNotConstructable.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWrapperCache.h"
+#include "JSTestSubObj.h"
+#include "ScriptExecutionContext.h"
+#include "Settings.h"
+#include "WebCoreJSClientData.h"
+#include <JavaScriptCore/FunctionPrototype.h>
+#include <JavaScriptCore/HeapSnapshotBuilder.h>
+#include <JavaScriptCore/JSCInlines.h>
+#include <wtf/GetPtr.h>
+#include <wtf/PointerPreparations.h>
+#include <wtf/URL.h>
+
+
+namespace WebCore {
+using namespace JSC;
+
+// Attributes
+
+JSC::EncodedJSValue jsTestEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestEnabledForContextTestSubObjEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestEnabledForContextTestSubObjEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+
+class JSTestEnabledForContextPrototype : public JSC::JSNonFinalObject {
+public:
+    using Base = JSC::JSNonFinalObject;
+    static JSTestEnabledForContextPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+    {
+        JSTestEnabledForContextPrototype* ptr = new (NotNull, JSC::allocateCell<JSTestEnabledForContextPrototype>(vm.heap)) JSTestEnabledForContextPrototype(vm, globalObject, structure);
+        ptr->finishCreation(vm);
+        return ptr;
+    }
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+private:
+    JSTestEnabledForContextPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+        : JSC::JSNonFinalObject(vm, structure)
+    {
+    }
+
+    void finishCreation(JSC::VM&);
+};
+
+using JSTestEnabledForContextConstructor = JSDOMConstructorNotConstructable<JSTestEnabledForContext>;
+
+template<> JSValue JSTestEnabledForContextConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+    UNUSED_PARAM(vm);
+    return globalObject.functionPrototype();
+}
+
+template<> void JSTestEnabledForContextConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    putDirect(vm, vm.propertyNames->prototype, JSTestEnabledForContext::prototype(vm, globalObject), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String("TestEnabledForContext"_s)), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+    putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+}
+
+template<> const ClassInfo JSTestEnabledForContextConstructor::s_info = { "TestEnabledForContext", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestEnabledForContextConstructor) };
+
+/* Hash table for prototype */
+
+static const HashTableValue JSTestEnabledForContextPrototypeTableValues[] =
+{
+    { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestEnabledForContextConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestEnabledForContextConstructor) } },
+};
+
+const ClassInfo JSTestEnabledForContextPrototype::s_info = { "TestEnabledForContextPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestEnabledForContextPrototype) };
+
+void JSTestEnabledForContextPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    reifyStaticProperties(vm, JSTestEnabledForContext::info(), JSTestEnabledForContextPrototypeTableValues, *this);
+}
+
+const ClassInfo JSTestEnabledForContext::s_info = { "TestEnabledForContext", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestEnabledForContext) };
+
+JSTestEnabledForContext::JSTestEnabledForContext(Structure* structure, JSDOMGlobalObject& globalObject, Ref<TestEnabledForContext>&& impl)
+    : JSDOMWrapper<TestEnabledForContext>(structure, globalObject, WTFMove(impl))
+{
+}
+
+void JSTestEnabledForContext::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+
+    if ((downcast<Document>(jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext())->settings().testSettingEnabled() && TestSubObjEnabledForContext::enabledForContext(*jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext())))
+        putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().TestSubObjEnabledForContextPublicName(), CustomGetterSetter::create(vm, jsTestEnabledForContextTestSubObjEnabledForContextConstructor, setJSTestEnabledForContextTestSubObjEnabledForContextConstructor), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum)));
+}
+
+JSObject* JSTestEnabledForContext::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return JSTestEnabledForContextPrototype::create(vm, &globalObject, JSTestEnabledForContextPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
+}
+
+JSObject* JSTestEnabledForContext::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return getDOMPrototype<JSTestEnabledForContext>(vm, globalObject);
+}
+
+JSValue JSTestEnabledForContext::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+    return getDOMConstructor<JSTestEnabledForContextConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+void JSTestEnabledForContext::destroy(JSC::JSCell* cell)
+{
+    JSTestEnabledForContext* thisObject = static_cast<JSTestEnabledForContext*>(cell);
+    thisObject->JSTestEnabledForContext::~JSTestEnabledForContext();
+}
+
+template<> inline JSTestEnabledForContext* IDLAttribute<JSTestEnabledForContext>::cast(ExecState& state, EncodedJSValue thisValue)
+{
+    return jsDynamicCast<JSTestEnabledForContext*>(state.vm(), JSValue::decode(thisValue));
+}
+
+EncodedJSValue jsTestEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicCast<JSTestEnabledForContextPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype))
+        return throwVMTypeError(state, throwScope);
+    return JSValue::encode(JSTestEnabledForContext::getConstructor(state->vm(), prototype->globalObject()));
+}
+
+bool setJSTestEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicCast<JSTestEnabledForContextPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype)) {
+        throwVMTypeError(state, throwScope);
+        return false;
+    }
+    // Shadowing a built-in constructor
+    return prototype->putDirect(vm, vm.propertyNames->constructor, JSValue::decode(encodedValue));
+}
+
+static inline JSValue jsTestEnabledForContextTestSubObjEnabledForContextConstructorGetter(ExecState& state, JSTestEnabledForContext& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    return JSTestSubObj::getConstructor(state.vm(), thisObject.globalObject());
+}
+
+EncodedJSValue jsTestEnabledForContextTestSubObjEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return IDLAttribute<JSTestEnabledForContext>::get<jsTestEnabledForContextTestSubObjEnabledForContextConstructorGetter>(*state, thisValue, "TestSubObjEnabledForContext");
+}
+
+static inline bool setJSTestEnabledForContextTestSubObjEnabledForContextConstructorSetter(ExecState& state, JSTestEnabledForContext& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    // Shadowing a built-in constructor.
+    return thisObject.putDirect(state.vm(), Identifier::fromString(&state.vm(), reinterpret_cast<const LChar*>("TestSubObjEnabledForContext"), strlen("TestSubObjEnabledForContext")), value);
+}
+
+bool setJSTestEnabledForContextTestSubObjEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return IDLAttribute<JSTestEnabledForContext>::set<setJSTestEnabledForContextTestSubObjEnabledForContextConstructorSetter>(*state, thisValue, encodedValue, "TestSubObjEnabledForContext");
+}
+
+void JSTestEnabledForContext::heapSnapshot(JSCell* cell, HeapSnapshotBuilder& builder)
+{
+    auto* thisObject = jsCast<JSTestEnabledForContext*>(cell);
+    builder.setWrappedObjectForCell(cell, &thisObject->wrapped());
+    if (thisObject->scriptExecutionContext())
+        builder.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
+    Base::heapSnapshot(cell, builder);
+}
+
+bool JSTestEnabledForContextOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor, const char** reason)
+{
+    UNUSED_PARAM(handle);
+    UNUSED_PARAM(visitor);
+    UNUSED_PARAM(reason);
+    return false;
+}
+
+void JSTestEnabledForContextOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+    auto* jsTestEnabledForContext = static_cast<JSTestEnabledForContext*>(handle.slot()->asCell());
+    auto& world = *static_cast<DOMWrapperWorld*>(context);
+    uncacheWrapper(world, &jsTestEnabledForContext->wrapped(), jsTestEnabledForContext);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable: 4483)
+extern "C" { extern void (*const __identifier("??_7TestEnabledForContext@WebCore@@6B@")[])(); }
+#else
+extern "C" { extern void* _ZTVN7WebCore21TestEnabledForContextE[]; }
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<TestEnabledForContext>&& impl)
+{
+
+#if ENABLE(BINDING_INTEGRITY)
+    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
+#if PLATFORM(WIN)
+    void* expectedVTablePointer = WTF_PREPARE_VTBL_POINTER_FOR_INSPECTION(__identifier("??_7TestEnabledForContext@WebCore@@6B@"));
+#else
+    void* expectedVTablePointer = WTF_PREPARE_VTBL_POINTER_FOR_INSPECTION(&_ZTVN7WebCore21TestEnabledForContextE[2]);
+#endif
+
+    // If this fails TestEnabledForContext does not have a vtable, so you need to add the
+    // ImplementationLacksVTable attribute to the interface definition
+    static_assert(std::is_polymorphic<TestEnabledForContext>::value, "TestEnabledForContext is not polymorphic");
+
+    // If you hit this assertion you either have a use after free bug, or
+    // TestEnabledForContext has subclasses. If TestEnabledForContext has subclasses that get passed
+    // to toJS() we currently require TestEnabledForContext you to opt out of binding hardening
+    // by adding the SkipVTableValidation attribute to the interface IDL definition
+    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+    return createWrapper<TestEnabledForContext>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestEnabledForContext& impl)
+{
+    return wrap(state, globalObject, impl);
+}
+
+TestEnabledForContext* JSTestEnabledForContext::toWrapped(JSC::VM& vm, JSC::JSValue value)
+{
+    if (auto* wrapper = jsDynamicCast<JSTestEnabledForContext*>(vm, value))
+        return &wrapper->wrapped();
+    return nullptr;
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestEnabledForContexth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.h (0 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.h                          (rev 0)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.h     2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -0,0 +1,88 @@
</span><ins>+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "TestEnabledForContext.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSTestEnabledForContext : public JSDOMWrapper<TestEnabledForContext> {
+public:
+    using Base = JSDOMWrapper<TestEnabledForContext>;
+    static JSTestEnabledForContext* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestEnabledForContext>&& impl)
+    {
+        JSTestEnabledForContext* ptr = new (NotNull, JSC::allocateCell<JSTestEnabledForContext>(globalObject->vm().heap)) JSTestEnabledForContext(structure, *globalObject, WTFMove(impl));
+        ptr->finishCreation(globalObject->vm());
+        return ptr;
+    }
+
+    static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+    static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+    static TestEnabledForContext* toWrapped(JSC::VM&, JSC::JSValue);
+    static void destroy(JSC::JSCell*);
+
+    DECLARE_INFO;
+
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+    static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+    static void heapSnapshot(JSCell*, JSC::HeapSnapshotBuilder&);
+public:
+    static const unsigned StructureFlags = Base::StructureFlags | JSC::HasStaticPropertyTable;
+protected:
+    JSTestEnabledForContext(JSC::Structure*, JSDOMGlobalObject&, Ref<TestEnabledForContext>&&);
+
+    void finishCreation(JSC::VM&);
+};
+
+class JSTestEnabledForContextOwner : public JSC::WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&, const char**);
+    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, TestEnabledForContext*)
+{
+    static NeverDestroyed<JSTestEnabledForContextOwner> owner;
+    return &owner.get();
+}
+
+inline void* wrapperKey(TestEnabledForContext* wrappableObject)
+{
+    return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestEnabledForContext&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestEnabledForContext* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<TestEnabledForContext>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<TestEnabledForContext>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<TestEnabledForContext> {
+    using WrapperClass = JSTestEnabledForContext;
+    using ToWrappedReturnType = TestEnabledForContext*;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp     2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp        2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include "JSTestDOMJIT.h"
</span><span class="cx"> #include "JSTestDomainSecurity.h"
</span><span class="cx"> #include "JSTestEnabledBySetting.h"
</span><ins>+#include "JSTestEnabledForContext.h"
</ins><span class="cx"> #include "JSTestEventConstructor.h"
</span><span class="cx"> #include "JSTestEventTarget.h"
</span><span class="cx"> #include "JSTestException.h"
</span><span class="lines">@@ -172,6 +173,8 @@
</span><span class="cx"> bool setJSTestGlobalObjectTestDomainSecurityConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
</span><span class="cx"> JSC::EncodedJSValue jsTestGlobalObjectTestEnabledBySettingConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="cx"> bool setJSTestGlobalObjectTestEnabledBySettingConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
</span><ins>+JSC::EncodedJSValue jsTestGlobalObjectTestEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestGlobalObjectTestEnabledForContextConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
</ins><span class="cx"> JSC::EncodedJSValue jsTestGlobalObjectTestEventConstructorConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="cx"> bool setJSTestGlobalObjectTestEventConstructorConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
</span><span class="cx"> JSC::EncodedJSValue jsTestGlobalObjectTestEventTargetConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="lines">@@ -702,6 +705,8 @@
</span><span class="cx">     if (RuntimeEnabledFeatures::sharedFeatures().testFeatureEnabled())
</span><span class="cx">         putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().enabledAtRuntimeAttributePublicName(), CustomGetterSetter::create(vm, jsTestGlobalObjectEnabledAtRuntimeAttribute, setJSTestGlobalObjectEnabledAtRuntimeAttribute), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor)));
</span><span class="cx"> #endif
</span><ins>+    if ((jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext()->isSecureContext() && TestEnabledForContext::enabledForContext(*jsCast<JSDOMGlobalObject*>(globalObject())->scriptExecutionContext())))
+        putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().TestEnabledForContextPublicName(), CustomGetterSetter::create(vm, jsTestGlobalObjectTestEnabledForContextConstructor, setJSTestGlobalObjectTestEnabledForContextConstructor), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum)));
</ins><span class="cx">     putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().publicAndPrivateAttributePrivateName(), CustomGetterSetter::create(vm, jsTestGlobalObjectPublicAndPrivateAttribute, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly));
</span><span class="cx"> #if ENABLE(TEST_FEATURE)
</span><span class="cx">     putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().publicAndPrivateConditionalAttributePrivateName(), CustomGetterSetter::create(vm, jsTestGlobalObjectPublicAndPrivateConditionalAttribute, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly));
</span><span class="lines">@@ -1116,6 +1121,30 @@
</span><span class="cx">     return IDLAttribute<JSTestGlobalObject>::set<setJSTestGlobalObjectTestEnabledBySettingConstructorSetter>(*state, thisValue, encodedValue, "TestEnabledBySetting");
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline JSValue jsTestGlobalObjectTestEnabledForContextConstructorGetter(ExecState& state, JSTestGlobalObject& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    return JSTestEnabledForContext::getConstructor(state.vm(), thisObject.globalObject());
+}
+
+EncodedJSValue jsTestGlobalObjectTestEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return IDLAttribute<JSTestGlobalObject>::get<jsTestGlobalObjectTestEnabledForContextConstructorGetter>(*state, thisValue, "TestEnabledForContext");
+}
+
+static inline bool setJSTestGlobalObjectTestEnabledForContextConstructorSetter(ExecState& state, JSTestGlobalObject& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    // Shadowing a built-in constructor.
+    return thisObject.putDirect(state.vm(), Identifier::fromString(&state.vm(), reinterpret_cast<const LChar*>("TestEnabledForContext"), strlen("TestEnabledForContext")), value);
+}
+
+bool setJSTestGlobalObjectTestEnabledForContextConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return IDLAttribute<JSTestGlobalObject>::set<setJSTestGlobalObjectTestEnabledForContextConstructorSetter>(*state, thisValue, encodedValue, "TestEnabledForContext");
+}
+
</ins><span class="cx"> static inline JSValue jsTestGlobalObjectTestEventConstructorConstructorGetter(ExecState& state, JSTestGlobalObject& thisObject, ThrowScope& throwScope)
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(throwScope);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestTestEnabledForContextidlfromrev245313trunkSourceWebCoreModulesapplepayPaymentSessionh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/bindings/scripts/test/TestEnabledForContext.idl (from rev 245313, trunk/Source/WebCore/Modules/applepay/PaymentSession.h) (0 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/TestEnabledForContext.idl                             (rev 0)
+++ trunk/Source/WebCore/bindings/scripts/test/TestEnabledForContext.idl        2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+/*
+ * Copyright (C) 2019 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.
+ */
+
+[
+    EnabledForContext,
+    SecureContext,
+] interface TestEnabledForContext {
+    [EnabledBySetting=TestSetting, EnabledForContext] attribute TestSubObjConstructor TestSubObjEnabledForContext;
+};
</ins></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Tools/ChangeLog       2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2019-05-14  Andy Estes  <aestes@apple.com>
+
+        [Apple Pay] Payment APIs should be completely disabled in web views into which clients have injected user scripts
+        https://bugs.webkit.org/show_bug.cgi?id=197751
+        <rdar://problem/50631563>
+
+        Reviewed by Alex Christensen.
+
+        Added new API tests.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm:
+        (-[TestApplePayScriptMessageHandler initWithAPIsAvailableExpectation:canMakePaymentsExpectation:]):
+        (-[TestApplePayScriptMessageHandler userContentController:didReceiveScriptMessage:]):
+        (TestWebKitAPI::TEST):
+        (-[TestApplePayScriptMessageHandler initWithExpectation:]): Deleted.
+        * TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html:
+
</ins><span class="cx"> 2019-05-14  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><span class="cx">         A service worker process should app nap when all its clients app nap
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaApplePaymm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm  2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplePay.mm     2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -41,29 +41,33 @@
</span><span class="cx"> @interface TestApplePayScriptMessageHandler : NSObject <WKScriptMessageHandler>
</span><span class="cx"> 
</span><span class="cx"> - (instancetype)init NS_UNAVAILABLE;
</span><del>-- (instancetype)initWithExpectation:(BOOL)expectation;
</del><ins>+- (instancetype)initWithAPIsAvailableExpectation:(BOOL)apisAvailableExpectation canMakePaymentsExpectation:(BOOL)canMakePaymentsExpectation;
</ins><span class="cx"> 
</span><ins>+@property (nonatomic, setter=setAPIsAvailableExpectation:) BOOL apisAvailableExpectation;
+@property (nonatomic) BOOL canMakePaymentsExpectation;
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@implementation TestApplePayScriptMessageHandler {
-    BOOL _expectation;
-}
</del><ins>+@implementation TestApplePayScriptMessageHandler
</ins><span class="cx"> 
</span><del>-- (instancetype)initWithExpectation:(BOOL)expectation
</del><ins>+- (instancetype)initWithAPIsAvailableExpectation:(BOOL)apisAvailableExpectation canMakePaymentsExpectation:(BOOL)canMakePaymentsExpectation
</ins><span class="cx"> {
</span><span class="cx">     if (!(self = [super init]))
</span><span class="cx">         return nil;
</span><span class="cx"> 
</span><del>-    _expectation = expectation;
</del><ins>+    _apisAvailableExpectation = apisAvailableExpectation;
+    _canMakePaymentsExpectation = canMakePaymentsExpectation;
</ins><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
</span><span class="cx"> {
</span><del>-    EXPECT_EQ(_expectation, [[message.body objectForKey:@"supportsVersion"] boolValue]);
-    EXPECT_EQ(_expectation, [[message.body objectForKey:@"canMakePayments"] boolValue]);
-    EXPECT_EQ(_expectation, [[message.body objectForKey:@"canMakePaymentsWithActiveCard"] boolValue]);
-    EXPECT_EQ(_expectation, [[message.body objectForKey:@"canMakePayment"] boolValue]);
</del><ins>+    EXPECT_EQ(_apisAvailableExpectation, [[message.body objectForKey:@"applePaySessionAvailable"] boolValue]);
+    EXPECT_EQ(_apisAvailableExpectation, [[message.body objectForKey:@"paymentRequestAvailable"] boolValue]);
+    EXPECT_EQ(_canMakePaymentsExpectation, [[message.body objectForKey:@"supportsVersion"] boolValue]);
+    EXPECT_EQ(_canMakePaymentsExpectation, [[message.body objectForKey:@"canMakePayments"] boolValue]);
+    EXPECT_EQ(_canMakePaymentsExpectation, [[message.body objectForKey:@"canMakePaymentsWithActiveCard"] boolValue]);
+    EXPECT_EQ(_canMakePaymentsExpectation, [[message.body objectForKey:@"canMakePayment"] boolValue]);
</ins><span class="cx">     isDone = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -75,7 +79,7 @@
</span><span class="cx"> {
</span><span class="cx">     [TestProtocol registerWithScheme:@"https"];
</span><span class="cx"> 
</span><del>-    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithExpectation:YES]);
</del><ins>+    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithAPIsAvailableExpectation:YES canMakePaymentsExpectation:YES]);
</ins><span class="cx"> 
</span><span class="cx">     WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
</span><span class="cx">     [configuration.userContentController addScriptMessageHandler:messageHandler.get() name:@"testApplePay"];
</span><span class="lines">@@ -88,11 +92,11 @@
</span><span class="cx">     [TestProtocol unregister];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TEST(ApplePay, UserScriptDisablesApplePay)
</del><ins>+TEST(ApplePay, UserScriptAtDocumentStartDisablesApplePay)
</ins><span class="cx"> {
</span><span class="cx">     [TestProtocol registerWithScheme:@"https"];
</span><span class="cx"> 
</span><del>-    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithExpectation:NO]);
</del><ins>+    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithAPIsAvailableExpectation:NO canMakePaymentsExpectation:NO]);
</ins><span class="cx">     auto userScript = adoptNS([[WKUserScript alloc] initWithSource:@"window.wkUserScriptInjected = true" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
</span><span class="cx"> 
</span><span class="cx">     WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
</span><span class="lines">@@ -109,11 +113,32 @@
</span><span class="cx">     [TestProtocol unregister];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(ApplePay, UserScriptAtDocumentEndDisablesApplePay)
+{
+    [TestProtocol registerWithScheme:@"https"];
+    
+    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithAPIsAvailableExpectation:NO canMakePaymentsExpectation:NO]);
+    auto userScript = adoptNS([[WKUserScript alloc] initWithSource:@"window.wkUserScriptInjected = true" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]);
+    
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
+    [configuration.userContentController addUserScript:userScript.get()];
+    [configuration.userContentController addScriptMessageHandler:messageHandler.get() name:@"testApplePay"];
+    
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://bundle-html-file/apple-pay-availability"]]];
+    
+    Util::run(&isDone);
+    
+    EXPECT_EQ(YES, [[webView objectByEvaluatingJavaScript:@"window.wkUserScriptInjected"] boolValue]);
+    
+    [TestProtocol unregister];
+}
+
</ins><span class="cx"> TEST(ApplePay, UserAgentScriptEvaluationDisablesApplePay)
</span><span class="cx"> {
</span><span class="cx">     [TestProtocol registerWithScheme:@"https"];
</span><span class="cx"> 
</span><del>-    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithExpectation:NO]);
</del><ins>+    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithAPIsAvailableExpectation:YES canMakePaymentsExpectation:NO]);
</ins><span class="cx"> 
</span><span class="cx">     WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
</span><span class="cx">     [configuration.userContentController addScriptMessageHandler:messageHandler.get() name:@"testApplePay"];
</span><span class="lines">@@ -130,6 +155,29 @@
</span><span class="cx">     [TestProtocol unregister];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(ApplePay, UserAgentScriptEvaluationDisablesApplePayInExistingObjects)
+{
+    [TestProtocol registerWithScheme:@"https"];
+
+    auto messageHandler = adoptNS([[TestApplePayScriptMessageHandler alloc] initWithAPIsAvailableExpectation:YES canMakePaymentsExpectation:YES]);
+
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
+    [configuration.userContentController addScriptMessageHandler:messageHandler.get() name:@"testApplePay"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://bundle-html-file/apple-pay-availability"]]];
+
+    Util::run(&isDone);
+
+    isDone = false;
+    [messageHandler setCanMakePaymentsExpectation:NO];
+    [webView evaluateJavaScript:@"document.location.hash = '#test'" completionHandler:nil];
+
+    Util::run(&isDone);
+
+    [TestProtocol unregister];
+}
+
</ins><span class="cx"> TEST(ApplePay, ActiveSessionBlocksUserAgentScripts)
</span><span class="cx"> {
</span><span class="cx">     [TestProtocol registerWithScheme:@"https"];
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaapplepayavailabilityhtml"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html (245313 => 245314)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html  2019-05-14 22:44:26 UTC (rev 245313)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/apple-pay-availability.html     2019-05-14 22:50:21 UTC (rev 245314)
</span><span class="lines">@@ -26,27 +26,41 @@
</span><span class="cx">         };
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    window.addEventListener('load', async () => {
</del><ins>+    const eventListener = async () => {
</ins><span class="cx">         internals.mockPaymentCoordinator.supportsUnrestrictedApplePay = false;
</span><span class="cx"> 
</span><ins>+        const applePaySessionAvailable = !!window.ApplePaySession;
+        const paymentRequestAvailable = !!window.PaymentRequest;
+        if (!applePaySessionAvailable || !paymentRequestAvailable) {
+            window.webkit.messageHandlers.testApplePay.postMessage({ applePaySessionAvailable, paymentRequestAvailable });
+            return;
+        }
+
</ins><span class="cx">         const supportsVersion = ApplePaySession.supportsVersion(1);
</span><span class="cx">         const canMakePayments = ApplePaySession.canMakePayments();
</span><span class="cx">         const canMakePaymentsWithActiveCard = await ApplePaySession.canMakePaymentsWithActiveCard('');
</span><span class="cx"> 
</span><del>-        const paymentRequest = new PaymentRequest([applePayMethod()], {
-            total: {
-                label: 'total',
-                amount: { currency: 'USD', value: '0.00' },
-            },
-        });
</del><ins>+        if (!window.wkPaymentRequest) {
+            wkPaymentRequest = new PaymentRequest([applePayMethod()], {
+                total: {
+                    label: 'total',
+                    amount: { currency: 'USD', value: '0.00' },
+                },
+            });
+        }
</ins><span class="cx"> 
</span><del>-        const canMakePayment = await paymentRequest.canMakePayment();
</del><ins>+        const canMakePayment = await wkPaymentRequest.canMakePayment();
</ins><span class="cx"> 
</span><span class="cx">         window.webkit.messageHandlers.testApplePay.postMessage({
</span><ins>+            applePaySessionAvailable,
+            paymentRequestAvailable,
</ins><span class="cx">             supportsVersion,
</span><span class="cx">             canMakePayments,
</span><span class="cx">             canMakePaymentsWithActiveCard,
</span><span class="cx">             canMakePayment,
</span><span class="cx">         });
</span><del>-    });
</del><ins>+    };
+
+    window.addEventListener('load', eventListener);
+    window.addEventListener('hashchange', eventListener);
</ins><span class="cx"> </script>
</span></span></pre>
</div>
</div>

</body>
</html>