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

Side by Side Diff: third_party/WebKit/Source/web/AssociatedURLLoader.cpp

Issue 1862073002: Let AssociatedURLLoader listen to destruction of the Document used for loading (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added comment to RELEASE_ASSERT Created 4 years, 8 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 12 matching lines...) Expand all
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "web/AssociatedURLLoader.h" 31 #include "web/AssociatedURLLoader.h"
32 32
33 #include "core/dom/ContextLifecycleObserver.h"
33 #include "core/fetch/CrossOriginAccessControl.h" 34 #include "core/fetch/CrossOriginAccessControl.h"
34 #include "core/fetch/FetchUtils.h" 35 #include "core/fetch/FetchUtils.h"
35 #include "core/loader/DocumentThreadableLoader.h" 36 #include "core/loader/DocumentThreadableLoader.h"
36 #include "core/loader/DocumentThreadableLoaderClient.h" 37 #include "core/loader/DocumentThreadableLoaderClient.h"
37 #include "platform/Timer.h" 38 #include "platform/Timer.h"
38 #include "platform/exported/WrappedResourceRequest.h" 39 #include "platform/exported/WrappedResourceRequest.h"
39 #include "platform/exported/WrappedResourceResponse.h" 40 #include "platform/exported/WrappedResourceResponse.h"
40 #include "platform/network/HTTPParsers.h" 41 #include "platform/network/HTTPParsers.h"
41 #include "platform/network/ResourceError.h" 42 #include "platform/network/ResourceError.h"
42 #include "public/platform/WebHTTPHeaderVisitor.h" 43 #include "public/platform/WebHTTPHeaderVisitor.h"
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 return; 241 return;
241 242
242 m_client->didReceiveCachedMetadata(m_loader, data, dataLength); 243 m_client->didReceiveCachedMetadata(m_loader, data, dataLength);
243 } 244 }
244 245
245 void AssociatedURLLoader::ClientAdapter::didFinishLoading(unsigned long identifi er, double finishTime) 246 void AssociatedURLLoader::ClientAdapter::didFinishLoading(unsigned long identifi er, double finishTime)
246 { 247 {
247 if (!m_client) 248 if (!m_client)
248 return; 249 return;
249 250
251 m_loader->disposeObserver();
252
250 m_client->didFinishLoading(m_loader, finishTime, WebURLLoaderClient::kUnknow nEncodedDataLength); 253 m_client->didFinishLoading(m_loader, finishTime, WebURLLoaderClient::kUnknow nEncodedDataLength);
251 } 254 }
252 255
253 void AssociatedURLLoader::ClientAdapter::didFail(const ResourceError& error) 256 void AssociatedURLLoader::ClientAdapter::didFail(const ResourceError& error)
254 { 257 {
255 if (!m_client) 258 if (!m_client)
256 return; 259 return;
257 260
261 m_loader->disposeObserver();
262
258 m_didFail = true; 263 m_didFail = true;
259 m_error = WebURLError(error); 264 m_error = WebURLError(error);
260 if (m_enableErrorNotifications) 265 if (m_enableErrorNotifications)
261 notifyError(&m_errorTimer); 266 notifyError(&m_errorTimer);
262 } 267 }
263 268
264 void AssociatedURLLoader::ClientAdapter::didFailRedirectCheck() 269 void AssociatedURLLoader::ClientAdapter::didFailRedirectCheck()
265 { 270 {
266 didFail(ResourceError()); 271 didFail(ResourceError());
267 } 272 }
268 273
269 void AssociatedURLLoader::ClientAdapter::setDelayedError(const ResourceError& er ror)
270 {
271 didFail(error);
272 }
273
274 void AssociatedURLLoader::ClientAdapter::enableErrorNotifications() 274 void AssociatedURLLoader::ClientAdapter::enableErrorNotifications()
275 { 275 {
276 m_enableErrorNotifications = true; 276 m_enableErrorNotifications = true;
277 // If an error has already been received, start a timer to report it to the client 277 // If an error has already been received, start a timer to report it to the client
278 // after AssociatedURLLoader::loadAsynchronously has returned to the caller. 278 // after AssociatedURLLoader::loadAsynchronously has returned to the caller.
279 if (m_didFail) 279 if (m_didFail)
280 m_errorTimer.startOneShot(0, BLINK_FROM_HERE); 280 m_errorTimer.startOneShot(0, BLINK_FROM_HERE);
281 } 281 }
282 282
283 void AssociatedURLLoader::ClientAdapter::notifyError(Timer<ClientAdapter>* timer ) 283 void AssociatedURLLoader::ClientAdapter::notifyError(Timer<ClientAdapter>* timer )
284 { 284 {
285 ASSERT_UNUSED(timer, timer == &m_errorTimer); 285 ASSERT_UNUSED(timer, timer == &m_errorTimer);
286 286
287 if (!m_client)
288 return;
289
287 m_client->didFail(m_loader, m_error); 290 m_client->didFail(m_loader, m_error);
288 } 291 }
289 292
293 class AssociatedURLLoader::Observer final : public GarbageCollectedFinalized<Obs erver>, public ContextLifecycleObserver {
294 USING_GARBAGE_COLLECTED_MIXIN(Observer);
295 public:
296 Observer(AssociatedURLLoader* parent, Document* document)
297 : ContextLifecycleObserver(document)
298 , m_parent(parent)
299 {
300 }
301
302 void dispose()
303 {
304 m_parent = nullptr;
305 clearContext();
306 }
307
308 void contextDestroyed() override
309 {
310 if (m_parent)
311 m_parent->documentDestroyed();
312 }
313
314 DEFINE_INLINE_VIRTUAL_TRACE()
315 {
316 ContextLifecycleObserver::trace(visitor);
317 }
318
319 AssociatedURLLoader* m_parent;
320 };
321
290 AssociatedURLLoader::AssociatedURLLoader(RawPtr<WebLocalFrameImpl> frameImpl, co nst WebURLLoaderOptions& options) 322 AssociatedURLLoader::AssociatedURLLoader(RawPtr<WebLocalFrameImpl> frameImpl, co nst WebURLLoaderOptions& options)
291 : m_frameImpl(frameImpl) 323 : m_options(options)
292 , m_options(options) 324 , m_observer(new Observer(this, frameImpl->frame()->document()))
293 , m_client(0)
294 { 325 {
295 DCHECK(m_frameImpl);
296 } 326 }
297 327
298 AssociatedURLLoader::~AssociatedURLLoader() 328 AssociatedURLLoader::~AssociatedURLLoader()
299 { 329 {
300 cancel(); 330 cancel();
301 } 331 }
302 332
303 #define STATIC_ASSERT_ENUM(a, b) \ 333 #define STATIC_ASSERT_ENUM(a, b) \
304 static_assert(static_cast<int>(a) == static_cast<int>(b), \ 334 static_assert(static_cast<int>(a) == static_cast<int>(b), \
305 "mismatching enum: " #a) 335 "mismatching enum: " #a)
306 336
307 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyDeny, DenyCrossO riginRequests); 337 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyDeny, DenyCrossO riginRequests);
308 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl , UseAccessControl); 338 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl , UseAccessControl);
309 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyAllow, AllowCros sOriginRequests); 339 STATIC_ASSERT_ENUM(WebURLLoaderOptions::CrossOriginRequestPolicyAllow, AllowCros sOriginRequests);
310 340
311 STATIC_ASSERT_ENUM(WebURLLoaderOptions::ConsiderPreflight, ConsiderPreflight); 341 STATIC_ASSERT_ENUM(WebURLLoaderOptions::ConsiderPreflight, ConsiderPreflight);
312 STATIC_ASSERT_ENUM(WebURLLoaderOptions::ForcePreflight, ForcePreflight); 342 STATIC_ASSERT_ENUM(WebURLLoaderOptions::ForcePreflight, ForcePreflight);
313 STATIC_ASSERT_ENUM(WebURLLoaderOptions::PreventPreflight, PreventPreflight); 343 STATIC_ASSERT_ENUM(WebURLLoaderOptions::PreventPreflight, PreventPreflight);
314 344
315 void AssociatedURLLoader::loadSynchronously(const WebURLRequest& request, WebURL Response& response, WebURLError& error, WebData& data) 345 void AssociatedURLLoader::loadSynchronously(const WebURLRequest& request, WebURL Response& response, WebURLError& error, WebData& data)
316 { 346 {
317 DCHECK(0); // Synchronous loading is not supported. 347 DCHECK(0); // Synchronous loading is not supported.
318 } 348 }
319 349
320 void AssociatedURLLoader::loadAsynchronously(const WebURLRequest& request, WebUR LLoaderClient* client) 350 void AssociatedURLLoader::loadAsynchronously(const WebURLRequest& request, WebUR LLoaderClient* client)
321 { 351 {
322 DCHECK(!m_loader); 352 DCHECK(!m_loader);
323 DCHECK(!m_client); 353 DCHECK(!m_clientAdapter);
324 354
325 m_client = client; 355 DCHECK(client);
326 DCHECK(m_client);
327 356
328 bool allowLoad = true; 357 bool allowLoad = true;
329 WebURLRequest newRequest(request); 358 WebURLRequest newRequest(request);
330 if (m_options.untrustedHTTP) { 359 if (m_options.untrustedHTTP) {
331 WebString method = newRequest.httpMethod(); 360 WebString method = newRequest.httpMethod();
332 allowLoad = isValidHTTPToken(method) && FetchUtils::isUsefulMethod(metho d); 361 allowLoad = m_observer && isValidHTTPToken(method) && FetchUtils::isUsef ulMethod(method);
333 if (allowLoad) { 362 if (allowLoad) {
334 newRequest.setHTTPMethod(FetchUtils::normalizeMethod(method)); 363 newRequest.setHTTPMethod(FetchUtils::normalizeMethod(method));
335 HTTPRequestHeaderValidator validator; 364 HTTPRequestHeaderValidator validator;
336 newRequest.visitHTTPHeaderFields(&validator); 365 newRequest.visitHTTPHeaderFields(&validator);
337 allowLoad = validator.isSafe(); 366 allowLoad = validator.isSafe();
338 } 367 }
339 } 368 }
340 369
341 m_clientAdapter = ClientAdapter::create(this, m_client, m_options); 370 m_clientAdapter = ClientAdapter::create(this, client, m_options);
342 371
343 if (allowLoad) { 372 if (allowLoad) {
344 ThreadableLoaderOptions options; 373 ThreadableLoaderOptions options;
345 options.preflightPolicy = static_cast<PreflightPolicy>(m_options.preflig htPolicy); 374 options.preflightPolicy = static_cast<PreflightPolicy>(m_options.preflig htPolicy);
346 options.crossOriginRequestPolicy = static_cast<CrossOriginRequestPolicy> (m_options.crossOriginRequestPolicy); 375 options.crossOriginRequestPolicy = static_cast<CrossOriginRequestPolicy> (m_options.crossOriginRequestPolicy);
347 376
348 ResourceLoaderOptions resourceLoaderOptions; 377 ResourceLoaderOptions resourceLoaderOptions;
349 resourceLoaderOptions.allowCredentials = m_options.allowCredentials ? Al lowStoredCredentials : DoNotAllowStoredCredentials; 378 resourceLoaderOptions.allowCredentials = m_options.allowCredentials ? Al lowStoredCredentials : DoNotAllowStoredCredentials;
350 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; 379 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
351 380
352 const ResourceRequest& webcoreRequest = newRequest.toResourceRequest(); 381 const ResourceRequest& webcoreRequest = newRequest.toResourceRequest();
353 if (webcoreRequest.requestContext() == WebURLRequest::RequestContextUnsp ecified) { 382 if (webcoreRequest.requestContext() == WebURLRequest::RequestContextUnsp ecified) {
354 // FIXME: We load URLs without setting a TargetType (and therefore a request context) in several 383 // FIXME: We load URLs without setting a TargetType (and therefore a request context) in several
355 // places in content/ (P2PPortAllocatorSession::AllocateLegacyRelayS ession, for example). Remove 384 // places in content/ (P2PPortAllocatorSession::AllocateLegacyRelayS ession, for example). Remove
356 // this once those places are patched up. 385 // this once those places are patched up.
357 newRequest.setRequestContext(WebURLRequest::RequestContextInternal); 386 newRequest.setRequestContext(WebURLRequest::RequestContextInternal);
358 } 387 }
359 388
360 Document* webcoreDocument = m_frameImpl->frame()->document(); 389 Document* document = toDocument(m_observer->lifecycleContext());
361 DCHECK(webcoreDocument); 390 DCHECK(document);
362 m_loader = DocumentThreadableLoader::create(*webcoreDocument, m_clientAd apter.get(), options, resourceLoaderOptions); 391 m_loader = DocumentThreadableLoader::create(*document, m_clientAdapter.g et(), options, resourceLoaderOptions);
363 m_loader->start(webcoreRequest); 392 m_loader->start(webcoreRequest);
364 } 393 }
365 394
366 if (!m_loader) { 395 if (!m_loader) {
367 // FIXME: return meaningful error codes. 396 // FIXME: return meaningful error codes.
368 m_clientAdapter->setDelayedError(ResourceError()); 397 m_clientAdapter->didFail(ResourceError());
369 } 398 }
370 m_clientAdapter->enableErrorNotifications(); 399 m_clientAdapter->enableErrorNotifications();
371 } 400 }
372 401
373 void AssociatedURLLoader::cancel() 402 void AssociatedURLLoader::cancel()
374 { 403 {
375 if (m_clientAdapter) 404 disposeObserver();
376 m_clientAdapter->clearClient(); 405
377 if (m_loader) 406 if (!m_clientAdapter)
407 return;
408
409 // Prevent invocation of the WebURLLoaderClient methods.
410 m_clientAdapter->clearClient();
411
412 if (m_loader) {
378 m_loader->cancel(); 413 m_loader->cancel();
414 m_loader.clear();
415 }
416 m_clientAdapter.clear();
379 } 417 }
380 418
381 void AssociatedURLLoader::setDefersLoading(bool defersLoading) 419 void AssociatedURLLoader::setDefersLoading(bool defersLoading)
382 { 420 {
383 if (m_loader) 421 if (m_loader)
384 m_loader->setDefersLoading(defersLoading); 422 m_loader->setDefersLoading(defersLoading);
385 } 423 }
386 424
387 void AssociatedURLLoader::setLoadingTaskRunner(blink::WebTaskRunner*) 425 void AssociatedURLLoader::setLoadingTaskRunner(blink::WebTaskRunner*)
388 { 426 {
389 // TODO(alexclarke): Maybe support this one day if it proves worthwhile. 427 // TODO(alexclarke): Maybe support this one day if it proves worthwhile.
390 } 428 }
391 429
430 void AssociatedURLLoader::documentDestroyed()
431 {
432 cancel();
433
434 m_client->didFail(this, ResourceError());
435 // |this| may be dead here.
436 }
437
438 void AssociatedURLLoader::disposeObserver()
439 {
440 if (!m_observer)
441 return;
442
443 // The method of detecting Document destruction implemented here doesn't
haraken 2016/04/08 07:34:13 Add TODO.
tyoshino (SeeGerritForStatus) 2016/04/08 07:56:58 Done.
444 // work for all kinds of Documents. In case we reached here after the
445 // Oilpan is destroyed, we just crash the renderer process to prevent UaF.
haraken 2016/04/08 07:34:13 Sorry, how does this cause UaF?
tyoshino (SeeGerritForStatus) 2016/04/08 07:56:58 m_observer is on-heap. If the Oilpan is already sh
446 RELEASE_ASSERT(ThreadState::current());
447
448 m_observer->dispose();
449 m_observer = nullptr;
450 }
451
392 } // namespace blink 452 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698