Changeset 224758 in webkit
- Timestamp:
- Nov 13, 2017, 10:32:00 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r224755 r224758 1 2017-11-13 Alex Christensen <achristensen@webkit.org> 2 3 Make DocumentLoader::willSendRequest asynchronous 4 https://bugs.webkit.org/show_bug.cgi?id=179549 5 6 Reviewed by Tim Horton. 7 8 No change in behavior, except now redirects will wait for PolicyChecker::checkNavigationPolicy's completion handler. 9 Before, they would just continue in DocumentLoader::redirectReceived hoping the client had responded to 10 decidePolicyForNavigationAction synchronously or that the client would have been ok with continuing. 11 12 * loader/DocumentLoader.cpp: 13 (WebCore::DocumentLoader::redirectReceived): 14 (WebCore::DocumentLoader::willSendRequest): 15 (WebCore::DocumentLoader::startLoadingMainResource): 16 * loader/DocumentLoader.h: 17 * loader/FrameLoader.cpp: 18 (WebCore::FrameLoader::loadURL): 19 (WebCore::FrameLoader::loadWithDocumentLoader): 20 * loader/PolicyChecker.cpp: 21 (WebCore::PolicyChecker::checkNavigationPolicy): 22 * loader/PolicyChecker.h: 23 1 24 2017-11-13 Wenson Hsieh <wenson_hsieh@apple.com> 2 25 -
trunk/Source/WebCore/loader/DocumentLoader.cpp
r224699 r224758 471 471 { 472 472 ASSERT_UNUSED(resource, &resource == m_mainResource); 473 willSendRequest(request, redirectResponse); 474 completionHandler(WTFMove(request)); 475 } 476 477 void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) 473 willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler)); 474 } 475 476 void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& completionHandler) 478 477 { 479 478 // Note that there are no asserts here as there are for the other callbacks. This is due to the … … 486 485 if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url(), didReceiveRedirectResponse)) { 487 486 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 488 return ;487 return completionHandler(WTFMove(newRequest)); 489 488 } 490 489 … … 497 496 FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string()); 498 497 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 499 return ;498 return completionHandler(WTFMove(newRequest)); 500 499 } 501 500 if (!portAllowed(newRequest.url())) { 502 501 FrameLoader::reportBlockedPortFailed(m_frame, newRequest.url().string()); 503 502 cancelMainResourceLoad(frameLoader()->blockedError(newRequest)); 504 return ;503 return completionHandler(WTFMove(newRequest)); 505 504 } 506 505 timing().addRedirect(redirectResponse.url(), newRequest.url()); … … 531 530 if (!m_frame->loader().mixedContentChecker().canDisplayInsecureContent(m_frame->document()->securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url(), MixedContentChecker::AlwaysDisplayInNonStrictMode::Yes)) { 532 531 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 533 return ;532 return completionHandler(WTFMove(newRequest)); 534 533 } 535 534 if (!frameLoader()->mixedContentChecker().canDisplayInsecureContent(topFrame.document()->securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url())) { 536 535 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 537 return ;536 return completionHandler(WTFMove(newRequest)); 538 537 } 539 538 } … … 541 540 #if ENABLE(CONTENT_FILTERING) 542 541 if (m_contentFilter && !m_contentFilter->continueAfterWillSendRequest(newRequest, redirectResponse)) 543 return ;542 return completionHandler(WTFMove(newRequest)); 544 543 #endif 545 544 … … 562 561 // synchronously for these redirect cases. 563 562 if (!didReceiveRedirectResponse) 564 return ;563 return completionHandler(WTFMove(newRequest)); 565 564 566 565 ASSERT(!m_waitingForNavigationPolicy); 567 566 m_waitingForNavigationPolicy = true; 568 frameLoader()->policyChecker().checkNavigationPolicy( newRequest, didReceiveRedirectResponse, [this, protectedThis = makeRef(*this)] (const ResourceRequest& request, FormState*, bool shouldContinue){567 frameLoader()->policyChecker().checkNavigationPolicy(ResourceRequest(newRequest), didReceiveRedirectResponse, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request, FormState*, bool shouldContinue) mutable { 569 568 continueAfterNavigationPolicy(request, shouldContinue); 569 completionHandler(WTFMove(request)); 570 570 }); 571 571 } … … 1454 1454 ASSERT(timing().fetchStart()); 1455 1455 1456 Ref<DocumentLoader> protectedThis(*this); // willSendRequest() may deallocate the provisional loader (which may be us) if it cancels the load. 1457 willSendRequest(m_request, ResourceResponse()); 1458 1459 // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest. 1460 if (!m_frame || m_request.isNull()) { 1461 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Load canceled after willSendRequest (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false); 1462 return; 1463 } 1464 1465 m_applicationCacheHost->maybeLoadMainResource(m_request, m_substituteData); 1466 1467 if (m_substituteData.isValid() && m_frame->page()) { 1468 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning cached main resource (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1469 m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier(); 1470 frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, m_request); 1471 frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, m_request, ResourceResponse()); 1472 handleSubstituteDataLoadSoon(); 1473 return; 1474 } 1475 1476 ResourceRequest request(m_request); 1477 request.setRequester(ResourceRequest::Requester::Main); 1478 // If this is a reload the cache layer might have made the previous request conditional. DocumentLoader can't handle 304 responses itself. 1479 request.makeUnconditional(); 1480 1481 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Starting load (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1482 1483 static NeverDestroyed<ResourceLoaderOptions> mainResourceLoadOptions(SendCallbacks, SniffContent, BufferData, StoredCredentialsPolicy::Use, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, SkipSecurityCheck, FetchOptions::Mode::NoCors, IncludeCertificateInfo, ContentSecurityPolicyImposition::SkipPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching); 1484 CachedResourceRequest mainResourceRequest(ResourceRequest(request), mainResourceLoadOptions); 1485 if (!m_frame->isMainFrame() && m_frame->document()) { 1486 // If we are loading the main resource of a subframe, use the cache partition of the main document. 1487 mainResourceRequest.setDomainForCachePartition(*m_frame->document()); 1488 } else { 1489 auto origin = SecurityOrigin::create(request.url()); 1490 origin->setStorageBlockingPolicy(frameLoader()->frame().settings().storageBlockingPolicy()); 1491 mainResourceRequest.setDomainForCachePartition(origin->domainForCachePartition()); 1492 } 1493 m_mainResource = m_cachedResourceLoader->requestMainResource(WTFMove(mainResourceRequest)).valueOr(nullptr); 1456 willSendRequest(ResourceRequest(m_request), ResourceResponse(), [this, protectedThis = makeRef(*this)] (ResourceRequest&& request) { 1457 m_request = request; 1458 1459 // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest. 1460 if (!m_frame || m_request.isNull()) { 1461 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Load canceled after willSendRequest (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false); 1462 return; 1463 } 1464 1465 m_applicationCacheHost->maybeLoadMainResource(m_request, m_substituteData); 1466 1467 if (m_substituteData.isValid() && m_frame->page()) { 1468 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning cached main resource (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1469 m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier(); 1470 frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, m_request); 1471 frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, m_request, ResourceResponse()); 1472 handleSubstituteDataLoadSoon(); 1473 return; 1474 } 1475 1476 request.setRequester(ResourceRequest::Requester::Main); 1477 // If this is a reload the cache layer might have made the previous request conditional. DocumentLoader can't handle 304 responses itself. 1478 request.makeUnconditional(); 1479 1480 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Starting load (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1481 1482 static NeverDestroyed<ResourceLoaderOptions> mainResourceLoadOptions(SendCallbacks, SniffContent, BufferData, StoredCredentialsPolicy::Use, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, SkipSecurityCheck, FetchOptions::Mode::NoCors, IncludeCertificateInfo, ContentSecurityPolicyImposition::SkipPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching); 1483 CachedResourceRequest mainResourceRequest(ResourceRequest(request), mainResourceLoadOptions); 1484 if (!m_frame->isMainFrame() && m_frame->document()) { 1485 // If we are loading the main resource of a subframe, use the cache partition of the main document. 1486 mainResourceRequest.setDomainForCachePartition(*m_frame->document()); 1487 } else { 1488 auto origin = SecurityOrigin::create(request.url()); 1489 origin->setStorageBlockingPolicy(frameLoader()->frame().settings().storageBlockingPolicy()); 1490 mainResourceRequest.setDomainForCachePartition(origin->domainForCachePartition()); 1491 } 1492 m_mainResource = m_cachedResourceLoader->requestMainResource(WTFMove(mainResourceRequest)).valueOr(nullptr); 1494 1493 1495 1494 #if ENABLE(CONTENT_EXTENSIONS) 1496 if (m_mainResource && m_mainResource->errorOccurred() && m_frame->page() && m_mainResource->resourceError().domain() == ContentExtensions::WebKitContentBlockerDomain) { 1497 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Blocked by content blocker error (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1498 cancelMainResourceLoad(frameLoader()->blockedByContentBlockerError(m_request)); 1499 return; 1500 } 1501 #endif 1502 1503 if (!m_mainResource) { 1504 if (!m_request.url().isValid()) { 1505 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, URL is invalid (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1506 cancelMainResourceLoad(frameLoader()->client().cannotShowURLError(m_request)); 1495 if (m_mainResource && m_mainResource->errorOccurred() && m_frame->page() && m_mainResource->resourceError().domain() == ContentExtensions::WebKitContentBlockerDomain) { 1496 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Blocked by content blocker error (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1497 cancelMainResourceLoad(frameLoader()->blockedByContentBlockerError(m_request)); 1507 1498 return; 1508 1499 } 1509 1510 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, returning empty document (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1511 1512 setRequest(ResourceRequest()); 1513 // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost 1514 // is now in a state where starting an empty load will be inconsistent. Replace it with 1515 // a new ApplicationCacheHost. 1516 m_applicationCacheHost = std::make_unique<ApplicationCacheHost>(*this); 1517 maybeLoadEmpty(); 1518 return; 1519 } 1520 1521 if (!mainResourceLoader()) { 1522 m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier(); 1523 frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, request); 1524 frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, request, ResourceResponse()); 1525 } 1526 1527 becomeMainResourceClient(); 1528 1529 // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those. 1530 if (mainResourceLoader()) 1531 request = mainResourceLoader()->originalRequest(); 1532 // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include 1533 // the fragment identifier, so add that back in. 1534 if (equalIgnoringFragmentIdentifier(m_request.url(), request.url())) 1535 request.setURL(m_request.url()); 1536 setRequest(request); 1500 #endif 1501 1502 if (!m_mainResource) { 1503 if (!m_request.url().isValid()) { 1504 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, URL is invalid (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1505 cancelMainResourceLoad(frameLoader()->client().cannotShowURLError(m_request)); 1506 return; 1507 } 1508 1509 RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, returning empty document (frame = %p, main = %d)", m_frame, m_frame->isMainFrame()); 1510 1511 setRequest(ResourceRequest()); 1512 // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost 1513 // is now in a state where starting an empty load will be inconsistent. Replace it with 1514 // a new ApplicationCacheHost. 1515 m_applicationCacheHost = std::make_unique<ApplicationCacheHost>(*this); 1516 maybeLoadEmpty(); 1517 return; 1518 } 1519 1520 if (!mainResourceLoader()) { 1521 m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier(); 1522 frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, request); 1523 frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, request, ResourceResponse()); 1524 } 1525 1526 becomeMainResourceClient(); 1527 1528 // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those. 1529 if (mainResourceLoader()) 1530 request = mainResourceLoader()->originalRequest(); 1531 // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include 1532 // the fragment identifier, so add that back in. 1533 if (equalIgnoringFragmentIdentifier(m_request.url(), request.url())) 1534 request.setURL(m_request.url()); 1535 setRequest(request); 1536 }); 1537 1537 } 1538 1538 -
trunk/Source/WebCore/loader/DocumentLoader.h
r224699 r224758 325 325 #endif 326 326 327 void willSendRequest(ResourceRequest& , const ResourceResponse&);327 void willSendRequest(ResourceRequest&&, const ResourceResponse&, CompletionHandler<void(ResourceRequest&&)>&&); 328 328 void finishedLoading(); 329 329 void mainReceivedError(const ResourceError&); -
trunk/Source/WebCore/loader/FrameLoader.cpp
r224684 r224758 1313 1313 policyChecker().stopCheck(); 1314 1314 policyChecker().setLoadType(newLoadType); 1315 policyChecker().checkNavigationPolicy( request, false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) {1315 policyChecker().checkNavigationPolicy(WTFMove(request), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) { 1316 1316 continueFragmentScrollAfterNavigationPolicy(request, shouldContinue); 1317 1317 }); … … 1473 1473 oldDocumentLoader->setLastCheckedRequest(ResourceRequest()); 1474 1474 policyChecker().stopCheck(); 1475 policyChecker().checkNavigationPolicy( loader->request(), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) {1475 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) { 1476 1476 continueFragmentScrollAfterNavigationPolicy(request, shouldContinue); 1477 1477 }); … … 1500 1500 } 1501 1501 1502 policyChecker().checkNavigationPolicy( loader->request(), false /* didReceiveRedirectResponse */, loader, formState, [this, allowNavigationToInvalidURL] (const ResourceRequest& request, FormState* formState, bool shouldContinue) {1502 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, loader, formState, [this, allowNavigationToInvalidURL] (const ResourceRequest& request, FormState* formState, bool shouldContinue) { 1503 1503 continueLoadAfterNavigationPolicy(request, formState, shouldContinue, allowNavigationToInvalidURL); 1504 1504 }); -
trunk/Source/WebCore/loader/PolicyChecker.cpp
r224699 r224758 77 77 } 78 78 79 void PolicyChecker::checkNavigationPolicy( const ResourceRequest& newRequest, bool didReceiveRedirectResponse, NavigationPolicyDecisionFunction&& function)80 { 81 checkNavigationPolicy( newRequest, didReceiveRedirectResponse, m_frame.loader().activeDocumentLoader(), nullptr, WTFMove(function));82 } 83 84 void PolicyChecker::checkNavigationPolicy( const ResourceRequest& request, bool didReceiveRedirectResponse, DocumentLoader* loader, FormState* formState, NavigationPolicyDecisionFunction&& function)79 void PolicyChecker::checkNavigationPolicy(ResourceRequest&& newRequest, bool didReceiveRedirectResponse, NavigationPolicyDecisionFunction&& function) 80 { 81 checkNavigationPolicy(WTFMove(newRequest), didReceiveRedirectResponse, m_frame.loader().activeDocumentLoader(), nullptr, WTFMove(function)); 82 } 83 84 void PolicyChecker::checkNavigationPolicy(ResourceRequest&& request, bool didReceiveRedirectResponse, DocumentLoader* loader, FormState* formState, NavigationPolicyDecisionFunction&& function) 85 85 { 86 86 NavigationAction action = loader->triggeringAction(); … … 93 93 // This avoids confusion on the part of the client. 94 94 if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) { 95 function( request, nullptr, true);96 loader->setLastCheckedRequest( ResourceRequest(request));95 function(ResourceRequest(request), nullptr, true); 96 loader->setLastCheckedRequest(WTFMove(request)); 97 97 return; 98 98 } … … 108 108 if (isBackForwardLoadType(m_loadType)) 109 109 m_loadType = FrameLoadType::Reload; 110 function( request, nullptr, shouldContinue);110 function(WTFMove(request), nullptr, shouldContinue); 111 111 return; 112 112 } … … 118 118 m_frame.ownerElement()->dispatchEvent(Event::create(eventNames().loadEvent, false, false)); 119 119 } 120 function( request, nullptr, false);120 function(WTFMove(request), nullptr, false); 121 121 return; 122 122 } … … 127 127 // Always allow QuickLook-generated URLs based on the protocol scheme. 128 128 if (!request.isNull() && isQuickLookPreviewURL(request.url())) 129 return function( request, formState, true);129 return function(WTFMove(request), formState, true); 130 130 #endif 131 131 … … 158 158 return function({ }, nullptr, false); 159 159 } 160 return function( request, formState.get(), true);160 return function(WTFMove(request), formState.get(), true); 161 161 } 162 162 ASSERT_NOT_REACHED(); -
trunk/Source/WebCore/loader/PolicyChecker.h
r222472 r224758 52 52 53 53 using NewWindowPolicyDecisionFunction = WTF::CompletionHandler<void(const ResourceRequest&, FormState*, const String& frameName, const NavigationAction&, bool shouldContinue)>; 54 using NavigationPolicyDecisionFunction = WTF::CompletionHandler<void( const ResourceRequest&, FormState*, bool shouldContinue)>;54 using NavigationPolicyDecisionFunction = WTF::CompletionHandler<void(ResourceRequest&&, FormState*, bool shouldContinue)>; 55 55 56 56 class PolicyChecker { … … 60 60 explicit PolicyChecker(Frame&); 61 61 62 void checkNavigationPolicy( const ResourceRequest&, bool didReceiveRedirectResponse, DocumentLoader*, FormState*, NavigationPolicyDecisionFunction&&);63 void checkNavigationPolicy( const ResourceRequest&, bool didReceiveRedirectResponse, NavigationPolicyDecisionFunction&&);62 void checkNavigationPolicy(ResourceRequest&&, bool didReceiveRedirectResponse, DocumentLoader*, FormState*, NavigationPolicyDecisionFunction&&); 63 void checkNavigationPolicy(ResourceRequest&&, bool didReceiveRedirectResponse, NavigationPolicyDecisionFunction&&); 64 64 void checkNewWindowPolicy(NavigationAction&&, const ResourceRequest&, FormState*, const String& frameName, NewWindowPolicyDecisionFunction&&); 65 65
Note:
See TracChangeset
for help on using the changeset viewer.