Skip to content

Commit

Permalink
[SecurePaymentConfirmation] Add PaymentCredential
Browse files Browse the repository at this point in the history
Add the PaymentCredential credential type to enable use of Credential
Management API for enrolling payment instruments associated with
Web Authentication credentials.

This adds the renderer-side code for creating the credential and also
a mojo interface for sending the information to the Payments component
for storage.

Bug:1110325

Change-Id: I7bf2ad1cf0d499a6a211e730e785d9b970fcdb07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2360313
Reviewed-by: Mike West <mkwst@chromium.org>
Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801871}
  • Loading branch information
kenrb authored and Commit Bot committed Aug 26, 2020
1 parent 4c8b686 commit 0786d28
Show file tree
Hide file tree
Showing 31 changed files with 634 additions and 6 deletions.
2 changes: 2 additions & 0 deletions chrome/browser/BUILD.gn
Expand Up @@ -4732,6 +4732,8 @@ static_library("browser") {
"crash_upload_list/crash_upload_list_crashpad.h",
"payments/chrome_payment_request_delegate.cc",
"payments/chrome_payment_request_delegate.h",
"payments/payment_credential_factory.cc",
"payments/payment_credential_factory.h",
"payments/payment_request_display_manager_factory.cc",
"payments/payment_request_display_manager_factory.h",
"payments/payment_request_factory.cc",
Expand Down
4 changes: 4 additions & 0 deletions chrome/browser/chrome_browser_interface_binders.cc
Expand Up @@ -66,6 +66,7 @@
#include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.h"
#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom.h"
#include "third_party/blink/public/mojom/loader/navigation_predictor.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_credential.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
#include "third_party/blink/public/public_buildflags.h"
Expand Down Expand Up @@ -108,6 +109,7 @@
#include "chrome/browser/media/kaleidoscope/kaleidoscope_data_provider_impl.h"
#include "chrome/browser/media/kaleidoscope/kaleidoscope_ui.h"
#include "chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom.h"
#include "chrome/browser/payments/payment_credential_factory.h"
#include "chrome/browser/payments/payment_request_factory.h"
#include "chrome/browser/promo_browser_command/promo_browser_command.mojom.h"
#include "chrome/browser/speech/speech_recognition_service.h"
Expand Down Expand Up @@ -463,6 +465,8 @@ void PopulateChromeFrameBinders(
map->Add<payments::mojom::PaymentRequest>(
base::BindRepeating(&payments::CreatePaymentRequest));
}
map->Add<payments::mojom::PaymentCredential>(
base::BindRepeating(&payments::CreatePaymentCredential));
#endif

#if BUILDFLAG(ENABLE_EXTENSIONS)
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/payments/BUILD.gn
Expand Up @@ -42,6 +42,7 @@ source_set("browsertests") {
"//components/payments/core",
"//components/payments/core:test_support",
"//components/ukm:test_support",
"//device/fido:test_support",
]

if (is_android) {
Expand Down
26 changes: 26 additions & 0 deletions chrome/browser/payments/payment_credential_factory.cc
@@ -0,0 +1,26 @@
// 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.

#include "chrome/browser/payments/payment_credential_factory.h"

#include "base/feature_list.h"
#include "chrome/browser/payments/chrome_payment_request_delegate.h"
#include "components/payments/content/payment_request_web_contents_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"

namespace payments {

void CreatePaymentCredential(
content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<mojom::PaymentCredential> receiver) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
if (!web_contents)
return;
PaymentRequestWebContentsManager::GetOrCreateForWebContents(web_contents)
->CreatePaymentCredential(std::move(receiver));
}

} // namespace payments
24 changes: 24 additions & 0 deletions chrome/browser/payments/payment_credential_factory.h
@@ -0,0 +1,24 @@
// 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.

#ifndef CHROME_BROWSER_PAYMENTS_PAYMENT_CREDENTIAL_FACTORY_H_
#define CHROME_BROWSER_PAYMENTS_PAYMENT_CREDENTIAL_FACTORY_H_

#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/mojom/payments/payment_credential.mojom-forward.h"

namespace content {
class RenderFrameHost;
}

namespace payments {

// Connect a PaymentCredential receiver to handle payment credential creation.
void CreatePaymentCredential(
content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<mojom::PaymentCredential> receiver);

} // namespace payments

#endif // CHROME_BROWSER_PAYMENTS_PAYMENT_CREDENTIAL_FACTORY_H_
81 changes: 81 additions & 0 deletions chrome/browser/payments/secure_payment_confirmation_browsertest.cc
Expand Up @@ -6,9 +6,11 @@
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "chrome/test/payments/payment_request_platform_browsertest_base.h"
#include "content/public/browser/authenticator_environment.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "device/fido/virtual_fido_device_factory.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace payments {
Expand All @@ -29,6 +31,33 @@ std::string getInvokePaymentRequestSnippet() {
return base::StringPrintf("getStatusForMethodData(%s)", kTestMethodData);
}

#if !defined(OS_ANDROID)
static constexpr char kCreatePaymentCredential[] =
"var PAYMENT_INSTRUMENT = {"
" displayName: 'display_name_for_instrument',"
" icon: 'https://pics.acme.com/00/p/aBjjjpqPb.png'"
"};"
"var PUBLIC_KEY_RP = {"
" id: 'a.com',"
" name: 'Acme'"
"};"
"var PUBLIC_KEY_PARAMETERS = [{"
" type: 'public-key',"
" alg: -7,"
"},];"
"var PAYMENT_CREATION_OPTIONS = {"
" rp: PUBLIC_KEY_RP,"
" instrument: PAYMENT_INSTRUMENT,"
" challenge: new TextEncoder().encode('climb a mountain'),"
" pubKeyCredParams: PUBLIC_KEY_PARAMETERS,"
"};"
"navigator.credentials.create({ payment : PAYMENT_CREATION_OPTIONS })"
" .then(c => window.domAutomationController.send("
" 'paymentCredential: OK'),"
" e => window.domAutomationController.send("
" 'paymentCredential: ' + e.toString()));";
#endif

class SecurePaymentConfirmationTest
: public PaymentRequestPlatformBrowserTestBase {
public:
Expand Down Expand Up @@ -155,5 +184,57 @@ IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationDisabledTest,
}
}

// Creation tests do not work on Android because there is not a way to
// override authenticator creation.
#if !defined(OS_ANDROID)
class SecurePaymentConfirmationCreationTest
: public SecurePaymentConfirmationTest {
public:
// PaymentCredential creation uses the normal Web Authentication code path
// for creating the public key credential, rather than using
// IntenralAuthenticator. This stubs out authenticator instantiation in
// content.
void ReplaceFidoDiscoveryFactory() {
auto owned_virtual_device_factory =
std::make_unique<device::test::VirtualFidoDeviceFactory>();
auto* virtual_device_factory = owned_virtual_device_factory.get();
content::AuthenticatorEnvironment::GetInstance()
->ReplaceDefaultDiscoveryFactoryForTesting(
std::move(owned_virtual_device_factory));
virtual_device_factory->SetTransport(
device::FidoTransportProtocol::kInternal);
virtual_device_factory->SetSupportedProtocol(
device::ProtocolVersion::kCtap2);
virtual_device_factory->mutable_state()->fingerprints_enrolled = true;

// Currently this only supports tests relying on user-verifying platform
// authenticators.
device::VirtualCtap2Device::Config config;
config.is_platform_authenticator = true;
config.internal_uv_support = true;
virtual_device_factory->SetCtap2Config(config);
}
};

#if defined(OS_WIN)
// TODO(kenrb): This experiment is currently only available on Mac, but this
// test should work on all non-Android platforms. There is a Windows failure
// that still needs to be investigated.
#define MAYBE_CreatePaymentCredential DISABLED_CreatePaymentCredential
#else
#define MAYBE_CreatePaymentCredential CreatePaymentCredential
#endif
IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
MAYBE_CreatePaymentCredential) {
ReplaceFidoDiscoveryFactory();
NavigateTo("a.com", "/payment_handler_status.html");

std::string result;
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
GetActiveWebContents(), kCreatePaymentCredential, &result));
EXPECT_EQ(result, "paymentCredential: OK");
}
#endif // !defined(OS_ANDROID)

} // namespace
} // namespace payments
2 changes: 2 additions & 0 deletions components/payments/content/BUILD.gn
Expand Up @@ -85,6 +85,8 @@ static_library("content") {
} else {
sources += [
"content_payment_request_delegate.h",
"payment_credential.cc",
"payment_credential.h",
"payment_request.cc",
"payment_request.h",
"payment_request_dialog.h",
Expand Down
25 changes: 25 additions & 0 deletions components/payments/content/payment_credential.cc
@@ -0,0 +1,25 @@
// 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.

#include "components/payments/content/payment_credential.h"

namespace payments {

PaymentCredential::PaymentCredential(
mojo::PendingReceiver<mojom::PaymentCredential> receiver) {
receiver_.Bind(std::move(receiver));
}

PaymentCredential::~PaymentCredential() = default;

void PaymentCredential::StorePaymentCredential(
payments::mojom::PaymentCredentialInstrumentPtr instrument,
const std::vector<uint8_t>& credential_id,
const std::string& rp_id,
StorePaymentCredentialCallback callback) {
// TODO(kenrb): Create storage for this credential and save it.
std::move(callback).Run(mojom::PaymentCredentialCreationStatus::SUCCESS);
}

} // namespace payments
43 changes: 43 additions & 0 deletions components/payments/content/payment_credential.h
@@ -0,0 +1,43 @@
// 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.

#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_CREDENTIAL_H_
#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_CREDENTIAL_H_

#include <string>
#include <vector>

#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/mojom/payments/payment_credential.mojom.h"

namespace payments {

// Implementation of the mojom::PaymentCredential interface for storing
// PaymentCredential instruments and their associated WebAuthn credential IDs.
// These can be retrieved later to authenticate during a PaymentRequest
// that uses Secure Payment Confirmation.
class PaymentCredential : public mojom::PaymentCredential {
public:
explicit PaymentCredential(
mojo::PendingReceiver<mojom::PaymentCredential> receiver);
~PaymentCredential() override;

PaymentCredential(const PaymentCredential&) = delete;
PaymentCredential& operator=(const PaymentCredential&) = delete;

// mojom::PaymentCredential:
void StorePaymentCredential(
payments::mojom::PaymentCredentialInstrumentPtr instrument,
const std::vector<uint8_t>& credential_id,
const std::string& rp_id,
StorePaymentCredentialCallback callback) override;

private:
mojo::Receiver<mojom::PaymentCredential> receiver_{this};
};

} // namespace payments

#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_CREDENTIAL_H_
Expand Up @@ -9,6 +9,7 @@
#include "base/check.h"
#include "base/feature_list.h"
#include "components/payments/content/content_payment_request_delegate.h"
#include "components/payments/content/payment_credential.h"
#include "components/payments/content/payment_request.h"
#include "components/payments/content/payment_request_display_manager.h"
#include "components/payments/content/secure_payment_confirmation_payment_request_delegate.h"
Expand Down Expand Up @@ -64,6 +65,7 @@ void PaymentRequestWebContentsManager::DidStartNavigation(
it.second->DidStartMainFrameNavigationToDifferentDocument(
!navigation_handle->IsRendererInitiated());
}
payment_credential_ = nullptr;
}

void PaymentRequestWebContentsManager::RenderFrameDeleted(
Expand All @@ -87,6 +89,12 @@ void PaymentRequestWebContentsManager::DestroyRequest(PaymentRequest* request) {
payment_requests_.erase(request);
}

void PaymentRequestWebContentsManager::CreatePaymentCredential(
mojo::PendingReceiver<payments::mojom::PaymentCredential> receiver) {
payment_credential_ =
std::make_unique<PaymentCredential>(std::move(receiver));
}

PaymentRequestWebContentsManager::PaymentRequestWebContentsManager(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
Expand Down
Expand Up @@ -9,10 +9,12 @@
#include <memory>

#include "base/macros.h"
#include "components/payments/content/payment_credential.h"
#include "components/payments/content/payment_request.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/mojom/payments/payment_credential.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"

namespace content {
Expand Down Expand Up @@ -56,6 +58,9 @@ class PaymentRequestWebContentsManager
// Destroys the given |request|.
void DestroyRequest(PaymentRequest* request);

void CreatePaymentCredential(
mojo::PendingReceiver<payments::mojom::PaymentCredential> receiver);

// WebContentsObserver::
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
Expand All @@ -72,6 +77,8 @@ class PaymentRequestWebContentsManager
// the requests themselves call DestroyRequest().
std::map<PaymentRequest*, std::unique_ptr<PaymentRequest>> payment_requests_;

std::unique_ptr<PaymentCredential> payment_credential_;

WEB_CONTENTS_USER_DATA_KEY_DECL();

DISALLOW_COPY_AND_ASSIGN(PaymentRequestWebContentsManager);
Expand Down
3 changes: 3 additions & 0 deletions content/browser/browser_interface_binders.cc
Expand Up @@ -100,6 +100,7 @@
#include "third_party/blink/public/mojom/native_io/native_io.mojom.h"
#include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_credential.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
Expand Down Expand Up @@ -729,6 +730,8 @@ void PopulateBinderMapWithContext(
&EmptyBinderForFrame<blink::mojom::InsecureInputService>));
map->Add<blink::mojom::PrerenderProcessor>(base::BindRepeating(
&EmptyBinderForFrame<blink::mojom::PrerenderProcessor>));
map->Add<payments::mojom::PaymentCredential>(base::BindRepeating(
&EmptyBinderForFrame<payments::mojom::PaymentCredential>));
map->Add<payments::mojom::PaymentRequest>(base::BindRepeating(
&EmptyBinderForFrame<payments::mojom::PaymentRequest>));
map->Add<blink::mojom::AnchorElementMetricsHost>(base::BindRepeating(
Expand Down
1 change: 1 addition & 0 deletions third_party/blink/public/mojom/BUILD.gn
Expand Up @@ -119,6 +119,7 @@ mojom("mojom_platform") {
"page/record_content_to_visible_time_request.mojom",
"page/widget.mojom",
"payments/payment_app.mojom",
"payments/payment_credential.mojom",
"peerconnection/peer_connection_tracker.mojom",
"performance_manager/v8_per_frame_memory.mojom",
"permissions/permission.mojom",
Expand Down

0 comments on commit 0786d28

Please sign in to comment.