Changeset 145973 in webkit
- Timestamp:
- Mar 15, 2013 6:20:44 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r145972 r145973 1 2013-03-15 Nate Chapin <japhet@chromium.org> 2 3 Merge MainResourceLoader::willSendRequest into DocumentLoader 4 https://bugs.webkit.org/show_bug.cgi?id=109757 5 6 This is one of the steps to merging MainResourceLoader entirely into 7 DocumentLoader, given the lack of clear division of responsibility 8 between the two. 9 10 Reviewed by Antti Koivisto. 11 12 No new tests, refactor only. 13 14 * loader/DocumentLoader.cpp: 15 (WebCore::DocumentLoader::mainResourceData): 16 (WebCore::DocumentLoader::isPostOrRedirectAfterPost): 17 (WebCore::DocumentLoader::willSendRequest): 18 (WebCore::DocumentLoader::callContinueAfterNavigationPolicy): 19 (WebCore::DocumentLoader::continueAfterNavigationPolicy): 20 (WebCore::DocumentLoader::startLoadingMainResource): 21 * loader/DocumentLoader.h: 22 * loader/MainResourceLoader.cpp: 23 (WebCore::MainResourceLoader::resourceData): 24 (WebCore::MainResourceLoader::redirectReceived): 25 (WebCore::MainResourceLoader::continueAfterContentPolicy): 26 (WebCore::MainResourceLoader::reportMemoryUsage): 27 (WebCore::MainResourceLoader::handleSubstituteDataLoadNow): 28 (WebCore::MainResourceLoader::load): 29 * loader/MainResourceLoader.h: 30 (WebCore::MainResourceLoader::takeIdentifierFromResourceLoader): Temporarily 31 exposed for moving from a normal load to SubstituteData load on redirect. 32 1 33 2013-03-15 Zhenyao Mo <zmo@google.com> 2 34 -
trunk/Source/WebCore/loader/DocumentLoader.cpp
r145914 r145973 40 40 #include "DocumentWriter.h" 41 41 #include "Event.h" 42 #include "FormState.h" 42 43 #include "Frame.h" 43 44 #include "FrameLoader.h" 44 45 #include "FrameLoaderClient.h" 45 46 #include "FrameTree.h" 47 #include "HTMLFormElement.h" 46 48 #include "HistoryItem.h" 47 49 #include "InspectorInstrumentation.h" … … 140 142 if (m_mainResourceData) 141 143 return m_mainResourceData; 144 if (m_substituteData.isValid()) 145 return ResourceBuffer::create(m_substituteData.content()->data(), m_substituteData.content()->size()); 142 146 if (m_mainResourceLoader) 143 147 return m_mainResourceLoader->resourceData(); … … 367 371 } 368 372 m_applicationCacheHost->finishedLoadingMainResource(); 373 } 374 375 bool DocumentLoader::isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse) 376 { 377 if (newRequest.httpMethod() == "POST") 378 return true; 379 380 int status = redirectResponse.httpStatusCode(); 381 if (((status >= 301 && status <= 303) || status == 307) 382 && m_originalRequest.httpMethod() == "POST") 383 return true; 384 385 return false; 386 } 387 388 void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) 389 { 390 // Note that there are no asserts here as there are for the other callbacks. This is due to the 391 // fact that this "callback" is sent when starting every load, and the state of callback 392 // deferrals plays less of a part in this function in preventing the bad behavior deferring 393 // callbacks is meant to prevent. 394 ASSERT(!newRequest.isNull()); 395 396 if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url())) { 397 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 398 return; 399 } 400 401 ASSERT(timing()->fetchStart()); 402 if (!redirectResponse.isNull()) { 403 // If the redirecting url is not allowed to display content from the target origin, 404 // then block the redirect. 405 RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url()); 406 if (!redirectingOrigin->canDisplay(newRequest.url())) { 407 FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string()); 408 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 409 return; 410 } 411 timing()->addRedirect(redirectResponse.url(), newRequest.url()); 412 } 413 414 // Update cookie policy base URL as URL changes, except for subframes, which use the 415 // URL of the main frame which doesn't change when we redirect. 416 if (frameLoader()->isLoadingMainFrame()) 417 newRequest.setFirstPartyForCookies(newRequest.url()); 418 419 // If we're fielding a redirect in response to a POST, force a load from origin, since 420 // this is a common site technique to return to a page viewing some data that the POST 421 // just modified. 422 // Also, POST requests always load from origin, but this does not affect subresources. 423 if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse)) 424 newRequest.setCachePolicy(ReloadIgnoringCacheData); 425 426 Frame* top = m_frame->tree()->top(); 427 if (top != m_frame) { 428 if (!frameLoader()->mixedContentChecker()->canDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url())) { 429 cancelMainResourceLoad(frameLoader()->cancelledError(newRequest)); 430 return; 431 } 432 } 433 434 setRequest(newRequest); 435 436 if (!redirectResponse.isNull()) { 437 // We checked application cache for initial URL, now we need to check it for redirected one. 438 ASSERT(!m_substituteData.isValid()); 439 m_applicationCacheHost->maybeLoadMainResourceForRedirect(newRequest, m_substituteData); 440 if (m_substituteData.isValid()) 441 m_mainResourceLoader->takeIdentifierFromResourceLoader(); 442 } 443 444 // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate 445 // listener. But there's no way to do that in practice. So instead we cancel later if the 446 // listener tells us to. In practice that means the navigation policy needs to be decided 447 // synchronously for these redirect cases. 448 if (!redirectResponse.isNull()) 449 frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this); 450 } 451 452 void DocumentLoader::callContinueAfterNavigationPolicy(void* argument, const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) 453 { 454 static_cast<DocumentLoader*>(argument)->continueAfterNavigationPolicy(request, shouldContinue); 455 } 456 457 void DocumentLoader::continueAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue) 458 { 459 if (!shouldContinue) 460 m_mainResourceLoader->stopLoadingForPolicyChange(); 461 else if (m_substituteData.isValid()) { 462 // A redirect resulted in loading substitute data. 463 ASSERT(timing()->redirectCount()); 464 465 // We need to remove our reference to the CachedResource in favor of a SubstituteData load. 466 // This will probably trigger the cancellation of the CachedResource's underlying ResourceLoader, though there is a 467 // small chance that the resource is being loaded by a different Frame, preventing the ResourceLoader from being cancelled. 468 // If the ResourceLoader is indeed cancelled, it would normally send resource load callbacks. 469 // However, from an API perspective, this isn't a cancellation. Therefore, sever our relationship with the network load, 470 // but prevent the ResourceLoader from sending ResourceLoadNotifier callbacks. 471 RefPtr<ResourceLoader> resourceLoader = m_mainResourceLoader->loader(); 472 ASSERT(resourceLoader->shouldSendResourceLoadCallbacks()); 473 resourceLoader->setSendCallbackPolicy(DoNotSendCallbacks); 474 m_mainResourceLoader->clearResource(); 475 resourceLoader->setSendCallbackPolicy(SendCallbacks); 476 m_mainResourceLoader->handleSubstituteDataLoadSoon(request); 477 } 369 478 } 370 479 … … 1031 1140 // because we pass a wrong loadType (see FIXME in addExtraFieldsToMainResourceRequest()). 1032 1141 frameLoader()->addExtraFieldsToMainResourceRequest(m_request); 1033 m_mainResourceLoader->load(m_request, m_substituteData); 1142 1143 ASSERT(timing()->navigationStart()); 1144 ASSERT(!timing()->fetchStart()); 1145 timing()->markFetchStart(); 1146 willSendRequest(m_request, ResourceResponse()); 1147 1148 // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest. 1149 if (!m_frame || m_request.isNull()) 1150 return; 1151 1152 m_applicationCacheHost->maybeLoadMainResource(m_request, m_substituteData); 1153 1154 m_mainResourceLoader->load(m_request); 1034 1155 1035 1156 if (m_request.isNull()) { -
trunk/Source/WebCore/loader/DocumentLoader.h
r145914 r145973 59 59 class CachedResourceLoader; 60 60 class ContentFilter; 61 class FormState; 61 62 class Frame; 62 63 class FrameLoader; … … 258 259 void checkLoadComplete(); 259 260 261 // FIXME: This should be private once DocumentLoader and MainResourceLoader are merged. 262 void willSendRequest(ResourceRequest&, const ResourceResponse&); 263 260 264 protected: 261 265 DocumentLoader(const ResourceRequest&, const SubstituteData&); … … 277 281 278 282 bool isMultipartReplacingLoad() const; 283 bool isPostOrRedirectAfterPost(const ResourceRequest&, const ResourceResponse&); 284 285 static void callContinueAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); 286 void continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); 279 287 280 288 void deliverSubstituteResourcesAfterDelay(); -
trunk/Source/WebCore/loader/MainResourceLoader.cpp
r145914 r145973 42 42 #include "DocumentLoader.h" 43 43 #include "FeatureObserver.h" 44 #include "FormState.h"45 44 #include "Frame.h" 46 45 #include "FrameLoader.h" … … 160 159 } 161 160 162 void MainResourceLoader::callContinueAfterNavigationPolicy(void* argument, const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)163 {164 static_cast<MainResourceLoader*>(argument)->continueAfterNavigationPolicy(request, shouldContinue);165 }166 167 void MainResourceLoader::continueAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)168 {169 if (!shouldContinue)170 stopLoadingForPolicyChange();171 else if (m_substituteData.isValid()) {172 // A redirect resulted in loading substitute data.173 ASSERT(documentLoader()->timing()->redirectCount());174 175 // We need to remove our reference to the CachedResource in favor of a SubstituteData load.176 // This will probably trigger the cancellation of the CachedResource's underlying ResourceLoader, though there is a177 // small chance that the resource is being loaded by a different Frame, preventing the ResourceLoader from being cancelled.178 // If the ResourceLoader is indeed cancelled, it would normally send resource load callbacks.179 // However, from an API perspective, this isn't a cancellation. Therefore, sever our relationship with the network load via clearResource(),180 // but prevent the ResourceLoader from sending ResourceLoadNotifier callbacks.181 RefPtr<ResourceLoader> resourceLoader = loader();182 ASSERT(resourceLoader->shouldSendResourceLoadCallbacks());183 resourceLoader->setSendCallbackPolicy(DoNotSendCallbacks);184 clearResource();185 resourceLoader->setSendCallbackPolicy(SendCallbacks);186 handleSubstituteDataLoadSoon(request);187 }188 189 deref(); // balances ref in willSendRequest190 }191 192 bool MainResourceLoader::isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)193 {194 if (newRequest.httpMethod() == "POST")195 return true;196 197 int status = redirectResponse.httpStatusCode();198 if (((status >= 301 && status <= 303) || status == 307)199 && frameLoader()->initialRequest().httpMethod() == "POST")200 return true;201 202 return false;203 }204 205 161 PassRefPtr<ResourceBuffer> MainResourceLoader::resourceData() 206 162 { 207 ASSERT(!m_resource || !m_substituteData.isValid());208 163 if (m_resource) 209 164 return m_resource->resourceBuffer(); 210 if (m_substituteData.isValid())211 return ResourceBuffer::create(m_substituteData.content()->data(), m_substituteData.content()->size());212 165 return 0; 213 166 } … … 216 169 { 217 170 ASSERT_UNUSED(resource, resource == m_resource); 218 willSendRequest(request, redirectResponse); 219 } 220 221 void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) 222 { 223 // Note that there are no asserts here as there are for the other callbacks. This is due to the 224 // fact that this "callback" is sent when starting every load, and the state of callback 225 // deferrals plays less of a part in this function in preventing the bad behavior deferring 226 // callbacks is meant to prevent. 227 ASSERT(!newRequest.isNull()); 228 229 // The additional processing can do anything including possibly removing the last 230 // reference to this object; one example of this is 3266216. 231 RefPtr<MainResourceLoader> protect(this); 232 233 if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url())) { 234 cancel(); 235 return; 236 } 237 238 ASSERT(documentLoader()->timing()->fetchStart()); 239 if (!redirectResponse.isNull()) { 240 // If the redirecting url is not allowed to display content from the target origin, 241 // then block the redirect. 242 RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url()); 243 if (!redirectingOrigin->canDisplay(newRequest.url())) { 244 FrameLoader::reportLocalLoadFailed(m_documentLoader->frame(), newRequest.url().elidedString()); 245 cancel(); 246 return; 247 } 248 documentLoader()->timing()->addRedirect(redirectResponse.url(), newRequest.url()); 249 } 250 251 // Update cookie policy base URL as URL changes, except for subframes, which use the 252 // URL of the main frame which doesn't change when we redirect. 253 if (frameLoader()->isLoadingMainFrame()) 254 newRequest.setFirstPartyForCookies(newRequest.url()); 255 256 // If we're fielding a redirect in response to a POST, force a load from origin, since 257 // this is a common site technique to return to a page viewing some data that the POST 258 // just modified. 259 // Also, POST requests always load from origin, but this does not affect subresources. 260 if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse)) 261 newRequest.setCachePolicy(ReloadIgnoringCacheData); 262 263 Frame* top = m_documentLoader->frame()->tree()->top(); 264 if (top != m_documentLoader->frame()) { 265 if (!frameLoader()->mixedContentChecker()->canDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url())) { 266 cancel(); 267 return; 268 } 269 } 270 271 // Don't set this on the first request. It is set when the main load was started. 272 m_documentLoader->setRequest(newRequest); 273 274 if (!redirectResponse.isNull()) { 275 // We checked application cache for initial URL, now we need to check it for redirected one. 276 ASSERT(!m_substituteData.isValid()); 277 documentLoader()->applicationCacheHost()->maybeLoadMainResourceForRedirect(newRequest, m_substituteData); 278 if (m_substituteData.isValid()) 279 m_identifierForLoadWithoutResourceLoader = identifier(); 280 } 281 282 // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate 283 // listener. But there's no way to do that in practice. So instead we cancel later if the 284 // listener tells us to. In practice that means the navigation policy needs to be decided 285 // synchronously for these redirect cases. 286 if (!redirectResponse.isNull()) { 287 ref(); // balanced by deref in continueAfterNavigationPolicy 288 frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this); 289 } 171 m_documentLoader->willSendRequest(request, redirectResponse); 290 172 } 291 173 … … 303 185 #endif 304 186 || equalIgnoringCase("multipart/related", mimeType)) 305 && !m_ substituteData.isValid() && !SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol());187 && !m_documentLoader->substituteData().isValid() && !SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()); 306 188 if (!frameLoader()->client()->canShowMIMEType(mimeType) || isRemoteWebArchive) { 307 189 frameLoader()->policyChecker()->cannotShowMIMEType(r); … … 358 240 } 359 241 360 if (!m_documentLoader->isStopping() && m_ substituteData.isValid()) {361 if (m_ substituteData.content()->size())362 dataReceived(0, m_ substituteData.content()->data(), m_substituteData.content()->size());242 if (!m_documentLoader->isStopping() && m_documentLoader->substituteData().isValid()) { 243 if (m_documentLoader->substituteData().content()->size()) 244 dataReceived(0, m_documentLoader->substituteData().content()->data(), m_documentLoader->substituteData().content()->size()); 363 245 if (m_documentLoader->isLoadingMainResource()) 364 246 didFinishLoading(0); … … 512 394 info.addMember(m_resource, "resource"); 513 395 info.addMember(m_initialRequest, "initialRequest"); 514 info.addMember(m_substituteData, "substituteData");515 396 info.addMember(m_dataLoadTimer, "dataLoadTimer"); 516 397 info.addMember(m_documentLoader, "documentLoader"); … … 521 402 RefPtr<MainResourceLoader> protect(this); 522 403 523 KURL url = m_ substituteData.responseURL();404 KURL url = m_documentLoader->substituteData().responseURL(); 524 405 if (url.isEmpty()) 525 406 url = m_initialRequest.url(); … … 529 410 m_initialRequest = ResourceRequest(); 530 411 531 ResourceResponse response(url, m_ substituteData.mimeType(), m_substituteData.content()->size(), m_substituteData.textEncoding(), "");412 ResourceResponse response(url, m_documentLoader->substituteData().mimeType(), m_documentLoader->substituteData().content()->size(), m_documentLoader->substituteData().textEncoding(), ""); 532 413 responseReceived(0, response); 533 414 } … … 553 434 } 554 435 555 void MainResourceLoader::load(const ResourceRequest& initialRequest, const SubstituteData& substituteData) 556 { 557 // It appears that it is possible for this load to be cancelled and derefenced by the DocumentLoader 558 // in willSendRequest() if loadNow() is called. 559 RefPtr<MainResourceLoader> protect(this); 560 561 m_substituteData = substituteData; 562 563 ASSERT(documentLoader()->timing()->navigationStart()); 564 ASSERT(!documentLoader()->timing()->fetchStart()); 565 documentLoader()->timing()->markFetchStart(); 436 void MainResourceLoader::load(const ResourceRequest& initialRequest) 437 { 438 RefPtr<MainResourceLoader> protect(this); 566 439 ResourceRequest request(initialRequest); 567 440 568 // Send this synthetic delegate callback since clients expect it, and 569 // we no longer send the callback from within NSURLConnection for 570 // initial requests. 571 willSendRequest(request, ResourceResponse()); 572 ASSERT(!deletionHasBegun()); 573 574 // willSendRequest() may lead to our DocumentLoader being detached or cancelling the load via nulling the ResourceRequest. 575 if (!documentLoader()->frame() || request.isNull()) 576 return; 577 578 documentLoader()->applicationCacheHost()->maybeLoadMainResource(request, m_substituteData); 579 580 if (m_substituteData.isValid()) { 441 if (m_documentLoader->substituteData().isValid()) { 581 442 m_identifierForLoadWithoutResourceLoader = m_documentLoader->frame()->page()->progress()->createUniqueIdentifier(); 582 443 frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, documentLoader(), request); -
trunk/Source/WebCore/loader/MainResourceLoader.h
r145734 r145973 45 45 namespace WebCore { 46 46 47 class FormState;48 47 class ResourceRequest; 49 48 … … 54 53 virtual ~MainResourceLoader(); 55 54 56 void load(const ResourceRequest& , const SubstituteData&);55 void load(const ResourceRequest&); 57 56 void cancel(); 58 57 void cancel(const ResourceError&); … … 78 77 void reportMemoryUsage(MemoryObjectInfo*) const; 79 78 79 void takeIdentifierFromResourceLoader() { m_identifierForLoadWithoutResourceLoader = identifier(); } 80 void stopLoadingForPolicyChange(); 81 void handleSubstituteDataLoadSoon(const ResourceRequest&); 82 void clearResource(); 83 80 84 private: 81 85 explicit MainResourceLoader(DocumentLoader*); … … 86 90 virtual void notifyFinished(CachedResource*) OVERRIDE; 87 91 88 void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse);89 92 void didFinishLoading(double finishTime); 90 void handleSubstituteDataLoadSoon(const ResourceRequest&);91 93 void handleSubstituteDataLoadNow(MainResourceLoaderTimer*); 92 94 … … 95 97 void receivedError(const ResourceError&); 96 98 ResourceError interruptedForPolicyChangeError() const; 97 void stopLoadingForPolicyChange();98 bool isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse);99 100 static void callContinueAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);101 void continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);102 99 103 100 static void callContinueAfterContentPolicy(void*, PolicyAction); … … 113 110 114 111 const ResourceRequest& request() const; 115 void clearResource();116 112 117 113 bool defersLoading() const; … … 120 116 121 117 ResourceRequest m_initialRequest; 122 SubstituteData m_substituteData;123 118 ResourceResponse m_response; 124 119
Note: See TracChangeset
for help on using the changeset viewer.