Changeset 194006 in webkit


Ignore:
Timestamp:
Dec 12, 2015 1:26:42 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Safari background tabs should be fully suspended where possible.
https://bugs.webkit.org/show_bug.cgi?id=150515

Patch by Katlyn Graff <kgraff@apple.com> on 2015-12-12
Reviewed by Ryosuke Niwa.

Source/WebCore:

Support for tab suspension for Mac, enabled by defaults writing to WebKitTabSuspension.
Page-down suspension consolidated with PageCache suspension code in Document::
suspend and Document::resume. Pages canTabSuspend if cacheable, nonvisible, nonprerender,
and nonactive.

  • dom/Document.cpp: moved scrollbar handling from setInPageCache to suspend/resume

(WebCore::Document::suspend): moved scrollbar, dom, animation, timer, and visual update suspending into here
(WebCore::Document::resume): moved scrollbar, dom, animation, timer, and visual update resuming into here

  • dom/Document.h: added m_isSuspended to prevent repeat calls from PageCache/Tab Suspension contention
  • history/CachedFrame.cpp: moved dom, animation, and timer suspension into Document::suspend

(WebCore::CachedFrame::CachedFrame):

  • history/PageCache.cpp: Added a few nullchecks to prevent crashes if canCacheFrame is called but document is null

(WebCore::PageCache::canCacheFrame):

  • page/Page.cpp:

(WebCore::Page::Page): Added timer to fire delayed suspension
(WebCore::Page::setPageActivityState): Added a call to schedule tab suspension
(WebCore::Page::setIsVisibleInternal): Added a call to schedule tab suspension
(WebCore::Page::canTabSuspend): Added support for suspending if cacheable, nonvisible, nonprerender, and nonactive
(WebCore::Page::setIsTabSuspended): Added a function to suspend or resume tabs
(WebCore::Page::setTabSuspensionEnabled): Added support for a defaults write enable
(WebCore::Page::scheduleTabSuspension): Added ability to schedule the suspension timer to fire or resume
(WebCore::Page::timerFired): Added a suspension timer

  • page/Page.h:
  • page/PageThrottler.h:

(WebCore::PageThrottler::activityState): Added access to m_activityState for canTabSuspend

Source/WebKit2:

Added a runtime flag enabling tab suspension, default off.

  • Shared/WebProcessCreationParameters.cpp:

(WebKit::WebProcessCreationParameters::WebProcessCreationParameters):
(WebKit::WebProcessCreationParameters::encode):
(WebKit::WebProcessCreationParameters::decode):

  • Shared/WebProcessCreationParameters.h:
  • UIProcess/Cocoa/WebProcessPoolCocoa.mm:

(WebKit::registerUserDefaultsIfNeeded):
(WebKit::WebProcessPool::platformInitializeWebProcess):

  • WebProcess/cocoa/WebProcessCocoa.mm:

(WebKit::WebProcess::platformInitializeWebProcess):

Location:
trunk/Source
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r194004 r194006  
     12015-12-12  Katlyn Graff  <kgraff@apple.com>
     2
     3        Safari background tabs should be fully suspended where possible.
     4        https://bugs.webkit.org/show_bug.cgi?id=150515
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Support for tab suspension for Mac, enabled by defaults writing to WebKitTabSuspension.
     9        Page-down suspension consolidated with PageCache suspension code in Document::
     10        suspend and Document::resume. Pages canTabSuspend if cacheable, nonvisible, nonprerender,
     11        and nonactive.
     12
     13        * dom/Document.cpp: moved scrollbar handling from setInPageCache to suspend/resume
     14        (WebCore::Document::suspend): moved scrollbar, dom, animation, timer, and visual update suspending into here
     15        (WebCore::Document::resume): moved scrollbar, dom, animation, timer, and visual update resuming into here
     16        * dom/Document.h: added m_isSuspended to prevent repeat calls from PageCache/Tab Suspension contention
     17        * history/CachedFrame.cpp: moved dom, animation, and timer suspension into Document::suspend
     18        (WebCore::CachedFrame::CachedFrame):
     19       * history/PageCache.cpp: Added a few nullchecks to prevent crashes if canCacheFrame is called but document is null
     20        (WebCore::PageCache::canCacheFrame):
     21        * page/Page.cpp:
     22        (WebCore::Page::Page): Added timer to fire delayed suspension
     23        (WebCore::Page::setPageActivityState): Added a call to schedule tab suspension
     24        (WebCore::Page::setIsVisibleInternal): Added a call to schedule tab suspension
     25        (WebCore::Page::canTabSuspend): Added support for suspending if cacheable, nonvisible, nonprerender, and nonactive
     26        (WebCore::Page::setIsTabSuspended): Added a function to suspend or resume tabs
     27        (WebCore::Page::setTabSuspensionEnabled): Added support for a defaults write enable
     28        (WebCore::Page::scheduleTabSuspension): Added ability to schedule the suspension timer to fire or resume
     29        (WebCore::Page::timerFired): Added a suspension timer
     30        * page/Page.h:
     31        * page/PageThrottler.h:
     32        (WebCore::PageThrottler::activityState): Added access to m_activityState for canTabSuspend
     33
    1342015-12-11  Simon Fraser  <simon.fraser@apple.com>
    235
  • trunk/Source/WebCore/dom/Document.cpp

    r194001 r194006  
    45744574    Page* page = this->page();
    45754575
    4576     if (page)
    4577         page->lockAllOverlayScrollbarsToHidden(flag);
    4578 
    45794576    if (flag) {
    45804577        if (v) {
     
    46094606void Document::suspend()
    46104607{
     4608    if (m_isSuspended)
     4609        return;
     4610
    46114611    documentWillBecomeInactive();
    46124612
     
    46204620#endif
    46214621
     4622    ASSERT(page());
     4623    page()->lockAllOverlayScrollbarsToHidden(true);
     4624
    46224625    if (RenderView* view = renderView()) {
    46234626        if (view->usesCompositing())
    46244627            view->compositor().cancelCompositingLayerUpdate();
    46254628    }
     4629
     4630    suspendScriptedAnimationControllerCallbacks();
     4631    suspendActiveDOMObjects(ActiveDOMObject::PageCache);
     4632
     4633    ASSERT(m_frame);
     4634    m_frame->clearTimers();
     4635
     4636    m_visualUpdatesAllowed = false;
     4637    m_visualUpdatesSuppressionTimer.stop();
     4638
     4639    m_isSuspended = true;
    46264640}
    46274641
    46284642void Document::resume()
    46294643{
     4644    if (!m_isSuspended)
     4645        return;
     4646
    46304647    Vector<Element*> elements;
    46314648    copyToVector(m_documentSuspensionCallbackElements, elements);
     
    46414658    ASSERT(m_frame);
    46424659    m_frame->loader().client().dispatchDidBecomeFrameset(isFrameSet());
     4660    m_frame->animation().resumeAnimationsForDocument(this);
     4661
     4662    resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
     4663    resumeScriptedAnimationControllerCallbacks();
     4664
     4665    m_visualUpdatesAllowed = true;
     4666
     4667    m_isSuspended = false;
    46434668}
    46444669
  • trunk/Source/WebCore/dom/Document.h

    r193885 r194006  
    17651765    bool m_hasStyleWithViewportUnits;
    17661766    bool m_isTimerThrottlingEnabled { false };
     1767    bool m_isSuspended { false };
    17671768
    17681769    HashSet<MediaProducer*> m_audioProducers;
  • trunk/Source/WebCore/history/CachedFrame.cpp

    r192848 r194006  
    166166    // Suspending must also happen after we've recursed over child frames, in case
    167167    // those create more objects.
     168
    168169    m_document->suspend();
    169     m_document->suspendScriptedAnimationControllerCallbacks();
    170     m_document->suspendActiveDOMObjects(ActiveDOMObject::PageCache);
     170
    171171    m_cachedFrameScriptData = std::make_unique<ScriptCachedFrameData>(frame);
    172172
     
    179179
    180180    frame.view()->clearScrollableAreas();
    181 
    182     // suspend() can set up a layout timer on the FrameView, so clear timers after that.
    183     frame.clearTimers();
    184181
    185182    // Deconstruct the FrameTree, to restore it later.
  • trunk/Source/WebCore/history/PageCache.cpp

    r192848 r194006  
    123123        isCacheable = false;
    124124    }
    125     if (frame.isMainFrame() && frame.document()->url().protocolIs("https") && documentLoader->response().cacheControlContainsNoStore()) {
     125    if (frame.isMainFrame() && frame.document() && frame.document()->url().protocolIs("https") && documentLoader->response().cacheControlContainsNoStore()) {
    126126        PCLOG("   -Frame is HTTPS, and cache control prohibits storing");
    127127        logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::httpsNoStoreKey());
     
    150150
    151151    Vector<ActiveDOMObject*> unsuspendableObjects;
    152     if (!frame.document()->canSuspendActiveDOMObjectsForDocumentSuspension(&unsuspendableObjects)) {
     152    if (frame.document() && !frame.document()->canSuspendActiveDOMObjectsForDocumentSuspension(&unsuspendableObjects)) {
    153153        PCLOG("   -The document cannot suspend its active DOM Objects");
    154154        for (auto* activeDOMObject : unsuspendableObjects) {
  • trunk/Source/WebCore/page/Page.cpp

    r193885 r194006  
    144144
    145145static const ViewState::Flags PageInitialViewState = ViewState::IsVisible | ViewState::IsInWindow;
     146bool Page::s_tabSuspensionIsEnabled = false;
    146147
    147148Page::Page(PageConfiguration& pageConfiguration)
     
    224225    , m_sessionID(SessionID::defaultSessionID())
    225226    , m_isClosing(false)
     227    , m_tabSuspensionTimer(*this, &Page::tabSuspensionTimerFired)
    226228{
    227229    setTimerThrottlingEnabled(m_viewState & ViewState::IsVisuallyIdle);
     
    12941296{
    12951297    chrome().client().setPageActivityState(activityState);
     1298   
     1299    if (activityState == PageActivityState::NoFlags && !isVisible())
     1300        scheduleTabSuspension(true);
     1301    else
     1302        scheduleTabSuspension(false);
    12961303}
    12971304
     
    13451352            view->hide();
    13461353    }
     1354
     1355    scheduleTabSuspension(!isVisible);
    13471356}
    13481357
     
    18441853#endif
    18451854
     1855bool Page::canTabSuspend()
     1856{
     1857    return s_tabSuspensionIsEnabled && !m_isPrerender && (m_pageThrottler.activityState() == PageActivityState::NoFlags) && PageCache::singleton().canCache(this);
     1858}
     1859
     1860void Page::setIsTabSuspended(bool shouldSuspend)
     1861{
     1862    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
     1863        if (auto* document = frame->document()) {
     1864            if (shouldSuspend)
     1865                document->suspend();
     1866            else
     1867                document->resume();
     1868        }
     1869    }
     1870}
     1871
     1872void Page::setTabSuspensionEnabled(bool enable)
     1873{
     1874    s_tabSuspensionIsEnabled = enable;
     1875}
     1876
     1877void Page::scheduleTabSuspension(bool shouldSuspend)
     1878{
     1879    if (m_shouldTabSuspend == shouldSuspend)
     1880        return;
     1881   
     1882    if (shouldSuspend && canTabSuspend()) {
     1883        m_shouldTabSuspend = shouldSuspend;
     1884        m_tabSuspensionTimer.startOneShot(0);
     1885    } else {
     1886        m_tabSuspensionTimer.stop();
     1887        if (!shouldSuspend) {
     1888            m_shouldTabSuspend = shouldSuspend;
     1889            setIsTabSuspended(false);
     1890        }
     1891    }
     1892}
     1893
     1894void Page::tabSuspensionTimerFired()
     1895{
     1896    setIsTabSuspended(true);
     1897}
     1898
    18461899} // namespace WebCore
  • trunk/Source/WebCore/page/Page.h

    r193885 r194006  
    139139    WEBCORE_EXPORT static void updateStyleForAllPagesAfterGlobalChangeInEnvironment();
    140140    WEBCORE_EXPORT static void clearPreviousItemFromAllPages(HistoryItem*);
     141    WEBCORE_EXPORT static void setTabSuspensionEnabled(bool);
    141142
    142143    WEBCORE_EXPORT explicit Page(PageConfiguration&);
     
    366367    static const int maxNumberOfFrames = 1000;
    367368
     369    static bool s_tabSuspensionIsEnabled;
     370
    368371    void setEditable(bool isEditable) { m_isEditable = isEditable; }
    369372    bool isEditable() { return m_isEditable; }
     
    492495    void setShowAllPlugins(bool showAll) { m_showAllPlugins = showAll; }
    493496    bool showAllPlugins() const;
     497    void setIsTabSuspended(bool);
    494498
    495499private:
     
    517521    void hiddenPageDOMTimerThrottlingStateChanged();
    518522    void setTimerThrottlingEnabled(bool);
     523    bool canTabSuspend();
     524    void scheduleTabSuspension(bool);
     525    void tabSuspensionTimerFired();
    519526
    520527    const std::unique_ptr<Chrome> m_chrome;
     
    606613    bool m_isPrerender;
    607614    ViewState::Flags m_viewState;
     615    PageActivityState::Flags m_pageActivityState;
    608616
    609617    LayoutMilestones m_requestedLayoutMilestones;
     
    656664
    657665    bool m_isClosing;
     666    bool m_shouldTabSuspend { false };
     667    Timer m_tabSuspensionTimer;
    658668
    659669    MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying };
  • trunk/Source/WebCore/page/PageThrottler.h

    r177541 r194006  
    6060
    6161    void didReceiveUserInput() { m_userInputHysteresis.impulse(); }
     62    PageActivityState::Flags activityState() { return m_activityState; }
    6263    void pluginDidEvaluateWhileAudioIsPlaying() { m_audiblePluginHysteresis.impulse(); }
    6364    PageActivityAssertionToken mediaActivityToken();
  • trunk/Source/WebKit2/ChangeLog

    r194000 r194006  
     12015-12-12  Katlyn Graff  <kgraff@apple.com>
     2
     3        Safari background tabs should be fully suspended where possible.
     4        https://bugs.webkit.org/show_bug.cgi?id=150515
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Added a runtime flag enabling tab suspension, default off.
     9
     10        * Shared/WebProcessCreationParameters.cpp:
     11        (WebKit::WebProcessCreationParameters::WebProcessCreationParameters):
     12        (WebKit::WebProcessCreationParameters::encode):
     13        (WebKit::WebProcessCreationParameters::decode):
     14        * Shared/WebProcessCreationParameters.h:
     15        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
     16        (WebKit::registerUserDefaultsIfNeeded):
     17        (WebKit::WebProcessPool::platformInitializeWebProcess):
     18        * WebProcess/cocoa/WebProcessCocoa.mm:
     19        (WebKit::WebProcess::platformInitializeWebProcess):
     20
    1212015-12-11  Eric Carlson  <eric.carlson@apple.com>
    222
  • trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp

    r192796 r194006  
    4444    , shouldEnableFTLJIT(false)
    4545#endif
     46#if PLATFORM(MAC)
     47    , shouldEnableTabSuspension(false)
     48#endif
    4649    , memoryCacheDisabled(false)
    4750#if ENABLE(SERVICE_CONTROLS)
     
    119122#endif
    120123
     124#if PLATFORM(MAC)
     125    encoder << shouldEnableTabSuspension;
     126#endif
     127
    121128#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
    122129    encoder << notificationPermissions;
     
    258265#endif
    259266
     267#if PLATFORM(MAC)
     268    if (!decoder.decode(parameters.shouldEnableTabSuspension))
     269        return false;
     270#endif
     271
    260272#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
    261273    if (!decoder.decode(parameters.notificationPermissions))
  • trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h

    r192796 r194006  
    143143#endif // PLATFORM(COCOA)
    144144
     145#if PLATFORM(MAC)
     146    bool shouldEnableTabSuspension;
     147#endif
     148
    145149#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
    146150    HashMap<String, bool> notificationPermissions;
  • trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm

    r192796 r194006  
    8585#endif
    8686
     87#if PLATFORM(MAC)
     88NSString *WebKitTabSuspension = @"WebKitTabSuspension";
     89#endif
     90
    8791namespace WebKit {
    8892
     
    101105    [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitJSCJITEnabledDefaultsKey];
    102106    [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitJSCFTLJITEnabledDefaultsKey];
     107
     108#if PLATFORM(MAC)
     109    [registrationDictionary setObject:[NSNumber numberWithBool:NO] forKey:WebKitTabSuspension];
     110#endif
    103111
    104112#if ENABLE(NETWORK_CACHE)
     
    169177#else
    170178    parameters.accessibilityEnhancedUserInterfaceEnabled = false;
     179#endif
     180
     181#if PLATFORM(MAC)
     182    parameters.shouldEnableTabSuspension = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitTabSuspension];
    171183#endif
    172184
  • trunk/Source/WebKit2/WebProcess/cocoa/WebProcessCocoa.mm

    r192280 r194006  
    146146#if PLATFORM(MAC)
    147147    WebCore::FontCache::setFontWhitelist(parameters.fontWhitelist);
     148    Page::setTabSuspensionEnabled(parameters.shouldEnableTabSuspension);
    148149#endif
    149150
Note: See TracChangeset for help on using the changeset viewer.