OLD | NEW |
---|---|
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.ResolveInfo; | 8 import android.content.pm.ResolveInfo; |
9 import android.net.Uri; | |
10 import android.text.TextUtils; | 9 import android.text.TextUtils; |
11 | 10 |
12 import org.chromium.base.Log; | 11 import org.chromium.base.Log; |
13 import org.chromium.chrome.browser.ChromeActivity; | 12 import org.chromium.chrome.browser.ChromeActivity; |
14 import org.chromium.chrome.browser.UrlConstants; | 13 import org.chromium.chrome.browser.UrlConstants; |
15 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedC allback; | 14 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedC allback; |
16 import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVeri fyCallback; | 15 import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVeri fyCallback; |
17 import org.chromium.components.payments.PaymentManifestDownloader; | 16 import org.chromium.components.payments.PaymentManifestDownloader; |
18 import org.chromium.components.payments.PaymentManifestParser; | 17 import org.chromium.components.payments.PaymentManifestParser; |
19 import org.chromium.content_public.browser.WebContents; | 18 import org.chromium.content_public.browser.WebContents; |
(...skipping 14 matching lines...) Expand all Loading... | |
34 * is a URI that starts with "https://". The "basic-card" payment method is an e xception: it's a | 33 * 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. | 34 * common payment method that does not have a manifest and can be used by any pa yment app. |
36 */ | 35 */ |
37 public class AndroidPaymentAppFinder implements ManifestVerifyCallback { | 36 public class AndroidPaymentAppFinder implements ManifestVerifyCallback { |
38 private static final String TAG = "cr_PaymentAppFinder"; | 37 private static final String TAG = "cr_PaymentAppFinder"; |
39 | 38 |
40 /** The name of the intent for the service to check whether an app is ready to pay. */ | 39 /** 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 = | 40 /* package */ static final String ACTION_IS_READY_TO_PAY = |
42 "org.chromium.intent.action.IS_READY_TO_PAY"; | 41 "org.chromium.intent.action.IS_READY_TO_PAY"; |
43 | 42 |
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 /** | 43 /** |
49 * The basic-card payment method name used by merchant and defined by W3C: | 44 * The basic-card payment method name used by merchant and defined by W3C: |
50 * https://w3c.github.io/webpayments-methods-card/#method-id | 45 * https://w3c.github.io/webpayments-methods-card/#method-id |
51 */ | 46 */ |
52 /* package */ static final String BASIC_CARD_PAYMENT_METHOD = "basic-card"; | 47 /* package */ static final String BASIC_CARD_PAYMENT_METHOD = "basic-card"; |
53 | 48 |
49 /** | |
50 * Meta data name of an app's supported payment method names. | |
51 */ | |
52 static final String META_DATA_NAME_OF_PAYMENT_METHOD_NAMES = | |
53 "org.chromium.payment_method_names"; | |
54 | |
55 /** | |
56 * Meta data name of an app's supported default payment method name. | |
57 */ | |
58 static final String META_DATA_NAME_OF_DEFAULT_PAYMENT_METHOD_NAME = | |
59 "org.chromum.default_payment_method_name"; | |
60 | |
54 /** The maximum number of payment method manifests to download. */ | 61 /** The maximum number of payment method manifests to download. */ |
55 private static final int MAX_NUMBER_OF_MANIFESTS = 10; | 62 private static final int MAX_NUMBER_OF_MANIFESTS = 10; |
56 | 63 |
57 private final WebContents mWebContents; | 64 private final WebContents mWebContents; |
58 private final boolean mQueryBasicCard; | 65 private final boolean mQueryBasicCard; |
59 private final Set<URI> mPaymentMethods; | 66 private final Set<URI> mPaymentMethods; |
60 private final PaymentManifestDownloader mDownloader; | 67 private final PaymentManifestDownloader mDownloader; |
61 private final PaymentManifestParser mParser; | 68 private final PaymentManifestParser mParser; |
62 private final PackageManagerDelegate mPackageManagerDelegate; | 69 private final PackageManagerDelegate mPackageManagerDelegate; |
63 private final PaymentAppCreatedCallback mCallback; | 70 private final PaymentAppCreatedCallback mCallback; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 mPendingApps = new HashMap<>(); | 151 mPendingApps = new HashMap<>(); |
145 mResult = new HashMap<>(); | 152 mResult = new HashMap<>(); |
146 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); | 153 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); |
147 mIsIncognito = activity != null && activity.getCurrentTabModel() != null | 154 mIsIncognito = activity != null && activity.getCurrentTabModel() != null |
148 && activity.getCurrentTabModel().isIncognito(); | 155 && activity.getCurrentTabModel().isIncognito(); |
149 mRequireShowInSettings = requireShowInSettings; | 156 mRequireShowInSettings = requireShowInSettings; |
150 mSettingsLookup = new Intent(AndroidPaymentApp.ACTION_PAY); | 157 mSettingsLookup = new Intent(AndroidPaymentApp.ACTION_PAY); |
151 } | 158 } |
152 | 159 |
153 private void findAndroidPaymentApps() { | 160 private void findAndroidPaymentApps() { |
161 Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY); | |
162 List<ResolveInfo> apps = | |
163 mPackageManagerDelegate.getActivitiesThatCanRespondToIntent(payI ntent); | |
164 if (apps.isEmpty()) { | |
165 onSearchFinished(); | |
166 return; | |
167 } | |
168 | |
169 List<String[]> appSupportedMethods = new ArrayList<String[]>(); | |
170 for (int i = 0; i < apps.size(); i++) { | |
171 appSupportedMethods.add(mPackageManagerDelegate.getStringArrayMetaDa ta( | |
172 apps.get(i).activityInfo.packageName, META_DATA_NAME_OF_PAYM ENT_METHOD_NAMES)); | |
173 } | |
174 | |
175 List<String> appSupportedDefaultMethods = new ArrayList<String>(); | |
176 for (int i = 0; i < apps.size(); i++) { | |
177 appSupportedDefaultMethods.add( | |
178 mPackageManagerDelegate.getStringMetaData(apps.get(i).activi tyInfo.packageName, | |
179 META_DATA_NAME_OF_DEFAULT_PAYMENT_METHOD_NAME)); | |
180 } | |
181 | |
154 List<PaymentManifestVerifier> verifiers = new ArrayList<>(); | 182 List<PaymentManifestVerifier> verifiers = new ArrayList<>(); |
155 if (!mPaymentMethods.isEmpty()) { | 183 if (!mPaymentMethods.isEmpty()) { |
please use gerrit instead
2017/03/31 15:47:08
This check seems redundant now. Let's remove it.
gogerald1
2017/03/31 16:18:43
Why? mPaymentMethods is merchant queried methods w
please use gerrit instead
2017/03/31 16:26:30
It's redundant because the for loop on the next li
gogerald1
2017/03/31 16:28:54
yes, my bad, updated in the new patch
| |
156 Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY); | |
157 for (URI methodName : mPaymentMethods) { | 184 for (URI methodName : mPaymentMethods) { |
158 payIntent.setData(Uri.parse(methodName.toString())); | 185 List<ResolveInfo> supportedApps = findOutAppsSupportTheGivenPaym entMethod(apps, |
159 List<ResolveInfo> apps = | 186 appSupportedMethods, appSupportedDefaultMethods, methodN ame.toString()); |
160 mPackageManagerDelegate.getActivitiesThatCanRespondToInt ent(payIntent); | 187 if (supportedApps.isEmpty()) continue; |
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 know 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 seconds. |
165 if (!mParser.isUtilityProcessRunning()) mParser.startUtilityProc ess(); | 191 if (!mParser.isUtilityProcessRunning()) mParser.startUtilityProc ess(); |
166 | 192 |
167 verifiers.add(new PaymentManifestVerifier(methodName, apps, mDow nloader, mParser, | 193 verifiers.add(new PaymentManifestVerifier(methodName, supportedA pps, mDownloader, |
168 mPackageManagerDelegate, this /* callback */)); | 194 mParser, mPackageManagerDelegate, this /* callback */)); |
169 mPendingApps.put(methodName, new HashSet<>(apps)); | 195 mPendingApps.put(methodName, new HashSet<>(supportedApps)); |
196 | |
170 if (verifiers.size() == MAX_NUMBER_OF_MANIFESTS) { | 197 if (verifiers.size() == MAX_NUMBER_OF_MANIFESTS) { |
171 Log.d(TAG, "Reached maximum number of allowed payment app ma nifests."); | 198 Log.d(TAG, "Reached maximum number of allowed payment app ma nifests."); |
172 break; | 199 break; |
173 } | 200 } |
174 } | 201 } |
175 } | 202 } |
176 | 203 |
177 if (mQueryBasicCard) { | 204 if (mQueryBasicCard) { |
178 Intent basicCardPayIntent = new Intent(ACTION_PAY_BASIC_CARD); | 205 List<ResolveInfo> supportedApps = findOutAppsSupportTheGivenPaymentM ethod(apps, |
179 List<ResolveInfo> apps = | 206 appSupportedMethods, appSupportedDefaultMethods, BASIC_CARD_ PAYMENT_METHOD); |
180 mPackageManagerDelegate.getActivitiesThatCanRespondToIntent( basicCardPayIntent); | 207 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 . | 208 // Chrome does not verify app manifests for "basic-card" support . |
183 onValidPaymentApp(BASIC_CARD_PAYMENT_METHOD, apps.get(i)); | 209 onValidPaymentApp(BASIC_CARD_PAYMENT_METHOD, supportedApps.get(i )); |
184 } | 210 } |
185 } | 211 } |
186 | 212 |
187 if (verifiers.isEmpty()) { | 213 if (verifiers.isEmpty()) { |
188 onSearchFinished(); | 214 onSearchFinished(); |
189 return; | 215 return; |
190 } | 216 } |
191 | 217 |
192 for (int i = 0; i < verifiers.size(); i++) { | 218 for (int i = 0; i < verifiers.size(); i++) { |
193 verifiers.get(i).verify(); | 219 verifiers.get(i).verify(); |
194 } | 220 } |
195 } | 221 } |
196 | 222 |
223 private List<ResolveInfo> findOutAppsSupportTheGivenPaymentMethod(List<Resol veInfo> apps, | |
please use gerrit instead
2017/03/31 15:47:08
static?
please use gerrit instead
2017/03/31 15:47:08
filterAppsByMethodName().
gogerald1
2017/03/31 16:18:43
Done.
gogerald1
2017/03/31 16:18:43
Done.
| |
224 List<String[]> appsMethods, List<String> appsDefaultMethods, String targetMethodName) { | |
please use gerrit instead
2017/03/31 15:47:08
Let's pass URI data type in as many places as poss
gogerald1
2017/03/31 16:18:43
Looks not good since this interface is also used f
| |
225 assert apps.size() == appsMethods.size(); | |
226 assert apps.size() == appsDefaultMethods.size(); | |
227 | |
228 // Note that apps, appsMethods and appsDefaultMethods must have the same size. And the | |
229 // information at the same index must correspond to the same app. | |
230 List<ResolveInfo> supportedApps = new ArrayList<ResolveInfo>(); | |
231 for (int i = 0; i < apps.size(); i++) { | |
232 if (targetMethodName.equalsIgnoreCase(appsDefaultMethods.get(i))) { | |
please use gerrit instead
2017/03/31 15:47:08
Don't ignore case. Let's be strict.
gogerald1
2017/03/31 16:18:43
Done. I am worried that the merchant might use upp
please use gerrit instead
2017/03/31 16:26:30
We prohibit variations in the spec as much as poss
| |
233 supportedApps.add(apps.get(i)); | |
234 continue; | |
235 } | |
236 | |
237 String[] methods = appsMethods.get(i); | |
238 if (methods == null) continue; | |
239 for (int j = 0; j < methods.length; j++) { | |
240 if (targetMethodName.equalsIgnoreCase(methods[j])) { | |
241 supportedApps.add(apps.get(i)); | |
242 break; | |
243 } | |
244 } | |
245 } | |
246 return supportedApps; | |
247 } | |
248 | |
197 @Override | 249 @Override |
198 public void onValidPaymentApp(URI methodName, ResolveInfo resolveInfo) { | 250 public void onValidPaymentApp(URI methodName, ResolveInfo resolveInfo) { |
199 onValidPaymentApp(methodName.toString(), resolveInfo); | 251 onValidPaymentApp(methodName.toString(), resolveInfo); |
200 removePendingApp(methodName, resolveInfo); | 252 removePendingApp(methodName, resolveInfo); |
201 } | 253 } |
202 | 254 |
203 /** Same as above, but also works for non-URI method names, e.g., "basic-car d". */ | 255 /** Same as above, but also works for non-URI method names, e.g., "basic-car d". */ |
204 private void onValidPaymentApp(String methodName, ResolveInfo resolveInfo) { | 256 private void onValidPaymentApp(String methodName, ResolveInfo resolveInfo) { |
205 String packageName = resolveInfo.activityInfo.packageName; | 257 String packageName = resolveInfo.activityInfo.packageName; |
206 AndroidPaymentApp app = mResult.get(packageName); | 258 AndroidPaymentApp app = mResult.get(packageName); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 } | 315 } |
264 } | 316 } |
265 | 317 |
266 for (Map.Entry<String, AndroidPaymentApp> entry : mResult.entrySet()) { | 318 for (Map.Entry<String, AndroidPaymentApp> entry : mResult.entrySet()) { |
267 mCallback.onPaymentAppCreated(entry.getValue()); | 319 mCallback.onPaymentAppCreated(entry.getValue()); |
268 } | 320 } |
269 | 321 |
270 mCallback.onAllPaymentAppsCreated(); | 322 mCallback.onAllPaymentAppsCreated(); |
271 } | 323 } |
272 } | 324 } |
OLD | NEW |