Commit bba70ff1 authored by Rouslan Solomakhin's avatar Rouslan Solomakhin Committed by Commit Bot

[Payment Handler] No cross-origin iframe install by default.

Before this patch, any iframe could install a Payment Handler by calling
`paymentManager.instruments.set()`.

This patch checks for the feature policy "payment" before allowing any
operations on `paymentManager.instruments`.

After this patch, a cross-origin iframe will reject all operations on
`paymentManager.instruments` by default. The parent context can
explicitly allow the iframe to use the Payment Handler API through
feature policy. This can be accomplished via the iframe attribute
`allow="payment"`, for example. Note that the same feature policy
controls access to Payment Request API as well.

Discussion:
https://github.com/w3c/payment-handler/issues/281

Spec change:
https://github.com/w3c/payment-handler/pull/282

Payment Handlers are behind a flag:
chrome://flags/#service-worker-payment-apps

Manual test:
https://rsolomakhin.github.io/pr/apps/iframe/

Bug: 828948
Change-Id: I0259555692fa0b215d3700c233b3687724e665cb
Reviewed-on: https://chromium-review.googlesource.com/1005275
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarGanggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550629}
parent 5d642a3d
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <utility> #include <utility>
#include "base/location.h" #include "base/location.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/modules/manifest/manifest.mojom-blink.h" #include "third_party/blink/public/platform/modules/manifest/manifest.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_feature.mojom-blink.h" #include "third_party/blink/public/platform/web_feature.mojom-blink.h"
...@@ -17,6 +19,7 @@ ...@@ -17,6 +19,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/frame.h" #include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/frame/use_counter.h"
...@@ -74,6 +77,21 @@ bool rejectError(ScriptPromiseResolver* resolver, ...@@ -74,6 +77,21 @@ bool rejectError(ScriptPromiseResolver* resolver,
return false; return false;
} }
bool AllowedToUsePaymentFeatures(ScriptState* script_state) {
return ExecutionContext::From(script_state)
->GetSecurityContext()
.GetFeaturePolicy()
->IsFeatureEnabled(mojom::FeaturePolicyFeature::kPayment);
}
ScriptPromise RejectNotAllowedToUsePaymentFeatures(ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state, DOMException::Create(
kSecurityError,
"Must be in a top-level browsing context or an iframe "
"needs to specify allow=\"payment\" explicitly"));
}
} // namespace } // namespace
PaymentInstruments::PaymentInstruments( PaymentInstruments::PaymentInstruments(
...@@ -83,6 +101,9 @@ PaymentInstruments::PaymentInstruments( ...@@ -83,6 +101,9 @@ PaymentInstruments::PaymentInstruments(
ScriptPromise PaymentInstruments::deleteInstrument( ScriptPromise PaymentInstruments::deleteInstrument(
ScriptState* script_state, ScriptState* script_state,
const String& instrument_key) { const String& instrument_key) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
...@@ -101,6 +122,9 @@ ScriptPromise PaymentInstruments::deleteInstrument( ...@@ -101,6 +122,9 @@ ScriptPromise PaymentInstruments::deleteInstrument(
ScriptPromise PaymentInstruments::get(ScriptState* script_state, ScriptPromise PaymentInstruments::get(ScriptState* script_state,
const String& instrument_key) { const String& instrument_key) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
...@@ -118,6 +142,9 @@ ScriptPromise PaymentInstruments::get(ScriptState* script_state, ...@@ -118,6 +142,9 @@ ScriptPromise PaymentInstruments::get(ScriptState* script_state,
} }
ScriptPromise PaymentInstruments::keys(ScriptState* script_state) { ScriptPromise PaymentInstruments::keys(ScriptState* script_state) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
...@@ -135,6 +162,9 @@ ScriptPromise PaymentInstruments::keys(ScriptState* script_state) { ...@@ -135,6 +162,9 @@ ScriptPromise PaymentInstruments::keys(ScriptState* script_state) {
ScriptPromise PaymentInstruments::has(ScriptState* script_state, ScriptPromise PaymentInstruments::has(ScriptState* script_state,
const String& instrument_key) { const String& instrument_key) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
...@@ -155,6 +185,9 @@ ScriptPromise PaymentInstruments::set(ScriptState* script_state, ...@@ -155,6 +185,9 @@ ScriptPromise PaymentInstruments::set(ScriptState* script_state,
const String& instrument_key, const String& instrument_key,
const PaymentInstrument& details, const PaymentInstrument& details,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
...@@ -179,6 +212,9 @@ ScriptPromise PaymentInstruments::set(ScriptState* script_state, ...@@ -179,6 +212,9 @@ ScriptPromise PaymentInstruments::set(ScriptState* script_state,
} }
ScriptPromise PaymentInstruments::clear(ScriptState* script_state) { ScriptPromise PaymentInstruments::clear(ScriptState* script_state) {
if (!AllowedToUsePaymentFeatures(script_state))
return RejectNotAllowedToUsePaymentFeatures(script_state);
if (!manager_.is_bound()) { if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException( return ScriptPromise::RejectWithDOMException(
script_state, script_state,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment