| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/digital_credentials/digital_identity_provider_android.h" |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_string.h" |
| #include "base/json/json_writer.h" |
| #include "base/values.h" |
| #include "chrome/browser/digital_credentials/digital_identity_low_risk_origins.h" |
| #include "chrome/browser/ui/digital_credentials/digital_identity_safety_interstitial_bridge_android.h" |
| #include "chrome/browser/ui/digital_credentials/digital_identity_safety_interstitial_controller.h" |
| #include "content/public/browser/digital_identity_provider.h" |
| #include "content/public/browser/web_contents.h" |
| #include "ui/android/window_android.h" |
| |
| // Must come after all headers that specialize FromJniType() / ToJniType(). |
| #include "chrome/browser/webid/jni_headers/DigitalIdentityProvider_jni.h" |
| |
| using base::android::AttachCurrentThread; |
| using base::android::ConvertJavaStringToUTF8; |
| using base::android::ConvertUTF8ToJavaString; |
| using base::android::ScopedJavaLocalRef; |
| |
| using RequestStatusForMetrics = |
| content::DigitalIdentityProvider::RequestStatusForMetrics; |
| using DigitalIdentityInterstitialAbortCallback = |
| content::DigitalIdentityProvider::DigitalIdentityInterstitialAbortCallback; |
| |
| namespace { |
| |
| void RunDigitalIdentityCallback( |
| std::unique_ptr<DigitalIdentitySafetyInterstitialBridgeAndroid> controller, |
| content::DigitalIdentityProvider::DigitalIdentityInterstitialCallback |
| callback, |
| content::DigitalIdentityProvider::RequestStatusForMetrics |
| status_for_metrics) { |
| std::move(callback).Run(status_for_metrics); |
| } |
| |
| } // anonymous namespace |
| |
| DigitalIdentityProviderAndroid::DigitalIdentityProviderAndroid() { |
| JNIEnv* env = AttachCurrentThread(); |
| j_digital_identity_provider_android_.Reset( |
| Java_DigitalIdentityProvider_create(env, |
| reinterpret_cast<intptr_t>(this))); |
| } |
| |
| DigitalIdentityProviderAndroid::~DigitalIdentityProviderAndroid() { |
| JNIEnv* env = AttachCurrentThread(); |
| Java_DigitalIdentityProvider_destroy( |
| env, j_digital_identity_provider_android_); |
| } |
| |
| bool DigitalIdentityProviderAndroid::IsLowRiskOrigin( |
| const url::Origin& to_check) const { |
| return digital_credentials::IsLowRiskOrigin(to_check); |
| } |
| |
| DigitalIdentityInterstitialAbortCallback |
| DigitalIdentityProviderAndroid::ShowDigitalIdentityInterstitial( |
| content::WebContents& web_contents, |
| const url::Origin& origin, |
| content::DigitalIdentityInterstitialType interstitial_type, |
| DigitalIdentityInterstitialCallback callback) { |
| auto controller = |
| std::make_unique<DigitalIdentitySafetyInterstitialBridgeAndroid>(); |
| // Callback takes ownership of |controller|. |
| return controller->ShowInterstitial( |
| web_contents, origin, interstitial_type, |
| base::BindOnce(&RunDigitalIdentityCallback, std::move(controller), |
| std::move(callback))); |
| } |
| |
| void DigitalIdentityProviderAndroid::Request(content::WebContents* web_contents, |
| const url::Origin& origin, |
| const base::Value request, |
| DigitalIdentityCallback callback) { |
| callback_ = std::move(callback); |
| JNIEnv* env = AttachCurrentThread(); |
| ScopedJavaLocalRef<jstring> j_origin = |
| ConvertUTF8ToJavaString(env, origin.Serialize()); |
| std::optional<std::string> request_str = base::WriteJson(request); |
| ScopedJavaLocalRef<jstring> j_request = |
| ConvertUTF8ToJavaString(env, *request_str); |
| |
| base::android::ScopedJavaLocalRef<jobject> j_window = nullptr; |
| |
| if (web_contents && web_contents->GetTopLevelNativeWindow()) { |
| j_window = web_contents->GetTopLevelNativeWindow()->GetJavaObject(); |
| } |
| |
| Java_DigitalIdentityProvider_request( |
| env, j_digital_identity_provider_android_, j_window, j_origin, |
| j_request); |
| } |
| |
| void DigitalIdentityProviderAndroid::OnReceive(JNIEnv* env, |
| jstring j_digital_identity, |
| jint j_status_for_metrics) { |
| if (callback_) { |
| std::string digital_identity = |
| ConvertJavaStringToUTF8(env, j_digital_identity); |
| |
| auto status_for_metrics = |
| static_cast<RequestStatusForMetrics>(j_status_for_metrics); |
| std::move(callback_).Run( |
| (status_for_metrics == RequestStatusForMetrics::kSuccess) |
| ? base::expected<std::string, RequestStatusForMetrics>( |
| digital_identity) |
| : base::unexpected(status_for_metrics)); |
| } |
| } |