Commit f20e3bf7 authored by Glen Robertson's avatar Glen Robertson Committed by Commit Bot

digital-goods: Add mojo interface to get a DigitalGoods impl object.

DigitalGoodsFactory was split up to DigitalGoodsFactory{Factory,Impl}.
Allows the impl on the other side of the mojo interface to determine
whether the DigitalGoods API should be available. Previously the caller
could not distinguish a successful vs failed attempt to get a
DigitalGoods impl over mojo.

Bug: 1131747
Change-Id: Ib21b72d27522a101ceaf2430e7130069a149d576
Fixed: 1131747
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2426150Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarGlen Robertson <glenrob@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Commit-Queue: Glen Robertson <glenrob@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812599}
parent 07271aea
......@@ -183,7 +183,8 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/browserservices/VerificationResultStore.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsAdapter.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsConverter.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactory.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryFactory.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryImpl.java",
"java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsImpl.java",
"java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java",
"java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappGeolocationBridge.java",
......
......@@ -77,7 +77,7 @@ specific_include_rules = {
"QualityEnforcer\.java": [
"+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
],
"DigitalGoodsFactory\.java": [
"DigitalGoodsFactoryImpl\.java": [
"+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
],
"TwaFinishHandler\.java": [
......
......@@ -151,6 +151,7 @@ public class DigitalGoodsConverter {
case PLAY_BILLING_ITEM_UNAVAILABLE:
return BillingResponseCode.ITEM_UNAVAILABLE;
default:
Log.w(TAG, "Unexpected response code: " + responseCode);
return BillingResponseCode.ERROR;
}
}
......
// Copyright 2020 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.
package org.chromium.chrome.browser.browserservices.digitalgoods;
import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.payments.mojom.DigitalGoodsFactory;
import org.chromium.services.service_manager.InterfaceFactory;
/**
* A factory to produce instances of the mojo {@link DigitalGoodsFactory} interface.
*/
public class DigitalGoodsFactoryFactory implements InterfaceFactory<DigitalGoodsFactory> {
private final RenderFrameHost mRenderFrameHost;
public DigitalGoodsFactoryFactory(RenderFrameHost renderFrameHost) {
mRenderFrameHost = renderFrameHost;
}
@Override
public DigitalGoodsFactory createImpl() {
return new DigitalGoodsFactoryImpl(mRenderFrameHost);
}
}
......@@ -9,17 +9,21 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.components.payments.MethodStrings;
import org.chromium.components.payments.PaymentFeatureList;
import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsStatics;
import org.chromium.mojo.system.MojoException;
import org.chromium.payments.mojom.CreateDigitalGoodsResponseCode;
import org.chromium.payments.mojom.DigitalGoods;
import org.chromium.services.service_manager.InterfaceFactory;
import org.chromium.payments.mojom.DigitalGoodsFactory;
import org.chromium.payments.mojom.DigitalGoodsFactory.CreateDigitalGoodsResponse;
/**
* A factory to create instances of the {@link DigitalGoods} mojo interface.
* An implementation of the mojo {@link DigitalGoodsFactory} interface.
*/
public class DigitalGoodsFactory implements InterfaceFactory<DigitalGoods> {
public class DigitalGoodsFactoryImpl implements DigitalGoodsFactory {
private static DigitalGoods sImplForTesting;
private final RenderFrameHost mRenderFrameHost;
......@@ -31,30 +35,58 @@ public class DigitalGoodsFactory implements InterfaceFactory<DigitalGoods> {
sImplForTesting = impl;
}
public DigitalGoodsFactory(RenderFrameHost renderFrameHost) {
public DigitalGoodsFactoryImpl(RenderFrameHost renderFrameHost) {
mRenderFrameHost = renderFrameHost;
mDigitalGoodsDelegate = mRenderFrameHost::getLastCommittedURL;
mAdapter = new DigitalGoodsAdapter(
ChromeApplication.getComponent().resolveTrustedWebActivityClient());
}
@Override
public DigitalGoods createImpl() {
if (sImplForTesting != null) return sImplForTesting;
private int getResponseCode(String paymentMethod) {
if (!PaymentFeatureList.isEnabled(PaymentFeatureList.WEB_PAYMENTS_APP_STORE_BILLING)) {
return null;
return CreateDigitalGoodsResponseCode.UNSUPPORTED_CONTEXT;
}
// Ensure that the DigitalGoodsImpl is only created if we're in a TWA and on its verified
// origin.
WebContents wc = WebContentsStatics.fromRenderFrameHost(mRenderFrameHost);
ChromeActivity<?> activity = ChromeActivity.fromWebContents(wc);
if (!(activity instanceof CustomTabActivity)) return null;
if (!(activity instanceof CustomTabActivity)) {
return CreateDigitalGoodsResponseCode.UNSUPPORTED_CONTEXT;
}
CustomTabActivity cta = (CustomTabActivity) activity;
if (!cta.isInTwaMode()) return null;
if (!cta.isInTwaMode()) {
return CreateDigitalGoodsResponseCode.UNSUPPORTED_CONTEXT;
}
if (!MethodStrings.GOOGLE_PLAY_BILLING.equals(paymentMethod)) {
return CreateDigitalGoodsResponseCode.UNSUPPORTED_PAYMENT_METHOD;
}
// TODO(peconn): Add a test for this.
return new DigitalGoodsImpl(mAdapter, mDigitalGoodsDelegate);
return CreateDigitalGoodsResponseCode.OK;
}
@Override
public void createDigitalGoods(String paymentMethod, CreateDigitalGoodsResponse callback) {
if (sImplForTesting != null) {
callback.call(CreateDigitalGoodsResponseCode.OK, sImplForTesting);
return;
}
int code = getResponseCode(paymentMethod);
CreateDigitalGoodsResponseCode.validate(code);
if (code == CreateDigitalGoodsResponseCode.OK) {
callback.call(code, new DigitalGoodsImpl(mAdapter, mDigitalGoodsDelegate));
} else {
callback.call(code, null);
}
}
@Override
public void close() {}
@Override
public void onConnectionError(MojoException e) {}
}
......@@ -9,8 +9,13 @@ Android APIs are the source of truth for information such as price.
## Code
* `DigitalGoodsImpl` implements the `DigitalGoods` mojo API and is where
requests come from. It is created by the `DigitalGoodsFactory`.
* `DigitalGoodsImpl` implements the `DigitalGoods` mojo API, which handles
requests from JavaScript. It is created by the `DigitalGoodsFactoryImpl`.
* `DigitalGoodsFactoryImpl` implements the `DigitalGoodsFactory` mojo API, which
handles requests for new `DigitalGoods` instances. It is created by the
`DigitalGoodsFactoryFactory`. This extra indirection allows the
`DigitalGoodsFactory` to report success/failure when creating a `DigitalGoods`
instance, which would not be possible if instantiating it directly.
* `TrustedWebActivityClient` is the class that talks to Trusted Web Activities.
* `DigitalGoodsAdapter` sits between `DigitalGoodsImpl` and
`TrustedWebActivityClient`, transforming between appropriate data types.
......
......@@ -6,7 +6,7 @@ package org.chromium.chrome.browser.mojo;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.blink.mojom.Authenticator;
import org.chromium.chrome.browser.browserservices.digitalgoods.DigitalGoodsFactory;
import org.chromium.chrome.browser.browserservices.digitalgoods.DigitalGoodsFactoryFactory;
import org.chromium.chrome.browser.installedapp.InstalledAppProviderFactory;
import org.chromium.chrome.browser.payments.PaymentRequestFactory;
import org.chromium.chrome.browser.webauth.AuthenticatorFactory;
......@@ -15,7 +15,7 @@ import org.chromium.content_public.browser.InterfaceRegistrar;
import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.WebContents;
import org.chromium.installedapp.mojom.InstalledAppProvider;
import org.chromium.payments.mojom.DigitalGoods;
import org.chromium.payments.mojom.DigitalGoodsFactory;
import org.chromium.payments.mojom.PaymentRequest;
import org.chromium.services.service_manager.InterfaceRegistry;
import org.chromium.webshare.mojom.ShareService;
......@@ -49,7 +49,8 @@ class ChromeInterfaceRegistrar {
registry.addInterface(
InstalledAppProvider.MANAGER, new InstalledAppProviderFactory(renderFrameHost));
registry.addInterface(Authenticator.MANAGER, new AuthenticatorFactory(renderFrameHost));
registry.addInterface(DigitalGoods.MANAGER, new DigitalGoodsFactory(renderFrameHost));
registry.addInterface(
DigitalGoodsFactory.MANAGER, new DigitalGoodsFactoryFactory(renderFrameHost));
}
}
}
......@@ -91,13 +91,13 @@ public class DigitalGoodsTest {
/**
* Test that calling methods in JavaScript in the page gets correctly plumbed through to
* DigitalGoodsFactory.
* DigitalGoodsFactoryImpl.
*/
@Test
@MediumTest
public void javaImplConnected() throws TimeoutException {
FakeDigitalGoods fake = new FakeDigitalGoods();
DigitalGoodsFactory.setDigitalGoodsForTesting(fake);
DigitalGoodsFactoryImpl.setDigitalGoodsForTesting(fake);
fake.addItem("id1", "Item 1", "desc", "GBP", "10");
......@@ -144,7 +144,7 @@ public class DigitalGoodsTest {
@Test
@MediumTest
public void jsToTwaConnected() throws TimeoutException {
DigitalGoodsFactory.setDigitalGoodsForTesting(createFixedDigitalGoods());
DigitalGoodsFactoryImpl.setDigitalGoodsForTesting(createFixedDigitalGoods());
// Note: The response code much be 0 for success otherwise it doesn't propagate through to
// JS.
......@@ -166,7 +166,7 @@ public class DigitalGoodsTest {
@Test
@MediumTest
public void acknowledge() throws TimeoutException {
DigitalGoodsFactory.setDigitalGoodsForTesting(createFixedDigitalGoods());
DigitalGoodsFactoryImpl.setDigitalGoodsForTesting(createFixedDigitalGoods());
setTwaServiceResponse(RESPONSE_ACKNOWLEDGE, createAcknowledgeResponseBundle(0));
......@@ -182,7 +182,7 @@ public class DigitalGoodsTest {
@Test
@MediumTest
public void acknowledge_failsOnNonZeroResponse() throws TimeoutException {
DigitalGoodsFactory.setDigitalGoodsForTesting(createFixedDigitalGoods());
DigitalGoodsFactoryImpl.setDigitalGoodsForTesting(createFixedDigitalGoods());
setTwaServiceResponse(RESPONSE_ACKNOWLEDGE, createAcknowledgeResponseBundle(1));
......
......@@ -498,8 +498,8 @@ void PopulateChromeFrameBinders(
#if defined(OS_ANDROID)
map->Add<blink::mojom::InstalledAppProvider>(base::BindRepeating(
&ForwardToJavaFrame<blink::mojom::InstalledAppProvider>));
map->Add<payments::mojom::DigitalGoods>(base::BindRepeating(
&ForwardToJavaFrame<payments::mojom::DigitalGoods>));
map->Add<payments::mojom::DigitalGoodsFactory>(base::BindRepeating(
&ForwardToJavaFrame<payments::mojom::DigitalGoodsFactory>));
#if defined(BROWSER_MEDIA_CONTROLS_MENU)
map->Add<blink::mojom::MediaControlsMenuHost>(base::BindRepeating(
&ForwardToJavaFrame<blink::mojom::MediaControlsMenuHost>));
......
......@@ -23,8 +23,17 @@ interface DigitalGoods {
=> (BillingResponseCode code);
};
// TODO(crbug.com/1061503): Narrow down this list as discussions settle on
// https://github.com/WICG/digital-goods/blob/master/explainer.md
// Allow the renderer to request a |DigitalGoods| instance. DigitalGoods
// instances must be created via this factory to allow the backend to validate
// the current context.
interface DigitalGoodsFactory {
// Creates a DigitalGoods instance. The |digital_goods| is non-null iff
// |code| == kOk.
CreateDigitalGoods(string payment_method)
=> (CreateDigitalGoodsResponseCode code,
pending_remote<DigitalGoods>? digital_goods);
};
enum BillingResponseCode {
kOk,
kError,
......@@ -41,3 +50,10 @@ struct ItemDetails {
string description;
PaymentCurrencyAmount price;
};
enum CreateDigitalGoodsResponseCode {
kOk,
kError,
kUnsupportedPaymentMethod,
kUnsupportedContext,
};
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "third_party/blink/renderer/modules/payments/goods/digital_goods_service.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
......@@ -43,9 +45,10 @@ void OnAcknowledgeResponse(ScriptPromiseResolver* resolver,
} // namespace
DigitalGoodsService::DigitalGoodsService(ExecutionContext* context) {
context->GetBrowserInterfaceBroker().GetInterface(
mojo_service_.BindNewPipeAndPassReceiver());
DigitalGoodsService::DigitalGoodsService(
mojo::PendingRemote<payments::mojom::blink::DigitalGoods> pending_remote) {
DCHECK(pending_remote.is_valid());
mojo_service_.Bind(std::move(pending_remote));
DCHECK(mojo_service_);
}
......
......@@ -11,7 +11,6 @@
namespace blink {
class ExecutionContext;
class ScriptState;
class Visitor;
......@@ -19,7 +18,8 @@ class DigitalGoodsService final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
explicit DigitalGoodsService(ExecutionContext* context);
explicit DigitalGoodsService(
mojo::PendingRemote<payments::mojom::blink::DigitalGoods> pending_remote);
~DigitalGoodsService() override;
// IDL Interface:
......
......@@ -9,9 +9,11 @@
namespace mojo {
blink::ItemDetails*
TypeConverter<blink::ItemDetails*, payments::mojom::blink::ItemDetailsPtr>::
Convert(const payments::mojom::blink::ItemDetailsPtr& input) {
using payments::mojom::blink::BillingResponseCode;
using payments::mojom::blink::ItemDetailsPtr;
blink::ItemDetails* TypeConverter<blink::ItemDetails*, ItemDetailsPtr>::Convert(
const ItemDetailsPtr& input) {
if (!input)
return nullptr;
blink::ItemDetails* output = blink::ItemDetails::Create();
......@@ -23,26 +25,24 @@ TypeConverter<blink::ItemDetails*, payments::mojom::blink::ItemDetailsPtr>::
return output;
}
WTF::String
TypeConverter<WTF::String, payments::mojom::blink::BillingResponseCode>::
Convert(const payments::mojom::blink::BillingResponseCode& input) {
WTF::String TypeConverter<WTF::String, BillingResponseCode>::Convert(
const BillingResponseCode& input) {
switch (input) {
case payments::mojom::blink::BillingResponseCode::kOk:
case BillingResponseCode::kOk:
return "ok";
case payments::mojom::blink::BillingResponseCode::kError:
case BillingResponseCode::kError:
return "error";
case payments::mojom::blink::BillingResponseCode::kItemAlreadyOwned:
case BillingResponseCode::kItemAlreadyOwned:
return "itemAlreadyOwned";
case payments::mojom::blink::BillingResponseCode::kItemNotOwned:
case BillingResponseCode::kItemNotOwned:
return "itemNotOwned";
case payments::mojom::blink::BillingResponseCode::kItemUnavailable:
case BillingResponseCode::kItemUnavailable:
return "itemUnavailable";
case payments::mojom::blink::BillingResponseCode::kClientAppUnavailable:
case BillingResponseCode::kClientAppUnavailable:
return "clientAppUnavailable";
case payments::mojom::blink::BillingResponseCode::kClientAppError:
case BillingResponseCode::kClientAppError:
return "clientAppError";
}
NOTREACHED();
}
......
......@@ -4,17 +4,39 @@
#include "third_party/blink/renderer/modules/payments/goods/dom_window_digital_goods.h"
#include <utility>
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/modules/payments/goods/digital_goods_service.h"
namespace blink {
namespace {
using payments::mojom::blink::CreateDigitalGoodsResponseCode;
const char known_payment_method_[] = "https://play.google.com/billing";
} // namespace
void OnCreateDigitalGoodsResponse(
ScriptPromiseResolver* resolver,
CreateDigitalGoodsResponseCode code,
mojo::PendingRemote<payments::mojom::blink::DigitalGoods> pending_remote) {
if (code != CreateDigitalGoodsResponseCode::kOk) {
DCHECK(!pending_remote);
DVLOG(1) << "CreateDigitalGoodsResponseCode " << code;
resolver->Resolve();
return;
}
DCHECK(pending_remote);
namespace blink {
auto* digital_goods_service_ =
MakeGarbageCollected<DigitalGoodsService>(std::move(pending_remote));
resolver->Resolve(digital_goods_service_);
}
} // namespace
const char DOMWindowDigitalGoods::kSupplementName[] = "DOMWindowDigitalGoods";
......@@ -32,26 +54,31 @@ ScriptPromise DOMWindowDigitalGoods::GetDigitalGoodsService(
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
auto promise = resolver->Promise();
// TODO (crbug.com/1061503): Enable JS to connect to various payment method
// backends. For now, just connect to one known backend and check the URL is
// correct for that payment method.
if (payment_method.IsEmpty()) {
resolver->Resolve();
return promise;
}
if (payment_method != known_payment_method_) {
resolver->Resolve();
return promise;
}
if (!digital_goods_service_) {
digital_goods_service_ = MakeGarbageCollected<DigitalGoodsService>(
ExecutionContext::From(script_state));
// TODO: Bind only on platforms where an implementation exists.
if (!mojo_service_) {
ExecutionContext::From(script_state)
->GetBrowserInterfaceBroker()
.GetInterface(mojo_service_.BindNewPipeAndPassReceiver());
}
resolver->Resolve(digital_goods_service_);
mojo_service_->CreateDigitalGoods(
payment_method,
WTF::Bind(&OnCreateDigitalGoodsResponse, WrapPersistent(resolver)));
return promise;
}
void DOMWindowDigitalGoods::Trace(Visitor* visitor) const {
Supplement<LocalDOMWindow>::Trace(visitor);
visitor->Trace(digital_goods_service_);
}
// static
......
......@@ -5,12 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_GOODS_DOM_WINDOW_DIGITAL_GOODS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_GOODS_DOM_WINDOW_DIGITAL_GOODS_H_
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/digital_goods/digital_goods.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
class DigitalGoodsService;
class LocalDOMWindow;
class ScriptState;
class Visitor;
......@@ -31,7 +32,7 @@ class DOMWindowDigitalGoods final
void Trace(Visitor* visitor) const override;
private:
Member<DigitalGoodsService> digital_goods_service_;
mojo::Remote<payments::mojom::blink::DigitalGoodsFactory> mojo_service_;
static DOMWindowDigitalGoods* FromState(LocalDOMWindow*);
};
......
......@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(crbug.com/1061503): Add more fields from
// https://github.com/WICG/digital-goods/blob/master/explainer.md
// as the discussions settle.
dictionary ItemDetails {
DOMString itemId;
DOMString title;
......
......@@ -2,11 +2,12 @@
<html>
<head>
<title>Digital Goods API: Test calls from WebIDL to mojo and back.</title>
<script src="../resources/js-test.js"></script>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
<script src="file:///gen/components/payments/mojom/payment_request_data.mojom-lite.js"></script>
<script src="file:///gen/third_party/blink/public/mojom/digital_goods/digital_goods.mojom-lite.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/components/payments/mojom/payment_request_data.mojom.js"></script>
<script src="file:///gen/third_party/blink/public/mojom/digital_goods/digital_goods.mojom.js"></script>
<script src="resources/mock-digital-goods-service.js"></script>
</head>
<body>
......@@ -65,7 +66,7 @@ digital_goods_test(async service => {
await service.getDetails(['fail']);
assert_unreached();
} catch (error) {
assert_equals(error, 'error'); // TODO: throw an error instead of rejecting with a string?
assert_equals(error, 'error');
}
}, {title: 'GetDetails internal error.'});
......@@ -90,7 +91,7 @@ digital_goods_test(async service => {
await service.acknowledge('fail', 'repeatable');
assert_unreached();
} catch (error) {
assert_equals(error, 'error'); // TODO: throw an error instead of rejecting with a string?
assert_equals(error, 'error');
}
}, {title: 'Acknowledge bad ID should error.'});
......@@ -103,6 +104,17 @@ digital_goods_test(async service => {
}
}, {title: 'Acknowledge bad purchase type should error.'});
digital_goods_test(async service => {
const response1 = await service.getDetails(['id1']);
assert_equals(response1.length, 1);
gc();
const response2 = await service.getDetails(['id2']);
assert_equals(response2.length, 1);
gc();
const response3 = await service.getDetails(['id3']);
assert_equals(response3.length, 1);
}, {title: 'DigitalGoods referenced by scripts should survive garbage collector.'});
</script>
</body>
</html>
......@@ -2,19 +2,11 @@
class MockDigitalGoods {
constructor() {
this.interceptor_ =
new MojoInterfaceInterceptor(
payments.mojom.DigitalGoods.$interfaceName);
this.interceptor_.oninterfacerequest =
e => this.bindHandleToReceiver_(e.handle);
this.interceptor_.start();
this.resetRecordedAction_();
}
bindHandleToReceiver_(handle) {
this.receiver_ = new payments.mojom.DigitalGoodsReceiver(this);
this.receiver_.$.bindHandle(handle);
bind(request) {
this.binding = new mojo.Binding(payments.mojom.DigitalGoods, this, request);
}
getRecordedAction_() {
......@@ -80,6 +72,42 @@ class MockDigitalGoods {
let mockDigitalGoods = new MockDigitalGoods();
class MockDigitalGoodsFactory {
constructor() {
this.interceptor_ =
new MojoInterfaceInterceptor(
payments.mojom.DigitalGoodsFactory.name);
this.interceptor_.oninterfacerequest = e => this.bind(e.handle);
this.bindingSet_ = new mojo.BindingSet(payments.mojom.DigitalGoodsFactory);
this.interceptor_.start();
}
bind(handle) {
this.bindingSet_.addBinding(this, handle);
}
async createDigitalGoods(paymentMethod) {
if (paymentMethod !== 'https://play.google.com/billing') {
return {
code: /*CreateDigitalGoodsResponseCode.kUnsupportedPaymentMethod=*/2,
digitalGoods: null
};
}
let digitalGoodsPtr = new payments.mojom.DigitalGoodsPtr();
mockDigitalGoods.bind(mojo.makeRequest(digitalGoodsPtr));
return {
code: /*CreateDigitalGoodsResponseCode.kOk=*/0,
digitalGoods: digitalGoodsPtr
};
}
}
let mockDigitalGoodsFactory = new MockDigitalGoodsFactory();
function digital_goods_test(func, {
title,
expectedAction,
......
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