Changeset 249603 in webkit


Ignore:
Timestamp:
Sep 6, 2019 6:53:20 PM (5 years ago)
Author:
Chris Dumez
Message:

Move the ResourceLoadObserver logic to WebKit2
https://bugs.webkit.org/show_bug.cgi?id=201517

Reviewed by Brent Fulgham.

Move the ResourceLoadObserver logic to WebKit2 since it is not used by WebKit1. This allows us to simplify
code.

In a follow-up patch, I will simplify the code even further by leveraging the fact that a WebContent process
is always associated with a single WebsiteDataStore / sessionID:

  • No need for a HashMap of sessionIDs
  • No need to even allocate the ResourceLoadObserver if the WebProcess is associated with an ephemeral session.

Source/WebCore:

  • dom/Document.h:
  • loader/ResourceLoadObserver.cpp:

(WebCore::sharedObserver):
(WebCore::ResourceLoadObserver::setShared):
(WebCore::ResourceLoadObserver::shared):

  • loader/ResourceLoadObserver.h:

(WebCore::ResourceLoadObserver::~ResourceLoadObserver):
(WebCore::ResourceLoadObserver::logSubresourceLoading):
(WebCore::ResourceLoadObserver::logWebSocketLoading):
(WebCore::ResourceLoadObserver::logUserInteractionWithReducedTimeResolution):
(WebCore::ResourceLoadObserver::logFontLoad):
(WebCore::ResourceLoadObserver::logCanvasRead):
(WebCore::ResourceLoadObserver::logCanvasWriteOrMeasure):
(WebCore::ResourceLoadObserver::logNavigatorAPIAccessed):
(WebCore::ResourceLoadObserver::logScreenAPIAccessed):
(WebCore::ResourceLoadObserver::statisticsForURL):
(WebCore::ResourceLoadObserver::updateCentralStatisticsStore):
(WebCore::ResourceLoadObserver::clearState):
(WebCore::ResourceLoadObserver::setShouldLogUserInteraction):

  • page/DeprecatedGlobalSettings.h:

Source/WebKit:

  • NetworkProcess/NetworkConnectionToWebProcess.cpp:

(WebKit::NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated):

  • NetworkProcess/NetworkConnectionToWebProcess.h:
  • Sources.txt:
  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp: Copied from Source/WebCore/loader/ResourceLoadObserver.cpp.

(WebKit::is3xxRedirect):
(WebKit::WebResourceLoadObserver::WebResourceLoadObserver):
(WebKit::WebResourceLoadObserver::shouldLog const):
(WebKit::WebResourceLoadObserver::requestStorageAccessUnderOpener):
(WebKit::WebResourceLoadObserver::ensureResourceStatisticsForRegistrableDomain):
(WebKit::WebResourceLoadObserver::scheduleNotificationIfNeeded):
(WebKit::WebResourceLoadObserver::updateCentralStatisticsStore):
(WebKit::WebResourceLoadObserver::statisticsForURL):
(WebKit::WebResourceLoadObserver::takeStatistics):
(WebKit::WebResourceLoadObserver::clearState):
(WebKit::WebResourceLoadObserver::nonNullOwnerURL const):
(WebKit::WebResourceLoadObserver::logFontLoad):
(WebKit::WebResourceLoadObserver::logCanvasRead):
(WebKit::WebResourceLoadObserver::logCanvasWriteOrMeasure):
(WebKit::WebResourceLoadObserver::logNavigatorAPIAccessed):
(WebKit::WebResourceLoadObserver::logScreenAPIAccessed):
(WebKit::WebResourceLoadObserver::logSubresourceLoading):
(WebKit::WebResourceLoadObserver::logWebSocketLoading):
(WebKit::WebResourceLoadObserver::logUserInteractionWithReducedTimeResolution):

  • WebProcess/WebCoreSupport/WebResourceLoadObserver.h: Added.
  • WebProcess/WebProcess.cpp:
Location:
trunk/Source
Files:
1 added
11 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r249601 r249603  
     12019-09-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Move the ResourceLoadObserver logic to WebKit2
     4        https://bugs.webkit.org/show_bug.cgi?id=201517
     5
     6        Reviewed by Brent Fulgham.
     7
     8        Move the ResourceLoadObserver logic to WebKit2 since it is not used by WebKit1. This allows us to simplify
     9        code.
     10
     11        In a follow-up patch, I will simplify the code even further by leveraging the fact that a WebContent process
     12        is always associated with a single WebsiteDataStore / sessionID:
     13        - No need for a HashMap of sessionIDs
     14        - No need to even allocate the ResourceLoadObserver if the WebProcess is associated with an ephemeral session.
     15
     16        * dom/Document.h:
     17        * loader/ResourceLoadObserver.cpp:
     18        (WebCore::sharedObserver):
     19        (WebCore::ResourceLoadObserver::setShared):
     20        (WebCore::ResourceLoadObserver::shared):
     21        * loader/ResourceLoadObserver.h:
     22        (WebCore::ResourceLoadObserver::~ResourceLoadObserver):
     23        (WebCore::ResourceLoadObserver::logSubresourceLoading):
     24        (WebCore::ResourceLoadObserver::logWebSocketLoading):
     25        (WebCore::ResourceLoadObserver::logUserInteractionWithReducedTimeResolution):
     26        (WebCore::ResourceLoadObserver::logFontLoad):
     27        (WebCore::ResourceLoadObserver::logCanvasRead):
     28        (WebCore::ResourceLoadObserver::logCanvasWriteOrMeasure):
     29        (WebCore::ResourceLoadObserver::logNavigatorAPIAccessed):
     30        (WebCore::ResourceLoadObserver::logScreenAPIAccessed):
     31        (WebCore::ResourceLoadObserver::statisticsForURL):
     32        (WebCore::ResourceLoadObserver::updateCentralStatisticsStore):
     33        (WebCore::ResourceLoadObserver::clearState):
     34        (WebCore::ResourceLoadObserver::setShouldLogUserInteraction):
     35        * page/DeprecatedGlobalSettings.h:
     36
    1372019-09-06  Justin Fan  <justin_fan@apple.com>
    238
  • trunk/Source/WebCore/dom/Document.h

    r249378 r249603  
    14921492
    14931493#if ENABLE(RESOURCE_LOAD_STATISTICS)
    1494     bool hasRequestedPageSpecificStorageAccessWithUserInteraction(const RegistrableDomain&);
    1495     void setHasRequestedPageSpecificStorageAccessWithUserInteraction(const RegistrableDomain&);
     1494    WEBCORE_EXPORT bool hasRequestedPageSpecificStorageAccessWithUserInteraction(const RegistrableDomain&);
     1495    WEBCORE_EXPORT void setHasRequestedPageSpecificStorageAccessWithUserInteraction(const RegistrableDomain&);
    14961496    WEBCORE_EXPORT void wasLoadedWithDataTransferFromPrevalentResource();
    14971497    void downgradeReferrerToRegistrableDomain();
  • trunk/Source/WebCore/loader/ResourceLoadObserver.cpp

    r249126 r249603  
    2727#include "ResourceLoadObserver.h"
    2828
    29 #include "DeprecatedGlobalSettings.h"
    30 #include "Document.h"
    31 #include "Frame.h"
    32 #include "FrameLoader.h"
    33 #include "FrameLoaderClient.h"
    34 #include "HTMLFrameOwnerElement.h"
    35 #include "Logging.h"
    36 #include "Page.h"
    37 #include "RegistrableDomain.h"
    38 #include "ResourceLoadStatistics.h"
    39 #include "ResourceRequest.h"
    40 #include "ResourceResponse.h"
    41 #include "RuntimeEnabledFeatures.h"
    42 #include "ScriptExecutionContext.h"
    43 #include "SecurityOrigin.h"
    44 #include "Settings.h"
    45 #include <wtf/URL.h>
    46 
    4729namespace WebCore {
    4830
    49 static const Seconds minimumNotificationInterval { 5_s };
     31static ResourceLoadObserver*& sharedObserver()
     32{
     33    static ResourceLoadObserver* observer = nullptr;
     34    return observer;
     35}
    5036
    51 ResourceLoadObserver::ResourceLoadObserver()
    52     : m_notificationTimer(*this, &ResourceLoadObserver::updateCentralStatisticsStore)
     37void ResourceLoadObserver::setShared(ResourceLoadObserver& observer)
    5338{
     39    RELEASE_ASSERT(!sharedObserver());
     40    sharedObserver() = &observer;
    5441}
    5542
    5643ResourceLoadObserver& ResourceLoadObserver::shared()
    5744{
    58     static NeverDestroyed<ResourceLoadObserver> resourceLoadObserver;
    59     return resourceLoadObserver;
    60 }
    61 
    62 void ResourceLoadObserver::setStatisticsUpdatedCallback(Function<void(PerSessionResourceLoadData&&)>&& notificationCallback)
    63 {
    64     ASSERT(!m_notificationCallback);
    65     m_notificationCallback = WTFMove(notificationCallback);
    66 }
    67 
    68 void ResourceLoadObserver::setRequestStorageAccessUnderOpenerCallback(Function<void(PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, const RegistrableDomain& openerDomain)>&& callback)
    69 {
    70     ASSERT(!m_requestStorageAccessUnderOpenerCallback);
    71     m_requestStorageAccessUnderOpenerCallback = WTFMove(callback);
    72 }
    73 
    74 void ResourceLoadObserver::setLogUserInteractionNotificationCallback(Function<void(PAL::SessionID, const RegistrableDomain&)>&& callback)
    75 {
    76     ASSERT(!m_logUserInteractionNotificationCallback);
    77     m_logUserInteractionNotificationCallback = WTFMove(callback);
    78 }
    79    
    80 static inline bool is3xxRedirect(const ResourceResponse& response)
    81 {
    82     return response.httpStatusCode() >= 300 && response.httpStatusCode() <= 399;
    83 }
    84 
    85 bool ResourceLoadObserver::shouldLog(PAL::SessionID sessionID) const
    86 {
    87     return DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() && !sessionID.isEphemeral() && m_notificationCallback;
    88 }
    89 
    90 void ResourceLoadObserver::logSubresourceLoading(const Frame* frame, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
    91 {
    92     ASSERT(frame->page());
    93 
    94     if (!frame)
    95         return;
    96 
    97     auto* page = frame->page();
    98     if (!page || !shouldLog(page->sessionID()))
    99         return;
    100 
    101     bool isRedirect = is3xxRedirect(redirectResponse);
    102     const URL& redirectedFromURL = redirectResponse.url();
    103     const URL& targetURL = newRequest.url();
    104     const URL& topFrameURL = frame ? frame->mainFrame().document()->url() : URL();
    105    
    106     auto targetHost = targetURL.host();
    107     auto topFrameHost = topFrameURL.host();
    108 
    109     if (targetHost.isEmpty() || topFrameHost.isEmpty() || targetHost == topFrameHost || (isRedirect && targetHost == redirectedFromURL.host()))
    110         return;
    111 
    112     RegistrableDomain targetDomain { targetURL };
    113     RegistrableDomain topFrameDomain { topFrameURL };
    114     RegistrableDomain redirectedFromDomain { redirectedFromURL };
    115 
    116     if (targetDomain == topFrameDomain || (isRedirect && targetDomain == redirectedFromDomain))
    117         return;
    118 
    119     {
    120         auto& targetStatistics = ensureResourceStatisticsForRegistrableDomain(page->sessionID(), targetDomain);
    121         auto lastSeen = ResourceLoadStatistics::reduceTimeResolution(WallTime::now());
    122         targetStatistics.lastSeen = lastSeen;
    123         targetStatistics.subresourceUnderTopFrameDomains.add(topFrameDomain);
    124 
    125         scheduleNotificationIfNeeded();
    126     }
    127 
    128     if (isRedirect) {
    129         auto& redirectingOriginStatistics = ensureResourceStatisticsForRegistrableDomain(page->sessionID(), redirectedFromDomain);
    130         redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetDomain);
    131         auto& targetStatistics = ensureResourceStatisticsForRegistrableDomain(page->sessionID(), targetDomain);
    132         targetStatistics.subresourceUniqueRedirectsFrom.add(redirectedFromDomain);
    133 
    134         scheduleNotificationIfNeeded();
    135     }
    136 }
    137 
    138 void ResourceLoadObserver::logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, PAL::SessionID sessionID)
    139 {
    140     if (!shouldLog(sessionID))
    141         return;
    142 
    143     auto targetHost = targetURL.host();
    144     auto mainFrameHost = mainFrameURL.host();
    145    
    146     if (targetHost.isEmpty() || mainFrameHost.isEmpty() || targetHost == mainFrameHost)
    147         return;
    148    
    149     RegistrableDomain targetDomain { targetURL };
    150     RegistrableDomain topFrameDomain { mainFrameURL };
    151 
    152     if (targetDomain == topFrameDomain)
    153         return;
    154 
    155     auto lastSeen = ResourceLoadStatistics::reduceTimeResolution(WallTime::now());
    156 
    157     auto& targetStatistics = ensureResourceStatisticsForRegistrableDomain(sessionID, targetDomain);
    158     targetStatistics.lastSeen = lastSeen;
    159     targetStatistics.subresourceUnderTopFrameDomains.add(topFrameDomain);
    160 
    161     scheduleNotificationIfNeeded();
    162 }
    163 
    164 void ResourceLoadObserver::logUserInteractionWithReducedTimeResolution(const Document& document)
    165 {
    166     if (!document.sessionID().isValid() || !shouldLog(document.sessionID()))
    167         return;
    168 
    169     auto& url = document.url();
    170     if (url.protocolIsAbout() || url.isLocalFile() || url.isEmpty())
    171         return;
    172 
    173     RegistrableDomain topFrameDomain { url };
    174     auto newTime = ResourceLoadStatistics::reduceTimeResolution(WallTime::now());
    175     auto lastReportedUserInteraction = m_lastReportedUserInteractionMap.get(topFrameDomain);
    176     if (newTime == lastReportedUserInteraction)
    177         return;
    178 
    179     m_lastReportedUserInteractionMap.set(topFrameDomain, newTime);
    180 
    181     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID(), topFrameDomain);
    182     statistics.hadUserInteraction = true;
    183     statistics.lastSeen = newTime;
    184     statistics.mostRecentUserInteractionTime = newTime;
    185 
    186 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    187     if (auto* frame = document.frame()) {
    188         if (auto* opener = frame->loader().opener()) {
    189             if (auto* openerDocument = opener->document()) {
    190                 if (auto* openerFrame = openerDocument->frame()) {
    191                     if (auto openerPageID = openerFrame->loader().client().pageID())
    192                         requestStorageAccessUnderOpener(document.sessionID(), topFrameDomain, openerPageID.value(), *openerDocument);
    193                 }
    194             }
    195         }
    196     }
    197 
    198     // We notify right away in case of a user interaction instead of waiting the usual 5 seconds because we want
    199     // to update cookie blocking state as quickly as possible.
    200     m_logUserInteractionNotificationCallback(document.sessionID(), topFrameDomain);
    201 #endif
    202 
    203 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
    204     if (shouldLogUserInteraction()) {
    205         auto counter = ++m_loggingCounter;
    206 #define LOCAL_LOG(str, ...) \
    207         RELEASE_LOG(ResourceLoadStatistics, "ResourceLoadObserver::logUserInteraction: counter = %" PRIu64 ": " str, counter, ##__VA_ARGS__)
    208 
    209         auto escapeForJSON = [](String s) {
    210             s.replace('\\', "\\\\").replace('"', "\\\"");
    211             return s;
    212         };
    213         auto escapedURL = escapeForJSON(url.string());
    214         auto escapedDomain = escapeForJSON(topFrameDomain.string());
    215 
    216         LOCAL_LOG(R"({ "url": "%{public}s",)", escapedURL.utf8().data());
    217         LOCAL_LOG(R"(  "domain" : "%{public}s",)", escapedDomain.utf8().data());
    218         LOCAL_LOG(R"(  "until" : %f })", newTime.secondsSinceEpoch().seconds());
    219 
    220 #undef LOCAL_LOG
    221     }
    222 #endif
    223 }
    224 
    225 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    226 void ResourceLoadObserver::requestStorageAccessUnderOpener(PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, Document& openerDocument)
    227 {
    228     auto openerUrl = openerDocument.url();
    229     RegistrableDomain openerDomain { openerUrl };
    230     if (domainInNeedOfStorageAccess != openerDomain
    231         && !openerDocument.hasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess)
    232         && !equalIgnoringASCIICase(openerUrl.string(), WTF::blankURL())) {
    233         m_requestStorageAccessUnderOpenerCallback(sessionID, domainInNeedOfStorageAccess, openerPageID, openerDomain);
    234         // Remember user interaction-based requests since they don't need to be repeated.
    235         openerDocument.setHasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess);
    236     }
    237 }
    238 #endif
    239 
    240 void ResourceLoadObserver::logFontLoad(const Document& document, const String& familyName, bool loadStatus)
    241 {
    242 #if ENABLE(WEB_API_STATISTICS)
    243     if (!shouldLog(document.sessionID()))
    244         return;
    245     RegistrableDomain registrableDomain { document.url() };
    246     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    247     bool shouldCallNotificationCallback = false;
    248     if (!loadStatus) {
    249         if (statistics.fontsFailedToLoad.add(familyName).isNewEntry)
    250             shouldCallNotificationCallback = true;
    251     } else {
    252         if (statistics.fontsSuccessfullyLoaded.add(familyName).isNewEntry)
    253             shouldCallNotificationCallback = true;
    254     }
    255     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    256     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    257         shouldCallNotificationCallback = true;
    258     if (shouldCallNotificationCallback)
    259         scheduleNotificationIfNeeded();
    260 #else
    261     UNUSED_PARAM(document);
    262     UNUSED_PARAM(familyName);
    263     UNUSED_PARAM(loadStatus);
    264 #endif
    265 }
    266    
    267 void ResourceLoadObserver::logCanvasRead(const Document& document)
    268 {
    269 #if ENABLE(WEB_API_STATISTICS)
    270     if (!shouldLog(document.sessionID()))
    271         return;
    272     RegistrableDomain registrableDomain { document.url() };
    273     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID(), registrableDomain);
    274     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    275     statistics.canvasActivityRecord.wasDataRead = true;
    276     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    277         scheduleNotificationIfNeeded();
    278 #else
    279     UNUSED_PARAM(document);
    280 #endif
    281 }
    282 
    283 void ResourceLoadObserver::logCanvasWriteOrMeasure(const Document& document, const String& textWritten)
    284 {
    285 #if ENABLE(WEB_API_STATISTICS)
    286     if (!shouldLog(document.sessionID()))
    287         return;
    288     RegistrableDomain registrableDomain { document.url() };
    289     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    290     bool shouldCallNotificationCallback = false;
    291     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    292     if (statistics.canvasActivityRecord.recordWrittenOrMeasuredText(textWritten))
    293         shouldCallNotificationCallback = true;
    294     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    295         shouldCallNotificationCallback = true;
    296     if (shouldCallNotificationCallback)
    297         scheduleNotificationIfNeeded();
    298 #else
    299     UNUSED_PARAM(document);
    300     UNUSED_PARAM(textWritten);
    301 #endif
    302 }
    303    
    304 void ResourceLoadObserver::logNavigatorAPIAccessed(const Document& document, const ResourceLoadStatistics::NavigatorAPI functionName)
    305 {
    306 #if ENABLE(WEB_API_STATISTICS)
    307     if (!shouldLog(document.sessionID()))
    308         return;
    309     RegistrableDomain registrableDomain { document.url() };
    310     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    311     bool shouldCallNotificationCallback = false;
    312     if (!statistics.navigatorFunctionsAccessed.contains(functionName)) {
    313         statistics.navigatorFunctionsAccessed.add(functionName);
    314         shouldCallNotificationCallback = true;
    315     }
    316     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    317     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    318         shouldCallNotificationCallback = true;
    319     if (shouldCallNotificationCallback)
    320         scheduleNotificationIfNeeded();
    321 #else
    322     UNUSED_PARAM(document);
    323     UNUSED_PARAM(functionName);
    324 #endif
    325 }
    326    
    327 void ResourceLoadObserver::logScreenAPIAccessed(const Document& document, const ResourceLoadStatistics::ScreenAPI functionName)
    328 {
    329 #if ENABLE(WEB_API_STATISTICS)
    330     if (!shouldLog(document.sessionID()))
    331         return;
    332     RegistrableDomain registrableDomain { document.url() };
    333     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    334     bool shouldCallNotificationCallback = false;
    335     if (!statistics.screenFunctionsAccessed.contains(functionName)) {
    336         statistics.screenFunctionsAccessed.add(functionName);
    337         shouldCallNotificationCallback = true;
    338     }
    339     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    340     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    341         shouldCallNotificationCallback = true;
    342     if (shouldCallNotificationCallback)
    343         scheduleNotificationIfNeeded();
    344 #else
    345     UNUSED_PARAM(document);
    346     UNUSED_PARAM(functionName);
    347 #endif
    348 }
    349    
    350 ResourceLoadStatistics& ResourceLoadObserver::ensureResourceStatisticsForRegistrableDomain(PAL::SessionID sessionID, const RegistrableDomain& domain)
    351 {
    352     auto addResult = m_perSessionResourceStatisticsMap.ensure(sessionID, [] {
    353         return makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();
    354     });
    355 
    356     auto addDomainResult = addResult.iterator->value->ensure(domain, [&domain] {
    357         return ResourceLoadStatistics(domain);
    358     });
    359     return addDomainResult.iterator->value;
    360 }
    361 
    362 void ResourceLoadObserver::scheduleNotificationIfNeeded()
    363 {
    364     ASSERT(m_notificationCallback);
    365     if (m_perSessionResourceStatisticsMap.isEmpty()) {
    366         m_notificationTimer.stop();
    367         return;
    368     }
    369 
    370     if (!m_notificationTimer.isActive())
    371         m_notificationTimer.startOneShot(minimumNotificationInterval);
    372 }
    373 
    374 void ResourceLoadObserver::updateCentralStatisticsStore()
    375 {
    376     ASSERT(m_notificationCallback);
    377     m_notificationTimer.stop();
    378     m_notificationCallback(takeStatistics());
    379 }
    380 
    381 String ResourceLoadObserver::statisticsForURL(PAL::SessionID sessionID, const URL& url)
    382 {
    383     auto* resourceStatisticsByDomain = m_perSessionResourceStatisticsMap.get(sessionID);
    384     if (!resourceStatisticsByDomain)
    385         return emptyString();
    386 
    387     auto iter = resourceStatisticsByDomain->find(RegistrableDomain { url });
    388     if (iter == resourceStatisticsByDomain->end())
    389         return emptyString();
    390 
    391     return makeString("Statistics for ", url.host().toString(), ":\n", iter->value.toString());
    392 }
    393 
    394 auto ResourceLoadObserver::takeStatistics() -> PerSessionResourceLoadData
    395 {
    396     PerSessionResourceLoadData perSessionStatistics;
    397 
    398     for (auto& iter : m_perSessionResourceStatisticsMap) {
    399         Vector<ResourceLoadStatistics> statistics;
    400         statistics.reserveInitialCapacity(iter.value->size());
    401 
    402         for (auto& statistic : iter.value->values())
    403             statistics.uncheckedAppend(WTFMove(statistic));
    404 
    405         perSessionStatistics.append(std::make_pair(iter.key, WTFMove(statistics)));
    406     }
    407    
    408     m_perSessionResourceStatisticsMap.clear();
    409     return perSessionStatistics;
    410 }
    411 
    412 void ResourceLoadObserver::clearState()
    413 {
    414     m_notificationTimer.stop();
    415     m_perSessionResourceStatisticsMap.clear();
    416     m_lastReportedUserInteractionMap.clear();
    417 }
    418 
    419 URL ResourceLoadObserver::nonNullOwnerURL(const Document& document) const
    420 {
    421     auto url = document.url();
    422     auto* frame = document.frame();
    423     auto host = document.url().host();
    424 
    425     while ((host.isNull() || host.isEmpty()) && frame && !frame->isMainFrame()) {
    426         auto* ownerElement = frame->ownerElement();
    427 
    428         ASSERT(ownerElement != nullptr);
    429        
    430         auto& doc = ownerElement->document();
    431         frame = doc.frame();
    432         url = doc.url();
    433         host = url.host();
    434     }
    435 
    436     return url;
     45    if (!sharedObserver())
     46        sharedObserver() = new ResourceLoadObserver;
     47    return *sharedObserver();
    43748}
    43849
  • trunk/Source/WebCore/loader/ResourceLoadObserver.h

    r249223 r249603  
    2626#pragma once
    2727
    28 #include "CanvasActivityRecord.h"
    29 #include "PageIdentifier.h"
    3028#include "ResourceLoadStatistics.h"
    31 #include "Timer.h"
    3229#include <pal/SessionID.h>
    33 #include <wtf/HashMap.h>
    34 #include <wtf/HashSet.h>
    35 #include <wtf/NeverDestroyed.h>
    36 #include <wtf/text/WTFString.h>
    37 
    38 namespace WTF {
    39 class Lock;
    40 class WorkQueue;
    41 class WallTime;
    42 }
     30#include <wtf/Forward.h>
    4331
    4432namespace WebCore {
     
    4634class Document;
    4735class Frame;
    48 class Page;
    49 class RegistrableDomain;
    5036class ResourceRequest;
    5137class ResourceResponse;
    52 class ScriptExecutionContext;
    53 
    54 struct ResourceLoadStatistics;
    5538
    5639class ResourceLoadObserver {
    57     friend class WTF::NeverDestroyed<ResourceLoadObserver>;
     40    WTF_MAKE_FAST_ALLOCATED;
    5841public:
    59     using PerSessionResourceLoadData = Vector<std::pair<PAL::SessionID, Vector<ResourceLoadStatistics>>>;
    6042    WEBCORE_EXPORT static ResourceLoadObserver& shared();
     43    WEBCORE_EXPORT static void setShared(ResourceLoadObserver&);
     44   
     45    virtual ~ResourceLoadObserver() { }
    6146
    62     void logSubresourceLoading(const Frame*, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse);
    63     void logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, PAL::SessionID);
    64     void logUserInteractionWithReducedTimeResolution(const Document&);
     47    virtual void logSubresourceLoading(const Frame*, const ResourceRequest& /* newRequest */, const ResourceResponse& /* redirectResponse */) { }
     48    virtual void logWebSocketLoading(const URL& /* targetURL */, const URL& /* mainFrameURL */, PAL::SessionID) { }
     49    virtual void logUserInteractionWithReducedTimeResolution(const Document&) { }
     50    virtual void logFontLoad(const Document&, const String& /* familyName */, bool /* loadStatus */) { }
     51    virtual void logCanvasRead(const Document&) { }
     52    virtual void logCanvasWriteOrMeasure(const Document&, const String& /* textWritten */) { }
     53    virtual void logNavigatorAPIAccessed(const Document&, const ResourceLoadStatistics::NavigatorAPI) { }
     54    virtual void logScreenAPIAccessed(const Document&, const ResourceLoadStatistics::ScreenAPI) { }
     55
     56    virtual String statisticsForURL(PAL::SessionID, const URL&) { return { }; }
     57    virtual void updateCentralStatisticsStore() { }
     58    virtual void clearState() { }
    6559   
    66     void logFontLoad(const Document&, const String& familyName, bool loadStatus);
    67     void logCanvasRead(const Document&);
    68     void logCanvasWriteOrMeasure(const Document&, const String& textWritten);
    69     void logNavigatorAPIAccessed(const Document&, const ResourceLoadStatistics::NavigatorAPI);
    70     void logScreenAPIAccessed(const Document&, const ResourceLoadStatistics::ScreenAPI);
    71 
    72     WEBCORE_EXPORT String statisticsForURL(PAL::SessionID, const URL&);
    73 
    74     WEBCORE_EXPORT void setStatisticsUpdatedCallback(Function<void(PerSessionResourceLoadData&&)>&&);
    75     WEBCORE_EXPORT void setRequestStorageAccessUnderOpenerCallback(Function<void(PAL::SessionID, const RegistrableDomain&, PageIdentifier, const RegistrableDomain&)>&&);
    76     WEBCORE_EXPORT void setLogUserInteractionNotificationCallback(Function<void(PAL::SessionID, const RegistrableDomain&)>&&);
    77 
    78     WEBCORE_EXPORT void updateCentralStatisticsStore();
    79     WEBCORE_EXPORT void clearState();
    80 
    8160#if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
    82     bool shouldLogUserInteraction() const { return m_shouldLogUserInteraction; }
    83     void setShouldLogUserInteraction(bool shouldLogUserInteraction) { m_shouldLogUserInteraction = shouldLogUserInteraction; }
     61    virtual void setShouldLogUserInteraction(bool) { }
    8462#endif
    85 
    86 private:
    87     ResourceLoadObserver();
    88 
    89     bool shouldLog(PAL::SessionID) const;
    90     ResourceLoadStatistics& ensureResourceStatisticsForRegistrableDomain(PAL::SessionID, const RegistrableDomain&);
    91     void scheduleNotificationIfNeeded();
    92 
    93     PerSessionResourceLoadData takeStatistics();
    94 
    95 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    96     void requestStorageAccessUnderOpener(PAL::SessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, Document& openerDocument);
    97 #endif
    98 
    99     HashMap<PAL::SessionID, std::unique_ptr<HashMap<RegistrableDomain, ResourceLoadStatistics>>> m_perSessionResourceStatisticsMap;
    100     HashMap<RegistrableDomain, WTF::WallTime> m_lastReportedUserInteractionMap;
    101     Function<void(PerSessionResourceLoadData)> m_notificationCallback;
    102     Function<void(PAL::SessionID, const RegistrableDomain&, PageIdentifier, const RegistrableDomain&)> m_requestStorageAccessUnderOpenerCallback;
    103     Function<void(PAL::SessionID, const RegistrableDomain&)> m_logUserInteractionNotificationCallback;
    104 
    105     Timer m_notificationTimer;
    106 
    107 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
    108     uint64_t m_loggingCounter { 0 };
    109     bool m_shouldLogUserInteraction { false };
    110 #endif
    111 
    112     URL nonNullOwnerURL(const Document&) const;
    11363};
    11464   
  • trunk/Source/WebCore/page/DeprecatedGlobalSettings.h

    r240644 r249603  
    135135
    136136    static bool gLowPowerVideoAudioBufferSizeEnabled;
    137     static bool gResourceLoadStatisticsEnabledEnabled;
     137    WEBCORE_EXPORT static bool gResourceLoadStatisticsEnabledEnabled;
    138138    static bool gAllowsAnySSLCertificate;
    139139};
  • trunk/Source/WebKit/ChangeLog

    r249600 r249603  
     12019-09-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Move the ResourceLoadObserver logic to WebKit2
     4        https://bugs.webkit.org/show_bug.cgi?id=201517
     5
     6        Reviewed by Brent Fulgham.
     7
     8        Move the ResourceLoadObserver logic to WebKit2 since it is not used by WebKit1. This allows us to simplify
     9        code.
     10
     11        In a follow-up patch, I will simplify the code even further by leveraging the fact that a WebContent process
     12        is always associated with a single WebsiteDataStore / sessionID:
     13        - No need for a HashMap of sessionIDs
     14        - No need to even allocate the ResourceLoadObserver if the WebProcess is associated with an ephemeral session.
     15
     16        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
     17        (WebKit::NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated):
     18        * NetworkProcess/NetworkConnectionToWebProcess.h:
     19        * Sources.txt:
     20        * WebKit.xcodeproj/project.pbxproj:
     21        * WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp: Copied from Source/WebCore/loader/ResourceLoadObserver.cpp.
     22        (WebKit::is3xxRedirect):
     23        (WebKit::WebResourceLoadObserver::WebResourceLoadObserver):
     24        (WebKit::WebResourceLoadObserver::shouldLog const):
     25        (WebKit::WebResourceLoadObserver::requestStorageAccessUnderOpener):
     26        (WebKit::WebResourceLoadObserver::ensureResourceStatisticsForRegistrableDomain):
     27        (WebKit::WebResourceLoadObserver::scheduleNotificationIfNeeded):
     28        (WebKit::WebResourceLoadObserver::updateCentralStatisticsStore):
     29        (WebKit::WebResourceLoadObserver::statisticsForURL):
     30        (WebKit::WebResourceLoadObserver::takeStatistics):
     31        (WebKit::WebResourceLoadObserver::clearState):
     32        (WebKit::WebResourceLoadObserver::nonNullOwnerURL const):
     33        (WebKit::WebResourceLoadObserver::logFontLoad):
     34        (WebKit::WebResourceLoadObserver::logCanvasRead):
     35        (WebKit::WebResourceLoadObserver::logCanvasWriteOrMeasure):
     36        (WebKit::WebResourceLoadObserver::logNavigatorAPIAccessed):
     37        (WebKit::WebResourceLoadObserver::logScreenAPIAccessed):
     38        (WebKit::WebResourceLoadObserver::logSubresourceLoading):
     39        (WebKit::WebResourceLoadObserver::logWebSocketLoading):
     40        (WebKit::WebResourceLoadObserver::logUserInteractionWithReducedTimeResolution):
     41        * WebProcess/WebCoreSupport/WebResourceLoadObserver.h: Added.
     42        * WebProcess/WebProcess.cpp:
     43
    1442019-09-06  Jiewen Tan  <jiewen_tan@apple.com>
    245
  • trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp

    r249501 r249603  
    697697}
    698698
    699 void NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated(ResourceLoadObserver::PerSessionResourceLoadData&& statistics)
     699void NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated(WebResourceLoadObserver::PerSessionResourceLoadData&& statistics)
    700700{
    701701    for (auto& iter : statistics) {
  • trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h

    r249501 r249603  
    3535#include "NetworkResourceLoadMap.h"
    3636#include "WebPaymentCoordinatorProxy.h"
     37#include "WebResourceLoadObserver.h"
    3738#include <WebCore/FrameIdentifier.h>
    3839#include <WebCore/MessagePortChannelProvider.h>
     
    4243#include <WebCore/ProcessIdentifier.h>
    4344#include <WebCore/RegistrableDomain.h>
    44 #include <WebCore/ResourceLoadObserver.h>
    4545#include <wtf/RefCounted.h>
    4646
     
    236236
    237237    void logUserInteraction(PAL::SessionID, const RegistrableDomain&);
    238     void resourceLoadStatisticsUpdated(WebCore::ResourceLoadObserver::PerSessionResourceLoadData&&);
     238    void resourceLoadStatisticsUpdated(WebResourceLoadObserver::PerSessionResourceLoadData&&);
    239239    void hasStorageAccess(PAL::SessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
    240240    void requestStorageAccess(PAL::SessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebPageProxyIdentifier, CompletionHandler<void(WebCore::StorageAccessWasGranted, WebCore::StorageAccessPromptWasShown)>&&);
  • trunk/Source/WebKit/Sources.txt

    r249589 r249603  
    555555WebProcess/WebCoreSupport/WebPopupMenu.cpp
    556556WebProcess/WebCoreSupport/WebProgressTrackerClient.cpp
     557WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp
    557558WebProcess/WebCoreSupport/WebSearchPopupMenu.cpp
    558559WebProcess/WebCoreSupport/WebUserMediaClient.cpp
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r249589 r249603  
    911911                465F4E06230B2E95003CEDB7 /* StorageNamespaceIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 465F4E05230B2E7C003CEDB7 /* StorageNamespaceIdentifier.h */; };
    912912                466BC03C1FA266DA002FA9C1 /* WebSWContextManagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 466BC0391FA266C9002FA9C1 /* WebSWContextManagerConnection.h */; };
     913                4671FF1F23217EFF001B64C7 /* WebResourceLoadObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4671FF1D23217EFF001B64C7 /* WebResourceLoadObserver.h */; };
    913914                467E43E82243FF7D00B13924 /* WebProcessDataStoreParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 467E43E72243FF6D00B13924 /* WebProcessDataStoreParameters.h */; };
    914915                46A2B6091E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */; };
     
    32183219                466BC0391FA266C9002FA9C1 /* WebSWContextManagerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSWContextManagerConnection.h; sourceTree = "<group>"; };
    32193220                466BC03A1FA266C9002FA9C1 /* WebSWContextManagerConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebSWContextManagerConnection.messages.in; sourceTree = "<group>"; };
     3221                4671FF1D23217EFF001B64C7 /* WebResourceLoadObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebResourceLoadObserver.h; sourceTree = "<group>"; };
     3222                4671FF1E23217EFF001B64C7 /* WebResourceLoadObserver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebResourceLoadObserver.cpp; sourceTree = "<group>"; };
    32203223                467E43E72243FF6D00B13924 /* WebProcessDataStoreParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebProcessDataStoreParameters.h; sourceTree = "<group>"; };
    32213224                4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProvisionalPageProxy.h; sourceTree = "<group>"; };
     
    76267629                                1A1E093118861D3800D2DC49 /* WebProgressTrackerClient.cpp */,
    76277630                                1A1E093218861D3800D2DC49 /* WebProgressTrackerClient.h */,
     7631                                4671FF1E23217EFF001B64C7 /* WebResourceLoadObserver.cpp */,
     7632                                4671FF1D23217EFF001B64C7 /* WebResourceLoadObserver.h */,
    76287633                                D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */,
    76297634                                D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */,
     
    99949999                                37948404150C350600E52CE9 /* WebRenderLayer.h in Headers */,
    999510000                                3760881F150413E900FC82C7 /* WebRenderObject.h in Headers */,
     10001                                A5860E71230F67FC00461AAE /* WebResourceInterceptController.h in Headers */,
    999610002                                510AFFBA16542048001BA05E /* WebResourceLoader.h in Headers */,
    999710003                                51F060E01654317F00F3281B /* WebResourceLoaderMessages.h in Headers */,
     10004                                4671FF1F23217EFF001B64C7 /* WebResourceLoadObserver.h in Headers */,
    999810005                                7AFBD36321E50F39005DBACB /* WebResourceLoadStatisticsStore.h in Headers */,
    999910006                                413075B01DE85F580039EC69 /* WebRTCMonitor.h in Headers */,
     
    1021210219                                A54293A4195A43DA002782C7 /* WKInspectorNodeSearchGestureRecognizer.h in Headers */,
    1021310220                                6EE849C81368D9390038D481 /* WKInspectorPrivateMac.h in Headers */,
    10214                                 A5860E71230F67FC00461AAE /* WebResourceInterceptController.h in Headers */,
    1021510221                                994BADF41F7D781400B571E7 /* WKInspectorViewController.h in Headers */,
    1021610222                                A518B5D21FE1D55B00F9FA28 /* WKInspectorWKWebView.h in Headers */,
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp

    r249602 r249603  
    11/*
    2  * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  *
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
    14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
    17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    23  * THE POSSIBILITY OF SUCH DAMAGE.
    24  */
     2* Copyright (C) 2019 Apple Inc. All rights reserved.
     3*
     4* Redistribution and use in source and binary forms, with or without
     5* modification, are permitted provided that the following conditions
     6* are met:
     7* 1. Redistributions of source code must retain the above copyright
     8*    notice, this list of conditions and the following disclaimer.
     9* 2. Redistributions in binary form must reproduce the above copyright
     10*    notice, this list of conditions and the following disclaimer in the
     11*    documentation and/or other materials provided with the distribution.
     12*
     13* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24*/
    2525
    2626#include "config.h"
    27 #include "ResourceLoadObserver.h"
    28 
    29 #include "DeprecatedGlobalSettings.h"
    30 #include "Document.h"
    31 #include "Frame.h"
    32 #include "FrameLoader.h"
    33 #include "FrameLoaderClient.h"
    34 #include "HTMLFrameOwnerElement.h"
    35 #include "Logging.h"
    36 #include "Page.h"
    37 #include "RegistrableDomain.h"
    38 #include "ResourceLoadStatistics.h"
    39 #include "ResourceRequest.h"
    40 #include "ResourceResponse.h"
    41 #include "RuntimeEnabledFeatures.h"
    42 #include "ScriptExecutionContext.h"
    43 #include "SecurityOrigin.h"
    44 #include "Settings.h"
    45 #include <wtf/URL.h>
    46 
    47 namespace WebCore {
     27#include "WebResourceLoadObserver.h"
     28
     29#if ENABLE(RESOURCE_LOAD_STATISTICS)
     30
     31#include "NetworkConnectionToWebProcessMessages.h"
     32#include "NetworkProcessConnection.h"
     33#include "WebProcess.h"
     34#include <WebCore/DeprecatedGlobalSettings.h>
     35#include <WebCore/Frame.h>
     36#include <WebCore/FrameLoader.h>
     37#include <WebCore/HTMLFrameOwnerElement.h>
     38
     39namespace WebKit {
     40
     41using namespace WebCore;
    4842
    4943static const Seconds minimumNotificationInterval { 5_s };
    5044
    51 ResourceLoadObserver::ResourceLoadObserver()
    52     : m_notificationTimer(*this, &ResourceLoadObserver::updateCentralStatisticsStore)
    53 {
    54 }
    55 
    56 ResourceLoadObserver& ResourceLoadObserver::shared()
    57 {
    58     static NeverDestroyed<ResourceLoadObserver> resourceLoadObserver;
    59     return resourceLoadObserver;
    60 }
    61 
    62 void ResourceLoadObserver::setStatisticsUpdatedCallback(Function<void(PerSessionResourceLoadData&&)>&& notificationCallback)
    63 {
    64     ASSERT(!m_notificationCallback);
    65     m_notificationCallback = WTFMove(notificationCallback);
    66 }
    67 
    68 void ResourceLoadObserver::setRequestStorageAccessUnderOpenerCallback(Function<void(PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, const RegistrableDomain& openerDomain)>&& callback)
    69 {
    70     ASSERT(!m_requestStorageAccessUnderOpenerCallback);
    71     m_requestStorageAccessUnderOpenerCallback = WTFMove(callback);
    72 }
    73 
    74 void ResourceLoadObserver::setLogUserInteractionNotificationCallback(Function<void(PAL::SessionID, const RegistrableDomain&)>&& callback)
    75 {
    76     ASSERT(!m_logUserInteractionNotificationCallback);
    77     m_logUserInteractionNotificationCallback = WTFMove(callback);
    78 }
    79    
    80 static inline bool is3xxRedirect(const ResourceResponse& response)
     45static bool is3xxRedirect(const ResourceResponse& response)
    8146{
    8247    return response.httpStatusCode() >= 300 && response.httpStatusCode() <= 399;
    8348}
    8449
    85 bool ResourceLoadObserver::shouldLog(PAL::SessionID sessionID) const
    86 {
    87     return DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() && !sessionID.isEphemeral() && m_notificationCallback;
    88 }
    89 
    90 void ResourceLoadObserver::logSubresourceLoading(const Frame* frame, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
     50static bool shouldLogResourceLoadStatistics(PAL::SessionID sessionID)
     51{
     52    return DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() && !sessionID.isEphemeral();
     53}
     54
     55WebResourceLoadObserver::WebResourceLoadObserver()
     56    : m_notificationTimer(*this, &WebResourceLoadObserver::updateCentralStatisticsStore)
     57{
     58}
     59
     60void WebResourceLoadObserver::requestStorageAccessUnderOpener(PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, Document& openerDocument)
     61{
     62    auto openerUrl = openerDocument.url();
     63    RegistrableDomain openerDomain { openerUrl };
     64    if (domainInNeedOfStorageAccess != openerDomain
     65        && !openerDocument.hasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess)
     66        && !equalIgnoringASCIICase(openerUrl.string(), WTF::blankURL())) {
     67        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RequestStorageAccessUnderOpener(sessionID, domainInNeedOfStorageAccess, openerPageID, openerDomain), 0);
     68       
     69        // Remember user interaction-based requests since they don't need to be repeated.
     70        openerDocument.setHasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess);
     71    }
     72}
     73   
     74ResourceLoadStatistics& WebResourceLoadObserver::ensureResourceStatisticsForRegistrableDomain(PAL::SessionID sessionID, const RegistrableDomain& domain)
     75{
     76    auto addResult = m_perSessionResourceStatisticsMap.ensure(sessionID, [] {
     77        return makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();
     78    });
     79
     80    auto addDomainResult = addResult.iterator->value->ensure(domain, [&domain] {
     81        return ResourceLoadStatistics(domain);
     82    });
     83    return addDomainResult.iterator->value;
     84}
     85
     86void WebResourceLoadObserver::scheduleNotificationIfNeeded()
     87{
     88    if (m_perSessionResourceStatisticsMap.isEmpty()) {
     89        m_notificationTimer.stop();
     90        return;
     91    }
     92
     93    if (!m_notificationTimer.isActive())
     94        m_notificationTimer.startOneShot(minimumNotificationInterval);
     95}
     96
     97void WebResourceLoadObserver::updateCentralStatisticsStore()
     98{
     99    m_notificationTimer.stop();
     100    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResourceLoadStatisticsUpdated(takeStatistics()), 0);
     101}
     102
     103String WebResourceLoadObserver::statisticsForURL(PAL::SessionID sessionID, const URL& url)
     104{
     105    auto* resourceStatisticsByDomain = m_perSessionResourceStatisticsMap.get(sessionID);
     106    if (!resourceStatisticsByDomain)
     107        return emptyString();
     108
     109    auto iter = resourceStatisticsByDomain->find(RegistrableDomain { url });
     110    if (iter == resourceStatisticsByDomain->end())
     111        return emptyString();
     112
     113    return makeString("Statistics for ", url.host().toString(), ":\n", iter->value.toString());
     114}
     115
     116auto WebResourceLoadObserver::takeStatistics() -> PerSessionResourceLoadData
     117{
     118    PerSessionResourceLoadData perSessionStatistics;
     119
     120    for (auto& iter : m_perSessionResourceStatisticsMap) {
     121        Vector<ResourceLoadStatistics> statistics;
     122        statistics.reserveInitialCapacity(iter.value->size());
     123
     124        for (auto& statistic : iter.value->values())
     125            statistics.uncheckedAppend(WTFMove(statistic));
     126
     127        perSessionStatistics.append(std::make_pair(iter.key, WTFMove(statistics)));
     128    }
     129   
     130    m_perSessionResourceStatisticsMap.clear();
     131    return perSessionStatistics;
     132}
     133
     134void WebResourceLoadObserver::clearState()
     135{
     136    m_notificationTimer.stop();
     137    m_perSessionResourceStatisticsMap.clear();
     138    m_lastReportedUserInteractionMap.clear();
     139}
     140
     141void WebResourceLoadObserver::logFontLoad(const Document& document, const String& familyName, bool loadStatus)
     142{
     143#if ENABLE(WEB_API_STATISTICS)
     144    if (!shouldLogResourceLoadStatistics(document.sessionID()))
     145        return;
     146
     147    RegistrableDomain registrableDomain { document.url() };
     148    auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
     149    bool shouldCallNotificationCallback = false;
     150    if (!loadStatus) {
     151        if (statistics.fontsFailedToLoad.add(familyName).isNewEntry)
     152            shouldCallNotificationCallback = true;
     153    } else {
     154        if (statistics.fontsSuccessfullyLoaded.add(familyName).isNewEntry)
     155            shouldCallNotificationCallback = true;
     156    }
     157    RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
     158    if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
     159        shouldCallNotificationCallback = true;
     160    if (shouldCallNotificationCallback)
     161        scheduleNotificationIfNeeded();
     162#else
     163    UNUSED_PARAM(document);
     164    UNUSED_PARAM(familyName);
     165    UNUSED_PARAM(loadStatus);
     166#endif
     167}
     168   
     169void WebResourceLoadObserver::logCanvasRead(const Document& document)
     170{
     171#if ENABLE(WEB_API_STATISTICS)
     172    if (!shouldLogResourceLoadStatistics(document.sessionID()))
     173        return;
     174
     175    RegistrableDomain registrableDomain { document.url() };
     176    auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID(), registrableDomain);
     177    RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
     178    statistics.canvasActivityRecord.wasDataRead = true;
     179    if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
     180        scheduleNotificationIfNeeded();
     181#else
     182    UNUSED_PARAM(document);
     183#endif
     184}
     185
     186void WebResourceLoadObserver::logCanvasWriteOrMeasure(const Document& document, const String& textWritten)
     187{
     188#if ENABLE(WEB_API_STATISTICS)
     189    if (!shouldLogResourceLoadStatistics(document.sessionID()))
     190        return;
     191
     192    RegistrableDomain registrableDomain { document.url() };
     193    auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
     194    bool shouldCallNotificationCallback = false;
     195    RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
     196    if (statistics.canvasActivityRecord.recordWrittenOrMeasuredText(textWritten))
     197        shouldCallNotificationCallback = true;
     198    if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
     199        shouldCallNotificationCallback = true;
     200    if (shouldCallNotificationCallback)
     201        scheduleNotificationIfNeeded();
     202#else
     203    UNUSED_PARAM(document);
     204    UNUSED_PARAM(textWritten);
     205#endif
     206}
     207   
     208void WebResourceLoadObserver::logNavigatorAPIAccessed(const Document& document, const ResourceLoadStatistics::NavigatorAPI functionName)
     209{
     210#if ENABLE(WEB_API_STATISTICS)
     211    if (!shouldLogResourceLoadStatistics(document.sessionID()))
     212        return;
     213
     214    RegistrableDomain registrableDomain { document.url() };
     215    auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
     216    bool shouldCallNotificationCallback = false;
     217    if (!statistics.navigatorFunctionsAccessed.contains(functionName)) {
     218        statistics.navigatorFunctionsAccessed.add(functionName);
     219        shouldCallNotificationCallback = true;
     220    }
     221    RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
     222    if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
     223        shouldCallNotificationCallback = true;
     224    if (shouldCallNotificationCallback)
     225        scheduleNotificationIfNeeded();
     226#else
     227    UNUSED_PARAM(document);
     228    UNUSED_PARAM(functionName);
     229#endif
     230}
     231   
     232void WebResourceLoadObserver::logScreenAPIAccessed(const Document& document, const ResourceLoadStatistics::ScreenAPI functionName)
     233{
     234#if ENABLE(WEB_API_STATISTICS)
     235    if (!shouldLogResourceLoadStatistics(document.sessionID()))
     236        return;
     237
     238    RegistrableDomain registrableDomain { document.url() };
     239    auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
     240    bool shouldCallNotificationCallback = false;
     241    if (!statistics.screenFunctionsAccessed.contains(functionName)) {
     242        statistics.screenFunctionsAccessed.add(functionName);
     243        shouldCallNotificationCallback = true;
     244    }
     245    RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
     246    if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
     247        shouldCallNotificationCallback = true;
     248    if (shouldCallNotificationCallback)
     249        scheduleNotificationIfNeeded();
     250#else
     251    UNUSED_PARAM(document);
     252    UNUSED_PARAM(functionName);
     253#endif
     254}
     255
     256void WebResourceLoadObserver::logSubresourceLoading(const Frame* frame, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
    91257{
    92258    ASSERT(frame->page());
     
    96262
    97263    auto* page = frame->page();
    98     if (!page || !shouldLog(page->sessionID()))
     264    if (!page || !shouldLogResourceLoadStatistics(page->sessionID()))
    99265        return;
    100266
     
    136302}
    137303
    138 void ResourceLoadObserver::logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, PAL::SessionID sessionID)
    139 {
    140     if (!shouldLog(sessionID))
     304void WebResourceLoadObserver::logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, PAL::SessionID sessionID)
     305{
     306    if (!shouldLogResourceLoadStatistics(sessionID))
    141307        return;
    142308
     
    162328}
    163329
    164 void ResourceLoadObserver::logUserInteractionWithReducedTimeResolution(const Document& document)
    165 {
    166     if (!document.sessionID().isValid() || !shouldLog(document.sessionID()))
     330void WebResourceLoadObserver::logUserInteractionWithReducedTimeResolution(const Document& document)
     331{
     332    if (!document.sessionID().isValid() || !shouldLogResourceLoadStatistics(document.sessionID()))
    167333        return;
    168334
     
    184350    statistics.mostRecentUserInteractionTime = newTime;
    185351
    186 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    187352    if (auto* frame = document.frame()) {
    188353        if (auto* opener = frame->loader().opener()) {
     
    198363    // We notify right away in case of a user interaction instead of waiting the usual 5 seconds because we want
    199364    // to update cookie blocking state as quickly as possible.
    200     m_logUserInteractionNotificationCallback(document.sessionID(), topFrameDomain);
    201 #endif
    202 
    203 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
    204     if (shouldLogUserInteraction()) {
     365    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::LogUserInteraction(document.sessionID(), topFrameDomain), 0);
     366
     367#if !RELEASE_LOG_DISABLED
     368    if (m_shouldLogUserInteraction) {
    205369        auto counter = ++m_loggingCounter;
    206370#define LOCAL_LOG(str, ...) \
     
    223387}
    224388
    225 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    226 void ResourceLoadObserver::requestStorageAccessUnderOpener(PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, Document& openerDocument)
    227 {
    228     auto openerUrl = openerDocument.url();
    229     RegistrableDomain openerDomain { openerUrl };
    230     if (domainInNeedOfStorageAccess != openerDomain
    231         && !openerDocument.hasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess)
    232         && !equalIgnoringASCIICase(openerUrl.string(), WTF::blankURL())) {
    233         m_requestStorageAccessUnderOpenerCallback(sessionID, domainInNeedOfStorageAccess, openerPageID, openerDomain);
    234         // Remember user interaction-based requests since they don't need to be repeated.
    235         openerDocument.setHasRequestedPageSpecificStorageAccessWithUserInteraction(domainInNeedOfStorageAccess);
    236     }
    237 }
    238 #endif
    239 
    240 void ResourceLoadObserver::logFontLoad(const Document& document, const String& familyName, bool loadStatus)
    241 {
    242 #if ENABLE(WEB_API_STATISTICS)
    243     if (!shouldLog(document.sessionID()))
    244         return;
    245     RegistrableDomain registrableDomain { document.url() };
    246     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    247     bool shouldCallNotificationCallback = false;
    248     if (!loadStatus) {
    249         if (statistics.fontsFailedToLoad.add(familyName).isNewEntry)
    250             shouldCallNotificationCallback = true;
    251     } else {
    252         if (statistics.fontsSuccessfullyLoaded.add(familyName).isNewEntry)
    253             shouldCallNotificationCallback = true;
    254     }
    255     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    256     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    257         shouldCallNotificationCallback = true;
    258     if (shouldCallNotificationCallback)
    259         scheduleNotificationIfNeeded();
    260 #else
    261     UNUSED_PARAM(document);
    262     UNUSED_PARAM(familyName);
    263     UNUSED_PARAM(loadStatus);
    264 #endif
    265 }
    266    
    267 void ResourceLoadObserver::logCanvasRead(const Document& document)
    268 {
    269 #if ENABLE(WEB_API_STATISTICS)
    270     if (!shouldLog(document.sessionID()))
    271         return;
    272     RegistrableDomain registrableDomain { document.url() };
    273     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID(), registrableDomain);
    274     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    275     statistics.canvasActivityRecord.wasDataRead = true;
    276     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    277         scheduleNotificationIfNeeded();
    278 #else
    279     UNUSED_PARAM(document);
    280 #endif
    281 }
    282 
    283 void ResourceLoadObserver::logCanvasWriteOrMeasure(const Document& document, const String& textWritten)
    284 {
    285 #if ENABLE(WEB_API_STATISTICS)
    286     if (!shouldLog(document.sessionID()))
    287         return;
    288     RegistrableDomain registrableDomain { document.url() };
    289     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    290     bool shouldCallNotificationCallback = false;
    291     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    292     if (statistics.canvasActivityRecord.recordWrittenOrMeasuredText(textWritten))
    293         shouldCallNotificationCallback = true;
    294     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    295         shouldCallNotificationCallback = true;
    296     if (shouldCallNotificationCallback)
    297         scheduleNotificationIfNeeded();
    298 #else
    299     UNUSED_PARAM(document);
    300     UNUSED_PARAM(textWritten);
    301 #endif
    302 }
    303    
    304 void ResourceLoadObserver::logNavigatorAPIAccessed(const Document& document, const ResourceLoadStatistics::NavigatorAPI functionName)
    305 {
    306 #if ENABLE(WEB_API_STATISTICS)
    307     if (!shouldLog(document.sessionID()))
    308         return;
    309     RegistrableDomain registrableDomain { document.url() };
    310     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    311     bool shouldCallNotificationCallback = false;
    312     if (!statistics.navigatorFunctionsAccessed.contains(functionName)) {
    313         statistics.navigatorFunctionsAccessed.add(functionName);
    314         shouldCallNotificationCallback = true;
    315     }
    316     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    317     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    318         shouldCallNotificationCallback = true;
    319     if (shouldCallNotificationCallback)
    320         scheduleNotificationIfNeeded();
    321 #else
    322     UNUSED_PARAM(document);
    323     UNUSED_PARAM(functionName);
    324 #endif
    325 }
    326    
    327 void ResourceLoadObserver::logScreenAPIAccessed(const Document& document, const ResourceLoadStatistics::ScreenAPI functionName)
    328 {
    329 #if ENABLE(WEB_API_STATISTICS)
    330     if (!shouldLog(document.sessionID()))
    331         return;
    332     RegistrableDomain registrableDomain { document.url() };
    333     auto& statistics = ensureResourceStatisticsForRegistrableDomain(document.sessionID, registrableDomain);
    334     bool shouldCallNotificationCallback = false;
    335     if (!statistics.screenFunctionsAccessed.contains(functionName)) {
    336         statistics.screenFunctionsAccessed.add(functionName);
    337         shouldCallNotificationCallback = true;
    338     }
    339     RegistrableDomain mainFrameRegistrableDomain { document.topDocument().url() };
    340     if (statistics.topFrameRegistrableDomainsWhichAccessedWebAPIs.add(mainFrameRegistrableDomain.string()).isNewEntry)
    341         shouldCallNotificationCallback = true;
    342     if (shouldCallNotificationCallback)
    343         scheduleNotificationIfNeeded();
    344 #else
    345     UNUSED_PARAM(document);
    346     UNUSED_PARAM(functionName);
    347 #endif
    348 }
    349    
    350 ResourceLoadStatistics& ResourceLoadObserver::ensureResourceStatisticsForRegistrableDomain(PAL::SessionID sessionID, const RegistrableDomain& domain)
    351 {
    352     auto addResult = m_perSessionResourceStatisticsMap.ensure(sessionID, [] {
    353         return makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();
    354     });
    355 
    356     auto addDomainResult = addResult.iterator->value->ensure(domain, [&domain] {
    357         return ResourceLoadStatistics(domain);
    358     });
    359     return addDomainResult.iterator->value;
    360 }
    361 
    362 void ResourceLoadObserver::scheduleNotificationIfNeeded()
    363 {
    364     ASSERT(m_notificationCallback);
    365     if (m_perSessionResourceStatisticsMap.isEmpty()) {
    366         m_notificationTimer.stop();
    367         return;
    368     }
    369 
    370     if (!m_notificationTimer.isActive())
    371         m_notificationTimer.startOneShot(minimumNotificationInterval);
    372 }
    373 
    374 void ResourceLoadObserver::updateCentralStatisticsStore()
    375 {
    376     ASSERT(m_notificationCallback);
    377     m_notificationTimer.stop();
    378     m_notificationCallback(takeStatistics());
    379 }
    380 
    381 String ResourceLoadObserver::statisticsForURL(PAL::SessionID sessionID, const URL& url)
    382 {
    383     auto* resourceStatisticsByDomain = m_perSessionResourceStatisticsMap.get(sessionID);
    384     if (!resourceStatisticsByDomain)
    385         return emptyString();
    386 
    387     auto iter = resourceStatisticsByDomain->find(RegistrableDomain { url });
    388     if (iter == resourceStatisticsByDomain->end())
    389         return emptyString();
    390 
    391     return makeString("Statistics for ", url.host().toString(), ":\n", iter->value.toString());
    392 }
    393 
    394 auto ResourceLoadObserver::takeStatistics() -> PerSessionResourceLoadData
    395 {
    396     PerSessionResourceLoadData perSessionStatistics;
    397 
    398     for (auto& iter : m_perSessionResourceStatisticsMap) {
    399         Vector<ResourceLoadStatistics> statistics;
    400         statistics.reserveInitialCapacity(iter.value->size());
    401 
    402         for (auto& statistic : iter.value->values())
    403             statistics.uncheckedAppend(WTFMove(statistic));
    404 
    405         perSessionStatistics.append(std::make_pair(iter.key, WTFMove(statistics)));
    406     }
    407    
    408     m_perSessionResourceStatisticsMap.clear();
    409     return perSessionStatistics;
    410 }
    411 
    412 void ResourceLoadObserver::clearState()
    413 {
    414     m_notificationTimer.stop();
    415     m_perSessionResourceStatisticsMap.clear();
    416     m_lastReportedUserInteractionMap.clear();
    417 }
    418 
    419 URL ResourceLoadObserver::nonNullOwnerURL(const Document& document) const
    420 {
    421     auto url = document.url();
    422     auto* frame = document.frame();
    423     auto host = document.url().host();
    424 
    425     while ((host.isNull() || host.isEmpty()) && frame && !frame->isMainFrame()) {
    426         auto* ownerElement = frame->ownerElement();
    427 
    428         ASSERT(ownerElement != nullptr);
    429        
    430         auto& doc = ownerElement->document();
    431         frame = doc.frame();
    432         url = doc.url();
    433         host = url.host();
    434     }
    435 
    436     return url;
    437 }
    438 
    439 } // namespace WebCore
     389} // namespace WebKit
     390
     391#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
  • trunk/Source/WebKit/WebProcess/WebProcess.cpp

    r249501 r249603  
    6868#include "WebProcessPoolMessages.h"
    6969#include "WebProcessProxyMessages.h"
     70#include "WebResourceLoadObserver.h"
    7071#include "WebSWContextManagerConnection.h"
    7172#include "WebSWContextManagerConnectionMessages.h"
     
    111112#include <WebCore/ProcessWarming.h>
    112113#include <WebCore/RegistrableDomain.h>
    113 #include <WebCore/ResourceLoadObserver.h>
    114114#include <WebCore/ResourceLoadStatistics.h>
    115115#include <WebCore/RuntimeApplicationChecks.h>
     
    218218
    219219#if ENABLE(RESOURCE_LOAD_STATISTICS)
    220     ResourceLoadObserver::shared().setStatisticsUpdatedCallback([this] (auto&& statistics) {
    221         ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
    222     });
    223 
    224     ResourceLoadObserver::shared().setRequestStorageAccessUnderOpenerCallback([this] (PAL::SessionID sessionID, const RegistrableDomain& domainInNeedOfStorageAccess, PageIdentifier openerPageID, const RegistrableDomain& openerDomain) {
    225         ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RequestStorageAccessUnderOpener(sessionID, domainInNeedOfStorageAccess, openerPageID, openerDomain), 0);
    226     });
    227    
    228     ResourceLoadObserver::shared().setLogUserInteractionNotificationCallback([this] (PAL::SessionID sessionID, const RegistrableDomain& domain) {    ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::LogUserInteraction(sessionID, domain), 0);
    229     });
     220    ResourceLoadObserver::setShared(*new WebResourceLoadObserver);
    230221#endif
    231222   
     
    16561647void WebProcess::clearResourceLoadStatistics()
    16571648{
     1649#if ENABLE(RESOURCE_LOAD_STATISTICS)
    16581650    ResourceLoadObserver::shared().clearState();
     1651#endif
    16591652}
    16601653
Note: See TracChangeset for help on using the changeset viewer.