OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "android_webview/native/android_protocol_handler.h" | 5 #include "android_webview/native/android_protocol_handler.h" |
6 | 6 |
7 #include "android_webview/browser/net/android_stream_reader_url_request_job.h" | 7 #include "android_webview/browser/net/android_stream_reader_url_request_job.h" |
8 #include "android_webview/browser/net/aw_url_request_job_factory.h" | 8 #include "android_webview/browser/net/aw_url_request_job_factory.h" |
9 #include "android_webview/common/url_constants.h" | 9 #include "android_webview/common/url_constants.h" |
10 #include "android_webview/native/input_stream_impl.h" | 10 #include "android_webview/native/input_stream_impl.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 delete g_resource_context; | 42 delete g_resource_context; |
43 | 43 |
44 g_resource_context = ref; | 44 g_resource_context = ref; |
45 } | 45 } |
46 | 46 |
47 class AndroidStreamReaderURLRequestJobDelegateImpl | 47 class AndroidStreamReaderURLRequestJobDelegateImpl |
48 : public AndroidStreamReaderURLRequestJob::Delegate { | 48 : public AndroidStreamReaderURLRequestJob::Delegate { |
49 public: | 49 public: |
50 AndroidStreamReaderURLRequestJobDelegateImpl(); | 50 AndroidStreamReaderURLRequestJobDelegateImpl(); |
51 | 51 |
52 bool CanOpenInputStream(JNIEnv* env, net::URLRequest* request); | |
53 | |
52 virtual scoped_ptr<InputStream> OpenInputStream( | 54 virtual scoped_ptr<InputStream> OpenInputStream( |
53 JNIEnv* env, | 55 JNIEnv* env, |
54 net::URLRequest* request) OVERRIDE; | 56 net::URLRequest* request) OVERRIDE; |
55 | 57 |
56 virtual bool GetMimeType(JNIEnv* env, | 58 virtual bool GetMimeType(JNIEnv* env, |
57 net::URLRequest* request, | 59 net::URLRequest* request, |
58 InputStream* stream, | 60 InputStream* stream, |
59 std::string* mime_type) OVERRIDE; | 61 std::string* mime_type) OVERRIDE; |
60 | 62 |
61 virtual bool GetCharset(JNIEnv* env, | 63 virtual bool GetCharset(JNIEnv* env, |
62 net::URLRequest* request, | 64 net::URLRequest* request, |
63 InputStream* stream, | 65 InputStream* stream, |
64 std::string* charset) OVERRIDE; | 66 std::string* charset) OVERRIDE; |
65 | 67 |
66 virtual ~AndroidStreamReaderURLRequestJobDelegateImpl(); | 68 virtual ~AndroidStreamReaderURLRequestJobDelegateImpl(); |
69 | |
70 private: | |
71 scoped_ptr<InputStream> DoOpenInputStream(JNIEnv* env, | |
72 net::URLRequest* request); | |
73 | |
74 net::URLRequest* cached_input_stream_request_; | |
75 scoped_ptr<InputStream> cached_input_stream_; | |
67 }; | 76 }; |
68 | 77 |
69 class AssetFileProtocolInterceptor : | 78 class AssetFileProtocolHandler : |
70 public net::URLRequestJobFactory::ProtocolHandler { | 79 public net::URLRequestJobFactory::ProtocolHandler { |
71 public: | 80 public: |
72 virtual ~AssetFileProtocolInterceptor() OVERRIDE; | 81 AssetFileProtocolHandler(); |
73 static scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory( | 82 |
74 scoped_ptr<net::URLRequestJobFactory> base_job_factory); | 83 virtual ~AssetFileProtocolHandler() OVERRIDE; |
75 virtual net::URLRequestJob* MaybeCreateJob( | 84 virtual net::URLRequestJob* MaybeCreateJob( |
76 net::URLRequest* request, | 85 net::URLRequest* request, |
77 net::NetworkDelegate* network_delegate) const OVERRIDE; | 86 net::NetworkDelegate* network_delegate) const OVERRIDE; |
78 | 87 |
79 private: | 88 private: |
80 AssetFileProtocolInterceptor(); | |
81 | |
82 // file:///android_asset/ | 89 // file:///android_asset/ |
83 const std::string asset_prefix_; | 90 const std::string asset_prefix_; |
84 // file:///android_res/ | 91 // file:///android_res/ |
85 const std::string resource_prefix_; | 92 const std::string resource_prefix_; |
86 }; | 93 }; |
87 | 94 |
88 // Protocol handler for content:// scheme requests. | 95 // Protocol handler for content:// scheme requests. |
89 class ContentSchemeProtocolHandler : | 96 class ContentSchemeProtocolHandler : |
90 public net::URLRequestJobFactory::ProtocolHandler { | 97 public net::URLRequestJobFactory::ProtocolHandler { |
91 public: | 98 public: |
92 ContentSchemeProtocolHandler() {} | 99 ContentSchemeProtocolHandler(); |
93 | |
94 virtual net::URLRequestJob* MaybeCreateJob( | 100 virtual net::URLRequestJob* MaybeCreateJob( |
95 net::URLRequest* request, | 101 net::URLRequest* request, |
96 net::NetworkDelegate* network_delegate) const OVERRIDE { | 102 net::NetworkDelegate* network_delegate) const OVERRIDE; |
97 DCHECK(request->url().SchemeIs(android_webview::kContentScheme)); | |
98 return new AndroidStreamReaderURLRequestJob( | |
99 request, | |
100 network_delegate, | |
101 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>( | |
102 new AndroidStreamReaderURLRequestJobDelegateImpl())); | |
103 } | |
104 }; | 103 }; |
105 | 104 |
106 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) { | 105 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) { |
107 if (g_resource_context) | 106 if (g_resource_context) |
108 return g_resource_context->get(env); | 107 return g_resource_context->get(env); |
109 ScopedJavaLocalRef<jobject> context; | 108 ScopedJavaLocalRef<jobject> context; |
110 // We have to reset as GetApplicationContext() returns a jobject with a | 109 // We have to reset as GetApplicationContext() returns a jobject with a |
111 // global ref. The constructor that takes a jobject would expect a local ref | 110 // global ref. The constructor that takes a jobject would expect a local ref |
112 // and would assert. | 111 // and would assert. |
113 context.Reset(env, base::android::GetApplicationContext()); | 112 context.Reset(env, base::android::GetApplicationContext()); |
114 return context; | 113 return context; |
115 } | 114 } |
116 | 115 |
116 // AndroidStreamReaderURLRequestJobDelegateImpl ------------------------------- | |
117 | |
117 AndroidStreamReaderURLRequestJobDelegateImpl:: | 118 AndroidStreamReaderURLRequestJobDelegateImpl:: |
118 AndroidStreamReaderURLRequestJobDelegateImpl() { | 119 AndroidStreamReaderURLRequestJobDelegateImpl() |
119 } | 120 : cached_input_stream_request_(NULL) {} |
120 | 121 |
121 AndroidStreamReaderURLRequestJobDelegateImpl:: | 122 AndroidStreamReaderURLRequestJobDelegateImpl:: |
122 ~AndroidStreamReaderURLRequestJobDelegateImpl() { | 123 ~AndroidStreamReaderURLRequestJobDelegateImpl() { |
123 } | 124 } |
124 | 125 |
126 bool AndroidStreamReaderURLRequestJobDelegateImpl::CanOpenInputStream( | |
127 JNIEnv* env, | |
128 net::URLRequest* request) { | |
129 cached_input_stream_request_ = request; | |
130 cached_input_stream_ = DoOpenInputStream(env, request); | |
131 return cached_input_stream_.get() != NULL; | |
132 } | |
133 | |
125 scoped_ptr<InputStream> | 134 scoped_ptr<InputStream> |
126 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream( | 135 AndroidStreamReaderURLRequestJobDelegateImpl::DoOpenInputStream( |
127 JNIEnv* env, net::URLRequest* request) { | 136 JNIEnv* env, |
137 net::URLRequest* request) { | |
128 DCHECK(request); | 138 DCHECK(request); |
129 DCHECK(env); | 139 DCHECK(env); |
130 | 140 |
131 // Open the input stream. | 141 // Open the input stream. |
132 ScopedJavaLocalRef<jstring> url = | 142 ScopedJavaLocalRef<jstring> url = |
133 ConvertUTF8ToJavaString(env, request->url().spec()); | 143 ConvertUTF8ToJavaString(env, request->url().spec()); |
134 ScopedJavaLocalRef<jobject> stream = | 144 ScopedJavaLocalRef<jobject> stream = |
135 android_webview::Java_AndroidProtocolHandler_open( | 145 android_webview::Java_AndroidProtocolHandler_open( |
136 env, | 146 env, |
137 GetResourceContext(env).obj(), | 147 GetResourceContext(env).obj(), |
138 url.obj()); | 148 url.obj()); |
139 | 149 |
140 // Check and clear pending exceptions. | 150 // Check and clear pending exceptions. |
141 if (ClearException(env) || stream.is_null()) { | 151 if (ClearException(env) || stream.is_null()) { |
142 DLOG(ERROR) << "Unable to open input stream for Android URL"; | 152 DLOG(ERROR) << "Unable to open input stream for Android URL"; |
143 return scoped_ptr<InputStream>(); | 153 return scoped_ptr<InputStream>(); |
144 } | 154 } |
145 return make_scoped_ptr<InputStream>(new InputStreamImpl(stream)); | 155 return make_scoped_ptr<InputStream>(new InputStreamImpl(stream)); |
146 } | 156 } |
147 | 157 |
158 scoped_ptr<InputStream> | |
159 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream( | |
160 JNIEnv* env, net::URLRequest* request) { | |
161 if (cached_input_stream_request_ == request) { | |
162 cached_input_stream_request_ = NULL; | |
163 return cached_input_stream_.Pass(); | |
164 } | |
165 return DoOpenInputStream(env, request); | |
166 } | |
167 | |
148 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType( | 168 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType( |
149 JNIEnv* env, | 169 JNIEnv* env, |
150 net::URLRequest* request, | 170 net::URLRequest* request, |
151 android_webview::InputStream* stream, | 171 android_webview::InputStream* stream, |
152 std::string* mime_type) { | 172 std::string* mime_type) { |
153 DCHECK(env); | 173 DCHECK(env); |
154 DCHECK(request); | 174 DCHECK(request); |
155 DCHECK(mime_type); | 175 DCHECK(mime_type); |
156 | 176 |
157 // Query the mime type from the Java side. It is possible for the query to | 177 // Query the mime type from the Java side. It is possible for the query to |
(...skipping 16 matching lines...) Expand all Loading... | |
174 | 194 |
175 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset( | 195 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset( |
176 JNIEnv* env, | 196 JNIEnv* env, |
177 net::URLRequest* request, | 197 net::URLRequest* request, |
178 android_webview::InputStream* stream, | 198 android_webview::InputStream* stream, |
179 std::string* charset) { | 199 std::string* charset) { |
180 // TODO: We should probably be getting this from the managed side. | 200 // TODO: We should probably be getting this from the managed side. |
181 return false; | 201 return false; |
182 } | 202 } |
183 | 203 |
184 AssetFileProtocolInterceptor::AssetFileProtocolInterceptor() | 204 // AssetFileProtocolHandler ----------------------------------------------- |
205 | |
206 AssetFileProtocolHandler::AssetFileProtocolHandler() | |
185 : asset_prefix_(std::string(chrome::kFileScheme) + | 207 : asset_prefix_(std::string(chrome::kFileScheme) + |
186 std::string(content::kStandardSchemeSeparator) + | 208 std::string(content::kStandardSchemeSeparator) + |
187 android_webview::kAndroidAssetPath), | 209 android_webview::kAndroidAssetPath), |
188 resource_prefix_(std::string(chrome::kFileScheme) + | 210 resource_prefix_(std::string(chrome::kFileScheme) + |
189 std::string(content::kStandardSchemeSeparator) + | 211 std::string(content::kStandardSchemeSeparator) + |
190 android_webview::kAndroidResourcePath) { | 212 android_webview::kAndroidResourcePath) { |
191 } | 213 } |
192 | 214 |
193 AssetFileProtocolInterceptor::~AssetFileProtocolInterceptor() { | 215 AssetFileProtocolHandler::~AssetFileProtocolHandler() { |
194 } | 216 } |
195 | 217 |
196 // static | 218 net::URLRequestJob* AssetFileProtocolHandler::MaybeCreateJob( |
197 scoped_ptr<net::URLRequestJobFactory> | |
198 AssetFileProtocolInterceptor::CreateURLRequestJobFactory( | |
199 scoped_ptr<net::URLRequestJobFactory> base_job_factory) { | |
200 scoped_ptr<net::URLRequestJobFactory> top_job_factory( | |
201 new net::ProtocolInterceptJobFactory( | |
202 base_job_factory.Pass(), | |
203 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>( | |
204 new AssetFileProtocolInterceptor()))); | |
205 return top_job_factory.Pass(); | |
206 } | |
207 | |
208 net::URLRequestJob* AssetFileProtocolInterceptor::MaybeCreateJob( | |
209 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { | 219 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { |
210 if (!request->url().SchemeIsFile()) return NULL; | 220 if (!request->url().SchemeIsFile()) return NULL; |
211 | 221 |
212 const std::string& url = request->url().spec(); | 222 const std::string& url = request->url().spec(); |
213 if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) && | 223 if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) && |
214 !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) { | 224 !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) { |
215 return NULL; | 225 return NULL; |
216 } | 226 } |
217 | 227 |
228 scoped_ptr<AndroidStreamReaderURLRequestJobDelegateImpl> reader_delegate( | |
229 new AndroidStreamReaderURLRequestJobDelegateImpl()); | |
230 | |
231 // For WebViewClassic compatibility this job can only accept URLs that can be | |
232 // opened. | |
233 if (!reader_delegate->CanOpenInputStream(AttachCurrentThread(), request)) { | |
mkosiba (inactive)
2013/03/01 18:21:00
Just thought of the right way to solve this - use
mkosiba (inactive)
2013/03/05 16:34:43
and turns out doing this is a major pain. opted to
| |
234 return NULL; | |
235 } | |
236 | |
218 return new AndroidStreamReaderURLRequestJob( | 237 return new AndroidStreamReaderURLRequestJob( |
219 request, | 238 request, |
220 network_delegate, | 239 network_delegate, |
221 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>( | 240 reader_delegate.PassAs<AndroidStreamReaderURLRequestJob::Delegate>()); |
222 new AndroidStreamReaderURLRequestJobDelegateImpl())); | 241 } |
242 | |
243 // ContentSchemeProtocolHandler ----------------------------------------------- | |
244 | |
245 ContentSchemeProtocolHandler::ContentSchemeProtocolHandler() { | |
246 } | |
247 | |
248 net::URLRequestJob* ContentSchemeProtocolHandler::MaybeCreateJob( | |
249 net::URLRequest* request, | |
250 net::NetworkDelegate* network_delegate) const { | |
251 if (!request->url().SchemeIs(android_webview::kContentScheme)) { | |
252 return NULL; | |
253 } | |
254 | |
255 scoped_ptr<AndroidStreamReaderURLRequestJobDelegateImpl> reader_delegate( | |
256 new AndroidStreamReaderURLRequestJobDelegateImpl()); | |
257 | |
258 // For WebViewClassic compatibility this job can only accept URLs that can be | |
259 // opened. | |
260 if (!reader_delegate->CanOpenInputStream(AttachCurrentThread(), request)) { | |
261 return NULL; | |
262 } | |
263 | |
264 return new AndroidStreamReaderURLRequestJob( | |
265 request, | |
266 network_delegate, | |
267 reader_delegate.PassAs<AndroidStreamReaderURLRequestJob::Delegate>()); | |
223 } | 268 } |
224 | 269 |
225 } // namespace | 270 } // namespace |
226 | 271 |
227 namespace android_webview { | 272 namespace android_webview { |
228 | 273 |
229 bool RegisterAndroidProtocolHandler(JNIEnv* env) { | 274 bool RegisterAndroidProtocolHandler(JNIEnv* env) { |
230 return RegisterNativesImpl(env); | 275 return RegisterNativesImpl(env); |
231 } | 276 } |
232 | 277 |
233 // static | 278 // static |
234 scoped_ptr<net::URLRequestJobFactory> CreateAndroidRequestJobFactory( | 279 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> |
235 scoped_ptr<AwURLRequestJobFactory> job_factory) { | 280 CreateContentSchemeProtocolHandler() { |
236 // Register content://. Note that even though a scheme is | 281 return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>( |
237 // registered here, it cannot be used by child processes until access to it is | 282 new ContentSchemeProtocolHandler()); |
238 // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in | 283 } |
239 // AwContentBrowserClient. | 284 |
240 // The job factory takes ownership of the handler. | 285 // static |
241 bool set_protocol = job_factory->SetProtocolHandler( | 286 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> |
242 android_webview::kContentScheme, new ContentSchemeProtocolHandler()); | 287 CreateAssetFileProtocolHandler() { |
243 DCHECK(set_protocol); | 288 return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>( |
244 return AssetFileProtocolInterceptor::CreateURLRequestJobFactory( | 289 new AssetFileProtocolHandler()); |
245 job_factory.PassAs<net::URLRequestJobFactory>()); | |
246 } | 290 } |
247 | 291 |
248 // Set a context object to be used for resolving resource queries. This can | 292 // Set a context object to be used for resolving resource queries. This can |
249 // be used to override the default application context and redirect all | 293 // be used to override the default application context and redirect all |
250 // resource queries to a specific context object, e.g., for the purposes of | 294 // resource queries to a specific context object, e.g., for the purposes of |
251 // testing. | 295 // testing. |
252 // | 296 // |
253 // |context| should be a android.content.Context instance or NULL to enable | 297 // |context| should be a android.content.Context instance or NULL to enable |
254 // the use of the standard application context. | 298 // the use of the standard application context. |
255 static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/, | 299 static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/, |
(...skipping 11 matching lines...) Expand all Loading... | |
267 env, android_webview::kAndroidAssetPath).Release(); | 311 env, android_webview::kAndroidAssetPath).Release(); |
268 } | 312 } |
269 | 313 |
270 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) { | 314 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) { |
271 // OK to release, JNI binding. | 315 // OK to release, JNI binding. |
272 return ConvertUTF8ToJavaString( | 316 return ConvertUTF8ToJavaString( |
273 env, android_webview::kAndroidResourcePath).Release(); | 317 env, android_webview::kAndroidResourcePath).Release(); |
274 } | 318 } |
275 | 319 |
276 } // namespace android_webview | 320 } // namespace android_webview |
OLD | NEW |