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 "base/string_util.h" | |
13 #include "chrome/browser/android/android_stream_reader_url_request_job.h" | |
14 #include "chrome/common/url_constants.h" | |
15 #include "googleurl/src/gurl.h" | |
16 #include "jni/AndroidProtocolAdapter_jni.h" | |
17 #include "net/base/io_buffer.h" | |
18 #include "net/base/mime_util.h" | |
19 #include "net/base/net_errors.h" | |
20 #include "net/base/net_util.h" | |
21 #include "net/http/http_util.h" | |
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 | |
90 if (scheme == chrome::kFileScheme && | |
91 !StartsWithASCII(url, assetPrefix, true) && | |
Nico
2012/07/31 14:07:13
nit: If you say |StartsWithASCII(url, assetPrefix,
felipeg
2012/07/31 14:54:36
Done.
I like this.
thanks
| |
92 !StartsWithASCII(url, resourcePrefix, true)) { | |
93 return net::URLRequestFileJob::Factory(request, scheme); | |
94 } | |
95 | |
96 return new AndroidStreamReaderURLRequestJob( | |
97 request, | |
98 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>( | |
99 new AndroidStreamReaderURLRequestJobDelegateImpl())); | |
100 } | |
101 | |
102 // static | |
103 bool AndroidProtocolAdapter::RegisterProtocols(JNIEnv* env) { | |
104 DCHECK(env); | |
105 | |
106 if (!InitJNIBindings(env)) | |
107 return false; | |
108 | |
109 // Register content:// and file://. Note that even though a scheme is | |
110 // registered here, it cannot be used by child processes until access to it is | |
111 // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in | |
112 // RenderViewHost. | |
113 net::URLRequestJobManager* job_manager = | |
114 net::URLRequestJobManager::GetInstance(); | |
115 job_manager->RegisterProtocolFactory(chrome::kContentScheme, | |
116 &AndroidProtocolAdapter::Factory); | |
117 job_manager->RegisterProtocolFactory( | |
118 chrome::kFileScheme, &AndroidProtocolAdapter::Factory); | |
119 | |
120 return true; | |
121 } | |
122 | |
123 // Set a context object to be used for resolving resource queries. This can | |
124 // be used to override the default application context and redirect all | |
125 // resource queries to a specific context object, e.g., for the purposes of | |
126 // testing. | |
127 // | |
128 // |context| should be a android.content.Context instance or NULL to enable | |
129 // the use of the standard application context. | |
130 static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/, | |
131 jobject context) { | |
132 if (context) { | |
133 ResetResourceContext(new JavaObjectWeakGlobalRef(env, context)); | |
134 } else { | |
135 ResetResourceContext(NULL); | |
136 } | |
137 } | |
138 | |
139 static jstring GetAndroidAssetPath(JNIEnv* env, jclass /*clazz*/) { | |
140 // OK to release, JNI binding. | |
141 return ConvertUTF8ToJavaString(env, chrome::kAndroidAssetPath).Release(); | |
142 } | |
143 | |
144 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) { | |
145 // OK to release, JNI binding. | |
146 return ConvertUTF8ToJavaString(env, chrome::kAndroidResourcePath).Release(); | |
147 } | |
148 | |
149 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) { | |
150 if (g_resource_context) | |
151 return g_resource_context->get(env); | |
152 ScopedJavaLocalRef<jobject> context; | |
153 // We have to reset as GetApplicationContext() returns a jobject with a | |
154 // global ref. The constructor that takes a jobject would expect a local ref | |
155 // and would assert. | |
156 context.Reset(env, base::android::GetApplicationContext()); | |
157 return context; | |
158 } | |
159 | |
160 AndroidStreamReaderURLRequestJobDelegateImpl:: | |
161 AndroidStreamReaderURLRequestJobDelegateImpl() { | |
162 } | |
163 | |
164 AndroidStreamReaderURLRequestJobDelegateImpl:: | |
165 ~AndroidStreamReaderURLRequestJobDelegateImpl() { | |
166 } | |
167 | |
168 ScopedJavaLocalRef<jobject> | |
169 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream( | |
170 JNIEnv* env, net::URLRequest* request) { | |
171 DCHECK(request); | |
172 DCHECK(env); | |
173 | |
174 // Open the input stream. | |
175 ScopedJavaLocalRef<jstring> url = | |
176 ConvertUTF8ToJavaString(env, request->url().spec()); | |
177 ScopedJavaLocalRef<jobject> stream = Java_AndroidProtocolAdapter_open( | |
178 env, | |
179 GetResourceContext(env).obj(), | |
180 url.obj()); | |
181 | |
182 // Check and clear pending exceptions. | |
183 if (ClearException(env) || stream.is_null()) { | |
184 DLOG(ERROR) << "Unable to open input stream for Android URL"; | |
185 return ScopedJavaLocalRef<jobject>(env, NULL); | |
186 } | |
187 return stream; | |
188 } | |
189 | |
190 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType( | |
191 JNIEnv* env, | |
192 net::URLRequest* request, | |
193 jobject stream, | |
194 std::string* mime_type) { | |
195 DCHECK(env); | |
196 DCHECK(request); | |
197 DCHECK(mime_type); | |
198 | |
199 if (!stream) | |
200 return false; | |
201 | |
202 // Query the mime type from the Java side. It is possible for the query to | |
203 // fail, as the mime type cannot be determined for all supported schemes. | |
204 ScopedJavaLocalRef<jstring> url = | |
205 ConvertUTF8ToJavaString(env, request->url().spec()); | |
206 ScopedJavaLocalRef<jstring> returned_type = | |
207 Java_AndroidProtocolAdapter_getMimeType(env, | |
208 GetResourceContext(env).obj(), | |
209 stream, url.obj()); | |
210 if (ClearException(env) || returned_type.is_null()) | |
211 return false; | |
212 | |
213 *mime_type = base::android::ConvertJavaStringToUTF8(returned_type); | |
214 return true; | |
215 } | |
216 | |
217 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset( | |
218 JNIEnv* env, | |
219 net::URLRequest* request, | |
220 jobject stream, | |
221 std::string* charset) { | |
222 // TODO: We should probably be getting this from the managed side. | |
223 return false; | |
224 } | |
OLD | NEW |