Changeset 181480 in webkit
- Timestamp:
- Mar 13, 2015, 10:58:50 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 12 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/tests/navigation/page-cache-xhr-expected.txt (added)
-
LayoutTests/http/tests/navigation/page-cache-xhr.html (added)
-
LayoutTests/http/tests/navigation/resources/page-cache-helper.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/history/PageCache.cpp (modified) (2 diffs)
-
Source/WebCore/loader/DocumentLoader.cpp (modified) (1 diff)
-
Source/WebCore/loader/DocumentThreadableLoader.cpp (modified) (2 diffs)
-
Source/WebCore/loader/DocumentThreadableLoader.h (modified) (1 diff)
-
Source/WebCore/loader/ThreadableLoader.h (modified) (2 diffs)
-
Source/WebCore/loader/cache/CachedResource.cpp (modified) (1 diff)
-
Source/WebCore/loader/cache/CachedResource.h (modified) (1 diff)
-
Source/WebCore/loader/cache/CachedResourceClient.h (modified) (1 diff)
-
Source/WebCore/xml/XMLHttpRequest.cpp (modified) (6 diffs)
-
Source/WebCore/xml/XMLHttpRequest.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r181478 r181480 1 2015-03-13 Chris Dumez <cdumez@apple.com> 2 3 XMLHttpRequests should not prevent a page from entering PageCache 4 https://bugs.webkit.org/show_bug.cgi?id=142612 5 <rdar://problem/19923085> 6 7 Reviewed by Alexey Proskuryakov. 8 9 Add a tests to make sure that loading XMLHttpRequests do not prevent a 10 page from entering PageCache. 11 12 * http/tests/navigation/page-cache-xhr-expected.txt: Added. 13 * http/tests/navigation/page-cache-xhr.html: Added. 14 * http/tests/navigation/resources/page-cache-helper.html: Added. 15 1 16 2015-03-13 Marcos Chavarría Teijeiro <chavarria1991@gmail.com> 2 17 -
trunk/Source/WebCore/ChangeLog
r181475 r181480 1 2015-03-13 Chris Dumez <cdumez@apple.com> 2 3 XMLHttpRequests should not prevent a page from entering PageCache 4 https://bugs.webkit.org/show_bug.cgi?id=142612 5 <rdar://problem/19923085> 6 7 Reviewed by Alexey Proskuryakov. 8 9 Make XMLHttpRequest ActiveDOMObjects suspendable in most cases to 10 drastically improve the likelihood of pages using them to enter 11 PageCache. XMLHttpRequest used to be only suspendable when not 12 loading. After this patch, if the XMLHttpRequest is loading when 13 navigating away from the page, it will be aborted and the page 14 will enter the PageCache. Upon restoring the page from PageCache, 15 the XMLHttpRequests' error handlers will be executed to give them 16 a chance to reload if they want to. 17 18 Test: http/tests/navigation/page-cache-xhr.html 19 20 * history/PageCache.cpp: 21 (WebCore::logCanCacheFrameDecision): 22 (WebCore::PageCache::canCachePageContainingThisFrame): 23 Do not prevent a page to enter the page cache ff the main document has 24 an error that is a cancellation and all remaining subresource loaders 25 are for XHR. We extend the pre-existing mechanism used on iOS, which 26 allowed PageCaching if the remaining resource loads are for images. 27 28 * loader/DocumentLoader.cpp: 29 (WebCore::areAllLoadersPageCacheAcceptable): 30 Mark XHR loaders as PageCache acceptable. 31 32 * loader/DocumentThreadableLoader.cpp: 33 (WebCore::DocumentThreadableLoader::isXMLHttpRequest): 34 * loader/DocumentThreadableLoader.h: 35 * loader/ThreadableLoader.h: 36 * loader/cache/CachedResource.cpp: 37 (WebCore::CachedResource::areAllClientsXMLHttpRequests): 38 * loader/cache/CachedResource.h: 39 * loader/cache/CachedResourceClient.h: 40 (WebCore::CachedResourceClient::isXMLHttpRequest): 41 * xml/XMLHttpRequest.cpp: 42 (WebCore::XMLHttpRequest::XMLHttpRequest): 43 (WebCore::XMLHttpRequest::createRequest): 44 (WebCore::XMLHttpRequest::canSuspend): 45 Report that we can suspend XMLHttpRequests as long as the window load 46 event has already fired. If the window load event has not fired yet, 47 it would be unsafe to cancel the load in suspend() as it would 48 potentially cause arbitrary JS execution while suspending. 49 50 (WebCore::XMLHttpRequest::suspend): 51 If suspending for PageCache and the request is currently loading, abort 52 the load and mark that we should fire the error event upon restoring 53 from PageCache. 54 55 (WebCore::XMLHttpRequest::resume): 56 (WebCore::XMLHttpRequest::resumeTimerFired): 57 Upon resuming, fire the error event in a timer if the load was aborted 58 for suspending. We need to do this in a timer because we are not allowed 59 to execute arbitrary JS inside resume(). 60 61 (WebCore::XMLHttpRequest::stop): 62 Add a assertion to make sure we are not firing event inside stop() as 63 this would potentially cause arbitrary JS execution and it would be 64 unsafe. It seems to me that our code is currently unsafe but the 65 assertion does not seem to be hit by our current layout tests. I am 66 adding the assertion as it would make it clear we have a bug and we 67 need to fix it. 68 69 * xml/XMLHttpRequest.h: 70 1 71 2015-03-13 Joonghun Park <jh718.park@samsung.com> 2 72 -
trunk/Source/WebCore/history/PageCache.cpp
r180770 r181480 129 129 PCLOG(" -Main document has an error"); 130 130 logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::mainDocumentErrorKey()); 131 #if !PLATFORM(IOS) 132 rejectReasons |= 1 << MainDocumentError; 133 #else 131 134 132 if (frame.loader().documentLoader()->mainDocumentError().isCancellation() && frame.loader().documentLoader()->subresourceLoadersArePageCacheAcceptable()) 135 PCLOG(" -But, it was a cancellation and all loaders during the cancel were loading images.");133 PCLOG(" -But, it was a cancellation and all loaders during the cancelation were loading images or XHR."); 136 134 else 137 135 rejectReasons |= 1 << MainDocumentError; 138 #endif139 136 } 140 137 if (frame.loader().documentLoader()->substituteData().isValid() && frame.loader().documentLoader()->substituteData().failingURL().isEmpty()) { … … 305 302 306 303 return documentLoader 307 #if !PLATFORM(IOS)308 && documentLoader->mainDocumentError().isNull()309 #else310 304 && (documentLoader->mainDocumentError().isNull() || (documentLoader->mainDocumentError().isCancellation() && documentLoader->subresourceLoadersArePageCacheAcceptable())) 311 #endif312 305 // Do not cache error pages (these can be recognized as pages with substitute data or unreachable URLs). 313 306 && !(documentLoader->substituteData().isValid() && !documentLoader->substituteData().failingURL().isEmpty()) -
trunk/Source/WebCore/loader/DocumentLoader.cpp
r181409 r181480 100 100 copyValuesToVector(loaders, loadersCopy); 101 101 for (auto& loader : loadersCopy) { 102 ResourceHandle* handle = loader->handle();103 if (!handle)104 return false;105 106 102 if (!loader->frameLoader()) 107 103 return false; 108 104 109 CachedResource* cachedResource = MemoryCache::singleton().resourceForURL( handle->firstRequest().url(), loader->frameLoader()->frame().page()->sessionID());105 CachedResource* cachedResource = MemoryCache::singleton().resourceForURL(loader->request().url(), loader->frameLoader()->frame().page()->sessionID()); 110 106 if (!cachedResource) 111 107 return false; 112 108 109 // Only image and XHR loads do prevent the page from entering the PageCache. 113 110 // All non-image loads will prevent the page from entering the PageCache. 114 if (!cachedResource->isImage() )111 if (!cachedResource->isImage() && !cachedResource->areAllClientsXMLHttpRequests()) 115 112 return false; 116 113 } -
trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp
r180132 r181480 35 35 #include "CachedResourceLoader.h" 36 36 #include "CachedResourceRequest.h" 37 #include "CachedResourceRequestInitiators.h" 37 38 #include "CrossOriginAccessControl.h" 38 39 #include "CrossOriginPreflightResultCache.h" … … 419 420 } 420 421 422 bool DocumentThreadableLoader::isXMLHttpRequest() const 423 { 424 return m_options.initiator == cachedResourceRequestInitiators().xmlhttprequest; 425 } 426 421 427 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const 422 428 { -
trunk/Source/WebCore/loader/DocumentThreadableLoader.h
r176172 r181480 97 97 bool isAllowedRedirect(const URL&); 98 98 99 bool isXMLHttpRequest() const override final; 100 99 101 SecurityOrigin* securityOrigin() const; 100 102 -
trunk/Source/WebCore/loader/ThreadableLoader.h
r149876 r181480 37 37 #include <wtf/RefPtr.h> 38 38 #include <wtf/Vector.h> 39 40 #if ENABLE(RESOURCE_TIMING)41 39 #include <wtf/text/AtomicString.h> 42 #endif43 40 44 41 namespace WebCore { … … 70 67 CrossOriginRequestPolicy crossOriginRequestPolicy; 71 68 RefPtr<SecurityOrigin> securityOrigin; 72 #if ENABLE(RESOURCE_TIMING)73 69 AtomicString initiator; 74 #endif75 70 }; 76 71 -
trunk/Source/WebCore/loader/cache/CachedResource.cpp
r180517 r181480 736 736 } 737 737 738 bool CachedResource::areAllClientsXMLHttpRequests() const 739 { 740 if (type() != RawResource) 741 return false; 742 743 for (auto& client : m_clients) { 744 if (!client.key->isXMLHttpRequest()) 745 return false; 746 } 747 return true; 748 } 749 738 750 void CachedResource::setLoadPriority(const Optional<ResourceLoadPriority>& loadPriority) 739 751 { -
trunk/Source/WebCore/loader/cache/CachedResource.h
r180207 r181480 159 159 SubresourceLoader* loader() { return m_loader.get(); } 160 160 161 bool areAllClientsXMLHttpRequests() const; 162 161 163 bool isImage() const { return type() == ImageResource; } 162 164 // FIXME: CachedRawResource could be either a main resource or a raw XHR resource. -
trunk/Source/WebCore/loader/cache/CachedResourceClient.h
r175549 r181480 44 44 virtual void notifyFinished(CachedResource*) { } 45 45 virtual void deprecatedDidReceiveCachedResource(CachedResource*) { } 46 virtual bool isXMLHttpRequest() const { return false; } 46 47 47 48 static CachedResourceClientType expectedType() { return BaseResourceType; } -
trunk/Source/WebCore/xml/XMLHttpRequest.cpp
r181411 r181480 25 25 26 26 #include "Blob.h" 27 #include "CachedResourceRequestInitiators.h" 27 28 #include "ContentSecurityPolicy.h" 28 29 #include "CrossOriginAccessControl.h" … … 65 66 #include <wtf/text/CString.h> 66 67 67 #if ENABLE(RESOURCE_TIMING)68 #include "CachedResourceRequestInitiators.h"69 #endif70 71 68 namespace WebCore { 72 69 … … 140 137 , m_responseTypeCode(ResponseTypeDefault) 141 138 , m_responseCacheIsValid(false) 139 , m_resumeTimer(*this, &XMLHttpRequest::resumeTimerFired) 140 , m_dispatchErrorOnResuming(false) 142 141 { 143 142 #ifndef NDEBUG … … 765 764 options.crossOriginRequestPolicy = UseAccessControl; 766 765 options.securityOrigin = securityOrigin(); 767 #if ENABLE(RESOURCE_TIMING)768 766 options.initiator = cachedResourceRequestInitiators().xmlhttprequest; 769 #endif770 767 771 768 #if ENABLE(XHR_TIMEOUT) … … 1256 1253 bool XMLHttpRequest::canSuspend() const 1257 1254 { 1258 return !m_loader; 1255 // If the load event has not fired yet, cancelling the load in suspend() may cause 1256 // the load event to be fired and arbitrary JS execution, which would be unsafe. 1257 // Therefore, we prevent suspending in this case. 1258 return document()->loadEventFinished(); 1259 1259 } 1260 1260 … … 1264 1264 } 1265 1265 1266 void XMLHttpRequest::suspend(ReasonForSuspension) 1267 { 1266 void XMLHttpRequest::suspend(ReasonForSuspension reason) 1267 { 1268 NoEventDispatchAssertion assertNoEventDispatch; 1269 1268 1270 m_progressEventThrottle.suspend(); 1271 1272 if (m_resumeTimer.isActive()) { 1273 m_resumeTimer.stop(); 1274 m_dispatchErrorOnResuming = true; 1275 } 1276 1277 if (reason == ActiveDOMObject::DocumentWillBecomeInactive && m_loader) { 1278 // Going into PageCache, abort the request and dispatch a network error on resuming. 1279 genericError(); 1280 m_dispatchErrorOnResuming = true; 1281 bool aborted = internalAbort(); 1282 // It should not be possible to restart the load when aborting in suspend() because 1283 // we are not allowed to execute in JS in suspend(). 1284 ASSERT_UNUSED(aborted, aborted); 1285 } 1269 1286 } 1270 1287 1271 1288 void XMLHttpRequest::resume() 1272 1289 { 1290 NoEventDispatchAssertion assertNoEventDispatch; 1291 1273 1292 m_progressEventThrottle.resume(); 1293 1294 // We are not allowed to execute arbitrary JS in resume() so dispatch 1295 // the error event in a timer. 1296 if (m_dispatchErrorOnResuming && !m_resumeTimer.isActive()) 1297 m_resumeTimer.startOneShot(0); 1298 } 1299 1300 void XMLHttpRequest::resumeTimerFired() 1301 { 1302 ASSERT(m_dispatchErrorOnResuming); 1303 m_dispatchErrorOnResuming = false; 1304 dispatchErrorEvents(eventNames().errorEvent); 1274 1305 } 1275 1306 1276 1307 void XMLHttpRequest::stop() 1277 1308 { 1309 NoEventDispatchAssertion assertNoEventDispatch; 1278 1310 internalAbort(); 1279 1311 } -
trunk/Source/WebCore/xml/XMLHttpRequest.h
r181169 r181480 206 206 void dispatchErrorEvents(const AtomicString&); 207 207 208 void resumeTimerFired(); 209 208 210 std::unique_ptr<XMLHttpRequestUpload> m_upload; 209 211 … … 255 257 ResponseTypeCode m_responseTypeCode; 256 258 bool m_responseCacheIsValid; 259 260 Timer m_resumeTimer; 261 bool m_dispatchErrorOnResuming; 257 262 }; 258 263
Note:
See TracChangeset
for help on using the changeset viewer.