Cache payment manifests.
In this patch:
Try to fetch all supported web app ids for the payment method from
the cache before downloading its manifest online. If cached web app
ids contain all matching apps ids, proceed fetching corresponding web
apps manifests from the cache. Otherwise fall back to download the
payment method's manifest online. If failed to fetch at least one web
app's manifest from the cache, then fall back to download payment
method's manifest online.
In addition:
Cache downloaded and parsed supported web apps ids of the payment
method for future reference. Cache downloaded and parsed web app
manifest sections for future reference.
Refer to below doc for details.
https://docs.google.com/a/google.com/document/d/1Ncsp96Ae5836NLOdPwHRzcX3zkgj-4-5fq_nI2azC7M
BUG=708508
Review-Url: https://codereview.chromium.org/2838433002
Cr-Commit-Position: refs/heads/master@{#467688}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index c47ebb5..1920172b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3113,6 +3113,8 @@
"payments/android/chrome_payments_jni_registrar.h",
"payments/android/journey_logger_android.cc",
"payments/android/journey_logger_android.h",
+ "payments/android/payment_manifest_web_data_service_android.cc",
+ "payments/android/payment_manifest_web_data_service_android.h",
"payments/android/ssl_validity_checker_android.cc",
"payments/android/ssl_validity_checker_android.h",
"permissions/grouped_permission_infobar_delegate_android.cc",
@@ -4187,6 +4189,7 @@
"../android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java",
"../android/java/src/org/chromium/chrome/browser/password_manager/Credential.java",
"../android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java",
+ "../android/java/src/org/chromium/chrome/browser/payments/PaymentManifestWebDataService.java",
"../android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java",
"../android/java/src/org/chromium/chrome/browser/payments/SslValidityChecker.java",
"../android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java",
diff --git a/chrome/browser/payments/android/chrome_payments_jni_registrar.cc b/chrome/browser/payments/android/chrome_payments_jni_registrar.cc
index f04a124..293945b 100644
--- a/chrome/browser/payments/android/chrome_payments_jni_registrar.cc
+++ b/chrome/browser/payments/android/chrome_payments_jni_registrar.cc
@@ -8,6 +8,7 @@
#include "base/android/jni_registrar.h"
#include "base/macros.h"
#include "chrome/browser/payments/android/journey_logger_android.h"
+#include "chrome/browser/payments/android/payment_manifest_web_data_service_android.h"
#include "chrome/browser/payments/android/ssl_validity_checker_android.h"
namespace payments {
@@ -16,6 +17,8 @@
static base::android::RegistrationMethod kChromePaymentsRegisteredMethods[] = {
{"JourneyLogger", JourneyLoggerAndroid::Register},
{"SslValidityChecker", RegisterSslValidityChecker},
+ {"PaymentManifestWebDataService",
+ PaymentManifestWebDataServiceAndroid::Register},
};
bool RegisterChromePayments(JNIEnv* env) {
diff --git a/chrome/browser/payments/android/payment_manifest_web_data_service_android.cc b/chrome/browser/payments/android/payment_manifest_web_data_service_android.cc
new file mode 100644
index 0000000..0938af0
--- /dev/null
+++ b/chrome/browser/payments/android/payment_manifest_web_data_service_android.cc
@@ -0,0 +1,233 @@
+// Copyright 2017 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/android/payment_manifest_web_data_service_android.h"
+
+#include <string>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/web_data_service_factory.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/webdata/common/web_data_results.h"
+#include "jni/PaymentManifestWebDataService_jni.h"
+
+namespace payments {
+
+// static
+bool PaymentManifestWebDataServiceAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+PaymentManifestWebDataServiceAndroid::PaymentManifestWebDataServiceAndroid(
+ JNIEnv* env,
+ jobject obj)
+ : weak_java_obj_(env, obj) {}
+
+PaymentManifestWebDataServiceAndroid::~PaymentManifestWebDataServiceAndroid() {}
+
+void PaymentManifestWebDataServiceAndroid::OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle h,
+ std::unique_ptr<WDTypedResult> result) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (weak_java_obj_.get(env).is_null())
+ return;
+
+ if (web_data_service_requests_.find(h) == web_data_service_requests_.end())
+ return;
+
+ switch (result->GetType()) {
+ case PAYMENT_WEB_APP_MANIFEST:
+ OnWebAppManifestRequestDone(env, h, result.get());
+ break;
+ case PAYMENT_METHOD_MANIFEST:
+ OnPaymentMethodManifestRequestDone(env, h, result.get());
+ break;
+ default:
+ NOTREACHED() << "unsupported data type";
+ }
+}
+
+void PaymentManifestWebDataServiceAndroid::OnWebAppManifestRequestDone(
+ JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result) {
+ const WDResult<std::vector<mojom::WebAppManifestSectionPtr>>* typed_result =
+ static_cast<
+ const WDResult<std::vector<mojom::WebAppManifestSectionPtr>>*>(
+ result);
+ const std::vector<mojom::WebAppManifestSectionPtr>* manifest =
+ &(typed_result->GetValue());
+
+ base::android::ScopedJavaLocalRef<jobjectArray> jmanifest =
+ Java_PaymentManifestWebDataService_createManifest(env, manifest->size());
+
+ for (size_t i = 0; i < manifest->size(); ++i) {
+ const mojom::WebAppManifestSectionPtr& section = manifest->at(i);
+ DCHECK_GE(100U, section->fingerprints.size());
+
+ Java_PaymentManifestWebDataService_addSectionToManifest(
+ env, jmanifest.obj(), base::checked_cast<int>(i),
+ base::android::ConvertUTF8ToJavaString(env, section->id),
+ section->min_version,
+ base::checked_cast<int>(section->fingerprints.size()));
+
+ for (size_t j = 0; j < section->fingerprints.size(); ++j) {
+ const std::vector<uint8_t>& fingerprint = section->fingerprints[j];
+ Java_PaymentManifestWebDataService_addFingerprintToSection(
+ env, jmanifest.obj(), base::checked_cast<int>(i),
+ base::checked_cast<int>(j),
+ base::android::ToJavaByteArray(env, fingerprint));
+ }
+ }
+
+ Java_PaymentManifestWebDataServiceCallback_onPaymentWebAppManifestFetched(
+ env, web_data_service_requests_[h]->obj(), jmanifest.obj());
+ web_data_service_requests_.erase(h);
+}
+
+void PaymentManifestWebDataServiceAndroid::OnPaymentMethodManifestRequestDone(
+ JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result) {
+ const WDResult<std::vector<std::string>>* typed_result =
+ static_cast<const WDResult<std::vector<std::string>>*>(result);
+ const std::vector<std::string>* web_apps_ids = &(typed_result->GetValue());
+
+ Java_PaymentManifestWebDataServiceCallback_onPaymentMethodManifestFetched(
+ env, web_data_service_requests_[h]->obj(),
+ base::android::ToJavaArrayOfStrings(env, *web_apps_ids));
+ web_data_service_requests_.erase(h);
+}
+
+void PaymentManifestWebDataServiceAndroid::Destroy(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj) {
+ delete this;
+}
+
+void PaymentManifestWebDataServiceAndroid::AddPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobjectArray>& japps_package_names) {
+ std::vector<std::string> apps_package_names;
+ base::android::AppendJavaStringArrayToStringVector(env, japps_package_names,
+ &apps_package_names);
+
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+ ProfileManager::GetActiveUserProfile(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+ if (web_data_service == nullptr)
+ return;
+
+ web_data_service->AddPaymentMethodManifest(
+ base::android::ConvertJavaStringToUTF8(jmethod_name),
+ std::move(apps_package_names));
+}
+
+void PaymentManifestWebDataServiceAndroid::AddPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jobjectArray>& jmanifest_sections) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+ ProfileManager::GetActiveUserProfile(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+ if (web_data_service == nullptr)
+ return;
+
+ std::vector<mojom::WebAppManifestSectionPtr> manifest;
+
+ jsize jcount_of_sections = env->GetArrayLength(jmanifest_sections.obj());
+ for (jsize i = 0; i < jcount_of_sections; i++) {
+ mojom::WebAppManifestSectionPtr section =
+ mojom::WebAppManifestSection::New();
+
+ base::android::ScopedJavaLocalRef<jobject> jsection(
+ env, env->GetObjectArrayElement(jmanifest_sections.obj(), i));
+ section->id = base::android::ConvertJavaStringToUTF8(
+ Java_PaymentManifestWebDataService_getIdFromSection(env,
+ jsection.obj()));
+ section->min_version = static_cast<int64_t>(
+ Java_PaymentManifestWebDataService_getMinVersionFromSection(
+ env, jsection.obj()));
+
+ base::android::ScopedJavaLocalRef<jobjectArray> jsection_fingerprints(
+ Java_PaymentManifestWebDataService_getFingerprintsFromSection(
+ env, jsection.obj()));
+ jsize jcount_of_fingerprints =
+ env->GetArrayLength(jsection_fingerprints.obj());
+ for (jsize j = 0; j < jcount_of_fingerprints; j++) {
+ std::vector<uint8_t> fingerprint;
+ base::android::ScopedJavaLocalRef<jbyteArray> jfingerprint(
+ env, (jbyteArray)env->GetObjectArrayElement(
+ jsection_fingerprints.obj(), j));
+ base::android::JavaByteArrayToByteVector(env, jfingerprint.obj(),
+ &fingerprint);
+ section->fingerprints.emplace_back(fingerprint);
+ }
+
+ manifest.emplace_back(std::move(section));
+ }
+
+ web_data_service->AddPaymentWebAppManifest(std::move(manifest));
+}
+
+bool PaymentManifestWebDataServiceAndroid::GetPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobject>& jcallback) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+ ProfileManager::GetActiveUserProfile(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+ if (web_data_service == nullptr)
+ return false;
+
+ WebDataServiceBase::Handle handle =
+ web_data_service->GetPaymentMethodManifest(
+ base::android::ConvertJavaStringToUTF8(env, jmethod_name), this);
+ web_data_service_requests_[handle] =
+ base::MakeUnique<base::android::ScopedJavaGlobalRef<jobject>>(jcallback);
+
+ return true;
+}
+
+bool PaymentManifestWebDataServiceAndroid::GetPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& japp_package_name,
+ const base::android::JavaParamRef<jobject>& jcallback) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+ ProfileManager::GetActiveUserProfile(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+ if (web_data_service == nullptr)
+ return false;
+
+ WebDataServiceBase::Handle handle =
+ web_data_service->GetPaymentWebAppManifest(
+ base::android::ConvertJavaStringToUTF8(env, japp_package_name), this);
+ web_data_service_requests_[handle] =
+ base::MakeUnique<base::android::ScopedJavaGlobalRef<jobject>>(jcallback);
+
+ return true;
+}
+
+static jlong Init(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ PaymentManifestWebDataServiceAndroid* manifest_web_data_service_android =
+ new PaymentManifestWebDataServiceAndroid(env, obj);
+ return reinterpret_cast<intptr_t>(manifest_web_data_service_android);
+}
+
+} // namespace payments
diff --git a/chrome/browser/payments/android/payment_manifest_web_data_service_android.h b/chrome/browser/payments/android/payment_manifest_web_data_service_android.h
new file mode 100644
index 0000000..0033c0e
--- /dev/null
+++ b/chrome/browser/payments/android/payment_manifest_web_data_service_android.h
@@ -0,0 +1,95 @@
+// Copyright 2017 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_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
+#define CHROME_BROWSER_PAYMENTS_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
+
+#include <jni.h>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "components/payments/android/payment_manifest_web_data_service.h"
+#include "components/payments/mojom/payment_manifest_parser.mojom.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+
+namespace payments {
+
+// Android wrapper of the PaymentManifestWebDataService which provides access
+// from the Java layer. Note that on Android, there's only a single profile, and
+// therefore a single instance of this wrapper.
+class PaymentManifestWebDataServiceAndroid : public WebDataServiceConsumer {
+ public:
+ // Registers the JNI bindings for this class.
+ static bool Register(JNIEnv* env);
+
+ PaymentManifestWebDataServiceAndroid(JNIEnv* env, jobject obj);
+ ~PaymentManifestWebDataServiceAndroid() override;
+
+ // Override WebDataServiceConsumer interface.
+ void OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle h,
+ std::unique_ptr<WDTypedResult> result) override;
+
+ // Destroys this object.
+ void Destroy(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj);
+
+ // Adds the supported |japp_package_names| of the |jmethod_name| to the
+ // cache.
+ void AddPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobjectArray>& japp_package_names);
+
+ // Adds the web app |jmanifest_sections|.
+ void AddPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jobjectArray>& jmanifest_sections);
+
+ // Gets the payment |jmethod_name|'s manifest asynchronously from the web data
+ // service. Return true if the result will be returned through |jcallback|.
+ bool GetPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobject>& jcallback);
+
+ // Gets the payment |japp_package_name|'s manifest asynchronously from the web
+ // data service. Return true if the result will be returned through
+ // |jcallback|.
+ bool GetPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& japp_package_name,
+ const base::android::JavaParamRef<jobject>& jcallback);
+
+ private:
+ void OnWebAppManifestRequestDone(JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result);
+ void OnPaymentMethodManifestRequestDone(JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result);
+
+ // Pointer to the java counterpart.
+ JavaObjectWeakGlobalRef weak_java_obj_;
+
+ // Map of request handle and its correspond callback.
+ std::map<WebDataServiceBase::Handle,
+ std::unique_ptr<base::android::ScopedJavaGlobalRef<jobject>>>
+ web_data_service_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaymentManifestWebDataServiceAndroid);
+};
+
+} // namespace payments
+
+#endif // CHROME_BROWSER_PAYMENTS_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
diff --git a/chrome/browser/ui/profile_error_dialog.h b/chrome/browser/ui/profile_error_dialog.h
index 0c552a7..011a1ab 100644
--- a/chrome/browser/ui/profile_error_dialog.h
+++ b/chrome/browser/ui/profile_error_dialog.h
@@ -21,6 +21,7 @@
DB_KEYWORD_WEB_DATA,
CREATE_FAILURE_SPECIFIED,
CREATE_FAILURE_ALL,
+ DB_PAYMENT_MANIFEST_WEB_DATA,
END
};
diff --git a/chrome/browser/web_data_service_factory.cc b/chrome/browser/web_data_service_factory.cc
index 258de38..e0cf5cb3 100644
--- a/chrome/browser/web_data_service_factory.cc
+++ b/chrome/browser/web_data_service_factory.cc
@@ -25,6 +25,10 @@
#include "components/password_manager/core/browser/webdata/password_web_data_service_win.h"
#endif
+#if defined(OS_ANDROID)
+#include "components/payments/android/payment_manifest_web_data_service.h"
+#endif
+
using content::BrowserThread;
namespace {
@@ -45,6 +49,9 @@
case WebDataServiceWrapper::ERROR_LOADING_PASSWORD:
return ProfileErrorType::DB_WEB_DATA;
+ case WebDataServiceWrapper::ERROR_LOADING_PAYMENT_MANIFEST:
+ return ProfileErrorType::DB_PAYMENT_MANIFEST_WEB_DATA;
+
default:
NOTREACHED()
<< "Unknown WebDataServiceWrapper::ErrorType: " << error_type;
@@ -150,6 +157,21 @@
}
#endif
+#if defined(OS_ANDROID)
+// static
+scoped_refptr<payments::PaymentManifestWebDataService>
+WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+ Profile* profile,
+ ServiceAccessType access_type) {
+ WebDataServiceWrapper* wrapper =
+ WebDataServiceFactory::GetForProfile(profile, access_type);
+ // |wrapper| can be null in Incognito mode.
+ return wrapper
+ ? wrapper->GetPaymentManifestWebData()
+ : scoped_refptr<payments::PaymentManifestWebDataService>(nullptr);
+}
+#endif
+
// static
WebDataServiceFactory* WebDataServiceFactory::GetInstance() {
return base::Singleton<WebDataServiceFactory>::get();
diff --git a/chrome/browser/web_data_service_factory.h b/chrome/browser/web_data_service_factory.h
index 9ab05630..c2a4a8a6 100644
--- a/chrome/browser/web_data_service_factory.h
+++ b/chrome/browser/web_data_service_factory.h
@@ -24,6 +24,12 @@
class PasswordWebDataService;
#endif
+#if defined(OS_ANDROID)
+namespace payments {
+class PaymentManifestWebDataService;
+}
+#endif
+
namespace autofill {
class AutofillWebDataService;
}
@@ -61,6 +67,12 @@
ServiceAccessType access_type);
#endif
+#if defined(OS_ANDROID)
+ static scoped_refptr<payments::PaymentManifestWebDataService>
+ GetPaymentManifestWebDataForProfile(Profile* profile,
+ ServiceAccessType access_type);
+#endif
+
static WebDataServiceFactory* GetInstance();
private: