Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: android_webview/native/android_protocol_handler.cc

Issue 12377051: [android_webview] Don't intercept resource and asset URLRequests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use request restart to fall-through to other handlers Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 26 matching lines...) Expand all
37 // testing. 37 // testing.
38 JavaObjectWeakGlobalRef* g_resource_context = NULL; 38 JavaObjectWeakGlobalRef* g_resource_context = NULL;
39 39
40 void ResetResourceContext(JavaObjectWeakGlobalRef* ref) { 40 void ResetResourceContext(JavaObjectWeakGlobalRef* ref) {
41 if (g_resource_context) 41 if (g_resource_context)
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 void* kPreviouslyFailedKey = &kPreviouslyFailedKey;
48
49 void MarkRequestAsFailed(net::URLRequest* request) {
50 request->SetUserData(kPreviouslyFailedKey,
51 new base::SupportsUserData::Data());
52 }
53
54 bool HasRequestPreviouslyFailed(net::URLRequest* request) {
55 return request->GetUserData(kPreviouslyFailedKey) != NULL;
56 }
57
47 class AndroidStreamReaderURLRequestJobDelegateImpl 58 class AndroidStreamReaderURLRequestJobDelegateImpl
48 : public AndroidStreamReaderURLRequestJob::Delegate { 59 : public AndroidStreamReaderURLRequestJob::Delegate {
49 public: 60 public:
50 AndroidStreamReaderURLRequestJobDelegateImpl(); 61 AndroidStreamReaderURLRequestJobDelegateImpl();
51 62
52 virtual scoped_ptr<InputStream> OpenInputStream( 63 virtual scoped_ptr<InputStream> OpenInputStream(
53 JNIEnv* env, 64 JNIEnv* env,
54 net::URLRequest* request) OVERRIDE; 65 const GURL& url) OVERRIDE;
66
67 virtual void OnInputStreamOpenFailed(net::URLRequest* request,
68 bool* restart) OVERRIDE;
55 69
56 virtual bool GetMimeType(JNIEnv* env, 70 virtual bool GetMimeType(JNIEnv* env,
57 net::URLRequest* request, 71 net::URLRequest* request,
58 InputStream* stream, 72 InputStream* stream,
59 std::string* mime_type) OVERRIDE; 73 std::string* mime_type) OVERRIDE;
60 74
61 virtual bool GetCharset(JNIEnv* env, 75 virtual bool GetCharset(JNIEnv* env,
62 net::URLRequest* request, 76 net::URLRequest* request,
63 InputStream* stream, 77 InputStream* stream,
64 std::string* charset) OVERRIDE; 78 std::string* charset) OVERRIDE;
65 79
66 virtual ~AndroidStreamReaderURLRequestJobDelegateImpl(); 80 virtual ~AndroidStreamReaderURLRequestJobDelegateImpl();
81
82 private:
83 scoped_ptr<InputStream> DoOpenInputStream(JNIEnv* env, const GURL& url);
67 }; 84 };
68 85
69 class AssetFileProtocolInterceptor : 86 class AndroidProtocolHandlerBase :
70 public net::URLRequestJobFactory::ProtocolHandler { 87 public net::URLRequestJobFactory::ProtocolHandler {
71 public: 88 public:
72 virtual ~AssetFileProtocolInterceptor() OVERRIDE;
73 static scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
74 scoped_ptr<net::URLRequestJobFactory> base_job_factory);
75 virtual net::URLRequestJob* MaybeCreateJob( 89 virtual net::URLRequestJob* MaybeCreateJob(
76 net::URLRequest* request, 90 net::URLRequest* request,
77 net::NetworkDelegate* network_delegate) const OVERRIDE; 91 net::NetworkDelegate* network_delegate) const OVERRIDE;
78 92
93 virtual bool CanHandleRequest(const net::URLRequest* request) const = 0;
94 };
95
96 class AssetFileProtocolHandler : public AndroidProtocolHandlerBase {
97 public:
98 AssetFileProtocolHandler();
99
100 virtual ~AssetFileProtocolHandler() OVERRIDE;
101 virtual bool CanHandleRequest(const net::URLRequest* request) const OVERRIDE;
102
79 private: 103 private:
80 AssetFileProtocolInterceptor();
81
82 // file:///android_asset/ 104 // file:///android_asset/
83 const std::string asset_prefix_; 105 const std::string asset_prefix_;
84 // file:///android_res/ 106 // file:///android_res/
85 const std::string resource_prefix_; 107 const std::string resource_prefix_;
86 }; 108 };
87 109
88 // Protocol handler for content:// scheme requests. 110 // Protocol handler for content:// scheme requests.
89 class ContentSchemeProtocolHandler : 111 class ContentSchemeProtocolHandler : public AndroidProtocolHandlerBase {
90 public net::URLRequestJobFactory::ProtocolHandler {
91 public: 112 public:
92 ContentSchemeProtocolHandler() {} 113 ContentSchemeProtocolHandler();
93 114 virtual bool CanHandleRequest(const net::URLRequest* request) const OVERRIDE;
94 virtual net::URLRequestJob* MaybeCreateJob(
95 net::URLRequest* request,
96 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 }; 115 };
105 116
106 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) { 117 static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) {
107 if (g_resource_context) 118 if (g_resource_context)
108 return g_resource_context->get(env); 119 return g_resource_context->get(env);
109 ScopedJavaLocalRef<jobject> context; 120 ScopedJavaLocalRef<jobject> context;
110 // We have to reset as GetApplicationContext() returns a jobject with a 121 // 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 122 // global ref. The constructor that takes a jobject would expect a local ref
112 // and would assert. 123 // and would assert.
113 context.Reset(env, base::android::GetApplicationContext()); 124 context.Reset(env, base::android::GetApplicationContext());
114 return context; 125 return context;
115 } 126 }
116 127
128 // AndroidStreamReaderURLRequestJobDelegateImpl -------------------------------
129
117 AndroidStreamReaderURLRequestJobDelegateImpl:: 130 AndroidStreamReaderURLRequestJobDelegateImpl::
118 AndroidStreamReaderURLRequestJobDelegateImpl() { 131 AndroidStreamReaderURLRequestJobDelegateImpl() {}
119 }
120 132
121 AndroidStreamReaderURLRequestJobDelegateImpl:: 133 AndroidStreamReaderURLRequestJobDelegateImpl::
122 ~AndroidStreamReaderURLRequestJobDelegateImpl() { 134 ~AndroidStreamReaderURLRequestJobDelegateImpl() {
123 } 135 }
124 136
125 scoped_ptr<InputStream> 137 scoped_ptr<InputStream>
126 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream( 138 AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream(
127 JNIEnv* env, net::URLRequest* request) { 139 JNIEnv* env, const GURL& url) {
128 DCHECK(request); 140 DCHECK(url.is_valid());
129 DCHECK(env); 141 DCHECK(env);
130 142
131 // Open the input stream. 143 // Open the input stream.
132 ScopedJavaLocalRef<jstring> url = 144 ScopedJavaLocalRef<jstring> jurl =
133 ConvertUTF8ToJavaString(env, request->url().spec()); 145 ConvertUTF8ToJavaString(env, url.spec());
134 ScopedJavaLocalRef<jobject> stream = 146 ScopedJavaLocalRef<jobject> stream =
135 android_webview::Java_AndroidProtocolHandler_open( 147 android_webview::Java_AndroidProtocolHandler_open(
136 env, 148 env,
137 GetResourceContext(env).obj(), 149 GetResourceContext(env).obj(),
138 url.obj()); 150 jurl.obj());
139 151
140 // Check and clear pending exceptions. 152 // Check and clear pending exceptions.
141 if (ClearException(env) || stream.is_null()) { 153 if (ClearException(env) || stream.is_null()) {
142 DLOG(ERROR) << "Unable to open input stream for Android URL"; 154 DLOG(ERROR) << "Unable to open input stream for Android URL";
143 return scoped_ptr<InputStream>(); 155 return scoped_ptr<InputStream>();
144 } 156 }
145 return make_scoped_ptr<InputStream>(new InputStreamImpl(stream)); 157 return make_scoped_ptr<InputStream>(new InputStreamImpl(stream));
146 } 158 }
147 159
160 void AndroidStreamReaderURLRequestJobDelegateImpl::OnInputStreamOpenFailed(
161 net::URLRequest* request,
162 bool* restart) {
163 MarkRequestAsFailed(request);
boliu 2013/03/06 02:30:18 Should put a DCHECK(!HasRequestPreviouslyFailed(re
mkosiba (inactive) 2013/03/06 19:05:27 good idea!
164 *restart = true;
165 }
166
148 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType( 167 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType(
149 JNIEnv* env, 168 JNIEnv* env,
150 net::URLRequest* request, 169 net::URLRequest* request,
151 android_webview::InputStream* stream, 170 android_webview::InputStream* stream,
152 std::string* mime_type) { 171 std::string* mime_type) {
153 DCHECK(env); 172 DCHECK(env);
154 DCHECK(request); 173 DCHECK(request);
155 DCHECK(mime_type); 174 DCHECK(mime_type);
156 175
157 // Query the mime type from the Java side. It is possible for the query to 176 // Query the mime type from the Java side. It is possible for the query to
(...skipping 16 matching lines...) Expand all
174 193
175 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset( 194 bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset(
176 JNIEnv* env, 195 JNIEnv* env,
177 net::URLRequest* request, 196 net::URLRequest* request,
178 android_webview::InputStream* stream, 197 android_webview::InputStream* stream,
179 std::string* charset) { 198 std::string* charset) {
180 // TODO: We should probably be getting this from the managed side. 199 // TODO: We should probably be getting this from the managed side.
181 return false; 200 return false;
182 } 201 }
183 202
184 AssetFileProtocolInterceptor::AssetFileProtocolInterceptor() 203 // AndroidProtocolHandlerBase -------------------------------------------------
204
205 net::URLRequestJob* AndroidProtocolHandlerBase::MaybeCreateJob(
206 net::URLRequest* request,
207 net::NetworkDelegate* network_delegate) const {
208 if (!CanHandleRequest(request)) return NULL;
209
210 // For WebViewClassic compatibility this job can only accept URLs that can be
211 // opened. URLs that cannot be opened should be resolved by the next handler.
212 //
213 // If a request is initially handled here but the job fails due to it being
214 // unable to open the InputStream for that request the request is marked as
215 // previously failed and restarted.
216 // Restarting a request involves creating a new job for that request. This
217 // handler will ignore requests know to have previously failed to 1) prevent
218 // an infinite loop, 2) ensure that the next handler in line gets the
219 // opportunity to create a job for the request.
220 if (HasRequestPreviouslyFailed(request)) return NULL;
221
222 scoped_ptr<AndroidStreamReaderURLRequestJobDelegateImpl> reader_delegate(
223 new AndroidStreamReaderURLRequestJobDelegateImpl());
224
225 return new AndroidStreamReaderURLRequestJob(
226 request,
227 network_delegate,
228 reader_delegate.PassAs<AndroidStreamReaderURLRequestJob::Delegate>());
229 }
230
231 // AssetFileProtocolHandler ---------------------------------------------------
232
233 AssetFileProtocolHandler::AssetFileProtocolHandler()
185 : asset_prefix_(std::string(chrome::kFileScheme) + 234 : asset_prefix_(std::string(chrome::kFileScheme) +
186 std::string(content::kStandardSchemeSeparator) + 235 std::string(content::kStandardSchemeSeparator) +
187 android_webview::kAndroidAssetPath), 236 android_webview::kAndroidAssetPath),
188 resource_prefix_(std::string(chrome::kFileScheme) + 237 resource_prefix_(std::string(chrome::kFileScheme) +
189 std::string(content::kStandardSchemeSeparator) + 238 std::string(content::kStandardSchemeSeparator) +
190 android_webview::kAndroidResourcePath) { 239 android_webview::kAndroidResourcePath) {
191 } 240 }
192 241
193 AssetFileProtocolInterceptor::~AssetFileProtocolInterceptor() { 242 AssetFileProtocolHandler::~AssetFileProtocolHandler() {
194 } 243 }
195 244
196 // static 245 bool AssetFileProtocolHandler::CanHandleRequest(
197 scoped_ptr<net::URLRequestJobFactory> 246 const net::URLRequest* request) const {
198 AssetFileProtocolInterceptor::CreateURLRequestJobFactory( 247 if (!request->url().SchemeIsFile())
199 scoped_ptr<net::URLRequestJobFactory> base_job_factory) { 248 return false;
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 {
210 if (!request->url().SchemeIsFile()) return NULL;
211 249
212 const std::string& url = request->url().spec(); 250 const std::string& url = request->url().spec();
213 if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) && 251 if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) &&
214 !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) { 252 !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) {
215 return NULL; 253 return false;
216 } 254 }
217 255
218 return new AndroidStreamReaderURLRequestJob( 256 return true;
219 request, 257 }
220 network_delegate, 258
221 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>( 259 // ContentSchemeProtocolHandler -----------------------------------------------
222 new AndroidStreamReaderURLRequestJobDelegateImpl())); 260
261 ContentSchemeProtocolHandler::ContentSchemeProtocolHandler() {
262 }
263
264 bool ContentSchemeProtocolHandler::CanHandleRequest(
265 const net::URLRequest* request) const {
266 return request->url().SchemeIs(android_webview::kContentScheme);
223 } 267 }
224 268
225 } // namespace 269 } // namespace
226 270
227 namespace android_webview { 271 namespace android_webview {
228 272
229 bool RegisterAndroidProtocolHandler(JNIEnv* env) { 273 bool RegisterAndroidProtocolHandler(JNIEnv* env) {
230 return RegisterNativesImpl(env); 274 return RegisterNativesImpl(env);
231 } 275 }
232 276
233 // static 277 // static
234 scoped_ptr<net::URLRequestJobFactory> CreateAndroidRequestJobFactory( 278 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
235 scoped_ptr<AwURLRequestJobFactory> job_factory) { 279 CreateContentSchemeProtocolHandler() {
236 // Register content://. Note that even though a scheme is 280 return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
237 // registered here, it cannot be used by child processes until access to it is 281 new ContentSchemeProtocolHandler());
238 // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in 282 }
239 // AwContentBrowserClient. 283
240 // The job factory takes ownership of the handler. 284 // static
241 bool set_protocol = job_factory->SetProtocolHandler( 285 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
242 android_webview::kContentScheme, new ContentSchemeProtocolHandler()); 286 CreateAssetFileProtocolHandler() {
243 DCHECK(set_protocol); 287 return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
244 return AssetFileProtocolInterceptor::CreateURLRequestJobFactory( 288 new AssetFileProtocolHandler());
245 job_factory.PassAs<net::URLRequestJobFactory>());
246 } 289 }
247 290
248 // Set a context object to be used for resolving resource queries. This can 291 // 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 292 // 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 293 // resource queries to a specific context object, e.g., for the purposes of
251 // testing. 294 // testing.
252 // 295 //
253 // |context| should be a android.content.Context instance or NULL to enable 296 // |context| should be a android.content.Context instance or NULL to enable
254 // the use of the standard application context. 297 // the use of the standard application context.
255 static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/, 298 static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/,
(...skipping 11 matching lines...) Expand all
267 env, android_webview::kAndroidAssetPath).Release(); 310 env, android_webview::kAndroidAssetPath).Release();
268 } 311 }
269 312
270 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) { 313 static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) {
271 // OK to release, JNI binding. 314 // OK to release, JNI binding.
272 return ConvertUTF8ToJavaString( 315 return ConvertUTF8ToJavaString(
273 env, android_webview::kAndroidResourcePath).Release(); 316 env, android_webview::kAndroidResourcePath).Release();
274 } 317 }
275 318
276 } // namespace android_webview 319 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698