PaymentApp: Implement respondWith() in PaymentRequestEvent. (blink side)

The respondWith() method is used by the payment app to provide a
PaymentAppResponse when the payment successfully completes.

Related Spec Link:
  https://w3c.github.io/webpayments-payment-apps-api/#idl-def-paymentrequestevent

See the other CLs in this series:
  [1/3] https://codereview.chromium.org/2715663002/ (RespondWithObserver)
  [2/3] This patch
  [3/3] https://codereview.chromium.org/2718013004/ (content side and test)

BUG=661608
TEST=payment_app_browsertest.cc

Review-Url: https://codereview.chromium.org/2705293010
Cr-Commit-Position: refs/heads/master@{#457841}
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index 102533f..a7c1212 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -474,6 +474,7 @@
                     "payments/BasicCardRequest.idl",
                     "payments/PaymentAppManifest.idl",
                     "payments/PaymentAppOption.idl",
+                    "payments/PaymentAppResponse.idl",
                     "payments/PaymentAppRequest.idl",
                     "payments/PaymentCurrencyAmount.idl",
                     "payments/PaymentDetails.idl",
@@ -849,6 +850,8 @@
   "$blink_modules_output_dir/payments/PaymentAppManifest.h",
   "$blink_modules_output_dir/payments/PaymentAppOption.cpp",
   "$blink_modules_output_dir/payments/PaymentAppOption.h",
+  "$blink_modules_output_dir/payments/PaymentAppResponse.cpp",
+  "$blink_modules_output_dir/payments/PaymentAppResponse.h",
   "$blink_modules_output_dir/payments/PaymentAppRequest.cpp",
   "$blink_modules_output_dir/payments/PaymentAppRequest.h",
   "$blink_modules_output_dir/payments/PaymentCurrencyAmount.cpp",
diff --git a/third_party/WebKit/Source/modules/payments/BUILD.gn b/third_party/WebKit/Source/modules/payments/BUILD.gn
index e2f6fb6..394e709 100644
--- a/third_party/WebKit/Source/modules/payments/BUILD.gn
+++ b/third_party/WebKit/Source/modules/payments/BUILD.gn
@@ -22,6 +22,8 @@
     "PaymentRequest.h",
     "PaymentRequestEvent.cpp",
     "PaymentRequestEvent.h",
+    "PaymentRequestRespondWithObserver.cpp",
+    "PaymentRequestRespondWithObserver.h",
     "PaymentRequestUpdateEvent.cpp",
     "PaymentRequestUpdateEvent.h",
     "PaymentResponse.cpp",
diff --git a/third_party/WebKit/Source/modules/payments/PaymentAppRequestConversion.cpp b/third_party/WebKit/Source/modules/payments/PaymentAppRequestConversion.cpp
index abe0dd5..864bae6f 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentAppRequestConversion.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentAppRequestConversion.cpp
@@ -86,7 +86,13 @@
 PaymentAppRequest PaymentAppRequestConversion::toPaymentAppRequest(
     ScriptState* scriptState,
     const WebPaymentAppRequest& webAppRequest) {
+  DCHECK(scriptState);
+
   PaymentAppRequest appRequest;
+  if (!scriptState->contextIsValid())
+    return appRequest;
+
+  ScriptState::Scope scope(scriptState);
 
   appRequest.setOrigin(webAppRequest.origin);
   HeapVector<PaymentMethodData> methodData;
diff --git a/third_party/WebKit/Source/modules/payments/PaymentAppResponse.idl b/third_party/WebKit/Source/modules/payments/PaymentAppResponse.idl
new file mode 100644
index 0000000..3712e52
--- /dev/null
+++ b/third_party/WebKit/Source/modules/payments/PaymentAppResponse.idl
@@ -0,0 +1,10 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/webpayments-payment-apps-api/#idl-def-paymentappresponse
+
+dictionary PaymentAppResponse {
+    DOMString methodName;
+    object details;
+};
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
index 14fcf1d..cb2c755d 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/payments/PaymentRequestEvent.h"
 
+#include "modules/serviceworkers/RespondWithObserver.h"
 #include "wtf/text/AtomicString.h"
 
 namespace blink {
@@ -11,8 +12,10 @@
 PaymentRequestEvent* PaymentRequestEvent::create(
     const AtomicString& type,
     const PaymentAppRequest& appRequest,
-    WaitUntilObserver* observer) {
-  return new PaymentRequestEvent(type, appRequest, observer);
+    RespondWithObserver* respondWithObserver,
+    WaitUntilObserver* waitUntilObserver) {
+  return new PaymentRequestEvent(type, appRequest, respondWithObserver,
+                                 waitUntilObserver);
 }
 
 PaymentRequestEvent::~PaymentRequestEvent() {}
@@ -25,19 +28,28 @@
   appRequest = m_appRequest;
 }
 
-void PaymentRequestEvent::respondWith(ScriptPromise) {
-  NOTIMPLEMENTED();
+void PaymentRequestEvent::respondWith(ScriptState* scriptState,
+                                      ScriptPromise scriptPromise,
+                                      ExceptionState& exceptionState) {
+  stopImmediatePropagation();
+  if (m_observer) {
+    m_observer->respondWith(scriptState, scriptPromise, exceptionState);
+  }
 }
 
 DEFINE_TRACE(PaymentRequestEvent) {
   visitor->trace(m_appRequest);
+  visitor->trace(m_observer);
   ExtendableEvent::trace(visitor);
 }
 
-PaymentRequestEvent::PaymentRequestEvent(const AtomicString& type,
-                                         const PaymentAppRequest& appRequest,
-                                         WaitUntilObserver* observer)
-    : ExtendableEvent(type, ExtendableEventInit(), observer),
-      m_appRequest(appRequest) {}
+PaymentRequestEvent::PaymentRequestEvent(
+    const AtomicString& type,
+    const PaymentAppRequest& appRequest,
+    RespondWithObserver* respondWithObserver,
+    WaitUntilObserver* waitUntilObserver)
+    : ExtendableEvent(type, ExtendableEventInit(), waitUntilObserver),
+      m_appRequest(appRequest),
+      m_observer(respondWithObserver) {}
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
index 72313677..ea96462 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
@@ -16,6 +16,8 @@
 
 namespace blink {
 
+class RespondWithObserver;
+
 class MODULES_EXPORT PaymentRequestEvent final : public ExtendableEvent {
   DEFINE_WRAPPERTYPEINFO();
   WTF_MAKE_NONCOPYABLE(PaymentRequestEvent);
@@ -23,21 +25,24 @@
  public:
   static PaymentRequestEvent* create(const AtomicString& type,
                                      const PaymentAppRequest&,
+                                     RespondWithObserver*,
                                      WaitUntilObserver*);
   ~PaymentRequestEvent() override;
 
   const AtomicString& interfaceName() const override;
 
   void appRequest(PaymentAppRequest&) const;
-  void respondWith(ScriptPromise);
+  void respondWith(ScriptState*, ScriptPromise, ExceptionState&);
 
   DECLARE_VIRTUAL_TRACE();
 
  private:
   PaymentRequestEvent(const AtomicString& type,
                       const PaymentAppRequest&,
+                      RespondWithObserver*,
                       WaitUntilObserver*);
   PaymentAppRequest m_appRequest;
+  Member<RespondWithObserver> m_observer;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
index bea9ebd2..01cf8e5 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
@@ -9,5 +9,5 @@
     Exposed=ServiceWorker
 ] interface PaymentRequestEvent : ExtendableEvent {
     readonly attribute PaymentAppRequest appRequest;
-    void respondWith(Promise<PaymentResponse> response);
+    [CallWith=ScriptState, RaisesException] void respondWith(Promise<PaymentResponse> response);
 };
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.cpp
new file mode 100644
index 0000000..2e47c7b
--- /dev/null
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.cpp
@@ -0,0 +1,131 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/payments/PaymentRequestRespondWithObserver.h"
+
+#include <v8.h>
+#include "bindings/core/v8/ScriptValue.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/modules/v8/V8PaymentAppResponse.h"
+#include "core/dom/ExecutionContext.h"
+#include "core/inspector/ConsoleMessage.h"
+#include "modules/payments/PaymentAppResponse.h"
+#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
+#include "modules/serviceworkers/WaitUntilObserver.h"
+#include "public/platform/modules/payments/WebPaymentAppResponse.h"
+
+namespace blink {
+namespace {
+
+// Returns the error message to let the developer know about the reason of the
+// unusual failures.
+const String getMessageForResponseError(WebServiceWorkerResponseError error) {
+  String errorMessage =
+      "The respondWith() was rejected in PaymentRequestEvent: ";
+  switch (error) {
+    case WebServiceWorkerResponseErrorPromiseRejected:
+      errorMessage = errorMessage + "the promise was rejected.";
+      break;
+    case WebServiceWorkerResponseErrorDefaultPrevented:
+      errorMessage =
+          errorMessage +
+          "preventDefault() was called without calling respondWith().";
+      break;
+    case WebServiceWorkerResponseErrorNoV8Instance:
+      errorMessage = errorMessage +
+                     "an object that was not a PaymentResponse was passed to "
+                     "respondWith().";
+      break;
+    case WebServiceWorkerResponseErrorResponseTypeError:
+      errorMessage = errorMessage +
+                     "the promise was resolved with an error response object.";
+      break;
+    case WebServiceWorkerResponseErrorUnknown:
+      errorMessage = errorMessage + "an unexpected error occurred.";
+      break;
+    case WebServiceWorkerResponseErrorResponseTypeOpaque:
+    case WebServiceWorkerResponseErrorResponseTypeNotBasicOrDefault:
+    case WebServiceWorkerResponseErrorBodyUsed:
+    case WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest:
+    case WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect:
+    case WebServiceWorkerResponseErrorBodyLocked:
+    case WebServiceWorkerResponseErrorNoForeignFetchResponse:
+    case WebServiceWorkerResponseErrorForeignFetchHeadersWithoutOrigin:
+    case WebServiceWorkerResponseErrorForeignFetchMismatchedOrigin:
+    case WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest:
+      NOTREACHED();
+      errorMessage = errorMessage + "an unexpected error occurred.";
+      break;
+  }
+  return errorMessage;
+}
+
+}  // namespace
+
+PaymentRequestRespondWithObserver::~PaymentRequestRespondWithObserver() {}
+
+PaymentRequestRespondWithObserver* PaymentRequestRespondWithObserver::create(
+    ExecutionContext* context,
+    int eventID,
+    WaitUntilObserver* observer) {
+  return new PaymentRequestRespondWithObserver(context, eventID, observer);
+}
+
+void PaymentRequestRespondWithObserver::onResponseRejected(
+    WebServiceWorkerResponseError error) {
+  DCHECK(getExecutionContext());
+  getExecutionContext()->addConsoleMessage(ConsoleMessage::create(
+      JSMessageSource, WarningMessageLevel, getMessageForResponseError(error)));
+
+  WebPaymentAppResponse webData;
+  ServiceWorkerGlobalScopeClient::from(getExecutionContext())
+      ->respondToPaymentRequestEvent(m_eventID, webData, m_eventDispatchTime);
+}
+
+void PaymentRequestRespondWithObserver::onResponseFulfilled(
+    const ScriptValue& value) {
+  DCHECK(getExecutionContext());
+  ExceptionState exceptionState(value.isolate(), ExceptionState::UnknownContext,
+                                "PaymentRequestEvent", "respondWith");
+  PaymentAppResponse response = ScriptValue::to<PaymentAppResponse>(
+      toIsolate(getExecutionContext()), value, exceptionState);
+  if (exceptionState.hadException()) {
+    exceptionState.clearException();
+    onResponseRejected(WebServiceWorkerResponseErrorNoV8Instance);
+    return;
+  }
+
+  WebPaymentAppResponse webData;
+  webData.methodName = response.methodName();
+
+  v8::Local<v8::String> detailsValue;
+  if (!v8::JSON::Stringify(response.details().context(),
+                           response.details().v8Value().As<v8::Object>())
+           .ToLocal(&detailsValue)) {
+    onResponseRejected(WebServiceWorkerResponseErrorUnknown);
+    return;
+  }
+  webData.stringifiedDetails = toCoreString(detailsValue);
+  ServiceWorkerGlobalScopeClient::from(getExecutionContext())
+      ->respondToPaymentRequestEvent(m_eventID, webData, m_eventDispatchTime);
+}
+
+void PaymentRequestRespondWithObserver::onNoResponse() {
+  DCHECK(getExecutionContext());
+  ServiceWorkerGlobalScopeClient::from(getExecutionContext())
+      ->respondToPaymentRequestEvent(m_eventID, WebPaymentAppResponse(),
+                                     m_eventDispatchTime);
+}
+
+PaymentRequestRespondWithObserver::PaymentRequestRespondWithObserver(
+    ExecutionContext* context,
+    int eventID,
+    WaitUntilObserver* observer)
+    : RespondWithObserver(context, eventID, observer) {}
+
+DEFINE_TRACE(PaymentRequestRespondWithObserver) {
+  RespondWithObserver::trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.h b/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.h
new file mode 100644
index 0000000..f29d57df
--- /dev/null
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestRespondWithObserver.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PaymentRequestRespondWithObserver_h
+#define PaymentRequestRespondWithObserver_h
+
+#include "modules/ModulesExport.h"
+#include "modules/serviceworkers/RespondWithObserver.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerResponseError.h"
+
+namespace blink {
+
+class ExecutionContext;
+class ScriptValue;
+class WaitUntilObserver;
+
+// This class observes the service worker's handling of a PaymentRequestEvent
+// and notifies the client.
+class MODULES_EXPORT PaymentRequestRespondWithObserver final
+    : public RespondWithObserver {
+ public:
+  virtual ~PaymentRequestRespondWithObserver();
+
+  static PaymentRequestRespondWithObserver* create(ExecutionContext*,
+                                                   int eventID,
+                                                   WaitUntilObserver*);
+
+  void onResponseRejected(WebServiceWorkerResponseError) override;
+  void onResponseFulfilled(const ScriptValue&) override;
+  void onNoResponse() override;
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  PaymentRequestRespondWithObserver(ExecutionContext*,
+                                    int eventID,
+                                    WaitUntilObserver*);
+};
+
+}  // namespace blink
+
+#endif  // PaymentRequestRespondWithObserver_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
index d9492aed..5e7e435 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
@@ -45,6 +45,7 @@
 
 namespace blink {
 
+struct WebPaymentAppResponse;
 struct WebServiceWorkerClientQueryOptions;
 class ExecutionContext;
 class WebServiceWorkerResponse;
@@ -87,6 +88,9 @@
   virtual void respondToFetchEvent(int fetchEventID,
                                    const WebServiceWorkerResponse&,
                                    double eventDispatchTime) = 0;
+  virtual void respondToPaymentRequestEvent(int eventID,
+                                            const WebPaymentAppResponse&,
+                                            double eventDispatchTime) = 0;
   virtual void didHandleFetchEvent(int fetchEventID,
                                    WebServiceWorkerEventResult,
                                    double eventDispatchTime) = 0;
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
index 907f36b..8aaf020 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
@@ -30,12 +30,13 @@
 
 #include "web/ServiceWorkerGlobalScopeClientImpl.h"
 
-#include "modules/fetch/Response.h"
-#include "public/platform/WebURL.h"
-#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
-#include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
 #include <memory>
 #include <utility>
+#include "modules/fetch/Response.h"
+#include "public/platform/WebURL.h"
+#include "public/platform/modules/payments/WebPaymentAppResponse.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
+#include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
 
 namespace blink {
 
@@ -99,6 +100,13 @@
   m_client.respondToFetchEvent(fetchEventID, eventDispatchTime);
 }
 
+void ServiceWorkerGlobalScopeClientImpl::respondToPaymentRequestEvent(
+    int eventID,
+    const WebPaymentAppResponse& response,
+    double eventDispatchTime) {
+  m_client.respondToPaymentRequestEvent(eventID, response, eventDispatchTime);
+}
+
 void ServiceWorkerGlobalScopeClientImpl::respondToFetchEvent(
     int fetchEventID,
     const WebServiceWorkerResponse& response,
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
index 93ca3a2..84de4059 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
@@ -38,6 +38,7 @@
 
 namespace blink {
 
+struct WebPaymentAppResponse;
 class WebServiceWorkerContextClient;
 class WebServiceWorkerResponse;
 class WebURL;
@@ -72,6 +73,9 @@
   void respondToFetchEvent(int responseID,
                            const WebServiceWorkerResponse&,
                            double eventDispatchTime) override;
+  void respondToPaymentRequestEvent(int responseID,
+                                    const WebPaymentAppResponse&,
+                                    double eventDispatchTime) override;
   void didHandleFetchEvent(int fetchEventID,
                            WebServiceWorkerEventResult,
                            double eventDispatchTime) override;
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
index b64b6fc..5896576 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
@@ -50,6 +50,7 @@
 #include "modules/payments/PaymentAppRequest.h"
 #include "modules/payments/PaymentAppRequestConversion.h"
 #include "modules/payments/PaymentRequestEvent.h"
+#include "modules/payments/PaymentRequestRespondWithObserver.h"
 #include "modules/push_messaging/PushEvent.h"
 #include "modules/push_messaging/PushMessageData.h"
 #include "modules/serviceworkers/ExtendableEvent.h"
@@ -341,15 +342,27 @@
 void ServiceWorkerGlobalScopeProxy::dispatchPaymentRequestEvent(
     int eventID,
     const WebPaymentAppRequest& webAppRequest) {
-  WaitUntilObserver* observer = WaitUntilObserver::create(
+  WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(
       workerGlobalScope(), WaitUntilObserver::PaymentRequest, eventID);
+  RespondWithObserver* respondWithObserver =
+      PaymentRequestRespondWithObserver::create(workerGlobalScope(), eventID,
+                                                waitUntilObserver);
+
   Event* event = PaymentRequestEvent::create(
       EventTypeNames::paymentrequest,
       PaymentAppRequestConversion::toPaymentAppRequest(
           workerGlobalScope()->scriptController()->getScriptState(),
           webAppRequest),
-      observer);
-  workerGlobalScope()->dispatchExtendableEvent(event, observer);
+      respondWithObserver, waitUntilObserver);
+
+  waitUntilObserver->willDispatchEvent();
+  respondWithObserver->willDispatchEvent();
+  DispatchEventResult dispatchResult =
+      workerGlobalScope()->dispatchEvent(event);
+  respondWithObserver->didDispatchEvent(dispatchResult);
+  // false is okay because waitUntil for payment request event doesn't care
+  // about the promise rejection or an uncaught runtime script error.
+  waitUntilObserver->didDispatchEvent(false /* errorOccurred */);
 }
 
 bool ServiceWorkerGlobalScopeProxy::hasFetchEventHandler() {
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index a1ae793..86feba9 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -346,6 +346,7 @@
     "platform/modules/notifications/WebNotificationManager.h",
     "platform/modules/notifications/WebNotificationResources.h",
     "platform/modules/payments/WebPaymentAppRequest.h",
+    "platform/modules/payments/WebPaymentAppResponse.h",
     "platform/modules/payments/WebPaymentCurrencyAmount.h",
     "platform/modules/payments/WebPaymentDetailsModifier.h",
     "platform/modules/payments/WebPaymentItem.h",
diff --git a/third_party/WebKit/public/platform/modules/payments/WebPaymentAppResponse.h b/third_party/WebKit/public/platform/modules/payments/WebPaymentAppResponse.h
new file mode 100644
index 0000000..51ab72c
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/payments/WebPaymentAppResponse.h
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebPaymentAppResponse_h
+#define WebPaymentAppResponse_h
+
+#include "public/platform/WebString.h"
+
+namespace blink {
+
+// https://w3c.github.io/webpayments-payment-apps-api/#idl-def-paymentappresponse
+struct WebPaymentAppResponse {
+  WebString methodName;
+  WebString stringifiedDetails;
+};
+
+}  // namespace blink
+
+#endif  // WebPaymentAppResponse_h
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
index c272ec9b..d361c0a 100644
--- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
+++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
@@ -44,6 +44,7 @@
 
 namespace blink {
 
+struct WebPaymentAppResponse;
 struct WebServiceWorkerClientQueryOptions;
 class WebServiceWorkerContextProxy;
 class WebServiceWorkerNetworkProvider;
@@ -152,6 +153,10 @@
   virtual void respondToFetchEvent(int fetchEventID,
                                    const WebServiceWorkerResponse& response,
                                    double eventDispatchTime) {}
+  virtual void respondToPaymentRequestEvent(
+      int eventId,
+      const WebPaymentAppResponse& response,
+      double eventDispatchTime) {}
   virtual void didHandleFetchEvent(int fetchEventID,
                                    WebServiceWorkerEventResult result,
                                    double eventDispatchTime) {}