Changeset 195605 in webkit
- Timestamp:
- Jan 26, 2016 11:57:49 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r195603 r195605 1 2016-01-26 Chris Dumez <cdumez@apple.com> 2 3 Make sure a page is still PageCache-able after firing the 'pagehide' events 4 https://bugs.webkit.org/show_bug.cgi?id=153449 5 6 Reviewed by Andreas Kling. 7 8 Make sure a page is still PageCache-able after firing the 'pagehide' 9 events and abort if it isn't. This should improve robustness and it is 10 easy for pagehide event handlers to do things that would make a Page no 11 longer PageCache-able and this leads to bugs that are difficult to 12 investigate. 13 14 To achieve this, the 'pagehide' event firing logic was moved out of the 15 CachedFrame constructor. It now happens earlier in 16 PageCache::addIfCacheable() after checking if the page is cacheable and 17 before constructing the CachedPage / CachedFrames. After firing the 18 'pagehide' event in PageCache::addIfCacheable(), we check again that 19 the page is still cacheable and we abort early if it is not. 20 21 * history/CachedFrame.cpp: 22 (WebCore::CachedFrame::CachedFrame): 23 * history/PageCache.cpp: 24 (WebCore::setInPageCache): 25 (WebCore::firePageHideEventRecursively): 26 (WebCore::PageCache::addIfCacheable): 27 * history/PageCache.h: 28 * loader/FrameLoader.cpp: 29 (WebCore::FrameLoader::commitProvisionalLoad): 30 1 31 2016-01-26 Beth Dakin <bdakin@apple.com> 2 32 -
trunk/Source/WebCore/history/CachedFrame.cpp
r195496 r195605 40 40 #include "HistoryController.h" 41 41 #include "HistoryItem.h" 42 #include "IgnoreOpensDuringUnloadCountIncrementer.h"43 42 #include "Logging.h" 44 43 #include "MainFrame.h" … … 156 155 m_view->detachCustomScrollbars(); 157 156 158 m_document->setInPageCache(true); 159 frame.loader().stopLoading(UnloadEventPolicyUnloadAndPageHide); 160 161 { 162 // The following will fire the pagehide event in each subframe and the HTML specification states 163 // that the parent document's ignore-opens-during-unload counter should be incremented while the 164 // pagehide event is being fired in its subframes: 165 // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document 166 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_document.get()); 167 168 // Create the CachedFrames for all Frames in the FrameTree. 169 for (Frame* child = frame.tree().firstChild(); child; child = child->tree().nextSibling()) 170 m_childFrames.append(std::make_unique<CachedFrame>(*child)); 171 } 172 173 // Active DOM objects must be suspended before we cache the frame script data, 174 // but after we've fired the pagehide event, in case that creates more objects. 175 // Suspending must also happen after we've recursed over child frames, in case 176 // those create more objects. 177 157 ASSERT(m_document->inPageCache()); 158 159 // Create the CachedFrames for all Frames in the FrameTree. 160 for (Frame* child = frame.tree().firstChild(); child; child = child->tree().nextSibling()) 161 m_childFrames.append(std::make_unique<CachedFrame>(*child)); 162 163 // Active DOM objects must be suspended before we cache the frame script data. 178 164 m_document->suspend(); 179 165 -
trunk/Source/WebCore/history/PageCache.cpp
r195601 r195605 42 42 #include "FrameView.h" 43 43 #include "HistoryController.h" 44 #include "IgnoreOpensDuringUnloadCountIncrementer.h" 44 45 #include "Logging.h" 45 46 #include "MainFrame.h" … … 273 274 } 274 275 275 bool PageCache::canCache(Page* page) const 276 { 277 if (!page) 276 bool PageCache::canCache(Page& page) const 277 { 278 if (!m_maxSize) { 279 logPageCacheFailureDiagnosticMessage(&page, DiagnosticLoggingKeys::isDisabledKey()); 278 280 return false; 279 280 if (!m_maxSize) { 281 logPageCacheFailureDiagnosticMessage(page, DiagnosticLoggingKeys::isDisabledKey()); 281 } 282 283 if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) { 284 logPageCacheFailureDiagnosticMessage(&page, DiagnosticLoggingKeys::underMemoryPressureKey()); 282 285 return false; 283 286 } 284 285 if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) { 286 logPageCacheFailureDiagnosticMessage(page, DiagnosticLoggingKeys::underMemoryPressureKey()); 287 return false; 288 } 289 290 return canCachePage(*page); 287 288 return canCachePage(page); 291 289 } 292 290 … … 375 373 } 376 374 377 void PageCache::add(HistoryItem& item, Page& page) 378 { 379 ASSERT(canCache(&page)); 380 381 // Remove stale cache entry if necessary. 382 remove(item); 383 384 item.m_cachedPage = std::make_unique<CachedPage>(page); 375 static void setInPageCache(Page& page, bool isInPageCache) 376 { 377 for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) { 378 if (auto* document = frame->document()) 379 document->setInPageCache(isInPageCache); 380 } 381 } 382 383 static void firePageHideEventRecursively(Frame& frame) 384 { 385 auto* document = frame.document(); 386 if (!document) 387 return; 388 389 // stopLoading() will fire the pagehide event in each subframe and the HTML specification states 390 // that the parent document's ignore-opens-during-unload counter should be incremented while the 391 // pagehide event is being fired in its subframes: 392 // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document 393 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(document); 394 395 frame.loader().stopLoading(UnloadEventPolicyUnloadAndPageHide); 396 397 for (RefPtr<Frame> child = frame.tree().firstChild(); child; child = child->tree().nextSibling()) 398 firePageHideEventRecursively(*child); 399 } 400 401 void PageCache::addIfCacheable(HistoryItem& item, Page* page) 402 { 403 if (item.isInPageCache()) 404 return; 405 406 if (!page || !canCache(*page)) 407 return; 408 409 // Make sure all the documents know they are being added to the PageCache. 410 setInPageCache(*page, true); 411 412 // Fire the pagehide event in all frames. 413 firePageHideEventRecursively(page->mainFrame()); 414 415 // Check that the page is still page-cacheable after firing the pagehide event. The JS event handlers 416 // could have altered the page in a way that could prevent caching. 417 if (!canCache(*page)) { 418 setInPageCache(*page, false); 419 return; 420 } 421 422 // Make sure we no longer fire any JS events past this point. 423 NoEventDispatchAssertion assertNoEventDispatch; 424 425 item.m_cachedPage = std::make_unique<CachedPage>(*page); 385 426 item.m_pruningReason = PruningReason::None; 386 427 m_items.add(&item); -
trunk/Source/WebCore/history/PageCache.h
r184304 r195605 47 47 WEBCORE_EXPORT static PageCache& singleton(); 48 48 49 bool canCache(Page *) const;49 bool canCache(Page&) const; 50 50 51 51 // Used when memory is low to prune some cached pages. … … 54 54 unsigned maxSize() const { return m_maxSize; } 55 55 56 void add (HistoryItem&, Page&); // Prunes if maxSize() is exceeded.56 void addIfCacheable(HistoryItem&, Page*); // Prunes if maxSize() is exceeded. 57 57 WEBCORE_EXPORT void remove(HistoryItem&); 58 58 CachedPage* get(HistoryItem&, Page*); -
trunk/Source/WebCore/loader/FrameLoader.cpp
r195496 r195605 1773 1773 // Check to see if we need to cache the page we are navigating away from into the back/forward cache. 1774 1774 // We are doing this here because we know for sure that a new page is about to be loaded. 1775 HistoryItem& item = *history().currentItem(); 1776 if (!m_frame.tree().parent() && PageCache::singleton().canCache(m_frame.page()) && !item.isInPageCache()) 1777 PageCache::singleton().add(item, *m_frame.page()); 1775 if (!m_frame.tree().parent() && history().currentItem()) 1776 PageCache::singleton().addIfCacheable(*history().currentItem(), m_frame.page()); 1778 1777 1779 1778 if (m_loadType != FrameLoadType::Replace) -
trunk/Source/WebCore/page/Page.cpp
r195449 r195605 1864 1864 bool Page::canTabSuspend() 1865 1865 { 1866 return s_tabSuspensionIsEnabled && !m_isPrerender && (m_pageThrottler.activityState() == PageActivityState::NoFlags) && PageCache::singleton().canCache( this);1866 return s_tabSuspensionIsEnabled && !m_isPrerender && (m_pageThrottler.activityState() == PageActivityState::NoFlags) && PageCache::singleton().canCache(*this); 1867 1867 } 1868 1868
Note: See TracChangeset
for help on using the changeset viewer.