Title: [281901] branches/safari-612-branch
Revision
281901
Author
repst...@apple.com
Date
2021-09-01 18:05:18 -0700 (Wed, 01 Sep 2021)

Log Message

Cherry-pick r281860. rdar://problem/82651913

    PerformanceNavigationTiming should be instantiated before scripts run then updated when response finishes
    https://bugs.webkit.org/show_bug.cgi?id=229751

    Patch by Alex Christensen <achristen...@webkit.org> on 2021-09-01
    Reviewed by Chris Dumez.

    LayoutTests/imported/w3c:

    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt: Added.
    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html: Added.
    * web-platform-tests/navigation-timing/resources/respond_slowly.py: Added.
    (main):

    Source/WebCore:

    Test: imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html

    I noticed some server timing tests were calling performance.getEntriesByType('navigation')[0] before the document loaded, and in WebKit
    it would return undefined and in Chrome and Firefox it would return a PerformanceNavigationTiming object.  The solution is to make the object
    available earlier.  But what about responseEnd and duration before the main resource is finished responding?  It turns out in Chrome and now
    WebKit they are both 0 until they are filled in.  I added a WPT test to verify this behavior.

    * loader/DocumentLoader.cpp:
    (WebCore::DocumentLoader::notifyFinished):
    (WebCore::DocumentLoader::commitData):
    * loader/ResourceTiming.h:
    (WebCore::ResourceTiming::networkLoadMetrics):
    * page/Performance.cpp:
    (WebCore::Performance::addNavigationTiming):
    (WebCore::Performance::navigationFinished):
    * page/Performance.h:
    * page/PerformanceNavigationTiming.cpp:
    (WebCore::PerformanceNavigationTiming::navigationFinished):
    * page/PerformanceNavigationTiming.h:
    * page/PerformanceResourceTiming.cpp:
    (WebCore::PerformanceResourceTiming::responseEnd const):
    * page/PerformanceResourceTiming.h:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@281860 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Added Paths

Diff

Modified: branches/safari-612-branch/LayoutTests/imported/w3c/ChangeLog (281900 => 281901)


--- branches/safari-612-branch/LayoutTests/imported/w3c/ChangeLog	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/LayoutTests/imported/w3c/ChangeLog	2021-09-02 01:05:18 UTC (rev 281901)
@@ -1,5 +1,61 @@
 2021-09-01  Russell Epstein  <repst...@apple.com>
 
+        Cherry-pick r281860. rdar://problem/82651913
+
+    PerformanceNavigationTiming should be instantiated before scripts run then updated when response finishes
+    https://bugs.webkit.org/show_bug.cgi?id=229751
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2021-09-01
+    Reviewed by Chris Dumez.
+    
+    LayoutTests/imported/w3c:
+    
+    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt: Added.
+    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html: Added.
+    * web-platform-tests/navigation-timing/resources/respond_slowly.py: Added.
+    (main):
+    
+    Source/WebCore:
+    
+    Test: imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html
+    
+    I noticed some server timing tests were calling performance.getEntriesByType('navigation')[0] before the document loaded, and in WebKit
+    it would return undefined and in Chrome and Firefox it would return a PerformanceNavigationTiming object.  The solution is to make the object
+    available earlier.  But what about responseEnd and duration before the main resource is finished responding?  It turns out in Chrome and now
+    WebKit they are both 0 until they are filled in.  I added a WPT test to verify this behavior.
+    
+    * loader/DocumentLoader.cpp:
+    (WebCore::DocumentLoader::notifyFinished):
+    (WebCore::DocumentLoader::commitData):
+    * loader/ResourceTiming.h:
+    (WebCore::ResourceTiming::networkLoadMetrics):
+    * page/Performance.cpp:
+    (WebCore::Performance::addNavigationTiming):
+    (WebCore::Performance::navigationFinished):
+    * page/Performance.h:
+    * page/PerformanceNavigationTiming.cpp:
+    (WebCore::PerformanceNavigationTiming::navigationFinished):
+    * page/PerformanceNavigationTiming.h:
+    * page/PerformanceResourceTiming.cpp:
+    (WebCore::PerformanceResourceTiming::responseEnd const):
+    * page/PerformanceResourceTiming.h:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@281860 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-01  Alex Christensen  <achristen...@webkit.org>
+
+            PerformanceNavigationTiming should be instantiated before scripts run then updated when response finishes
+            https://bugs.webkit.org/show_bug.cgi?id=229751
+
+            Reviewed by Chris Dumez.
+
+            * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt: Added.
+            * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html: Added.
+            * web-platform-tests/navigation-timing/resources/respond_slowly.py: Added.
+            (main):
+
+2021-09-01  Russell Epstein  <repst...@apple.com>
+
         Cherry-pick r281662. rdar://problem/82651998
 
     REGRESSION(r275754): Using MarkOnlyThis to make the preferred width dirty introduces unexpected state

Added: branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt (0 => 281901)


--- branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt	                        (rev 0)
+++ branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt	2021-09-02 01:05:18 UTC (rev 281901)
@@ -0,0 +1,4 @@
+
+
+PASS Check that performance.getEntriesByType('navigation')[0].responseEnd has reasonable values before and after the load has finished
+

Added: branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html (0 => 281901)


--- branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html	                        (rev 0)
+++ branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html	2021-09-02 01:05:18 UTC (rev 281901)
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<script src=""
+<script src=""
+<iframe src=""
+<body>
+<script>
+async_test(function(t) {
+  window.addEventListener('message', t.step_func_done(function(event) {
+    let originalResponseEnd = event.data[0];
+    let originalDuration = event.data[1];
+    let responseEndDuringLoadEvent = event.data[2];
+    let durationDuringLoadEvent = event.data[3];
+    let responseEndAfterLoadEvent = event.data[4];
+    let durationAfterLoadEvent = event.data[5];
+    assert_equals(originalResponseEnd, 0, "PerformanceNavigationTiming.responseEnd == 0 before load event");
+    assert_equals(originalDuration, 0, "PerformanceNavigationTiming.duration is 0 before load event");
+    assert_greater_than(responseEndDuringLoadEvent, 500, "PerformanceNavigationTiming.responseEnd is reasonable during load event");
+    assert_equals(durationDuringLoadEvent, 0, "PerformanceNavigationTiming.duration is 0 during load event");
+    assert_greater_than(responseEndAfterLoadEvent, 500, "PerformanceNavigationTiming.responseEnd is reasonable after load event");
+    assert_greater_than(durationAfterLoadEvent, 500, "PerformanceNavigationTiming.duration is reasonable after load event");
+  }));
+}, "Check that performance.getEntriesByType('navigation')[0].responseEnd has reasonable values before and after the load has finished");
+</script>
+</body>
+</html>

Added: branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/resources/respond_slowly.py (0 => 281901)


--- branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/resources/respond_slowly.py	                        (rev 0)
+++ branches/safari-612-branch/LayoutTests/imported/w3c/web-platform-tests/navigation-timing/resources/respond_slowly.py	2021-09-02 01:05:18 UTC (rev 281901)
@@ -0,0 +1,31 @@
+import time
+
+
+def main(request, response):
+    head = b"""<script>
+    let navBeforeLoadFinished = performance.getEntriesByType('navigation')[0];
+    let originalResponseEnd = navBeforeLoadFinished.responseEnd;
+    let originalDuration = navBeforeLoadFinished.duration;
+    function checkResponseEnd() {
+        let navDuringLoadEvent = performance.getEntriesByType('navigation')[0];
+        let responseEndDuringLoadEvent = navDuringLoadEvent.responseEnd;
+        let durationDuringLoadEvent = navDuringLoadEvent.duration;
+        setTimeout(function() {
+            let navAfterLoadEvent = performance.getEntriesByType('navigation')[0];
+            parent.postMessage([
+                originalResponseEnd,
+                originalDuration,
+                responseEndDuringLoadEvent,
+                durationDuringLoadEvent,
+                navAfterLoadEvent.responseEnd,
+                navAfterLoadEvent.duration], '*');
+        }, 0);
+    }
+    </script><body _onload_='checkResponseEnd()'>"""
+    response.headers.set(b"Content-Length", str(len(head) + 10000))
+    response.headers.set(b"Content-Type", b"text/html")
+    response.write_status_headers()
+    response.writer.write_content(head)
+    for i in range(1000):
+        response.writer.write_content(b"1234567890")
+        time.sleep(0.001)

Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/ChangeLog	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog	2021-09-02 01:05:18 UTC (rev 281901)
@@ -1,5 +1,79 @@
 2021-09-01  Russell Epstein  <repst...@apple.com>
 
+        Cherry-pick r281860. rdar://problem/82651913
+
+    PerformanceNavigationTiming should be instantiated before scripts run then updated when response finishes
+    https://bugs.webkit.org/show_bug.cgi?id=229751
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2021-09-01
+    Reviewed by Chris Dumez.
+    
+    LayoutTests/imported/w3c:
+    
+    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event-expected.txt: Added.
+    * web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html: Added.
+    * web-platform-tests/navigation-timing/resources/respond_slowly.py: Added.
+    (main):
+    
+    Source/WebCore:
+    
+    Test: imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html
+    
+    I noticed some server timing tests were calling performance.getEntriesByType('navigation')[0] before the document loaded, and in WebKit
+    it would return undefined and in Chrome and Firefox it would return a PerformanceNavigationTiming object.  The solution is to make the object
+    available earlier.  But what about responseEnd and duration before the main resource is finished responding?  It turns out in Chrome and now
+    WebKit they are both 0 until they are filled in.  I added a WPT test to verify this behavior.
+    
+    * loader/DocumentLoader.cpp:
+    (WebCore::DocumentLoader::notifyFinished):
+    (WebCore::DocumentLoader::commitData):
+    * loader/ResourceTiming.h:
+    (WebCore::ResourceTiming::networkLoadMetrics):
+    * page/Performance.cpp:
+    (WebCore::Performance::addNavigationTiming):
+    (WebCore::Performance::navigationFinished):
+    * page/Performance.h:
+    * page/PerformanceNavigationTiming.cpp:
+    (WebCore::PerformanceNavigationTiming::navigationFinished):
+    * page/PerformanceNavigationTiming.h:
+    * page/PerformanceResourceTiming.cpp:
+    (WebCore::PerformanceResourceTiming::responseEnd const):
+    * page/PerformanceResourceTiming.h:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@281860 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-01  Alex Christensen  <achristen...@webkit.org>
+
+            PerformanceNavigationTiming should be instantiated before scripts run then updated when response finishes
+            https://bugs.webkit.org/show_bug.cgi?id=229751
+
+            Reviewed by Chris Dumez.
+
+            Test: imported/w3c/web-platform-tests/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html
+
+            I noticed some server timing tests were calling performance.getEntriesByType('navigation')[0] before the document loaded, and in WebKit
+            it would return undefined and in Chrome and Firefox it would return a PerformanceNavigationTiming object.  The solution is to make the object
+            available earlier.  But what about responseEnd and duration before the main resource is finished responding?  It turns out in Chrome and now
+            WebKit they are both 0 until they are filled in.  I added a WPT test to verify this behavior.
+
+            * loader/DocumentLoader.cpp:
+            (WebCore::DocumentLoader::notifyFinished):
+            (WebCore::DocumentLoader::commitData):
+            * loader/ResourceTiming.h:
+            (WebCore::ResourceTiming::networkLoadMetrics):
+            * page/Performance.cpp:
+            (WebCore::Performance::addNavigationTiming):
+            (WebCore::Performance::navigationFinished):
+            * page/Performance.h:
+            * page/PerformanceNavigationTiming.cpp:
+            (WebCore::PerformanceNavigationTiming::navigationFinished):
+            * page/PerformanceNavigationTiming.h:
+            * page/PerformanceResourceTiming.cpp:
+            (WebCore::PerformanceResourceTiming::responseEnd const):
+            * page/PerformanceResourceTiming.h:
+
+2021-09-01  Russell Epstein  <repst...@apple.com>
+
         Cherry-pick r281848. rdar://problem/82652449
 
     Regression(r272607) Removal of alert()/confirm() in third-party iframes breaks Salesforce

Modified: branches/safari-612-branch/Source/WebCore/loader/DocumentLoader.cpp (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/loader/DocumentLoader.cpp	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/loader/DocumentLoader.cpp	2021-09-02 01:05:18 UTC (rev 281901)
@@ -424,7 +424,7 @@
     if (auto document = makeRefPtr(this->document())) {
         if (auto domWindow = makeRefPtr(document->domWindow())) {
             if (document->settings().performanceNavigationTimingAPIEnabled())
-                domWindow->performance().addNavigationTiming(*this, *document, resource, timing(), metrics);
+                domWindow->performance().navigationFinished(metrics);
         }
     }
 
@@ -1318,9 +1318,15 @@
         if (!isLoading())
             return;
 
-        if (auto* window = document.domWindow())
+        if (auto* window = document.domWindow()) {
             window->prewarmLocalStorageIfNecessary();
 
+            if (document.settings().performanceNavigationTimingAPIEnabled() && m_mainResource) {
+                auto* metrics = m_response.deprecatedNetworkLoadMetricsOrNull();
+                window->performance().addNavigationTiming(*this, document, *m_mainResource, timing(), metrics ? *metrics : NetworkLoadMetrics { });
+            }
+        }
+
         bool userChosen;
         String encoding;
         if (overrideEncoding().isNull()) {

Modified: branches/safari-612-branch/Source/WebCore/loader/ResourceTiming.h (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/loader/ResourceTiming.h	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/loader/ResourceTiming.h	2021-09-02 01:05:18 UTC (rev 281901)
@@ -49,6 +49,7 @@
     const String& initiator() const { return m_initiator; }
     const ResourceLoadTiming& resourceLoadTiming() const { return m_resourceLoadTiming; }
     const NetworkLoadMetrics& networkLoadMetrics() const { return m_networkLoadMetrics; }
+    NetworkLoadMetrics& networkLoadMetrics() { return m_networkLoadMetrics; }
     Vector<Ref<PerformanceServerTiming>> populateServerTiming() const;
     ResourceTiming isolatedCopy() const;
 

Modified: branches/safari-612-branch/Source/WebCore/page/Performance.cpp (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/Performance.cpp	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/Performance.cpp	2021-09-02 01:05:18 UTC (rev 281901)
@@ -241,6 +241,16 @@
 {
     ASSERT(document.settings().performanceNavigationTimingAPIEnabled());
     m_navigationTiming = PerformanceNavigationTiming::create(m_timeOrigin, resource, timing, metrics, document.eventTiming(), document.securityOrigin(), documentLoader.triggeringAction().type());
+}
+
+void Performance::navigationFinished(const NetworkLoadMetrics& metrics)
+{
+    if (!m_navigationTiming) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    m_navigationTiming->navigationFinished(metrics);
+
     queueEntry(*m_navigationTiming);
 }
 

Modified: branches/safari-612-branch/Source/WebCore/page/Performance.h (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/Performance.h	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/Performance.h	2021-09-02 01:05:18 UTC (rev 281901)
@@ -97,6 +97,7 @@
     void clearMeasures(const String& measureName);
 
     void addNavigationTiming(DocumentLoader&, Document&, CachedResource&, const DocumentLoadTiming&, const NetworkLoadMetrics&);
+    void navigationFinished(const NetworkLoadMetrics&);
     void addResourceTiming(ResourceTiming&&);
 
     void reportFirstContentfulPaint();

Modified: branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.cpp (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.cpp	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.cpp	2021-09-02 01:05:18 UTC (rev 281901)
@@ -141,4 +141,12 @@
     return loadEventEnd() - startTime();
 }
 
+void PerformanceNavigationTiming::navigationFinished(const NetworkLoadMetrics& metrics)
+{
+    m_documentLoadTiming.markEndTime();
+
+    ASSERT(!m_resourceTiming.networkLoadMetrics().responseEnd);
+    m_resourceTiming.networkLoadMetrics() = metrics;
+}
+
 } // namespace WebCore

Modified: branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.h (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.h	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/PerformanceNavigationTiming.h	2021-09-02 01:05:18 UTC (rev 281901)
@@ -70,6 +70,7 @@
 
     DocumentEventTiming& documentEventTiming() { return m_documentEventTiming; }
     DocumentLoadTiming& documentLoadTiming() { return m_documentLoadTiming; }
+    void navigationFinished(const NetworkLoadMetrics&);
 
 private:
     PerformanceNavigationTiming(MonotonicTime timeOrigin, CachedResource&, const DocumentLoadTiming&, const NetworkLoadMetrics&, const DocumentEventTiming&, const SecurityOrigin&, WebCore::NavigationType);

Modified: branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.cpp (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.cpp	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.cpp	2021-09-02 01:05:18 UTC (rev 281901)
@@ -221,8 +221,11 @@
 
 double PerformanceResourceTiming::responseEnd() const
 {
-    // responseEnd is a required property.
-    ASSERT(m_resourceTiming.networkLoadMetrics().isComplete() || m_resourceTiming.resourceLoadTiming().endTime());
+    // responseEnd is a required property, but PerformanceNavigationTiming
+    // can be queried before the document load is complete
+    ASSERT(m_resourceTiming.networkLoadMetrics().isComplete()
+        || m_resourceTiming.resourceLoadTiming().endTime()
+        || performanceEntryType() == Type::Navigation);
 
     if (m_resourceTiming.networkLoadMetrics().isComplete()) {
         if (m_resourceTiming.networkLoadMetrics().responseEnd)

Modified: branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.h (281900 => 281901)


--- branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.h	2021-09-02 01:05:13 UTC (rev 281900)
+++ branches/safari-612-branch/Source/WebCore/page/PerformanceResourceTiming.h	2021-09-02 01:05:18 UTC (rev 281901)
@@ -75,7 +75,7 @@
     ~PerformanceResourceTiming();
 
     MonotonicTime m_timeOrigin;
-    const ResourceTiming m_resourceTiming;
+    ResourceTiming m_resourceTiming;
     Vector<Ref<PerformanceServerTiming>> m_serverTiming;
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to