OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // URL request job for reading from resources and assets. | |
6 | |
7 #include "chrome/browser/android/android_protocol_adapter.h" | |
8 | |
9 #include "base/android/jni_android.h" | |
10 #include "base/android/jni_helper.h" | |
11 #include "base/android/jni_string.h" | |
12 #include "chrome/browser/android/android_stream_reader_url_request_job.h" | |
13 #include "chrome/common/url_constants.h" | |
14 #include "googleurl/src/gurl.h" | |
15 #include "jni/AndroidProtocolAdapter_jni.h" | |
16 #include "net/base/io_buffer.h" | |
17 #include "net/base/mime_util.h" | |
18 #include "net/base/net_errors.h" | |
19 #include "net/base/net_util.h" | |
20 #include "net/http/http_util.h" | |
21 #include "net/url_request/url_request.h" | |
Nico
2012/07/27 14:22:23
Redundant with .h file
felipeg
2012/07/30 16:48:54
Done.
| |
22 #include "net/url_request/url_request_error_job.h" | |
23 #include "net/url_request/url_request_file_job.h" | |
24 #include "net/url_request/url_request_job_manager.h" | |
25 | |
26 using base::android::AttachCurrentThread; | |
27 using base::android::ClearException; | |
28 using base::android::ConvertUTF8ToJavaString; | |
29 using base::android::ScopedJavaGlobalRef; | |
30 using base::android::ScopedJavaLocalRef; | |
31 | |
32 namespace { | |
33 | |
34 // Override resource context for reading resource and asset files. Used for | |
35 // testing. | |
36 JavaObjectWeakGlobalRef* g_resource_context = NULL; | |
37 | |
38 void ResetResourceContext(JavaObjectWeakGlobalRef* ref) { | |
39 if (g_resource_context) | |
40 delete g_resource_context; | |
41 | |
42 g_resource_context = ref; | |
43 } | |
44 | |
45 class AndroidStreamReaderURLRequestJobDelegateImpl | |
46 : public AndroidStreamReaderURLRequestJob::Delegate { | |
47 public: | |
48 AndroidStreamReaderURLRequestJobDelegateImpl(); | |
49 | |
50 virtual ScopedJavaLocalRef<jobject> OpenInputStream( | |
51 JNIEnv* env, | |
52 net::URLRequest* request) OVERRIDE; | |
53 | |
54 virtual bool GetMimeType(JNIEnv* env, | |
55 net::URLRequest* request, | |
56 jobject stream, | |
57 std::string* mime_type) OVERRIDE; | |
58 | |
59 virtual bool GetCharset(JNIEnv* env, | |
60 net::URLRequest* request, | |
61 jobject stream, | |
62 std::string* charset) OVERRIDE; | |
63 | |
64 virtual ~AndroidStreamReaderURLRequestJobDelegateImpl(); | |
65 }; | |
66 | |
67 | |
68 } // namespace | |
69 | |
70 static bool InitJNIBindings(JNIEnv* env) { | |
71 return RegisterNativesImpl(env) && | |
72 AndroidStreamReaderURLRequestJob::InitJNIBindings(env); | |
73 } | |
74 | |
75 // static | |
76 net::URLRequestJob* AndroidProtocolAdapter::Factory( | |
77 net::URLRequest* request, const std::string& scheme) { | |
78 DCHECK(scheme == chrome::kFileScheme || | |
79 scheme == chrome::kContentScheme); | |
80 JNIEnv* env = AttachCurrentThread(); | |
81 DCHECK(env); | |
82 // If this is a file:// URL we cannot handle, fall back to the default | |
83 // handler. | |
84 const std::string& url = request->url().spec(); | |
85 std::string assetPrefix = std::string(chrome::kFileScheme) + "://" + | |
86 chrome::kAndroidAssetPath; | |
87 std::string resourcePrefix = std::string(chrome::kFileScheme) + "://" + | |
88 chrome::kAndroidResourcePath; | |
89 if (scheme == chrome::kFileScheme && url.find(assetPrefix) != 0 && | |
Nico
2012/07/27 14:22:23
StartsWithASCII() in base/string_util.h would read
felipeg
2012/07/30 16:48:54
Done.
| |
90 url.find(resourcePrefix) != 0) { | |
91 return net::URLRequestFileJob::Factory(request, scheme); | |
92 } | |
93 | |
94 return new AndroidStreamReaderURLRequestJob( | |
95 request, | |
96 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>( | |
97 new AndroidStreamReaderURLRequestJobDelegateImpl())); | |
98 } | |
99 | |
100 // static | |
101 bool AndroidProtocolAdapter::RegisterProtocols(JNIEnv* env) { | |
102 DCHECK(env); | |
103 | |
104 if (!InitJNIBindings(env)) | |
105 return false; | |
106 | |
107 // Register content:// and file://. Note that even though a scheme is | |
108 // registered here, it cannot be used by child processes until access to it is | |
109 // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in | |
110 // RenderViewHost. | |
111 net::URLRequestJobManager* job_manager = | |
112 net::URLRequestJobManager::GetInstance(); | |
113 job_manager->RegisterProtocolFactory(chrome::kContentScheme, | |
114 &AndroidProtocolAdapter::Factory); | |
115 job_manager->RegisterProtocolFactory( | |
116 chrome::kFileScheme, &AndroidProtocolAdapter::Factory); | |
117 | |
118 return true; | |
119 } | |
120 | |
121 // Set a context object to be used for resolving resource queries. This can | |
122 // be used to override the default application context and redirect all | |
123 // resource queries to a specific context object, e.g., for the purposes of | |
124 // testing. | |
Nico
2012/07/27 15:23:45
nit: If this is only for testing, add "ForTesting"
felipeg
2012/07/30 16:48:54
Done.
| |
125 // | |
126 // |context| should be a android.content.Context instance or NULL to enable | |
127 // the use of the standard application context. | |
128 static void SetResourceContext(JNIEnv* env, jclass /*clazz*/, jobject context) { | |
129 if (context) { | |
130 ResetResourceContext(new JavaObjectWeakGlobalRef(env, context)); | |
131 } else { | |
132 ResetResourceContext(NULL); | |
133 } | |
134 } | |
135 | |
136 static jstring GetAndroidAssetPath(JNIEnv* env, jclass /*clazz*/) { | |
137 // OK to release, JNI binding. | |
Nico
2012/07/27 15:23:45
I'm not familiar with JNI enough to judge if this
felipeg
2012/07/30 16:48:54
Yep.
| |
138 return ConvertUTF8ToJavaString(env, chrome::kAndroidAssetPath).Release(); | |
139 } | |
140 | |
141 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) { | |
142 // OK to release, JNI binding. | |
143 return ConvertUTF8ToJavaString(env, chrome::kAndroidResourcePath).Release(); | |
144 } | |
145 | |
146 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) { | |
147 if (g_resource_context) | |
148 return g_resource_context->get(env); | |
149 ScopedJavaLocalRef<jobject> context; | |
150 // We have to reset as GetApplicationContext() returns a jobject with a | |
Nico
2012/07/27 15:23:45
nit: s/ We/We/
felipeg
2012/07/30 16:48:54
Done.
| |
151 // global ref. The constructor that takes a jobject would expect a local ref | |
152 // and would assert. | |
153 context.Reset(env, base::android::GetApplicationContext()); | |
154 return context; | |
155 } | |
156 | |
157 AndroidStreamReaderURLRequestJobDelegateImpl:: | |
158 AndroidStreamReaderURLRequestJobDelegateImpl() { | |
159 } | |
160 | |
161 AndroidStreamReaderURLRequestJobDelegateImpl:: | |
162 ~AndroidStreamReaderURLRequestJobDelegateImpl() { | |
163 } | |
164 | |
165 ScopedJavaLocalRef<jobject> | |
166 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream( | |
167 JNIEnv* env, net::URLRequest* request) { | |
168 DCHECK(request); | |
169 DCHECK(env); | |
170 | |
171 // Open the input stream. | |
172 ScopedJavaLocalRef<jstring> url = | |
173 ConvertUTF8ToJavaString(env, request->url().spec()); | |
174 ScopedJavaLocalRef<jobject> stream = Java_AndroidProtocolAdapter_open( | |
175 env, | |
176 GetResourceContext(env).obj(), | |
177 url.obj()); | |
178 | |
179 // Check and clear pending exceptions. | |
180 if (ClearException(env) || stream.is_null()) { | |
181 DLOG(ERROR) << "Unable to open input stream for Android URL"; | |
182 return ScopedJavaLocalRef<jobject>(env, NULL); | |
183 } | |
184 return stream; | |
185 } | |
186 | |
187 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType( | |
188 JNIEnv* env, | |
189 net::URLRequest* request, | |
190 jobject stream, | |
191 std::string* mime_type) { | |
192 DCHECK(env); | |
193 DCHECK(request); | |
194 DCHECK(mime_type); | |
195 | |
196 if (!stream) | |
197 return false; | |
198 | |
199 // Query the mime type from the Java side. It is possible for the query to | |
200 // fail, as the mime type cannot be determined for all supported schemes. | |
201 ScopedJavaLocalRef<jstring> url = | |
202 ConvertUTF8ToJavaString(env, request->url().spec()); | |
203 ScopedJavaLocalRef<jstring> returned_type = | |
204 Java_AndroidProtocolAdapter_getMimeType(env, | |
205 GetResourceContext(env).obj(), | |
206 stream, url.obj()); | |
207 if (ClearException(env) || returned_type.is_null()) | |
208 return false; | |
209 | |
210 *mime_type = base::android::ConvertJavaStringToUTF8(returned_type); | |
211 return true; | |
212 } | |
213 | |
214 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset( | |
215 JNIEnv* env, | |
216 net::URLRequest* request, | |
217 jobject stream, | |
218 std::string* charset) { | |
219 // TODO: We should probably be getting this from the managed side. | |
220 return false; | |
221 } | |
OLD | NEW |