Changeset 266148 in webkit
- Timestamp:
- Aug 25, 2020, 3:08:51 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 5 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/loader/font-load-timer-expected.html (added)
-
LayoutTests/fast/loader/font-load-timer.html (added)
-
LayoutTests/fast/loader/resources/font-load-timer-navigation-destination.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/css/CSSFontSelector.cpp (modified) (5 diffs)
-
Source/WebCore/css/CSSFontSelector.h (modified) (6 diffs)
-
Source/WebCore/loader/DocumentLoader.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r266139 r266148 1 2020-08-25 Brady Eidson <beidson@apple.com> 2 3 Font loads quickly followed by navigations may fail indefinitely 4 <rdar://problem/65560550> and https://bugs.webkit.org/show_bug.cgi?id=215435 5 6 Reviewed by Myles C. Maxfield. 7 8 1) The page has some content that has “font-family: WebFont” but there are no @font-face blocks on the page 9 2) In script, after the page has loaded, add an @font-face rule to the page with “font-family: WebFont” and some valid font URL 10 3) Synchronously, within the same turn of the run loop, trigger a synchronous layout of the element (using offsetWidth or something). This will add the font to the 0-delay time work list. 11 4) Synchronously, within the same turn of the run loop, navigate to a second page that doesn’t use the web font. 12 5) The second page waits some small-but-positive amount of time. This will cause the 0-delay timer to fire, but because the page is in the middle of navigating, the font load should fail. 13 6) The second page adds the same @font-face rule to itself using script. This should pull the same (failed) CachedResource object out of the memory cache. 14 7) Use the CSS Font Loading API to wait for the font load to complete 15 8) Make sure that the font is used on the second page (as a reference test). Today, the second page’s font load will fail because it pulled the failed font out of the memory cache. The test makes sure the second page’s font load succeeds. 16 17 * fast/loader/font-load-timer-expected.html: Added. 18 * fast/loader/font-load-timer.html: Added. 19 * fast/loader/resources/font-load-timer-navigation-destination.html: Added. 20 1 21 2020-08-25 Hector Lopez <hector_i_lopez@apple.com> 2 22 -
trunk/Source/WebCore/ChangeLog
r266144 r266148 1 2020-08-25 Brady Eidson <beidson@apple.com> 2 3 Font loads quickly followed by navigations may fail indefinitely 4 <rdar://problem/65560550> and https://bugs.webkit.org/show_bug.cgi?id=215435 5 6 Reviewed by Myles C. Maxfield. 7 8 Second take at this. 9 10 Myles took the first swipe at this, but a conflict with SuspendableTimer caused issues 11 in the form of layout test asserts with 12 http/tests/security/navigate-when-restoring-cached-page.html 13 14 His original ChangeLog entry: 15 16 Font loads are coalesced using a zero-delay timer. However, that zero-delay timer 17 can fire while the page is in the middle of a navigation, which will cause the font 18 loads to fail. Then, the second page can request those same fonts, which are marked 19 as failed, and as such will never actually load/use the desired web font. 20 21 This patch just stops the zero-delay timer during navigations, and resumes it 22 when resuming the document. This means: 23 24 1. The second page in the above story will not see that the font has failed, or 25 even started, and will then re-request the font and load it successfully 26 2. If the user goes "back" to the previous page, the zero-delay timer is restarted, 27 the CachedFont realizes it's already succeeded, and the previous page is rendered 28 as expected. 29 30 Test: fast/loader/font-load-timer.html 31 32 --- 33 34 Now the explanation of the failure it caused: 35 The font loading timer was a SuspendableTimer, which is an ActiveDOMObject. 36 37 An ActiveDOMObject was used to make sure the delayed font loads play well with the 38 page cache, which is still necessary. 39 40 But we also still need to suspend the timer manually when "stopLoading()" is called, 41 which doesn't play well with ActiveDOMObject's automatic suspend/resume. 42 43 My solution: 44 - Make the timer "just a normal timer" 45 - Make CSSFontSelector itself the ActiveDOMObject 46 - Let DocumentLoader explicitly pause the font load timer 47 - Rely on ActiveDOMObject to resume the timer 48 49 These keep the bug fixed and resolve the layout test ASSERT seen with 50 http/tests/security/navigate-when-restoring-cached-page.html 51 52 * css/CSSFontSelector.cpp: 53 (WebCore::CSSFontSelector::CSSFontSelector): 54 (WebCore::CSSFontSelector::clearDocument): 55 (WebCore::CSSFontSelector::beginLoadingFontSoon): 56 (WebCore::CSSFontSelector::suspendFontLoadingTimer): 57 (WebCore::CSSFontSelector::fontLoadingTimerFired): 58 (WebCore::CSSFontSelector::stop): 59 (WebCore::CSSFontSelector::suspend): 60 (WebCore::CSSFontSelector::resume): 61 (WebCore::CSSFontSelector::beginLoadTimerFired): Deleted. 62 * css/CSSFontSelector.h: 63 * loader/DocumentLoader.cpp: 64 (WebCore::DocumentLoader::stopLoading): 65 1 66 2020-08-25 Peng Liu <peng.liu6@apple.com> 2 67 -
trunk/Source/WebCore/css/CSSFontSelector.cpp
r265782 r266148 63 63 64 64 CSSFontSelector::CSSFontSelector(Document& document) 65 : m_document(makeWeakPtr(document)) 65 : ActiveDOMObject(document) 66 , m_document(makeWeakPtr(document)) 66 67 , m_cssFontFaceSet(CSSFontFaceSet::create(this)) 67 , m_ beginLoadingTimer(&document, *this, &CSSFontSelector::beginLoadTimerFired)68 , m_fontLoadingTimer(*this, &CSSFontSelector::fontLoadingTimerFired) 68 69 , m_uniqueId(++fontSelectorId) 69 70 , m_version(0) … … 74 75 LOG(Fonts, "CSSFontSelector %p ctor", this); 75 76 76 m_beginLoadingTimer.suspendIfNeeded();77 suspendIfNeeded(); 77 78 } 78 79 … … 334 335 { 335 336 if (!m_document) { 336 ASSERT(!m_ beginLoadingTimer.isActive());337 ASSERT(!m_fontLoadingTimer.isActive()); 337 338 ASSERT(m_fontsToBeginLoading.isEmpty()); 338 339 return; 339 340 } 340 341 341 m_ beginLoadingTimer.cancel();342 m_fontLoadingTimer.stop(); 342 343 343 344 CachedResourceLoader& cachedResourceLoader = m_document->cachedResourceLoader(); … … 362 363 // Increment the request count now, in order to prevent didFinishLoad from being dispatched 363 364 // after this font has been requested but before it began loading. Balanced by 364 // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().365 // decrementRequestCount() in fontLoadingTimerFired() and in clearDocument(). 365 366 m_document->cachedResourceLoader().incrementRequestCount(font); 366 367 367 m_beginLoadingTimer.startOneShot(0_s); 368 } 369 370 void CSSFontSelector::beginLoadTimerFired() 368 if (!m_fontLoadingTimerIsSuspended) 369 m_fontLoadingTimer.startOneShot(0_s); 370 } 371 372 void CSSFontSelector::suspendFontLoadingTimer() 373 { 374 suspend(ReasonForSuspension::PageWillBeSuspended); 375 } 376 377 void CSSFontSelector::fontLoadingTimerFired() 371 378 { 372 379 Vector<CachedResourceHandle<CachedFont>> fontsToBeginLoading; … … 418 425 } 419 426 420 } 427 void CSSFontSelector::stop() 428 { 429 m_fontLoadingTimer.stop(); 430 } 431 432 void CSSFontSelector::suspend(ReasonForSuspension) 433 { 434 if (m_fontLoadingTimerIsSuspended) { 435 ASSERT(!m_fontLoadingTimer.isActive()); 436 return; 437 } 438 439 m_fontLoadingTimerIsSuspended = m_fontLoadingTimer.isActive(); 440 m_fontLoadingTimer.stop(); 441 } 442 443 void CSSFontSelector::resume() 444 { 445 if (!m_fontLoadingTimerIsSuspended) 446 return; 447 448 if (!m_fontsToBeginLoading.isEmpty()) 449 m_fontLoadingTimer.startOneShot(0_s); 450 451 m_fontLoadingTimerIsSuspended = false; 452 } 453 454 } -
trunk/Source/WebCore/css/CSSFontSelector.h
r265782 r266148 26 26 #pragma once 27 27 28 #include "ActiveDOMObject.h" 28 29 #include "CSSFontFace.h" 29 30 #include "CSSFontFaceSet.h" … … 31 32 #include "Font.h" 32 33 #include "FontSelector.h" 33 #include " SuspendableTimer.h"34 #include "Timer.h" 34 35 #include <memory> 35 36 #include <wtf/Forward.h> … … 48 49 class StyleRuleFontFace; 49 50 50 class CSSFontSelector final : public FontSelector, public CSSFontFaceSetClient, public CanMakeWeakPtr<CSSFontSelector> {51 class CSSFontSelector final : public FontSelector, public CSSFontFaceSetClient, public CanMakeWeakPtr<CSSFontSelector>, public ActiveDOMObject { 51 52 public: 52 53 static Ref<CSSFontSelector> create(Document& document) … … 81 82 82 83 void beginLoadingFontSoon(CachedFont&); 84 void suspendFontLoadingTimer(); 83 85 84 86 FontFaceSet* fontFaceSetIfExists(); … … 97 99 void fontModified() final; 98 100 99 void beginLoadTimerFired(); 101 void fontLoadingTimerFired(); 102 103 // ActiveDOMObject 104 void stop() final; 105 void suspend(ReasonForSuspension) final; 106 void resume() final; 107 const char* activeDOMObjectName() const final { return "CSSFontSelector"_s; } 100 108 101 109 struct PendingFontFaceRule { … … 113 121 HashSet<RefPtr<CSSFontFace>> m_cssConnectionsPossiblyToRemove; 114 122 HashSet<RefPtr<StyleRuleFontFace>> m_cssConnectionsEncounteredDuringBuild; 115 SuspendableTimer m_beginLoadingTimer; 123 124 Timer m_fontLoadingTimer; 125 bool m_fontLoadingTimerIsSuspended { false }; 116 126 117 127 unsigned m_uniqueId; -
trunk/Source/WebCore/loader/DocumentLoader.cpp
r265782 r266148 34 34 #include "Archive.h" 35 35 #include "ArchiveResourceCollection.h" 36 #include "CSSFontSelector.h" 36 37 #include "CachedPage.h" 37 38 #include "CachedRawResource.h" … … 314 315 cancelAll(m_multipartSubresourceLoaders); 315 316 317 if (auto* document = m_frame->document()) 318 document->fontSelector().suspendFontLoadingTimer(); 319 316 320 // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads. 317 321 m_applicationCacheHost->stopLoadingInFrame(*m_frame);
Note:
See TracChangeset
for help on using the changeset viewer.