• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_string.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/strings/string_util.h"
16 #include "url/android/parsed_android.h"
17 #include "url/third_party/mozilla/url_parse.h"
18 //
19 // Must come after all headers that specialize FromJniType() / ToJniType().
20 #include "url/url_jni_headers/GURL_jni.h"
21 
22 using jni_zero::AttachCurrentThread;
23 using jni_zero::JavaParamRef;
24 using jni_zero::JavaRef;
25 using jni_zero::ScopedJavaLocalRef;
26 
27 
28 namespace url {
29 namespace {
30 
InitFromGURL(JNIEnv * env,const GURL & gurl,const JavaRef<jobject> & target)31 static void InitFromGURL(JNIEnv* env,
32                          const GURL& gurl,
33                          const JavaRef<jobject>& target) {
34   // Ensure that the spec only contains US-ASCII (single-byte characters) or the
35   // parsed indices will be wrong as the indices are in bytes while Java Strings
36   // are always 16-bit.
37   DCHECK(base::IsStringASCII(gurl.possibly_invalid_spec()));
38   Java_GURL_init(env, target, gurl.possibly_invalid_spec(), gurl.is_valid(),
39                  ParsedAndroid::InitFromParsed(
40                      env, gurl.parsed_for_possibly_invalid_spec()));
41 }
42 
43 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it
44 // may be -1 if |array| is not a valid Java array), provide a safe wrapper
45 // that always returns a valid, non-negative size.
46 template <typename JavaArrayType>
SafeGetArrayLength(JNIEnv * env,const JavaRef<JavaArrayType> & jarray)47 size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) {
48   DCHECK(jarray);
49   jsize length = env->GetArrayLength(jarray.obj());
50   DCHECK_GE(length, 0) << "Invalid array length: " << length;
51   return static_cast<size_t>(std::max(0, length));
52 }
53 
54 }  // namespace
55 
56 // static
ToNativeGURL(JNIEnv * env,const base::android::JavaRef<jobject> & j_gurl)57 GURL GURLAndroid::ToNativeGURL(JNIEnv* env,
58                                const base::android::JavaRef<jobject>& j_gurl) {
59   GURL ret;
60   Parsed parsed;
61   Java_GURL_toNativeGURL(env, j_gurl, reinterpret_cast<jlong>(&ret),
62                          reinterpret_cast<jlong>(&parsed));
63   return ret;
64 }
65 
66 // static
FromNativeGURL(JNIEnv * env,const GURL & gurl)67 ScopedJavaLocalRef<jobject> GURLAndroid::FromNativeGURL(JNIEnv* env,
68                                                         const GURL& gurl) {
69   ScopedJavaLocalRef<jobject> j_gurl = Java_GURL_Constructor(env);
70   InitFromGURL(env, gurl, j_gurl);
71   return j_gurl;
72 }
73 
74 // static
EmptyGURL(JNIEnv * env)75 ScopedJavaLocalRef<jobject> GURLAndroid::EmptyGURL(JNIEnv* env) {
76   return Java_GURL_emptyGURL(env);
77 }
78 
JNI_GURL_GetOrigin(JNIEnv * env,GURL & gurl,const JavaParamRef<jobject> & target)79 static void JNI_GURL_GetOrigin(JNIEnv* env,
80                                GURL& gurl,
81                                const JavaParamRef<jobject>& target) {
82   InitFromGURL(env, gurl.DeprecatedGetOriginAsURL(), target);
83 }
84 
JNI_GURL_DomainIs(JNIEnv * env,GURL & gurl,std::string & domain)85 static jboolean JNI_GURL_DomainIs(JNIEnv* env,
86                                   GURL& gurl,
87                                   std::string& domain) {
88   return gurl.DomainIs(domain);
89 }
90 
JNI_GURL_Init(JNIEnv * env,std::string & spec,const base::android::JavaParamRef<jobject> & target)91 static void JNI_GURL_Init(JNIEnv* env,
92                           std::string& spec,
93                           const base::android::JavaParamRef<jobject>& target) {
94   auto gurl = GURL(spec);
95   InitFromGURL(env, gurl, target);
96 }
97 
JNI_GURL_InitNative(JNIEnv * env,std::string & spec,jboolean is_valid,jlong native_gurl,jlong native_parsed)98 static void JNI_GURL_InitNative(JNIEnv* env,
99                                 std::string& spec,
100                                 jboolean is_valid,
101                                 jlong native_gurl,
102                                 jlong native_parsed) {
103   GURL* gurl = reinterpret_cast<GURL*>(native_gurl);
104   Parsed* parsed = reinterpret_cast<Parsed*>(native_parsed);
105   *gurl = GURL(spec, *parsed, is_valid);
106 }
107 
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)108 static void JNI_GURL_ReplaceComponents(
109     JNIEnv* env,
110     GURL& gurl,
111     const JavaParamRef<jstring>& j_username_replacement,
112     jboolean clear_username,
113     const JavaParamRef<jstring>& j_password_replacement,
114     jboolean clear_password,
115     const JavaParamRef<jobject>& j_result) {
116   GURL::Replacements replacements;
117 
118   // Replacement strings must remain in scope for ReplaceComponents().
119   std::string username;
120   std::string password;
121 
122   if (clear_username) {
123     replacements.ClearUsername();
124   } else if (j_username_replacement) {
125     username =
126         base::android::ConvertJavaStringToUTF8(env, j_username_replacement);
127     replacements.SetUsernameStr(username);
128   }
129 
130   if (clear_password) {
131     replacements.ClearPassword();
132   } else if (j_password_replacement) {
133     password =
134         base::android::ConvertJavaStringToUTF8(env, j_password_replacement);
135     replacements.SetPasswordStr(password);
136   }
137 
138   InitFromGURL(env, gurl.ReplaceComponents(replacements), j_result);
139 }
140 
141 }  // namespace url
142