Chromium Code Reviews| 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 |