Changeset 212619 in webkit


Ignore:
Timestamp:
Feb 19, 2017 6:38:43 PM (7 years ago)
Author:
Chris Dumez
Message:

[WK2] Support termination of unresponsive WebContent processes that are in the background
https://bugs.webkit.org/show_bug.cgi?id=168479
<rdar://problem/30558745>

Reviewed by Antti Koivisto.

Support termination of unresponsive WebContent processes that are in the background.
This protects us against cases where a background tab is unresponsive and has high CPU
usage, thus draining the battery without the user knowing about it (e.g.
<rdar://problem/29808005>).

The feature works as follows:

  • If a WebProcessProxy has pages but none of them are visible, then it will check regularly if its associated WebContent process is still responsive.
  • Every time we find that the WebContent process is responsive, we exponentially back off the timer to avoid waking up the process too often. The timer initially uses a 20 seconds interval and can back off up to 8 hours.
  • If the WebContent process is unresponsive, then we terminate it. No notification is shown to the user and the termination is not immediately observable since the tab is not visible and its title remains. The tab is not immediately reloaded so as to avoid getting back into a bad state in the background (and have a yo-yo effect).
  • If the user switches to a tab that was previously killed for being unresponsive while in the background, we will then reload the tab in a fresh WebContent process. The crash banner will only be shown if the tab has ever been visible. If it wasn't ever visible (e.g. session restore case), then it will look as if the tab loads for the first time when the user switches to it.

The functionality is disabled by default and can be enabled by the client via the new
WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled() private API.

  • CMakeLists.txt:
  • UIProcess/API/APIProcessPoolConfiguration.cpp:

(API::ProcessPoolConfiguration::copy):

  • UIProcess/API/APIProcessPoolConfiguration.h:
  • UIProcess/API/C/WKContext.cpp:

(WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled):

  • UIProcess/API/C/WKContextPrivate.h:
  • UIProcess/UnresponsiveWebProcessTerminator.cpp: Added.

(WebKit::UnresponsiveWebProcessTerminator::UnresponsiveWebProcessTerminator):
(WebKit::UnresponsiveWebProcessTerminator::updateState):
(WebKit::pagesCopy):
(WebKit::UnresponsiveWebProcessTerminator::timerFired):

  • UIProcess/UnresponsiveWebProcessTerminator.h: Added.

(WebKit::UnresponsiveWebProcessTerminator::shouldBeActive):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::reattachToWebProcess):
(WebKit::WebPageProxy::reloadAfterBeingKilledInBackground):
(WebKit::WebPageProxy::dispatchActivityStateChange):
(WebKit::WebPageProxy::terminateProcess):
(WebKit::WebPageProxy::resetStateAfterProcessExited):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebProcessProxy.cpp:

(WebKit::WebProcessProxy::WebProcessProxy):
(WebKit::m_backgroundResponsivenessTimer):
(WebKit::WebProcessProxy::createWebPage):
(WebKit::WebProcessProxy::addExistingWebPage):
(WebKit::WebProcessProxy::removeWebPage):
(WebKit::WebProcessProxy::updateBackgroundResponsivenessTimer):

  • UIProcess/WebProcessProxy.h:

(WebKit::WebProcessProxy::visiblePageCount):

  • WebKit2.xcodeproj/project.pbxproj:
Location:
trunk/Source/WebKit2
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/CMakeLists.txt

    r211744 r212619  
    286286    UIProcess/StatisticsRequest.cpp
    287287    UIProcess/TextCheckerCompletion.cpp
     288    UIProcess/UnresponsiveWebProcessTerminator.cpp
    288289    UIProcess/UserMediaPermissionCheckProxy.cpp
    289290    UIProcess/UserMediaPermissionRequestManagerProxy.cpp
  • trunk/Source/WebKit2/ChangeLog

    r212608 r212619  
     12017-02-19  Chris Dumez  <cdumez@apple.com>
     2
     3        [WK2] Support termination of unresponsive WebContent processes that are in the background
     4        https://bugs.webkit.org/show_bug.cgi?id=168479
     5        <rdar://problem/30558745>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Support termination of unresponsive WebContent processes that are in the background.
     10        This protects us against cases where a background tab is unresponsive and has high CPU
     11        usage, thus draining the battery without the user knowing about it (e.g.
     12        <rdar://problem/29808005>).
     13
     14        The feature works as follows:
     15        - If a WebProcessProxy has pages but none of them are visible, then it will check
     16          regularly if its associated WebContent process is still responsive.
     17        - Every time we find that the WebContent process is responsive, we exponentially
     18          back off the timer to avoid waking up the process too often. The timer initially
     19          uses a 20 seconds interval and can back off up to 8 hours.
     20        - If the WebContent process is unresponsive, then we terminate it. No notification
     21          is shown to the user and the termination is not immediately observable since the
     22          tab is not visible and its title remains. The tab is not immediately reloaded
     23          so as to avoid getting back into a bad state in the background (and have a
     24          yo-yo effect).
     25        - If the user switches to a tab that was previously killed for being unresponsive
     26          while in the background, we will then reload the tab in a fresh WebContent
     27          process. The crash banner will only be shown if the tab has ever been visible.
     28          If it wasn't ever visible (e.g. session restore case), then it will look as if
     29          the tab loads for the first time when the user switches to it.
     30
     31        The functionality is disabled by default and can be enabled by the client via the new
     32        WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled() private API.
     33
     34        * CMakeLists.txt:
     35        * UIProcess/API/APIProcessPoolConfiguration.cpp:
     36        (API::ProcessPoolConfiguration::copy):
     37        * UIProcess/API/APIProcessPoolConfiguration.h:
     38        * UIProcess/API/C/WKContext.cpp:
     39        (WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled):
     40        * UIProcess/API/C/WKContextPrivate.h:
     41        * UIProcess/UnresponsiveWebProcessTerminator.cpp: Added.
     42        (WebKit::UnresponsiveWebProcessTerminator::UnresponsiveWebProcessTerminator):
     43        (WebKit::UnresponsiveWebProcessTerminator::updateState):
     44        (WebKit::pagesCopy):
     45        (WebKit::UnresponsiveWebProcessTerminator::timerFired):
     46        * UIProcess/UnresponsiveWebProcessTerminator.h: Added.
     47        (WebKit::UnresponsiveWebProcessTerminator::shouldBeActive):
     48        * UIProcess/WebPageProxy.cpp:
     49        (WebKit::WebPageProxy::reattachToWebProcess):
     50        (WebKit::WebPageProxy::reloadAfterBeingKilledInBackground):
     51        (WebKit::WebPageProxy::dispatchActivityStateChange):
     52        (WebKit::WebPageProxy::terminateProcess):
     53        (WebKit::WebPageProxy::resetStateAfterProcessExited):
     54        * UIProcess/WebPageProxy.h:
     55        * UIProcess/WebProcessProxy.cpp:
     56        (WebKit::WebProcessProxy::WebProcessProxy):
     57        (WebKit::m_backgroundResponsivenessTimer):
     58        (WebKit::WebProcessProxy::createWebPage):
     59        (WebKit::WebProcessProxy::addExistingWebPage):
     60        (WebKit::WebProcessProxy::removeWebPage):
     61        (WebKit::WebProcessProxy::updateBackgroundResponsivenessTimer):
     62        * UIProcess/WebProcessProxy.h:
     63        (WebKit::WebProcessProxy::visiblePageCount):
     64        * WebKit2.xcodeproj/project.pbxproj:
     65
    1662017-02-18  Michael Catanzaro  <mcatanzaro@igalia.com>
    267
  • trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.cpp

    r207346 r212619  
    9797    copy->m_cacheModel = this->m_cacheModel;
    9898    copy->m_diskCacheSpeculativeValidationEnabled = this->m_diskCacheSpeculativeValidationEnabled;
     99    copy->m_unresponsiveBackgroundProcessesTerminationEnabled = this->m_unresponsiveBackgroundProcessesTerminationEnabled;
    99100    copy->m_diskCacheSizeOverride = this->m_diskCacheSizeOverride;
    100101    copy->m_applicationCacheDirectory = this->m_applicationCacheDirectory;
  • trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.h

    r207346 r212619  
    5555    bool diskCacheSpeculativeValidationEnabled() const { return m_diskCacheSpeculativeValidationEnabled; }
    5656    void setDiskCacheSpeculativeValidationEnabled(bool enabled) { m_diskCacheSpeculativeValidationEnabled = enabled; }
     57
     58    bool unresponsiveBackgroundProcessesTerminationEnabled() const { return m_unresponsiveBackgroundProcessesTerminationEnabled; }
     59    void setUnresponsiveBackgroundProcessesTerminationEnabled(bool enabled) { m_unresponsiveBackgroundProcessesTerminationEnabled = enabled; }
    5760
    5861    WebKit::CacheModel cacheModel() const { return m_cacheModel; }
     
    122125    unsigned m_maximumProcessCount { 0 };
    123126    bool m_diskCacheSpeculativeValidationEnabled { false };
     127    bool m_unresponsiveBackgroundProcessesTerminationEnabled { false };
    124128    WebKit::CacheModel m_cacheModel { WebKit::CacheModelPrimaryWebBrowser };
    125129    int64_t m_diskCacheSizeOverride { -1 };
  • trunk/Source/WebKit2/UIProcess/API/C/WKContext.cpp

    r211946 r212619  
    398398}
    399399
     400void WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled(WKContextRef contextRef, bool value)
     401{
     402    toImpl(contextRef)->configuration().setUnresponsiveBackgroundProcessesTerminationEnabled(value);
     403}
     404
    400405WKCookieManagerRef WKContextGetCookieManager(WKContextRef contextRef)
    401406{
  • trunk/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h

    r203674 r212619  
    6363WK_EXPORT void WKContextSetDiskCacheSpeculativeValidationEnabled(WKContextRef context, bool value);
    6464
     65WK_EXPORT void WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled(WKContextRef context, bool value);
     66
    6567WK_EXPORT void WKContextSetIconDatabasePath(WKContextRef context, WKStringRef iconDatabasePath);
    6668
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r212608 r212619  
    713713
    714714    m_isValid = true;
     715    m_wasKilledForBeingUnresponsiveWhileInBackground = false;
    715716    m_process->removeWebPage(m_pageID);
    716717    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
     
    15141515}
    15151516
     1517void WebPageProxy::reloadAfterBeingKilledInBackground()
     1518{
     1519    ASSERT(!isValid());
     1520
     1521    RELEASE_LOG_IF_ALLOWED("%p - Reloading tab that was killed in the background", this);
     1522
     1523    // Only report as a crash if the page was ever visible, otherwise silently reload.
     1524    if (m_hasEverBeenVisible)
     1525        processDidCrash();
     1526    else
     1527        reattachToWebProcessForReload();
     1528}
     1529
    15161530void WebPageProxy::dispatchActivityStateChange()
    15171531{
     
    15201534#endif
    15211535
    1522     if (!isValid())
    1523         return;
     1536    if (!isValid()) {
     1537        if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible && m_wasKilledForBeingUnresponsiveWhileInBackground)
     1538            reloadAfterBeingKilledInBackground();
     1539        return;
     1540    }
    15241541
    15251542    // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
     
    15531570    updateThrottleState();
    15541571
    1555     // If we've started the responsiveness timer as part of telling the web process to update the backing store
    1556     // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
    1557     // stop the unresponsiveness timer here.
    1558     if ((changed & ActivityState::IsVisible) && !isViewVisible())
    1559         m_process->responsivenessTimer().stop();
    1560 
    15611572#if ENABLE(POINTER_LOCK)
    15621573    if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !m_pageClient.isViewWindowActive())
     
    15641575        requestPointerUnlock();
    15651576#endif
     1577
     1578    if (changed & ActivityState::IsVisible) {
     1579        if (isViewVisible()) {
     1580            m_hasEverBeenVisible = true;
     1581            m_visiblePageToken = m_process->visiblePageToken();
     1582        } else {
     1583            m_visiblePageToken = nullptr;
     1584
     1585            // If we've started the responsiveness timer as part of telling the web process to update the backing store
     1586            // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
     1587            // stop the unresponsiveness timer here.
     1588            m_process->responsivenessTimer().stop();
     1589        }
     1590    }
    15661591
    15671592    if (changed & ActivityState::IsInWindow) {
     
    23702395}
    23712396
    2372 void WebPageProxy::terminateProcess()
     2397void WebPageProxy::terminateProcess(TerminationReason terminationReason)
    23732398{
    23742399    // NOTE: This uses a check of m_isValid rather than calling isValid() since
     
    23792404    m_process->requestTermination();
    23802405    resetStateAfterProcessExited();
     2406    m_wasKilledForBeingUnresponsiveWhileInBackground = terminationReason == TerminationReason::UnresponsiveWhileInBackground;
    23812407}
    23822408
     
    54495475#endif
    54505476    m_pageIsUserObservableCount = nullptr;
     5477    m_visiblePageToken = nullptr;
    54515478
    54525479    m_isValid = false;
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r212608 r212619  
    234234typedef GenericCallback<API::SerializedScriptValue*, bool, const WebCore::ExceptionDetails&> ScriptValueCallback;
    235235
     236enum VisibleWebPageCounterType { };
     237using VisibleWebPageCounter = RefCounter<VisibleWebPageCounterType>;
     238using VisibleWebPageToken = VisibleWebPageCounter::Token;
     239
    236240#if PLATFORM(GTK)
    237241typedef GenericCallback<API::Error*> PrintFinishedCallback;
     
    672676    double estimatedProgress() const;
    673677
    674     void terminateProcess();
     678    enum class TerminationReason { UnresponsiveWhileInBackground, Other };
     679    void terminateProcess(TerminationReason = TerminationReason::Other);
    675680
    676681    SessionState sessionState(const std::function<bool (WebBackForwardListItem&)>& = nullptr) const;
     
    15711576    void viewDidLeaveWindow();
    15721577    void viewDidEnterWindow();
     1578    void reloadAfterBeingKilledInBackground();
    15731579
    15741580#if PLATFORM(MAC)
     
    19261932    ProcessSuppressionDisabledToken m_preventProcessSuppressionCount;
    19271933    HiddenPageThrottlingAutoIncreasesCounter::Token m_hiddenPageDOMTimerThrottlingAutoIncreasesCount;
     1934    VisibleWebPageToken m_visiblePageToken;
    19281935       
    19291936    WebCore::ScrollPinningBehavior m_scrollPinningBehavior;
     
    19441951    bool m_needsHiddenContentEditableQuirk { false };
    19451952    bool m_needsPlainTextQuirk { false };
     1953    bool m_hasEverBeenVisible { false };
    19461954
    19471955#if ENABLE(MEDIA_SESSION)
     
    19691977
    19701978    bool m_isUsingHighPerformanceWebGL { false };
     1979    bool m_wasKilledForBeingUnresponsiveWhileInBackground { false };
    19711980       
    19721981    WeakPtrFactory<WebPageProxy> m_weakPtrFactory;
  • trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp

    r212183 r212619  
    3737#include "TextChecker.h"
    3838#include "TextCheckerState.h"
     39#include "UnresponsiveWebProcessTerminator.h"
    3940#include "UserData.h"
    4041#include "WebBackForwardListItem.h"
     
    102103    , m_throttler(*this)
    103104    , m_isResponsive(NoOrMaybe::Maybe)
     105    , m_visiblePageCounter([this](RefCounterEvent) { updateBackgroundResponsivenessTimer(); })
     106    , m_backgroundResponsivenessTimer(processPool.configuration().unresponsiveBackgroundProcessesTerminationEnabled() ? std::make_unique<UnresponsiveWebProcessTerminator>(*this) : nullptr)
    104107{
    105108    WebPasteboardProxy::singleton().addWebProcessProxy(*this);
     
    256259    globalPageMap().set(pageID, webPage.ptr());
    257260
     261    updateBackgroundResponsivenessTimer();
     262
    258263    return webPage;
    259264}
     
    266271    m_pageMap.set(pageID, webPage);
    267272    globalPageMap().set(pageID, webPage);
     273
     274    updateBackgroundResponsivenessTimer();
    268275}
    269276
     
    272279    m_pageMap.remove(pageID);
    273280    globalPageMap().remove(pageID);
     281
     282    updateBackgroundResponsivenessTimer();
    274283   
    275284    Vector<uint64_t> itemIDsToRemove;
     
    707716    }
    708717    return result;
     718}
     719
     720auto WebProcessProxy::visiblePageToken() const -> VisibleWebPageToken
     721{
     722    return m_visiblePageCounter.count();
    709723}
    710724
     
    10741088}
    10751089
     1090void WebProcessProxy::updateBackgroundResponsivenessTimer()
     1091{
     1092    if (m_backgroundResponsivenessTimer)
     1093        m_backgroundResponsivenessTimer->updateState();
     1094}
     1095
    10761096#if !PLATFORM(COCOA)
    10771097const HashSet<String>& WebProcessProxy::platformPathsWithAssumedReadAccess()
  • trunk/Source/WebKit2/UIProcess/WebProcessProxy.h

    r212183 r212619  
    5656
    5757class NetworkProcessProxy;
     58class UnresponsiveWebProcessTerminator;
    5859class WebBackForwardListItem;
    5960class WebPageGroup;
     
    8485    WTF::IteratorRange<WebPageProxyMap::const_iterator::Values> pages() const { return m_pageMap.values(); }
    8586    unsigned pageCount() const { return m_pageMap.size(); }
     87    unsigned visiblePageCount() const { return m_visiblePageCounter.value(); }
    8688
    8789    void addVisitedLinkStore(VisitedLinkStore&);
     
    100102    void disconnectFramesFromPage(WebPageProxy*); // Including main frame.
    101103    size_t frameCountInPage(WebPageProxy*) const; // Including main frame.
     104
     105    VisibleWebPageToken visiblePageToken() const;
    102106
    103107    void updateTextCheckerState();
     
    190194    static const HashSet<String>& platformPathsWithAssumedReadAccess();
    191195
     196    void updateBackgroundResponsivenessTimer();
     197
    192198    // IPC::Connection::Client
    193199    friend class WebConnectionToWebProcess;
     
    248254    enum class NoOrMaybe { No, Maybe } m_isResponsive;
    249255    Vector<std::function<void(bool webProcessIsResponsive)>> m_isResponsiveCallbacks;
     256
     257    VisibleWebPageCounter m_visiblePageCounter;
     258    std::unique_ptr<UnresponsiveWebProcessTerminator> m_backgroundResponsivenessTimer;
    250259};
    251260
  • trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

    r212557 r212619  
    900900                41FAF5F91E3C1025001AE678 /* LibWebRTCResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */; };
    901901                4450AEC01DC3FAE5009943F2 /* SharedMemoryCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */; };
     902                46A2B6081E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */; };
     903                46A2B6091E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */; };
    902904                4A3CC18A19B063E700D14AEF /* UserMediaPermissionRequestManagerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */; };
    903905                4A3CC18B19B0640F00D14AEF /* UserMediaPermissionRequestManagerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A410F3A19AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.h */; };
     
    30513053                41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCResolver.cpp; path = Network/webrtc/LibWebRTCResolver.cpp; sourceTree = "<group>"; };
    30523054                4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharedMemoryCocoa.cpp; path = cocoa/SharedMemoryCocoa.cpp; sourceTree = "<group>"; };
     3055                46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnresponsiveWebProcessTerminator.cpp; sourceTree = "<group>"; };
     3056                46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnresponsiveWebProcessTerminator.h; sourceTree = "<group>"; };
    30533057                4A410F3519AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKUserMediaPermissionRequest.cpp; sourceTree = "<group>"; };
    30543058                4A410F3619AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKUserMediaPermissionRequest.h; sourceTree = "<group>"; };
     
    64586462                                1BB417C912C00CCA002BE67B /* TextCheckerCompletion.cpp */,
    64596463                                1CC417C912C00CCA002BE67B /* TextCheckerCompletion.h */,
     6464                                46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */,
     6465                                46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */,
    64606466                                07297F9C1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.cpp */,
    64616467                                07297F9D1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.h */,
     
    79657971                                1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */,
    79667972                                BC3065FA1259344E00E71278 /* CacheModel.h in Headers */,
     7973                                46A2B6091E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.h in Headers */,
    79677974                                1AA2E51D12E4C05E00BC4966 /* CGUtilities.h in Headers */,
    79687975                                1A2D956F12848564001EB962 /* ChildProcess.h in Headers */,
     
    96469653                                5C20CB9D1BB0DCFA00895BB1 /* NetworkSessionCocoa.mm in Sources */,
    96479654                                31A2EC551489982E00810D71 /* NotificationPermissionRequest.cpp in Sources */,
     9655                                46A2B6081E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.cpp in Sources */,
    96489656                                3131261E148FF82C00BA2A39 /* NotificationPermissionRequestManager.cpp in Sources */,
    96499657                                31A2EC501489980500810D71 /* NotificationPermissionRequestManagerProxy.cpp in Sources */,
Note: See TracChangeset for help on using the changeset viewer.