xref: /aosp_15_r20/external/cronet/url/android/gurl_android.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "url/android/gurl_android.h"
6 
7 #include <cstdint>
8 #include <string>
9 #include <vector>
10 
11 #include "base/android/jni_android.h"
12 #include "base/android/jni_string.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/strings/string_util.h"
17 #include "url/android/parsed_android.h"
18 #include "url/third_party/mozilla/url_parse.h"
19 #include "url/url_jni_headers/GURL_jni.h"
20 
21 using jni_zero::AttachCurrentThread;
22 using jni_zero::JavaParamRef;
23 using jni_zero::JavaRef;
24 using jni_zero::ScopedJavaLocalRef;
25 
26 namespace jni_zero {
27 
28 // Convert from java GURL.java pointer to native GURL object.
29 template <>
COMPONENT_EXPORT(URL)30 COMPONENT_EXPORT(URL)
31 GURL FromJniType<GURL>(JNIEnv* env, const JavaRef<jobject>& j_gurl) {
32   return url::GURLAndroid::ToNativeGURL(env, j_gurl);
33 }
34 
35 // Convert from native GURL object to a GURL.java object pointer.
36 template <>
COMPONENT_EXPORT(URL)37 COMPONENT_EXPORT(URL)
38 ScopedJavaLocalRef<jobject> ToJniType<GURL>(JNIEnv* env, const GURL& gurl) {
39   return url::GURLAndroid::FromNativeGURL(env, gurl);
40 }
41 }  // namespace jni_zero
42 
43 namespace url {
44 
45 namespace {
46 
InitFromGURL(JNIEnv * env,const GURL & gurl,const JavaRef<jobject> & target)47 static void InitFromGURL(JNIEnv* env,
48                          const GURL& gurl,
49                          const JavaRef<jobject>& target) {
50   // Ensure that the spec only contains US-ASCII (single-byte characters) or the
51   // parsed indices will be wrong as the indices are in bytes while Java Strings
52   // are always 16-bit.
53   DCHECK(base::IsStringASCII(gurl.possibly_invalid_spec()));
54   Java_GURL_init(env, target, gurl.possibly_invalid_spec(), gurl.is_valid(),
55                  ParsedAndroid::InitFromParsed(
56                      env, gurl.parsed_for_possibly_invalid_spec()));
57 }
58 
59 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it
60 // may be -1 if |array| is not a valid Java array), provide a safe wrapper
61 // that always returns a valid, non-negative size.
62 template <typename JavaArrayType>
SafeGetArrayLength(JNIEnv * env,const JavaRef<JavaArrayType> & jarray)63 size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) {
64   DCHECK(jarray);
65   jsize length = env->GetArrayLength(jarray.obj());
66   DCHECK_GE(length, 0) << "Invalid array length: " << length;
67   return static_cast<size_t>(std::max(0, length));
68 }
69 
70 }  // namespace
71 
72 // static
ToNativeGURL(JNIEnv * env,const base::android::JavaRef<jobject> & j_gurl)73 GURL GURLAndroid::ToNativeGURL(JNIEnv* env,
74                                const base::android::JavaRef<jobject>& j_gurl) {
75   GURL ret;
76   Parsed parsed;
77   Java_GURL_toNativeGURL(env, j_gurl, reinterpret_cast<jlong>(&ret),
78                          reinterpret_cast<jlong>(&parsed));
79   return ret;
80 }
81 
82 // static
FromNativeGURL(JNIEnv * env,const GURL & gurl)83 ScopedJavaLocalRef<jobject> GURLAndroid::FromNativeGURL(JNIEnv* env,
84                                                         const GURL& gurl) {
85   ScopedJavaLocalRef<jobject> j_gurl = Java_GURL_Constructor(env);
86   InitFromGURL(env, gurl, j_gurl);
87   return j_gurl;
88 }
89 
90 // static
EmptyGURL(JNIEnv * env)91 ScopedJavaLocalRef<jobject> GURLAndroid::EmptyGURL(JNIEnv* env) {
92   return Java_GURL_emptyGURL(env);
93 }
94 
JNI_GURL_GetOrigin(JNIEnv * env,GURL & gurl,const JavaParamRef<jobject> & target)95 static void JNI_GURL_GetOrigin(JNIEnv* env,
96                                GURL& gurl,
97                                const JavaParamRef<jobject>& target) {
98   InitFromGURL(env, gurl.DeprecatedGetOriginAsURL(), target);
99 }
100 
JNI_GURL_DomainIs(JNIEnv * env,GURL & gurl,std::string & domain)101 static jboolean JNI_GURL_DomainIs(JNIEnv* env,
102                                   GURL& gurl,
103                                   std::string& domain) {
104   return gurl.DomainIs(domain);
105 }
106 
JNI_GURL_Init(JNIEnv * env,std::string & spec,const base::android::JavaParamRef<jobject> & target)107 static void JNI_GURL_Init(JNIEnv* env,
108                           std::string& spec,
109                           const base::android::JavaParamRef<jobject>& target) {
110   auto gurl = GURL(spec);
111   InitFromGURL(env, gurl, target);
112 }
113 
JNI_GURL_InitNative(JNIEnv * env,std::string & spec,jboolean is_valid,jlong native_gurl,jlong native_parsed)114 static void JNI_GURL_InitNative(JNIEnv* env,
115                                 std::string& spec,
116                                 jboolean is_valid,
117                                 jlong native_gurl,
118                                 jlong native_parsed) {
119   GURL* gurl = reinterpret_cast<GURL*>(native_gurl);
120   Parsed* parsed = reinterpret_cast<Parsed*>(native_parsed);
121   *gurl = GURL(spec, *parsed, is_valid);
122 }
123 
JNI_GURL_ReplaceComponents(JNIEnv * env,GURL & gurl,const JavaParamRef<jstring> & j_username_replacement,jboolean clear_username,const JavaParamRef<jstring> & j_password_replacement,jboolean clear_password,const JavaParamRef<jobject> & j_result)124 static void JNI_GURL_ReplaceComponents(
125     JNIEnv* env,
126     GURL& gurl,
127     const JavaParamRef<jstring>& j_username_replacement,
128     jboolean clear_username,
129     const JavaParamRef<jstring>& j_password_replacement,
130     jboolean clear_password,
131     const JavaParamRef<jobject>& j_result) {
132   GURL::Replacements replacements;
133 
134   // Replacement strings must remain in scope for ReplaceComponents().
135   std::string username;
136   std::string password;
137 
138   if (clear_username) {
139     replacements.ClearUsername();
140   } else if (j_username_replacement) {
141     username =
142         base::android::ConvertJavaStringToUTF8(env, j_username_replacement);
143     replacements.SetUsernameStr(username);
144   }
145 
146   if (clear_password) {
147     replacements.ClearPassword();
148   } else if (j_password_replacement) {
149     password =
150         base::android::ConvertJavaStringToUTF8(env, j_password_replacement);
151     replacements.SetPasswordStr(password);
152   }
153 
154   InitFromGURL(env, gurl.ReplaceComponents(replacements), j_result);
155 }
156 
157 }  // namespace url
158