Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2270)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java

Issue 2507223002: Implement IsReadyToPay handling (Closed)
Patch Set: Use aidl Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..b38562ee18c5fa57a002ceaea4541428cf694c5c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
@@ -0,0 +1,250 @@
+// Copyright 2016 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.payments;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.JsonWriter;
+
+import org.json.JSONObject;
+
+import org.chromium.IsReadyToPayService;
+import org.chromium.chrome.R;
+import org.chromium.payments.mojom.PaymentItem;
+import org.chromium.ui.base.WindowAndroid;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** A locally installed payment app. */
+public class AndroidPaymentApp extends PaymentInstrument implements PaymentApp,
+ WindowAndroid.IntentCallback {
+ private static final String DATA_EXTRA = "data";
+ private static final String DETAILS_EXTRA = "details";
+ private static final String EMPTY_JSON_DATA = "{}";
+ private static final String METHOD_NAME_EXTRA = "methodName";
+ private static final String INSTRUMENT_DETAILS_EXTRA = "instrumentDetails";
+ private static final String ORIGIN_EXTRA = "origin";
+ private static final String READY_TO_PAY = "readyToPay";
+
+ private final Handler mHandler;
+ private final WindowAndroid mWindow;
+ private final Intent mIsReadyToPayIntent;
+ private final Intent mPayIntent;
+ private final Set<String> mMethodNames;
+ private IsReadyToPayService mIsReadyToPayService;
+ private InstrumentsCallback mInstrumentsCallback;
+ private InstrumentDetailsCallback mInstrumentDetailsCallback;
+
+ public AndroidPaymentApp(WindowAndroid window, String packageName, String activity,
+ String label, Drawable icon) {
+ super(packageName, label, null, icon);
+ mHandler = new Handler();
+ mWindow = window;
+ mIsReadyToPayIntent = new Intent();
+ mIsReadyToPayIntent.setPackage(packageName);
+ mPayIntent = new Intent();
+ mPayIntent.setClassName(packageName, activity);
+ mMethodNames = new HashSet<>();
+ }
+
+ public void addMethodName(String methodName) {
+ mMethodNames.add(methodName);
+ }
+
+ public void setIsReadyToPayAction(String className) {
+ mIsReadyToPayIntent.setClassName(mIsReadyToPayIntent.getPackage(), className);
+ }
+
+ @Override
+ public void getInstruments(
+ final Map<String, JSONObject> methodData, final String origin,
+ final InstrumentsCallback callback) {
+ mInstrumentsCallback = callback;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mIsReadyToPayIntent.getComponent() != null) {
+ isReadyToPay(origin, methodData.get(getInstrumentMethodName()));
+ } else {
+ sendInstrumentsReady(AndroidPaymentApp.this);
+ }
+ }
+ });
+ }
+
+ private void sendInstrumentsReady(PaymentInstrument instrument) {
+ assert mInstrumentsCallback != null;
+ List<PaymentInstrument> instruments = new ArrayList<>();
+ instruments.add(instrument);
+ mInstrumentsCallback.onInstrumentsReady(AndroidPaymentApp.this, instruments);
+ }
+
+ private void isReadyToPay(String origin, JSONObject data) {
+ Bundle extras = new Bundle();
+ extras.putString(METHOD_NAME_EXTRA, getInstrumentMethodName());
+ extras.putString(ORIGIN_EXTRA, origin);
+ extras.putString(DATA_EXTRA,
+ data == null ? EMPTY_JSON_DATA : data.toString());
+ mIsReadyToPayIntent.putExtras(extras);
+
+ if (mIsReadyToPayService != null) {
+ sendIsReadyToPay();
+ } else {
+ try {
+ mWindow.getApplicationContext().bindService(
+ mIsReadyToPayIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ } catch (SecurityException e) {
+ sendInstrumentsReady(null);
+ }
+ }
+ }
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mIsReadyToPayService = IsReadyToPayService.Stub.asInterface(service);
+ if (mIsReadyToPayService == null) {
+ sendInstrumentsReady(null);
+ } else {
+ sendIsReadyToPay();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ sendInstrumentsReady(null);
+ }
+ };
+ private void sendIsReadyToPay() {
+ assert mIsReadyToPayService != null;
+ try {
+ if (mIsReadyToPayService.isReadyToPay()) {
+ sendInstrumentsReady(AndroidPaymentApp.this);
+ return;
+ }
+ } catch (RemoteException e) {
+ }
+ mInstrumentsCallback.onInstrumentsReady(AndroidPaymentApp.this, null);
+ }
+
+ @Override
+ public String getAppIdentifier() {
+ return getIdentifier();
+ }
+
+ @Override
+ public Set<String> getAppMethodNames() {
+ return mMethodNames;
+ }
+
+ @Override
+ public String getInstrumentMethodName() {
+ assert !mMethodNames.isEmpty();
+ return mMethodNames.iterator().next();
+ }
+
+ @Override
+ public void getInstrumentDetails(String merchantName, String origin, PaymentItem total,
+ List<PaymentItem> cart, JSONObject data, InstrumentDetailsCallback callback) {
+ assert !mMethodNames.isEmpty();
+
+ Bundle extras = new Bundle();
+ extras.putString(METHOD_NAME_EXTRA, mMethodNames.iterator().next());
+ extras.putString(DATA_EXTRA, data == null ? EMPTY_JSON_DATA : data.toString());
+ extras.putString(ORIGIN_EXTRA, origin);
+ String details = serializeDetails(total, cart);
+ extras.putString(DETAILS_EXTRA, details == null ? EMPTY_JSON_DATA : details);
+ mPayIntent.putExtras(extras);
+
+ mInstrumentDetailsCallback = callback;
+ if (!mWindow.showIntent(mPayIntent, this, R.string.payments_android_app_error)) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mInstrumentDetailsCallback.onInstrumentDetailsError();
+ }
+ });
+ }
+ }
+
+ private static String serializeDetails(PaymentItem total, List<PaymentItem> cart) {
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter json = new JsonWriter(stringWriter);
+ try {
+ // details {{{
+ json.beginObject();
+
+ // total {{{
+ json.name("total");
+ serializePaymentItem(json, total);
+ // }}} total
+
+ // displayitems {{{
+ if (cart != null) {
+ json.name("displayItems").beginArray();
+ for (int i = 0; i < cart.size(); i++) {
+ serializePaymentItem(json, cart.get(i));
+ }
+ json.endArray();
+ }
+ // }}} displayItems
+
+ json.endObject();
+ // }}} details
+ } catch (IOException e) {
+ return null;
+ }
+
+ return stringWriter.toString();
+ }
+
+ private static void serializePaymentItem(JsonWriter json, PaymentItem item) throws IOException {
+ // item {{{
+ json.beginObject();
+ json.name("label").value(item.label);
+
+ // amount {{{
+ json.name("amount").beginObject();
+ json.name("currency").value(item.amount.currency);
+ json.name("value").value(item.amount.value);
+ json.endObject();
+ // }}} amount
+
+ json.endObject();
+ // }}} item
+ }
+
+ @Override
+ public void onIntentCompleted(
+ WindowAndroid window, int resultCode, ContentResolver contentResolver, Intent data) {
+ mWindow.removeIntentCallback(this);
+ if (data == null || data.getExtras() == null || resultCode != Activity.RESULT_OK) {
+ mInstrumentDetailsCallback.onInstrumentDetailsError();
+ } else {
+ mInstrumentDetailsCallback.onInstrumentDetailsReady(
+ data.getExtras().getString(METHOD_NAME_EXTRA),
+ data.getExtras().getString(INSTRUMENT_DETAILS_EXTRA));
+ }
+ mInstrumentDetailsCallback = null;
+ }
+
+ @Override
+ public void dismissInstrument() {}
+}

Powered by Google App Engine
This is Rietveld 408576698