• 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 <jni.h>
8 
9 #include <cstdint>
10 #include <string>
11 #include <vector>
12 
13 #include "base/android/jni_android.h"
14 #include "base/android/jni_string.h"
15 #include "base/functional/bind.h"
16 #include "base/functional/callback.h"
17 #include "base/memory/ptr_util.h"
18 #include "url/android/parsed_android.h"
19 #include "url/gurl_jni_headers/GURL_jni.h"
20 #include "url/third_party/mozilla/url_parse.h"
21 
22 using base::android::AttachCurrentThread;
23 using base::android::JavaParamRef;
24 using base::android::JavaRef;
25 using base::android::ScopedJavaLocalRef;
26 
27 namespace url {
28 
29 namespace {
30 
FromJString(JNIEnv * env,const JavaRef<jstring> & uri)31 static GURL FromJString(JNIEnv* env, const JavaRef<jstring>& uri) {
32   if (!uri)
33     return GURL();
34   return GURL(base::android::ConvertJavaStringToUTF16(env, uri));
35 }
36 
FromJavaGURL(JNIEnv * env,const JavaRef<jstring> & j_spec,bool is_valid,jlong parsed_ptr)37 static std::unique_ptr<GURL> FromJavaGURL(JNIEnv* env,
38                                           const JavaRef<jstring>& j_spec,
39                                           bool is_valid,
40                                           jlong parsed_ptr) {
41   Parsed* parsed = reinterpret_cast<Parsed*>(parsed_ptr);
42   const std::string& spec = ConvertJavaStringToUTF8(env, j_spec);
43   std::unique_ptr<GURL> gurl =
44       std::make_unique<GURL>(spec.data(), parsed->Length(), *parsed, is_valid);
45   delete parsed;
46   return gurl;
47 }
48 
InitFromGURL(JNIEnv * env,const GURL & gurl,const JavaRef<jobject> & target)49 static void InitFromGURL(JNIEnv* env,
50                          const GURL& gurl,
51                          const JavaRef<jobject>& target) {
52   Java_GURL_init(
53       env, target,
54       base::android::ConvertUTF8ToJavaString(env, gurl.possibly_invalid_spec()),
55       gurl.is_valid(),
56       ParsedAndroid::InitFromParsed(env,
57                                     gurl.parsed_for_possibly_invalid_spec()));
58 }
59 
60 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it
61 // may be -1 if |array| is not a valid Java array), provide a safe wrapper
62 // that always returns a valid, non-negative size.
63 template <typename JavaArrayType>
SafeGetArrayLength(JNIEnv * env,const JavaRef<JavaArrayType> & jarray)64 size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) {
65   DCHECK(jarray);
66   jsize length = env->GetArrayLength(jarray.obj());
67   DCHECK_GE(length, 0) << "Invalid array length: " << length;
68   return static_cast<size_t>(std::max(0, length));
69 }
70 
71 }  // namespace
72 
73 // static
ToNativeGURL(JNIEnv * env,const base::android::JavaRef<jobject> & j_gurl)74 std::unique_ptr<GURL> GURLAndroid::ToNativeGURL(
75     JNIEnv* env,
76     const base::android::JavaRef<jobject>& j_gurl) {
77   return base::WrapUnique<GURL>(
78       reinterpret_cast<GURL*>(Java_GURL_toNativeGURL(env, j_gurl)));
79 }
80 
JavaGURLArrayToGURLVector(JNIEnv * env,const base::android::JavaRef<jobjectArray> & array,std::vector<GURL> * out)81 void GURLAndroid::JavaGURLArrayToGURLVector(
82     JNIEnv* env,
83     const base::android::JavaRef<jobjectArray>& array,
84     std::vector<GURL>* out) {
85   DCHECK(out);
86   DCHECK(out->empty());
87   if (!array)
88     return;
89   size_t len = SafeGetArrayLength(env, array);
90   for (size_t i = 0; i < len; ++i) {
91     ScopedJavaLocalRef<jobject> j_gurl(
92         env, static_cast<jobject>(env->GetObjectArrayElement(array.obj(), i)));
93     out->emplace_back(
94         *reinterpret_cast<GURL*>(Java_GURL_toNativeGURL(env, j_gurl)));
95   }
96 }
97 
98 // static
FromNativeGURL(JNIEnv * env,const GURL & gurl)99 ScopedJavaLocalRef<jobject> GURLAndroid::FromNativeGURL(JNIEnv* env,
100                                                         const GURL& gurl) {
101   ScopedJavaLocalRef<jobject> j_gurl = Java_GURL_Constructor(env);
102   InitFromGURL(env, gurl, j_gurl);
103   return j_gurl;
104 }
105 
106 // static
EmptyGURL(JNIEnv * env)107 ScopedJavaLocalRef<jobject> GURLAndroid::EmptyGURL(JNIEnv* env) {
108   return Java_GURL_emptyGURL(env);
109 }
110 
111 // static
ToJavaArrayOfGURLs(JNIEnv * env,base::span<ScopedJavaLocalRef<jobject>> v)112 ScopedJavaLocalRef<jobjectArray> GURLAndroid::ToJavaArrayOfGURLs(
113     JNIEnv* env,
114     base::span<ScopedJavaLocalRef<jobject>> v) {
115   jclass clazz = org_chromium_url_GURL_clazz(env);
116   DCHECK(clazz);
117   jobjectArray joa = env->NewObjectArray(v.size(), clazz, nullptr);
118   base::android::CheckException(env);
119 
120   for (size_t i = 0; i < v.size(); ++i) {
121     env->SetObjectArrayElement(joa, i, v[i].obj());
122   }
123   return ScopedJavaLocalRef<jobjectArray>(env, joa);
124 }
125 
JNI_GURL_GetOrigin(JNIEnv * env,const JavaParamRef<jstring> & j_spec,jboolean is_valid,jlong parsed_ptr,const JavaParamRef<jobject> & target)126 static void JNI_GURL_GetOrigin(JNIEnv* env,
127                                const JavaParamRef<jstring>& j_spec,
128                                jboolean is_valid,
129                                jlong parsed_ptr,
130                                const JavaParamRef<jobject>& target) {
131   std::unique_ptr<GURL> gurl = FromJavaGURL(env, j_spec, is_valid, parsed_ptr);
132   InitFromGURL(env, gurl->DeprecatedGetOriginAsURL(), target);
133 }
134 
JNI_GURL_DomainIs(JNIEnv * env,const JavaParamRef<jstring> & j_spec,jboolean is_valid,jlong parsed_ptr,const JavaParamRef<jstring> & j_domain)135 static jboolean JNI_GURL_DomainIs(JNIEnv* env,
136                                   const JavaParamRef<jstring>& j_spec,
137                                   jboolean is_valid,
138                                   jlong parsed_ptr,
139                                   const JavaParamRef<jstring>& j_domain) {
140   std::unique_ptr<GURL> gurl = FromJavaGURL(env, j_spec, is_valid, parsed_ptr);
141   const std::string& domain = ConvertJavaStringToUTF8(env, j_domain);
142   return gurl->DomainIs(domain);
143 }
144 
JNI_GURL_Init(JNIEnv * env,const base::android::JavaParamRef<jstring> & uri,const base::android::JavaParamRef<jobject> & target)145 static void JNI_GURL_Init(JNIEnv* env,
146                           const base::android::JavaParamRef<jstring>& uri,
147                           const base::android::JavaParamRef<jobject>& target) {
148   const GURL& gurl = FromJString(env, uri);
149   InitFromGURL(env, gurl, target);
150 }
151 
JNI_GURL_CreateNative(JNIEnv * env,const JavaParamRef<jstring> & j_spec,jboolean is_valid,jlong parsed_ptr)152 static jlong JNI_GURL_CreateNative(JNIEnv* env,
153                                    const JavaParamRef<jstring>& j_spec,
154                                    jboolean is_valid,
155                                    jlong parsed_ptr) {
156   return reinterpret_cast<intptr_t>(
157       FromJavaGURL(env, j_spec, is_valid, parsed_ptr).release());
158 }
159 
160 }  // namespace url
161