// 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 "base/android/jni_string.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "url/android/parsed_android.h" #include "url/third_party/mozilla/url_parse.h" // // Must come after all headers that specialize FromJniType() / ToJniType(). #include "url/url_jni_headers/GURL_jni.h" using jni_zero::AttachCurrentThread; using jni_zero::JavaParamRef; using jni_zero::JavaRef; using jni_zero::ScopedJavaLocalRef; namespace url { namespace { static void InitFromGURL(JNIEnv* env, const GURL& gurl, const JavaRef& target) { // Ensure that the spec only contains US-ASCII (single-byte characters) or the // parsed indices will be wrong as the indices are in bytes while Java Strings // are always 16-bit. DCHECK(base::IsStringASCII(gurl.possibly_invalid_spec())); Java_GURL_init(env, target, 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 GURL GURLAndroid::ToNativeGURL(JNIEnv* env, const base::android::JavaRef& j_gurl) { GURL ret; Parsed parsed; Java_GURL_toNativeGURL(env, j_gurl, reinterpret_cast(&ret), reinterpret_cast(&parsed)); return ret; } // 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 void JNI_GURL_GetOrigin(JNIEnv* env, GURL& gurl, const JavaParamRef& target) { InitFromGURL(env, gurl.DeprecatedGetOriginAsURL(), target); } static jboolean JNI_GURL_DomainIs(JNIEnv* env, GURL& gurl, std::string& domain) { return gurl.DomainIs(domain); } static void JNI_GURL_Init(JNIEnv* env, std::string& spec, const base::android::JavaParamRef& target) { auto gurl = GURL(spec); InitFromGURL(env, gurl, target); } static void JNI_GURL_InitNative(JNIEnv* env, std::string& spec, jboolean is_valid, jlong native_gurl, jlong native_parsed) { GURL* gurl = reinterpret_cast(native_gurl); Parsed* parsed = reinterpret_cast(native_parsed); *gurl = GURL(spec, *parsed, is_valid); } static void JNI_GURL_ReplaceComponents( JNIEnv* env, GURL& gurl, const JavaParamRef& j_username_replacement, jboolean clear_username, const JavaParamRef& j_password_replacement, jboolean clear_password, const JavaParamRef& j_result) { GURL::Replacements replacements; // Replacement strings must remain in scope for ReplaceComponents(). std::string username; std::string password; if (clear_username) { replacements.ClearUsername(); } else if (j_username_replacement) { username = base::android::ConvertJavaStringToUTF8(env, j_username_replacement); replacements.SetUsernameStr(username); } if (clear_password) { replacements.ClearPassword(); } else if (j_password_replacement) { password = base::android::ConvertJavaStringToUTF8(env, j_password_replacement); replacements.SetPasswordStr(password); } InitFromGURL(env, gurl.ReplaceComponents(replacements), j_result); } } // namespace url