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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java

Issue 2793573002: [Payments] Use <meta-data> tag instead of intent filter data to detect supported payment methods. (Closed)
Patch Set: move <meta-data> to pay activity Created 3 years, 8 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.payments; 5 package org.chromium.chrome.browser.payments;
6 6
7 import android.content.Intent; 7 import android.content.Intent;
8 import android.content.pm.ActivityInfo;
8 import android.content.pm.ResolveInfo; 9 import android.content.pm.ResolveInfo;
9 import android.net.Uri; 10 import android.content.res.Resources;
10 import android.text.TextUtils; 11 import android.text.TextUtils;
11 12
12 import org.chromium.base.Log; 13 import org.chromium.base.Log;
13 import org.chromium.chrome.browser.ChromeActivity; 14 import org.chromium.chrome.browser.ChromeActivity;
14 import org.chromium.chrome.browser.UrlConstants; 15 import org.chromium.chrome.browser.UrlConstants;
15 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedC allback; 16 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedC allback;
16 import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVeri fyCallback; 17 import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVeri fyCallback;
17 import org.chromium.components.payments.PaymentManifestDownloader; 18 import org.chromium.components.payments.PaymentManifestDownloader;
18 import org.chromium.components.payments.PaymentManifestParser; 19 import org.chromium.components.payments.PaymentManifestParser;
19 import org.chromium.content_public.browser.WebContents; 20 import org.chromium.content_public.browser.WebContents;
20 21
21 import java.net.URI; 22 import java.net.URI;
22 import java.net.URISyntaxException; 23 import java.net.URISyntaxException;
23 import java.util.ArrayList; 24 import java.util.ArrayList;
24 import java.util.HashMap; 25 import java.util.HashMap;
25 import java.util.HashSet; 26 import java.util.HashSet;
26 import java.util.List; 27 import java.util.List;
27 import java.util.Locale; 28 import java.util.Locale;
28 import java.util.Map; 29 import java.util.Map;
29 import java.util.Set; 30 import java.util.Set;
30 31
32 import javax.annotation.Nullable;
33
31 /** 34 /**
32 * Finds installed native Android payment apps and verifies their signatures acc ording to the 35 * Finds installed native Android payment apps and verifies their signatures acc ording to the
33 * payment method manifests. The manifests are located based on the payment meth od name, which 36 * payment method manifests. The manifests are located based on the payment meth od name, which
34 * is a URI that starts with "https://". The "basic-card" payment method is an e xception: it's a 37 * is a URI that starts with "https://". The "basic-card" payment method is an e xception: it's a
35 * common payment method that does not have a manifest and can be used by any pa yment app. 38 * common payment method that does not have a manifest and can be used by any pa yment app.
36 */ 39 */
37 public class AndroidPaymentAppFinder implements ManifestVerifyCallback { 40 public class AndroidPaymentAppFinder implements ManifestVerifyCallback {
38 private static final String TAG = "cr_PaymentAppFinder"; 41 private static final String TAG = "cr_PaymentAppFinder";
39 42
40 /** The name of the intent for the service to check whether an app is ready to pay. */ 43 /** The name of the intent for the service to check whether an app is ready to pay. */
41 /* package */ static final String ACTION_IS_READY_TO_PAY = 44 /* package */ static final String ACTION_IS_READY_TO_PAY =
42 "org.chromium.intent.action.IS_READY_TO_PAY"; 45 "org.chromium.intent.action.IS_READY_TO_PAY";
43 46
44 /** The name of the intent for the action of paying using "basic-card" metho d. */
45 /* package */ static final String ACTION_PAY_BASIC_CARD =
46 "org.chromium.intent.action.PAY_BASIC_CARD";
47
48 /** 47 /**
49 * The basic-card payment method name used by merchant and defined by W3C: 48 * The basic-card payment method name used by merchant and defined by W3C:
50 * https://w3c.github.io/webpayments-methods-card/#method-id 49 * https://w3c.github.io/webpayments-methods-card/#method-id
51 */ 50 */
52 /* package */ static final String BASIC_CARD_PAYMENT_METHOD = "basic-card"; 51 /* package */ static final String BASIC_CARD_PAYMENT_METHOD = "basic-card";
53 52
53 /**
54 * Meta data name of an app's supported payment method names.
55 */
56 static final String META_DATA_NAME_OF_PAYMENT_METHOD_NAMES =
57 "org.chromium.payment_method_names";
58
59 /**
60 * Meta data name of an app's supported default payment method name.
61 */
62 static final String META_DATA_NAME_OF_DEFAULT_PAYMENT_METHOD_NAME =
63 "org.chromum.default_payment_method_name";
64
54 /** The maximum number of payment method manifests to download. */ 65 /** The maximum number of payment method manifests to download. */
55 private static final int MAX_NUMBER_OF_MANIFESTS = 10; 66 private static final int MAX_NUMBER_OF_MANIFESTS = 10;
56 67
57 private final WebContents mWebContents; 68 private final WebContents mWebContents;
58 private final boolean mQueryBasicCard; 69 private final boolean mQueryBasicCard;
59 private final Set<URI> mPaymentMethods; 70 private final Set<URI> mPaymentMethods;
60 private final PaymentManifestDownloader mDownloader; 71 private final PaymentManifestDownloader mDownloader;
61 private final PaymentManifestParser mParser; 72 private final PaymentManifestParser mParser;
62 private final PackageManagerDelegate mPackageManagerDelegate; 73 private final PackageManagerDelegate mPackageManagerDelegate;
63 private final PaymentAppCreatedCallback mCallback; 74 private final PaymentAppCreatedCallback mCallback;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 mPendingApps = new HashMap<>(); 155 mPendingApps = new HashMap<>();
145 mResult = new HashMap<>(); 156 mResult = new HashMap<>();
146 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); 157 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents);
147 mIsIncognito = activity != null && activity.getCurrentTabModel() != null 158 mIsIncognito = activity != null && activity.getCurrentTabModel() != null
148 && activity.getCurrentTabModel().isIncognito(); 159 && activity.getCurrentTabModel().isIncognito();
149 mRequireShowInSettings = requireShowInSettings; 160 mRequireShowInSettings = requireShowInSettings;
150 mSettingsLookup = new Intent(AndroidPaymentApp.ACTION_PAY); 161 mSettingsLookup = new Intent(AndroidPaymentApp.ACTION_PAY);
151 } 162 }
152 163
153 private void findAndroidPaymentApps() { 164 private void findAndroidPaymentApps() {
165 Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY);
166 List<ResolveInfo> apps =
167 mPackageManagerDelegate.getActivitiesThatCanRespondToIntentWithM etaData(payIntent);
168 if (apps.isEmpty()) {
169 onSearchFinished();
170 return;
171 }
172
173 List<String[]> appSupportedMethods = new ArrayList<String[]>();
174 for (int i = 0; i < apps.size(); i++) {
175 appSupportedMethods.add(getPaymentMethodNames(apps.get(i).activityIn fo));
176 }
177
178 List<String> appSupportedDefaultMethods = new ArrayList<String>();
179 for (int i = 0; i < apps.size(); i++) {
180 appSupportedDefaultMethods.add(getDefaultPaymentMethodName(apps.get( i).activityInfo));
181 }
182
154 List<PaymentManifestVerifier> verifiers = new ArrayList<>(); 183 List<PaymentManifestVerifier> verifiers = new ArrayList<>();
155 if (!mPaymentMethods.isEmpty()) { 184 for (URI methodName : mPaymentMethods) {
156 Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY); 185 List<ResolveInfo> supportedApps = filterAppsByMethodName(
157 for (URI methodName : mPaymentMethods) { 186 apps, appSupportedMethods, appSupportedDefaultMethods, metho dName.toString());
158 payIntent.setData(Uri.parse(methodName.toString())); 187 if (supportedApps.isEmpty()) continue;
159 List<ResolveInfo> apps =
160 mPackageManagerDelegate.getActivitiesThatCanRespondToInt ent(payIntent);
161 if (apps.isEmpty()) continue;
162 188
163 // Start the parser utility process as soon as possible, once we know that a 189 // Start the parser utility process as soon as possible, once we kno w that a
164 // manifest file needs to be parsed. The startup can take up to 2 seconds. 190 // manifest file needs to be parsed. The startup can take up to 2 se conds.
165 if (!mParser.isUtilityProcessRunning()) mParser.startUtilityProc ess(); 191 if (!mParser.isUtilityProcessRunning()) mParser.startUtilityProcess( );
166 192
167 verifiers.add(new PaymentManifestVerifier(methodName, apps, mDow nloader, mParser, 193 verifiers.add(new PaymentManifestVerifier(methodName, supportedApps, mDownloader,
168 mPackageManagerDelegate, this /* callback */)); 194 mParser, mPackageManagerDelegate, this /* callback */));
169 mPendingApps.put(methodName, new HashSet<>(apps)); 195 mPendingApps.put(methodName, new HashSet<>(supportedApps));
170 if (verifiers.size() == MAX_NUMBER_OF_MANIFESTS) { 196
171 Log.d(TAG, "Reached maximum number of allowed payment app ma nifests."); 197 if (verifiers.size() == MAX_NUMBER_OF_MANIFESTS) {
172 break; 198 Log.d(TAG, "Reached maximum number of allowed payment app manife sts.");
173 } 199 break;
174 } 200 }
175 } 201 }
176 202
177 if (mQueryBasicCard) { 203 if (mQueryBasicCard) {
178 Intent basicCardPayIntent = new Intent(ACTION_PAY_BASIC_CARD); 204 List<ResolveInfo> supportedApps = filterAppsByMethodName(apps, appSu pportedMethods,
179 List<ResolveInfo> apps = 205 appSupportedDefaultMethods, BASIC_CARD_PAYMENT_METHOD);
180 mPackageManagerDelegate.getActivitiesThatCanRespondToIntent( basicCardPayIntent); 206 for (int i = 0; i < supportedApps.size(); i++) {
181 for (int i = 0; i < apps.size(); i++) {
182 // Chrome does not verify app manifests for "basic-card" support . 207 // Chrome does not verify app manifests for "basic-card" support .
183 onValidPaymentApp(BASIC_CARD_PAYMENT_METHOD, apps.get(i)); 208 onValidPaymentApp(BASIC_CARD_PAYMENT_METHOD, supportedApps.get(i ));
184 } 209 }
185 } 210 }
186 211
187 if (verifiers.isEmpty()) { 212 if (verifiers.isEmpty()) {
188 onSearchFinished(); 213 onSearchFinished();
189 return; 214 return;
190 } 215 }
191 216
192 for (int i = 0; i < verifiers.size(); i++) { 217 for (int i = 0; i < verifiers.size(); i++) {
193 verifiers.get(i).verify(); 218 verifiers.get(i).verify();
194 } 219 }
195 } 220 }
196 221
222 @Nullable
223 private String[] getPaymentMethodNames(ActivityInfo activityInfo) {
224 if (activityInfo.metaData == null) return null;
225
226 int resId = activityInfo.metaData.getInt(META_DATA_NAME_OF_PAYMENT_METHO D_NAMES);
227 if (resId == 0) return null;
228
229 Resources resources =
230 mPackageManagerDelegate.getResourcesForApplication(activityInfo. applicationInfo);
231 if (resources == null) return null;
232 return resources.getStringArray(resId);
233 }
234
235 @Nullable
236 private String getDefaultPaymentMethodName(ActivityInfo activityInfo) {
237 if (activityInfo.metaData == null) return null;
238
239 return activityInfo.metaData.getString(META_DATA_NAME_OF_DEFAULT_PAYMENT _METHOD_NAME);
240 }
241
242 private static List<ResolveInfo> filterAppsByMethodName(List<ResolveInfo> ap ps,
243 List<String[]> appsMethods, List<String> appsDefaultMethods, String targetMethodName) {
244 assert apps.size() == appsMethods.size();
245 assert apps.size() == appsDefaultMethods.size();
246
247 // Note that apps, appsMethods and appsDefaultMethods must have the same size. And the
248 // information at the same index must correspond to the same app.
249 List<ResolveInfo> supportedApps = new ArrayList<ResolveInfo>();
250 for (int i = 0; i < apps.size(); i++) {
251 if (targetMethodName.equals(appsDefaultMethods.get(i))) {
252 supportedApps.add(apps.get(i));
253 continue;
254 }
255
256 String[] methods = appsMethods.get(i);
257 if (methods == null) continue;
258 for (int j = 0; j < methods.length; j++) {
259 if (targetMethodName.equals(methods[j])) {
260 supportedApps.add(apps.get(i));
261 break;
262 }
263 }
264 }
265 return supportedApps;
266 }
267
197 @Override 268 @Override
198 public void onValidPaymentApp(URI methodName, ResolveInfo resolveInfo) { 269 public void onValidPaymentApp(URI methodName, ResolveInfo resolveInfo) {
199 onValidPaymentApp(methodName.toString(), resolveInfo); 270 onValidPaymentApp(methodName.toString(), resolveInfo);
200 removePendingApp(methodName, resolveInfo); 271 removePendingApp(methodName, resolveInfo);
201 } 272 }
202 273
203 /** Same as above, but also works for non-URI method names, e.g., "basic-car d". */ 274 /** Same as above, but also works for non-URI method names, e.g., "basic-car d". */
204 private void onValidPaymentApp(String methodName, ResolveInfo resolveInfo) { 275 private void onValidPaymentApp(String methodName, ResolveInfo resolveInfo) {
205 String packageName = resolveInfo.activityInfo.packageName; 276 String packageName = resolveInfo.activityInfo.packageName;
206 AndroidPaymentApp app = mResult.get(packageName); 277 AndroidPaymentApp app = mResult.get(packageName);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 334 }
264 } 335 }
265 336
266 for (Map.Entry<String, AndroidPaymentApp> entry : mResult.entrySet()) { 337 for (Map.Entry<String, AndroidPaymentApp> entry : mResult.entrySet()) {
267 mCallback.onPaymentAppCreated(entry.getValue()); 338 mCallback.onPaymentAppCreated(entry.getValue());
268 } 339 }
269 340
270 mCallback.onAllPaymentAppsCreated(); 341 mCallback.onAllPaymentAppsCreated();
271 } 342 }
272 } 343 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698