// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "url/android/gurl_android.h" #include #include #include #include #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/ptr_util.h" #include "url/android/parsed_android.h" #include "url/gurl_jni_headers/GURL_jni.h" #include "url/third_party/mozilla/url_parse.h" using base::android::AttachCurrentThread; using base::android::JavaParamRef; using base::android::JavaRef; using base::android::ScopedJavaLocalRef; namespace url { namespace { static GURL FromJString(JNIEnv* env, const JavaRef& uri) { if (!uri) return GURL(); return GURL(base::android::ConvertJavaStringToUTF16(env, uri)); } static std::unique_ptr FromJavaGURL(JNIEnv* env, const JavaRef& j_spec, bool is_valid, jlong parsed_ptr) { Parsed* parsed = reinterpret_cast(parsed_ptr); const std::string& spec = ConvertJavaStringToUTF8(env, j_spec); std::unique_ptr gurl = std::make_unique(spec.data(), parsed->Length(), *parsed, is_valid); delete parsed; return gurl; } static void InitFromGURL(JNIEnv* env, const GURL& gurl, const JavaRef& target) { Java_GURL_init( env, target, base::android::ConvertUTF8ToJavaString(env, gurl.possibly_invalid_spec()), gurl.is_valid(), ParsedAndroid::InitFromParsed(env, gurl.parsed_for_possibly_invalid_spec())); } // As |GetArrayLength| makes no guarantees about the returned value (e.g., it // may be -1 if |array| is not a valid Java array), provide a safe wrapper // that always returns a valid, non-negative size. template size_t SafeGetArrayLength(JNIEnv* env, const JavaRef& jarray) { DCHECK(jarray); jsize length = env->GetArrayLength(jarray.obj()); DCHECK_GE(length, 0) << "Invalid array length: " << length; return static_cast(std::max(0, length)); } } // namespace // static std::unique_ptr GURLAndroid::ToNativeGURL( JNIEnv* env, const base::android::JavaRef& j_gurl) { return base::WrapUnique( reinterpret_cast(Java_GURL_toNativeGURL(env, j_gurl))); } void GURLAndroid::JavaGURLArrayToGURLVector( JNIEnv* env, const base::android::JavaRef& array, std::vector* out) { DCHECK(out); DCHECK(out->empty()); if (!array) return; size_t len = SafeGetArrayLength(env, array); for (size_t i = 0; i < len; ++i) { ScopedJavaLocalRef j_gurl( env, static_cast(env->GetObjectArrayElement(array.obj(), i))); out->emplace_back( *reinterpret_cast(Java_GURL_toNativeGURL(env, j_gurl))); } } // static ScopedJavaLocalRef GURLAndroid::FromNativeGURL(JNIEnv* env, const GURL& gurl) { ScopedJavaLocalRef j_gurl = Java_GURL_Constructor(env); InitFromGURL(env, gurl, j_gurl); return j_gurl; } // static ScopedJavaLocalRef GURLAndroid::EmptyGURL(JNIEnv* env) { return Java_GURL_emptyGURL(env); } // static ScopedJavaLocalRef GURLAndroid::ToJavaArrayOfGURLs( JNIEnv* env, base::span> v) { jclass clazz = org_chromium_url_GURL_clazz(env); DCHECK(clazz); jobjectArray joa = env->NewObjectArray(v.size(), clazz, nullptr); base::android::CheckException(env); for (size_t i = 0; i < v.size(); ++i) { env->SetObjectArrayElement(joa, i, v[i].obj()); } return ScopedJavaLocalRef(env, joa); } static void JNI_GURL_GetOrigin(JNIEnv* env, const JavaParamRef& j_spec, jboolean is_valid, jlong parsed_ptr, const JavaParamRef& target) { std::unique_ptr gurl = FromJavaGURL(env, j_spec, is_valid, parsed_ptr); InitFromGURL(env, gurl->DeprecatedGetOriginAsURL(), target); } static jboolean JNI_GURL_DomainIs(JNIEnv* env, const JavaParamRef& j_spec, jboolean is_valid, jlong parsed_ptr, const JavaParamRef& j_domain) { std::unique_ptr gurl = FromJavaGURL(env, j_spec, is_valid, parsed_ptr); const std::string& domain = ConvertJavaStringToUTF8(env, j_domain); return gurl->DomainIs(domain); } static void JNI_GURL_Init(JNIEnv* env, const base::android::JavaParamRef& uri, const base::android::JavaParamRef& target) { const GURL& gurl = FromJString(env, uri); InitFromGURL(env, gurl, target); } static jlong JNI_GURL_CreateNative(JNIEnv* env, const JavaParamRef& j_spec, jboolean is_valid, jlong parsed_ptr) { return reinterpret_cast( FromJavaGURL(env, j_spec, is_valid, parsed_ptr).release()); } } // namespace url