Commit dc08a996 authored by Liquan (Max) Gu's avatar Liquan (Max) Gu Committed by Commit Bot

[PRImpl] Move WebContents and JourneyLogger into CPRImpl

Change:
* Add null-check for
PRImpl's "WebContentsStatics.fromRenderFrameHost(renderFrameHost)".
And move it to CPRImpl.
* JourneyLogger's instantiation is moved from PRImpl's construction to
before CPRImpl's construction. Moving it earlier is because
JourneyLogger's role includes logging the error before CPRImpl's
construction.
* BrowserPaymentRequest's creation is no longer done in CPRImpl's
construction. This is because BrowserPaymentRequest's constructor
calls CPRImpl which is still partially initiated.
* The null-checks of client, methodData, details are moved from
CPRImpl#initAndValidate() to CPRImpl#createIfParamsValid(), because we
don't bother to create CPRImpl if render data is invalid.

Acronym:
CPRImpl = ComponentPaymentRequestImpl
PRImpl = PaymentRequestImpl

Bug: 1102522

Change-Id: I0faf70fe6a73b13858b30d1dadb30cf25857eda2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2357090
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798876}
parent e04f7fe9
...@@ -199,8 +199,8 @@ public class PaymentRequestFactory implements InterfaceFactory<PaymentRequest> { ...@@ -199,8 +199,8 @@ public class PaymentRequestFactory implements InterfaceFactory<PaymentRequest> {
return ComponentPaymentRequestImpl.createPaymentRequest(mRenderFrameHost, return ComponentPaymentRequestImpl.createPaymentRequest(mRenderFrameHost,
/*isOffTheRecord=*/delegate.isOffTheRecord(webContents), /*isOffTheRecord=*/delegate.isOffTheRecord(webContents),
/*skipUiForBasicCard=*/delegate.skipUiForBasicCard(), /*skipUiForBasicCard=*/delegate.skipUiForBasicCard(),
(renderFrameHost, componentPaymentRequest, isOffTheRecord, journeyLogger) (renderFrameHost, componentPaymentRequest, isOffTheRecord)
-> new PaymentRequestImpl(renderFrameHost, componentPaymentRequest, -> new PaymentRequestImpl(renderFrameHost, componentPaymentRequest,
isOffTheRecord, journeyLogger, delegate)); isOffTheRecord, delegate));
} }
} }
...@@ -63,7 +63,6 @@ import org.chromium.components.payments.Event; ...@@ -63,7 +63,6 @@ import org.chromium.components.payments.Event;
import org.chromium.components.payments.JourneyLogger; import org.chromium.components.payments.JourneyLogger;
import org.chromium.components.payments.MethodStrings; import org.chromium.components.payments.MethodStrings;
import org.chromium.components.payments.NotShownReason; import org.chromium.components.payments.NotShownReason;
import org.chromium.components.payments.OriginSecurityChecker;
import org.chromium.components.payments.PackageManagerDelegate; import org.chromium.components.payments.PackageManagerDelegate;
import org.chromium.components.payments.PayerData; import org.chromium.components.payments.PayerData;
import org.chromium.components.payments.PaymentApp; import org.chromium.components.payments.PaymentApp;
...@@ -83,7 +82,6 @@ import org.chromium.components.security_state.SecurityStateModel; ...@@ -83,7 +82,6 @@ import org.chromium.components.security_state.SecurityStateModel;
import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsStatics;
import org.chromium.payments.mojom.CanMakePaymentQueryResult; import org.chromium.payments.mojom.CanMakePaymentQueryResult;
import org.chromium.payments.mojom.HasEnrolledInstrumentQueryResult; import org.chromium.payments.mojom.HasEnrolledInstrumentQueryResult;
import org.chromium.payments.mojom.PayerDetail; import org.chromium.payments.mojom.PayerDetail;
...@@ -340,20 +338,18 @@ public class PaymentRequestImpl ...@@ -340,20 +338,18 @@ public class PaymentRequestImpl
* @param renderFrameHost The host of the frame that has invoked the PaymentRequest API. * @param renderFrameHost The host of the frame that has invoked the PaymentRequest API.
* @param componentPaymentRequestImpl The component side of the PaymentRequest implementation. * @param componentPaymentRequestImpl The component side of the PaymentRequest implementation.
* @param isOffTheRecord Whether the merchant page is shown in an off-the-record tab. * @param isOffTheRecord Whether the merchant page is shown in an off-the-record tab.
* @param journeyLogger The JourneyLogger that records the user journey of using the
* PaymentRequest service.
* @param delegate The delegate of this class. * @param delegate The delegate of this class.
*/ */
public PaymentRequestImpl(RenderFrameHost renderFrameHost, public PaymentRequestImpl(RenderFrameHost renderFrameHost,
ComponentPaymentRequestImpl componentPaymentRequestImpl, boolean isOffTheRecord, ComponentPaymentRequestImpl componentPaymentRequestImpl, boolean isOffTheRecord,
JourneyLogger journeyLogger, Delegate delegate) { Delegate delegate) {
assert renderFrameHost != null; assert renderFrameHost != null;
assert componentPaymentRequestImpl != null; assert componentPaymentRequestImpl != null;
assert delegate != null; assert delegate != null;
mRenderFrameHost = renderFrameHost; mRenderFrameHost = renderFrameHost;
mDelegate = delegate; mDelegate = delegate;
mWebContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost); mWebContents = componentPaymentRequestImpl.getWebContents();
mPaymentRequestOrigin = mPaymentRequestOrigin =
UrlFormatter.formatUrlForSecurityDisplay(mRenderFrameHost.getLastCommittedURL()); UrlFormatter.formatUrlForSecurityDisplay(mRenderFrameHost.getLastCommittedURL());
mPaymentRequestSecurityOrigin = mRenderFrameHost.getLastCommittedOrigin(); mPaymentRequestSecurityOrigin = mRenderFrameHost.getLastCommittedOrigin();
...@@ -362,7 +358,7 @@ public class PaymentRequestImpl ...@@ -362,7 +358,7 @@ public class PaymentRequestImpl
mMerchantName = mWebContents.getTitle(); mMerchantName = mWebContents.getTitle();
mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents); mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents);
mIsOffTheRecord = isOffTheRecord; mIsOffTheRecord = isOffTheRecord;
mJourneyLogger = journeyLogger; mJourneyLogger = componentPaymentRequestImpl.getJourneyLogger();
mPaymentUIsManager = new PaymentUIsManager(/*delegate=*/this, mPaymentUIsManager = new PaymentUIsManager(/*delegate=*/this,
/*params=*/this, mWebContents, mIsOffTheRecord, mJourneyLogger); /*params=*/this, mWebContents, mIsOffTheRecord, mJourneyLogger);
mComponentPaymentRequestImpl = componentPaymentRequestImpl; mComponentPaymentRequestImpl = componentPaymentRequestImpl;
...@@ -376,12 +372,6 @@ public class PaymentRequestImpl ...@@ -376,12 +372,6 @@ public class PaymentRequestImpl
assert mComponentPaymentRequestImpl != null; assert mComponentPaymentRequestImpl != null;
mMethodData = new HashMap<>(); mMethodData = new HashMap<>();
if (!OriginSecurityChecker.isOriginSecure(mWebContents.getLastCommittedUrl())) {
mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
disconnectFromClientWithDebugMessage(ErrorStrings.NOT_IN_A_SECURE_ORIGIN);
return false;
}
mPaymentOptions = options; mPaymentOptions = options;
mRequestShipping = options != null && options.requestShipping; mRequestShipping = options != null && options.requestShipping;
mRequestPayerName = options != null && options.requestPayerName; mRequestPayerName = options != null && options.requestPayerName;
...@@ -1456,11 +1446,6 @@ public class PaymentRequestImpl ...@@ -1456,11 +1446,6 @@ public class PaymentRequestImpl
return mPaymentHandlerHost; return mPaymentHandlerHost;
} }
@Override
public JourneyLogger getJourneyLogger() {
return mJourneyLogger;
}
@Override @Override
public void onDismiss() { public void onDismiss() {
mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER); mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
......
...@@ -27,12 +27,10 @@ public interface BrowserPaymentRequest { ...@@ -27,12 +27,10 @@ public interface BrowserPaymentRequest {
* the BrowserPaymentRequest instance. * the BrowserPaymentRequest instance.
* @param isOffTheRecord Whether the merchant page is in an OffTheRecord (e.g., incognito, * @param isOffTheRecord Whether the merchant page is in an OffTheRecord (e.g., incognito,
* guest mode) Tab. * guest mode) Tab.
* @param journeyLogger The logger that records the user journey of PaymentRequest.
* @return An instance of BrowserPaymentRequest, cannot be null. * @return An instance of BrowserPaymentRequest, cannot be null.
*/ */
BrowserPaymentRequest createBrowserPaymentRequest(RenderFrameHost renderFrameHost, BrowserPaymentRequest createBrowserPaymentRequest(RenderFrameHost renderFrameHost,
ComponentPaymentRequestImpl componentPaymentRequestImpl, boolean isOffTheRecord, ComponentPaymentRequestImpl componentPaymentRequestImpl, boolean isOffTheRecord);
JourneyLogger journeyLogger);
} }
/** /**
...@@ -90,9 +88,6 @@ public interface BrowserPaymentRequest { ...@@ -90,9 +88,6 @@ public interface BrowserPaymentRequest {
/** The browser part of the {@link PaymentRequest#canMakePayment} implementation. */ /** The browser part of the {@link PaymentRequest#canMakePayment} implementation. */
void canMakePayment(); void canMakePayment();
/** @return The JourneyLogger of PaymentRequestImpl. */
JourneyLogger getJourneyLogger();
/** Delegate to the same method of PaymentRequestImpl. */ /** Delegate to the same method of PaymentRequestImpl. */
void disconnectFromClientWithDebugMessage(String debugMessage); void disconnectFromClientWithDebugMessage(String debugMessage);
......
...@@ -7,8 +7,10 @@ package org.chromium.components.payments; ...@@ -7,8 +7,10 @@ package org.chromium.components.payments;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.Log;
import org.chromium.components.autofill.EditableOption; import org.chromium.components.autofill.EditableOption;
import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsStatics; import org.chromium.content_public.browser.WebContentsStatics;
import org.chromium.mojo.system.MojoException; import org.chromium.mojo.system.MojoException;
import org.chromium.payments.mojom.PayerDetail; import org.chromium.payments.mojom.PayerDetail;
...@@ -36,19 +38,20 @@ import java.util.List; ...@@ -36,19 +38,20 @@ import java.util.List;
* {@link ComponentPaymentRequestImpl#close()}, after which no usage is allowed. * {@link ComponentPaymentRequestImpl#close()}, after which no usage is allowed.
*/ */
public class ComponentPaymentRequestImpl { public class ComponentPaymentRequestImpl {
private static final String TAG = "CompPaymentRequest";
private static PaymentRequestServiceObserverForTest sObserverForTest; private static PaymentRequestServiceObserverForTest sObserverForTest;
private static NativeObserverForTest sNativeObserverForTest; private static NativeObserverForTest sNativeObserverForTest;
private final Runnable mOnClosedListener; private final Runnable mOnClosedListener;
private final WebContents mWebContents;
private final JourneyLogger mJourneyLogger;
private boolean mSkipUiForNonUrlPaymentMethodIdentifiers; private boolean mSkipUiForNonUrlPaymentMethodIdentifiers;
private PaymentRequestLifecycleObserver mPaymentRequestLifecycleObserver; private PaymentRequestLifecycleObserver mPaymentRequestLifecycleObserver;
private boolean mHasClosed; private boolean mHasClosed;
// After create(), mClient is null only when it has closed. // mClient is null only when it has closed.
@Nullable
private PaymentRequestClient mClient; private PaymentRequestClient mClient;
// After the constructor, mBrowserPaymentRequest is null only when it has closed. // mBrowserPaymentRequest is null when it has closed or is uninitiated.
@Nullable
private BrowserPaymentRequest mBrowserPaymentRequest; private BrowserPaymentRequest mBrowserPaymentRequest;
/** /**
...@@ -173,11 +176,45 @@ public class ComponentPaymentRequestImpl { ...@@ -173,11 +176,45 @@ public class ComponentPaymentRequestImpl {
assert browserPaymentRequestFactory != null; assert browserPaymentRequestFactory != null;
assert onClosedListener != null; assert onClosedListener != null;
ComponentPaymentRequestImpl instance = new ComponentPaymentRequestImpl(renderFrameHost, WebContents webContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost);
isOffTheRecord, skipUiForBasicCard, browserPaymentRequestFactory, onClosedListener); if (webContents == null) {
abortBeforeInstantiation(client, /*journeyLogger=*/null, ErrorStrings.NO_WEB_CONTENTS,
AbortReason.INVALID_DATA_FROM_RENDERER);
return null;
}
JourneyLogger journeyLogger = new JourneyLogger(isOffTheRecord, webContents);
if (client == null) {
abortBeforeInstantiation(/*client=*/null, journeyLogger, ErrorStrings.INVALID_STATE,
AbortReason.INVALID_DATA_FROM_RENDERER);
return null;
}
if (!OriginSecurityChecker.isOriginSecure(webContents.getLastCommittedUrl())) {
abortBeforeInstantiation(client, journeyLogger, ErrorStrings.NOT_IN_A_SECURE_ORIGIN,
AbortReason.INVALID_DATA_FROM_RENDERER);
return null;
}
if (methodData == null) {
abortBeforeInstantiation(client, journeyLogger,
ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA,
AbortReason.INVALID_DATA_FROM_RENDERER);
return null;
}
if (details == null) {
abortBeforeInstantiation(client, journeyLogger, ErrorStrings.INVALID_PAYMENT_DETAILS,
AbortReason.INVALID_DATA_FROM_RENDERER);
return null;
}
ComponentPaymentRequestImpl instance = new ComponentPaymentRequestImpl(client,
renderFrameHost, webContents, journeyLogger, skipUiForBasicCard, onClosedListener);
instance.onCreated(); instance.onCreated();
boolean valid = instance.initAndValidate( boolean valid = instance.initAndValidate(renderFrameHost, browserPaymentRequestFactory,
client, methodData, details, options, googlePayBridgeEligible); methodData, details, options, googlePayBridgeEligible, isOffTheRecord);
if (!valid) { if (!valid) {
instance.close(); instance.close();
return null; return null;
...@@ -190,15 +227,27 @@ public class ComponentPaymentRequestImpl { ...@@ -190,15 +227,27 @@ public class ComponentPaymentRequestImpl {
sObserverForTest.onPaymentRequestCreated(this); sObserverForTest.onPaymentRequestCreated(this);
} }
private ComponentPaymentRequestImpl(RenderFrameHost renderFrameHost, boolean isOffTheRecord, /** Abort the request, used before this class's instantiation. */
boolean skipUiForBasicCard, BrowserPaymentRequest.Factory browserPaymentRequestFactory, private static void abortBeforeInstantiation(@Nullable PaymentRequestClient client,
Runnable onClosedListener) { @Nullable JourneyLogger journeyLogger, String debugMessage, int reason) {
Log.d(TAG, debugMessage);
if (client != null) client.onError(reason, debugMessage);
if (journeyLogger != null) journeyLogger.setAborted(reason);
if (sNativeObserverForTest != null) sNativeObserverForTest.onConnectionTerminated();
}
private ComponentPaymentRequestImpl(PaymentRequestClient client,
RenderFrameHost renderFrameHost, WebContents webContents, JourneyLogger journeyLogger,
boolean skipUiForBasicCard, Runnable onClosedListener) {
assert client != null;
assert renderFrameHost != null;
assert webContents != null;
assert journeyLogger != null;
mSkipUiForNonUrlPaymentMethodIdentifiers = skipUiForBasicCard; mSkipUiForNonUrlPaymentMethodIdentifiers = skipUiForBasicCard;
JourneyLogger journeyLogger = new JourneyLogger( mClient = client;
isOffTheRecord, WebContentsStatics.fromRenderFrameHost(renderFrameHost)); mWebContents = webContents;
mBrowserPaymentRequest = browserPaymentRequestFactory.createBrowserPaymentRequest( mJourneyLogger = journeyLogger;
renderFrameHost, this, isOffTheRecord, journeyLogger);
assert mBrowserPaymentRequest != null;
mOnClosedListener = onClosedListener; mOnClosedListener = onClosedListener;
mHasClosed = false; mHasClosed = false;
} }
...@@ -219,24 +268,12 @@ public class ComponentPaymentRequestImpl { ...@@ -219,24 +268,12 @@ public class ComponentPaymentRequestImpl {
return sNativeObserverForTest; return sNativeObserverForTest;
} }
private boolean initAndValidate(@Nullable PaymentRequestClient client, private boolean initAndValidate(RenderFrameHost renderFrameHost,
@Nullable PaymentMethodData[] methodData, @Nullable PaymentDetails details, BrowserPaymentRequest.Factory factory, @Nullable PaymentMethodData[] methodData,
@Nullable PaymentOptions options, boolean googlePayBridgeEligible) { @Nullable PaymentDetails details, @Nullable PaymentOptions options,
if (client == null) { boolean googlePayBridgeEligible, boolean isOffTheRecord) {
abortForInvalidDataFromRenderer(ErrorStrings.INVALID_STATE); mBrowserPaymentRequest =
return false; factory.createBrowserPaymentRequest(renderFrameHost, this, isOffTheRecord);
}
mClient = client;
if (methodData == null) {
abortForInvalidDataFromRenderer(ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA);
return false;
}
if (details == null) {
abortForInvalidDataFromRenderer(ErrorStrings.INVALID_PAYMENT_DETAILS);
return false;
}
assert mBrowserPaymentRequest != null;
return mBrowserPaymentRequest.initAndValidate( return mBrowserPaymentRequest.initAndValidate(
methodData, details, options, googlePayBridgeEligible); methodData, details, options, googlePayBridgeEligible);
} }
...@@ -327,7 +364,7 @@ public class ComponentPaymentRequestImpl { ...@@ -327,7 +364,7 @@ public class ComponentPaymentRequestImpl {
// Every caller should stop referencing this class once close() is called. // Every caller should stop referencing this class once close() is called.
assert mBrowserPaymentRequest != null; assert mBrowserPaymentRequest != null;
mBrowserPaymentRequest.getJourneyLogger().setAborted(AbortReason.MOJO_RENDERER_CLOSING); mJourneyLogger.setAborted(AbortReason.MOJO_RENDERER_CLOSING);
close(); close();
if (sObserverForTest != null) { if (sObserverForTest != null) {
sObserverForTest.onRendererClosedMojoConnection(); sObserverForTest.onRendererClosedMojoConnection();
...@@ -346,7 +383,7 @@ public class ComponentPaymentRequestImpl { ...@@ -346,7 +383,7 @@ public class ComponentPaymentRequestImpl {
// Every caller should stop referencing this class once close() is called. // Every caller should stop referencing this class once close() is called.
assert mBrowserPaymentRequest != null; assert mBrowserPaymentRequest != null;
mBrowserPaymentRequest.getJourneyLogger().setAborted(AbortReason.MOJO_CONNECTION_ERROR); mJourneyLogger.setAborted(AbortReason.MOJO_CONNECTION_ERROR);
close(); close();
if (sNativeObserverForTest != null) { if (sNativeObserverForTest != null) {
sNativeObserverForTest.onConnectionTerminated(); sNativeObserverForTest.onConnectionTerminated();
...@@ -361,8 +398,7 @@ public class ComponentPaymentRequestImpl { ...@@ -361,8 +398,7 @@ public class ComponentPaymentRequestImpl {
// Every caller should stop referencing this class once close() is called. // Every caller should stop referencing this class once close() is called.
assert mBrowserPaymentRequest != null; assert mBrowserPaymentRequest != null;
mBrowserPaymentRequest.getJourneyLogger().setAborted( mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
AbortReason.INVALID_DATA_FROM_RENDERER);
mBrowserPaymentRequest.disconnectFromClientWithDebugMessage(debugMessage); mBrowserPaymentRequest.disconnectFromClientWithDebugMessage(debugMessage);
} }
...@@ -516,4 +552,17 @@ public class ComponentPaymentRequestImpl { ...@@ -516,4 +552,17 @@ public class ComponentPaymentRequestImpl {
mClient.warnNoFavicon(); mClient.warnNoFavicon();
} }
/**
* @return The logger of the user journey of the Android PaymentRequest service, cannot be
* null.
*/
public JourneyLogger getJourneyLogger() {
return mJourneyLogger;
}
/** @return The WebContents of the merchant's page, cannot be null. */
public WebContents getWebContents() {
return mWebContents;
}
} }
...@@ -24,6 +24,7 @@ const char kMethodNameRequired[] = "Method name required."; ...@@ -24,6 +24,7 @@ const char kMethodNameRequired[] = "Method name required.";
const char kMissingDetailsFromPaymentApp[] = "Payment app returned invalid response. Missing field \"details\"."; const char kMissingDetailsFromPaymentApp[] = "Payment app returned invalid response. Missing field \"details\".";
const char kMissingMethodNameFromPaymentApp[] = "Payment app returned invalid response. Missing field \"methodName\"."; const char kMissingMethodNameFromPaymentApp[] = "Payment app returned invalid response. Missing field \"methodName\".";
const char kNotInASecureOrigin[] = "Not in a secure origin."; const char kNotInASecureOrigin[] = "Not in a secure origin.";
const char kNoWebContents[] = "The frame that initiated payment is not associated with any web page.";
const char kPayerEmailEmpty[] = "Payment app returned invalid response. Missing field \"payerEmail\"."; const char kPayerEmailEmpty[] = "Payment app returned invalid response. Missing field \"payerEmail\".";
const char kPayerNameEmpty[] = "Payment app returned invalid response. Missing field \"payerName\"."; const char kPayerNameEmpty[] = "Payment app returned invalid response. Missing field \"payerName\".";
const char kPayerPhoneEmpty[] = "Payment app returned invalid response. Missing field \"payerPhone\"."; const char kPayerPhoneEmpty[] = "Payment app returned invalid response. Missing field \"payerPhone\".";
......
...@@ -58,6 +58,9 @@ extern const char kMissingMethodNameFromPaymentApp[]; ...@@ -58,6 +58,9 @@ extern const char kMissingMethodNameFromPaymentApp[];
// The PaymentRequest API is available only on secure origins. // The PaymentRequest API is available only on secure origins.
extern const char kNotInASecureOrigin[]; extern const char kNotInASecureOrigin[];
// WebContents is not available from RenderFrameHost.
extern const char kNoWebContents[];
// The payment handler responded with an empty "payer name" field. // The payment handler responded with an empty "payer name" field.
extern const char kPayerNameEmpty[]; extern const char kPayerNameEmpty[];
......
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