Title: [220946] trunk
Revision
220946
Author
[email protected]
Date
2017-08-18 17:27:59 -0700 (Fri, 18 Aug 2017)

Log Message

[Beacon] Improve error reporting
https://bugs.webkit.org/show_bug.cgi?id=175723

Reviewed by Darin Adler.

Source/WebCore:

Have Ping loads such as beacons report errors via their completion handler.
The Beacon API is using this error to log a console message when beacon loads
fail, provided that the page is still alive.

Test: http/wpt/beacon/beacon-async-error-logging.html

* Modules/beacon/NavigatorBeacon.cpp:
(WebCore::NavigatorBeacon::NavigatorBeacon):
(WebCore::NavigatorBeacon::~NavigatorBeacon):
(WebCore::NavigatorBeacon::from):
(WebCore::NavigatorBeacon::supplementName):
(WebCore::NavigatorBeacon::notifyFinished):
(WebCore::NavigatorBeacon::logError):
(WebCore::NavigatorBeacon::sendBeacon):
* Modules/beacon/NavigatorBeacon.h:
* loader/LoaderStrategy.h:
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::load):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::requestBeaconResource):
* loader/cache/CachedResourceLoader.h:
* platform/network/PingHandle.h:

Source/WebKit:

Have Ping loads such as beacons report errors via their completion handler.
The Beacon API is using this error to log a console message when beacon loads
fail, provided that the page is still alive.

* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::loadPing):
(WebKit::NetworkConnectionToWebProcess::didFinishPingLoad):
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/PingLoad.cpp:
(WebKit::PingLoad::~PingLoad):
(WebKit::PingLoad::didFinish):
(WebKit::PingLoad::willPerformHTTPRedirection):
(WebKit::PingLoad::didReceiveChallenge):
(WebKit::PingLoad::didReceiveResponseNetworkSession):
(WebKit::PingLoad::didCompleteWithError):
(WebKit::PingLoad::wasBlocked):
(WebKit::PingLoad::cannotShowURL):
(WebKit::PingLoad::timeoutTimerFired):
(WebKit::PingLoad::currentRequest const):
(WebKit::PingLoad::makeCrossOriginAccessRequestWithPreflight):
* NetworkProcess/PingLoad.h:
* WebProcess/Network/NetworkProcessConnection.cpp:
(WebKit::NetworkProcessConnection::didFinishPingLoad):
* WebProcess/Network/NetworkProcessConnection.h:
* WebProcess/Network/NetworkProcessConnection.messages.in:
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::networkProcessCrashed):
(WebKit::WebLoaderStrategy::startPingLoad):
(WebKit::WebLoaderStrategy::didFinishPingLoad):
* WebProcess/Network/WebLoaderStrategy.h:

Source/WebKitLegacy:

Have Ping loads such as beacons report errors via their completion handler.
The Beacon API is using this error to log a console message when beacon loads
fail, provided that the page is still alive.

* WebCoreSupport/WebResourceLoadScheduler.cpp:
(WebResourceLoadScheduler::startPingLoad):
* WebCoreSupport/WebResourceLoadScheduler.h:

LayoutTests:

Add layout test coverage.

* http/wpt/beacon/beacon-async-error-logging-expected.txt: Added.
* http/wpt/beacon/beacon-async-error-logging.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220945 => 220946)


--- trunk/LayoutTests/ChangeLog	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/LayoutTests/ChangeLog	2017-08-19 00:27:59 UTC (rev 220946)
@@ -1,3 +1,15 @@
+2017-08-18  Chris Dumez  <[email protected]>
+
+        [Beacon] Improve error reporting
+        https://bugs.webkit.org/show_bug.cgi?id=175723
+
+        Reviewed by Darin Adler.
+
+        Add layout test coverage.
+
+        * http/wpt/beacon/beacon-async-error-logging-expected.txt: Added.
+        * http/wpt/beacon/beacon-async-error-logging.html: Added.
+
 2017-08-18  Matt Lewis  <[email protected]>
 
         Marked fast/scrolling/arrow-key-scroll-in-rtl-document.html as flaky.

Added: trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging-expected.txt (0 => 220946)


--- trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging-expected.txt	2017-08-19 00:27:59 UTC (rev 220946)
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Beacon API cannot load http://invalid.localhost/. A server with the specified hostname could not be found.
+
+PASS Should log an error message in the console 
+

Added: trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging.html (0 => 220946)


--- trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-async-error-logging.html	2017-08-19 00:27:59 UTC (rev 220946)
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+    async_test(function(t) {
+        let invalidHost = "http://invalid.localhost";
+        assert_true(navigator.sendBeacon(invalidHost, 'test'), "sendBeacon should return true");
+        setTimeout(function() {
+            t.done();
+        }, 500);
+    }, "Should log an error message in the console");
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt (220945 => 220946)


--- trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt	2017-08-19 00:27:59 UTC (rev 220946)
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: line 44: Reached maximum amount of queued data of 64Kb for keepalive requests
-CONSOLE MESSAGE: line 52: Reached maximum amount of queued data of 64Kb for keepalive requests
+CONSOLE MESSAGE: line 44: Beacon API cannot load http://localhost:8800/. Reached maximum amount of queued data of 64Kb for keepalive requests
+CONSOLE MESSAGE: line 52: Beacon API cannot load http://localhost:8800/. Reached maximum amount of queued data of 64Kb for keepalive requests
 
 PASS Beacon with a body above the Quota Limit should fail. 
 PASS Multiple Beacons Quota Limit 

Modified: trunk/LayoutTests/http/wpt/beacon/beacon-quota.html (220945 => 220946)


--- trunk/LayoutTests/http/wpt/beacon/beacon-quota.html	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-quota.html	2017-08-19 00:27:59 UTC (rev 220946)
@@ -49,7 +49,7 @@
         var target = RESOURCES_DIR + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id;
 
         assert_true(navigator.sendBeacon(target, createPayload(expectedQuota)), "Beacon with a body at the Quota Limit should succeed.");
-        assert_false(navigator.sendBeacon(target, createPayload(1)), "Second beacon should not be sent because we reached the quota");
+        assert_false(navigator.sendBeacon("/", createPayload(1)), "Second beacon should not be sent because we reached the quota");
         return waitForBeacon(id).then(function() {
             assert_true(navigator.sendBeacon(target, createPayload(1)), "Allocated quota should be returned once the beacon is no longer in flight");
         });

Modified: trunk/Source/WebCore/ChangeLog (220945 => 220946)


--- trunk/Source/WebCore/ChangeLog	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/ChangeLog	2017-08-19 00:27:59 UTC (rev 220946)
@@ -1,3 +1,33 @@
+2017-08-18  Chris Dumez  <[email protected]>
+
+        [Beacon] Improve error reporting
+        https://bugs.webkit.org/show_bug.cgi?id=175723
+
+        Reviewed by Darin Adler.
+
+        Have Ping loads such as beacons report errors via their completion handler.
+        The Beacon API is using this error to log a console message when beacon loads
+        fail, provided that the page is still alive.
+
+        Test: http/wpt/beacon/beacon-async-error-logging.html
+
+        * Modules/beacon/NavigatorBeacon.cpp:
+        (WebCore::NavigatorBeacon::NavigatorBeacon):
+        (WebCore::NavigatorBeacon::~NavigatorBeacon):
+        (WebCore::NavigatorBeacon::from):
+        (WebCore::NavigatorBeacon::supplementName):
+        (WebCore::NavigatorBeacon::notifyFinished):
+        (WebCore::NavigatorBeacon::logError):
+        (WebCore::NavigatorBeacon::sendBeacon):
+        * Modules/beacon/NavigatorBeacon.h:
+        * loader/LoaderStrategy.h:
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::load):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::requestBeaconResource):
+        * loader/cache/CachedResourceLoader.h:
+        * platform/network/PingHandle.h:
+
 2017-08-18  Sam Weinig  <[email protected]>
 
         Remove the deprecated WebKitSubtleCrypto interface

Modified: trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp (220945 => 220946)


--- trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -26,9 +26,11 @@
 #include "config.h"
 #include "NavigatorBeacon.h"
 
+#include "CachedRawResource.h"
 #include "CachedResourceLoader.h"
 #include "Document.h"
 #include "FetchBody.h"
+#include "Frame.h"
 #include "HTTPParsers.h"
 #include "Navigator.h"
 #include "URL.h"
@@ -35,8 +37,70 @@
 
 namespace WebCore {
 
-ExceptionOr<bool> NavigatorBeacon::sendBeacon(Navigator&, Document& document, const String& url, std::optional<FetchBody::Init>&& body)
+NavigatorBeacon::NavigatorBeacon(Navigator& navigator)
+    : m_navigator(navigator)
 {
+}
+
+NavigatorBeacon::~NavigatorBeacon()
+{
+    for (auto& beacon : m_inflightBeacons)
+        beacon->removeClient(*this);
+}
+
+NavigatorBeacon* NavigatorBeacon::from(Navigator& navigator)
+{
+    auto* supplement = static_cast<NavigatorBeacon*>(Supplement<Navigator>::from(&navigator, supplementName()));
+    if (!supplement) {
+        auto newSupplement = std::make_unique<NavigatorBeacon>(navigator);
+        supplement = newSupplement.get();
+        provideTo(&navigator, supplementName(), WTFMove(newSupplement));
+    }
+    return supplement;
+}
+
+const char* NavigatorBeacon::supplementName()
+{
+    return "NavigatorBeacon";
+}
+
+void NavigatorBeacon::notifyFinished(CachedResource& resource)
+{
+    if (!resource.resourceError().isNull())
+        logError(resource.resourceError());
+
+    resource.removeClient(*this);
+    bool wasRemoved = m_inflightBeacons.removeFirst(&resource);
+    ASSERT_UNUSED(wasRemoved, wasRemoved);
+    ASSERT(!m_inflightBeacons.contains(&resource));
+}
+
+void NavigatorBeacon::logError(const ResourceError& error)
+{
+    ASSERT(!error.isNull());
+
+    auto* frame = m_navigator.frame();
+    if (!frame)
+        return;
+
+    auto* document = frame->document();
+    if (!document)
+        return;
+
+    const char* messageMiddle = ". ";
+    String description = error.localizedDescription();
+    if (description.isEmpty()) {
+        if (error.isAccessControl())
+            messageMiddle = " due to access control checks.";
+        else
+            messageMiddle = ".";
+    }
+
+    document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, makeString(ASCIILiteral("Beacon API cannot load "), error.failingURL().string(), ASCIILiteral(messageMiddle), description));
+}
+
+ExceptionOr<bool> NavigatorBeacon::sendBeacon(Document& document, const String& url, std::optional<FetchBody::Init>&& body)
+{
     URL parsedUrl = document.completeURL(url);
 
     // Set parsedUrl to the result of the URL parser steps with url and base. If the algorithm returns an error, or if
@@ -73,13 +137,23 @@
                 options.mode = FetchOptions::Mode::NoCors;
         }
     }
+
     auto cachedResource = document.cachedResourceLoader().requestBeaconResource({ WTFMove(request), options });
-    if (cachedResource)
-        return true;
+    if (!cachedResource) {
+        logError(cachedResource.error());
+        return false;
+    }
 
-    document.addConsoleMessage(MessageSource::Network, MessageLevel::Error, cachedResource.error().localizedDescription());
-    return false;
+    ASSERT(!m_inflightBeacons.contains(cachedResource.value().get()));
+    m_inflightBeacons.append(cachedResource.value().get());
+    cachedResource.value()->addClient(*this);
+    return true;
 }
 
+ExceptionOr<bool> NavigatorBeacon::sendBeacon(Navigator& navigator, Document& document, const String& url, std::optional<FetchBody::Init>&& body)
+{
+    return NavigatorBeacon::from(navigator)->sendBeacon(document, url, WTFMove(body));
 }
 
+}
+

Modified: trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.h (220945 => 220946)


--- trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -25,18 +25,37 @@
 
 #pragma once
 
+#include "CachedRawResourceClient.h"
+#include "CachedResourceHandle.h"
 #include "ExceptionOr.h"
 #include "FetchBody.h"
+#include "Supplementable.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
 
+class CachedRawResource;
 class Document;
 class Navigator;
+class ResourceError;
 
-class NavigatorBeacon {
+class NavigatorBeacon final : public Supplement<Navigator>, private CachedRawResourceClient {
 public:
+    explicit NavigatorBeacon(Navigator&);
+    ~NavigatorBeacon();
     static ExceptionOr<bool> sendBeacon(Navigator&, Document&, const String& url, std::optional<FetchBody::Init>&&);
+
+private:
+    ExceptionOr<bool> sendBeacon(Document&, const String& url, std::optional<FetchBody::Init>&&);
+
+    static NavigatorBeacon* from(Navigator&);
+    static const char* supplementName();
+
+    void notifyFinished(CachedResource&) final;
+    void logError(const ResourceError&);
+
+    Navigator& m_navigator;
+    Vector<CachedResourceHandle<CachedRawResource>> m_inflightBeacons;
 };
 
 }

Modified: trunk/Source/WebCore/loader/LoaderStrategy.h (220945 => 220946)


--- trunk/Source/WebCore/loader/LoaderStrategy.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/loader/LoaderStrategy.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -64,7 +64,8 @@
     virtual void suspendPendingRequests() = 0;
     virtual void resumePendingRequests() = 0;
 
-    virtual void startPingLoad(NetworkingContext*, ResourceRequest&, const HTTPHeaderMap& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy*, const FetchOptions&, WTF::Function<void()>&& completionHandler = { }) = 0;
+    using PingLoadCompletionHandler = WTF::Function<void(const ResourceError&)>;
+    virtual void startPingLoad(NetworkingContext*, ResourceRequest&, const HTTPHeaderMap& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy*, const FetchOptions&, PingLoadCompletionHandler&& = { }) = 0;
 
     virtual void storeDerivedDataToCache(const SHA1::Digest& bodyKey, const String& type, const String& partition, WebCore::SharedBuffer&) = 0;
 

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (220945 => 220946)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -274,8 +274,13 @@
             auto* contentSecurityPolicy = document && !document->shouldBypassMainWorldContentSecurityPolicy() ? document->contentSecurityPolicy() : nullptr;
             ASSERT(m_originalRequestHeaders);
             CachedResourceHandle<CachedResource> protectedThis(this);
-            platformStrategies()->loaderStrategy()->startPingLoad(frame.loader().networkingContext(), request, *m_originalRequestHeaders, *m_origin, contentSecurityPolicy, m_options, [this, protectedThis = WTFMove(protectedThis)] {
-                finishLoading(nullptr);
+            platformStrategies()->loaderStrategy()->startPingLoad(frame.loader().networkingContext(), request, *m_originalRequestHeaders, *m_origin, contentSecurityPolicy, m_options, [this, protectedThis = WTFMove(protectedThis)] (const ResourceError& error) {
+                if (error.isNull())
+                    finishLoading(nullptr);
+                else {
+                    setResourceError(error);
+                    this->error(LoadError);
+                }
             });
             return;
         }

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (220945 => 220946)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -296,9 +296,9 @@
     return castCachedResourceTo<CachedRawResource>(requestResource(CachedResource::RawResource, WTFMove(request)));
 }
 
-ResourceErrorOr<CachedResourceHandle<CachedResource>> CachedResourceLoader::requestBeaconResource(CachedResourceRequest&& request)
+ResourceErrorOr<CachedResourceHandle<CachedRawResource>> CachedResourceLoader::requestBeaconResource(CachedResourceRequest&& request)
 {
-    return requestResource(CachedResource::Beacon, WTFMove(request));
+    return castCachedResourceTo<CachedRawResource>(requestResource(CachedResource::Beacon, WTFMove(request)));
 }
 
 ResourceErrorOr<CachedResourceHandle<CachedRawResource>> CachedResourceLoader::requestMainResource(CachedResourceRequest&& request)

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.h (220945 => 220946)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -83,7 +83,7 @@
     ResourceErrorOr<CachedResourceHandle<CachedFont>> requestFont(CachedResourceRequest&&, bool isSVG);
     ResourceErrorOr<CachedResourceHandle<CachedRawResource>> requestMedia(CachedResourceRequest&&);
     ResourceErrorOr<CachedResourceHandle<CachedRawResource>> requestIcon(CachedResourceRequest&&);
-    ResourceErrorOr<CachedResourceHandle<CachedResource>> requestBeaconResource(CachedResourceRequest&&);
+    ResourceErrorOr<CachedResourceHandle<CachedRawResource>> requestBeaconResource(CachedResourceRequest&&);
     ResourceErrorOr<CachedResourceHandle<CachedRawResource>> requestRawResource(CachedResourceRequest&&);
     ResourceErrorOr<CachedResourceHandle<CachedRawResource>> requestMainResource(CachedResourceRequest&&);
     ResourceErrorOr<CachedResourceHandle<CachedSVGDocument>> requestSVGDocument(CachedResourceRequest&&);

Modified: trunk/Source/WebCore/platform/network/PingHandle.h (220945 => 220946)


--- trunk/Source/WebCore/platform/network/PingHandle.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebCore/platform/network/PingHandle.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -43,8 +43,9 @@
         No,
     };
     
-    PingHandle(NetworkingContext* networkingContext, const ResourceRequest& request, bool shouldUseCredentialStorage, UsesAsyncCallbacks useAsyncCallbacks, bool shouldFollowRedirects, WTF::Function<void()>&& completionHandler)
-        : m_timeoutTimer(*this, &PingHandle::timeoutTimerFired)
+    PingHandle(NetworkingContext* networkingContext, const ResourceRequest& request, bool shouldUseCredentialStorage, UsesAsyncCallbacks useAsyncCallbacks, bool shouldFollowRedirects, WTF::Function<void(const ResourceError&)>&& completionHandler)
+        : m_currentRequest(request)
+        , m_timeoutTimer(*this, &PingHandle::timeoutTimerFired)
         , m_shouldUseCredentialStorage(shouldUseCredentialStorage)
         , m_shouldFollowRedirects(shouldFollowRedirects)
         , m_usesAsyncCallbacks(useAsyncCallbacks)
@@ -64,25 +65,31 @@
     }
     void willSendRequestAsync(ResourceHandle* handle, ResourceRequest&& request, ResourceResponse&&) final
     {
+        m_currentRequest = WTFMove(request);
         if (m_shouldFollowRedirects) {
-            handle->continueWillSendRequest(WTFMove(request));
+            handle->continueWillSendRequest(ResourceRequest { m_currentRequest });
             return;
         }
-        delete this;
+        pingLoadComplete(ResourceError { String(), 0, m_currentRequest.url(), ASCIILiteral("Not allowed to follow redirects"), ResourceError::Type::AccessControl });
     }
-    void didReceiveResponse(ResourceHandle*, ResourceResponse&&) final { delete this; }
-    void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int) final { delete this; };
-    void didFinishLoading(ResourceHandle*) final { delete this; }
-    void didFail(ResourceHandle*, const ResourceError&) final { delete this; }
+    void didReceiveResponse(ResourceHandle*, ResourceResponse&&) final { pingLoadComplete(); }
+    void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int) final { pingLoadComplete(); }
+    void didFinishLoading(ResourceHandle*) final { pingLoadComplete(); }
+    void didFail(ResourceHandle*, const ResourceError& error) final { pingLoadComplete(error); }
     bool shouldUseCredentialStorage(ResourceHandle*) final { return m_shouldUseCredentialStorage; }
     bool usesAsyncCallbacks() final { return m_usesAsyncCallbacks == UsesAsyncCallbacks::Yes; }
-    void timeoutTimerFired() { delete this; }
+    void timeoutTimerFired() { pingLoadComplete(ResourceError { String(), 0, m_currentRequest.url(), ASCIILiteral("Load timed out"), ResourceError::Type::Timeout }); }
 
+    void pingLoadComplete(const ResourceError& error = { })
+    {
+        if (auto completionHandler = std::exchange(m_completionHandler, nullptr))
+            completionHandler(error);
+        delete this;
+    }
+
     virtual ~PingHandle()
     {
-        if (m_completionHandler)
-            m_completionHandler();
-
+        ASSERT(!m_completionHandler);
         if (m_handle) {
             ASSERT(m_handle->client() == this);
             m_handle->clearClient();
@@ -91,11 +98,12 @@
     }
 
     RefPtr<ResourceHandle> m_handle;
+    ResourceRequest m_currentRequest;
     Timer m_timeoutTimer;
     bool m_shouldUseCredentialStorage;
     bool m_shouldFollowRedirects;
     UsesAsyncCallbacks m_usesAsyncCallbacks;
-    WTF::Function<void()> m_completionHandler;
+    WTF::Function<void(const ResourceError&)> m_completionHandler;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (220945 => 220946)


--- trunk/Source/WebKit/ChangeLog	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/ChangeLog	2017-08-19 00:27:59 UTC (rev 220946)
@@ -1,5 +1,43 @@
 2017-08-18  Chris Dumez  <[email protected]>
 
+        [Beacon] Improve error reporting
+        https://bugs.webkit.org/show_bug.cgi?id=175723
+
+        Reviewed by Darin Adler.
+
+        Have Ping loads such as beacons report errors via their completion handler.
+        The Beacon API is using this error to log a console message when beacon loads
+        fail, provided that the page is still alive.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::loadPing):
+        (WebKit::NetworkConnectionToWebProcess::didFinishPingLoad):
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/PingLoad.cpp:
+        (WebKit::PingLoad::~PingLoad):
+        (WebKit::PingLoad::didFinish):
+        (WebKit::PingLoad::willPerformHTTPRedirection):
+        (WebKit::PingLoad::didReceiveChallenge):
+        (WebKit::PingLoad::didReceiveResponseNetworkSession):
+        (WebKit::PingLoad::didCompleteWithError):
+        (WebKit::PingLoad::wasBlocked):
+        (WebKit::PingLoad::cannotShowURL):
+        (WebKit::PingLoad::timeoutTimerFired):
+        (WebKit::PingLoad::currentRequest const):
+        (WebKit::PingLoad::makeCrossOriginAccessRequestWithPreflight):
+        * NetworkProcess/PingLoad.h:
+        * WebProcess/Network/NetworkProcessConnection.cpp:
+        (WebKit::NetworkProcessConnection::didFinishPingLoad):
+        * WebProcess/Network/NetworkProcessConnection.h:
+        * WebProcess/Network/NetworkProcessConnection.messages.in:
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::networkProcessCrashed):
+        (WebKit::WebLoaderStrategy::startPingLoad):
+        (WebKit::WebLoaderStrategy::didFinishPingLoad):
+        * WebProcess/Network/WebLoaderStrategy.h:
+
+2017-08-18  Chris Dumez  <[email protected]>
+
         REGRESSION (r220601): Crash when closing google doc after switching the order of tabs in safari
         https://bugs.webkit.org/show_bug.cgi?id=175721
         <rdar://problem/33928369>

Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp (220945 => 220946)


--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -245,18 +245,18 @@
     RefPtr<NetworkingContext> context = RemoteNetworkingContext::create(loadParameters.sessionID, loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect);
 
     // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled.
-    new PingHandle(context.get(), loadParameters.request, loadParameters.allowStoredCredentials == AllowStoredCredentials, PingHandle::UsesAsyncCallbacks::Yes, loadParameters.shouldFollowRedirects, [this, protectedThis = makeRef(*this), identifier = loadParameters.identifier] {
-        didFinishPingLoad(identifier);
+    new PingHandle(context.get(), loadParameters.request, loadParameters.allowStoredCredentials == AllowStoredCredentials, PingHandle::UsesAsyncCallbacks::Yes, loadParameters.shouldFollowRedirects, [this, protectedThis = makeRef(*this), identifier = loadParameters.identifier] (const ResourceError& error) {
+        didFinishPingLoad(identifier, error);
     });
 #endif
 }
 
-void NetworkConnectionToWebProcess::didFinishPingLoad(uint64_t pingLoadIdentifier)
+void NetworkConnectionToWebProcess::didFinishPingLoad(uint64_t pingLoadIdentifier, const ResourceError& error)
 {
     if (!m_connection->isValid())
         return;
 
-    m_connection->send(Messages::NetworkProcessConnection::DidFinishPingLoad(pingLoadIdentifier), 0);
+    m_connection->send(Messages::NetworkProcessConnection::DidFinishPingLoad(pingLoadIdentifier, error), 0);
 }
 
 void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h (220945 => 220946)


--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -38,6 +38,7 @@
 namespace WebCore {
 class BlobDataFileReference;
 class HTTPHeaderMap;
+class ResourceError;
 class ResourceRequest;
 }
 
@@ -61,7 +62,7 @@
     IPC::Connection& connection() { return m_connection.get(); }
 
     void didCleanupResourceLoader(NetworkResourceLoader&);
-    void didFinishPingLoad(uint64_t pingLoadIdentifier);
+    void didFinishPingLoad(uint64_t pingLoadIdentifier, const WebCore::ResourceError&);
 
     bool captureExtraNetworkLoadMetricsEnabled() const { return m_captureExtraNetworkLoadMetricsEnabled; }
 

Modified: trunk/Source/WebKit/NetworkProcess/PingLoad.cpp (220945 => 220946)


--- trunk/Source/WebKit/NetworkProcess/PingLoad.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/NetworkProcess/PingLoad.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -33,6 +33,7 @@
 #include "NetworkCORSPreflightChecker.h"
 #include "NetworkConnectionToWebProcess.h"
 #include "SessionTracker.h"
+#include "WebErrors.h"
 #include <WebCore/ContentSecurityPolicy.h>
 #include <WebCore/CrossOriginAccessControl.h>
 #include <WebCore/CrossOriginPreflightResultCache.h>
@@ -66,8 +67,6 @@
 
 PingLoad::~PingLoad()
 {
-    m_connection->didFinishPingLoad(m_parameters.identifier);
-
     if (m_redirectHandler)
         m_redirectHandler({ });
 
@@ -78,6 +77,12 @@
     }
 }
 
+void PingLoad::didFinish(const ResourceError& error)
+{
+    m_connection->didFinishPingLoad(m_parameters.identifier, error);
+    delete this;
+}
+
 void PingLoad::loadRequest(ResourceRequest&& request)
 {
     RELEASE_LOG_IF_ALLOWED("startNetworkLoad");
@@ -97,6 +102,8 @@
 
 void PingLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler)
 {
+    m_lastRedirectionRequest = request;
+
     RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - shouldFollowRedirects? %d", m_parameters.shouldFollowRedirects);
     if (!m_parameters.shouldFollowRedirects) {
         completionHandler({ });
@@ -149,7 +156,7 @@
 {
     RELEASE_LOG_IF_ALLOWED("didReceiveChallenge");
     completionHandler(AuthenticationChallengeDisposition::Cancel, { });
-    delete this;
+    didFinish(ResourceError { String(), 0, currentRequest().url(), ASCIILiteral("Failed HTTP authentication"), ResourceError::Type::AccessControl });
 }
 
 void PingLoad::didReceiveResponseNetworkSession(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
@@ -156,7 +163,7 @@
 {
     RELEASE_LOG_IF_ALLOWED("didReceiveResponseNetworkSession - httpStatusCode: %d", response.httpStatusCode());
     completionHandler(PolicyAction::PolicyIgnore);
-    delete this;
+    didFinish();
 }
 
 void PingLoad::didReceiveData(Ref<SharedBuffer>&&)
@@ -171,7 +178,8 @@
         RELEASE_LOG_IF_ALLOWED("didComplete");
     else
         RELEASE_LOG_IF_ALLOWED("didCompleteWithError, error_code: %d", error.errorCode());
-    delete this;
+
+    didFinish(error);
 }
 
 void PingLoad::didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend)
@@ -181,21 +189,29 @@
 void PingLoad::wasBlocked()
 {
     RELEASE_LOG_IF_ALLOWED("wasBlocked");
-    delete this;
+    didFinish(blockedError(currentRequest()));
 }
 
 void PingLoad::cannotShowURL()
 {
     RELEASE_LOG_IF_ALLOWED("cannotShowURL");
-    delete this;
+    didFinish(cannotShowURLError(currentRequest()));
 }
 
 void PingLoad::timeoutTimerFired()
 {
     RELEASE_LOG_IF_ALLOWED("timeoutTimerFired");
-    delete this;
+    didFinish(ResourceError { String(), 0, currentRequest().url(), ASCIILiteral("Load timed out"), ResourceError::Type::Timeout });
 }
 
+const ResourceRequest& PingLoad::currentRequest() const
+{
+    if (m_lastRedirectionRequest)
+        return *m_lastRedirectionRequest;
+
+    return m_parameters.request;
+}
+
 bool PingLoad::isAllowedRedirect(const URL& url) const
 {
     if (m_parameters.mode == FetchOptions::Mode::NoCors)
@@ -262,7 +278,7 @@
         if (result == NetworkCORSPreflightChecker::Result::Success)
             preflightSuccess(ResourceRequest { corsPreflightChecker->originalRequest() });
         else
-            delete this;
+            didFinish(ResourceError { String(), 0, corsPreflightChecker->originalRequest().url(), ASCIILiteral("CORS preflight failed"), ResourceError::Type::AccessControl });
     });
     m_corsPreflightChecker->startPreflight();
 }

Modified: trunk/Source/WebKit/NetworkProcess/PingLoad.h (220945 => 220946)


--- trunk/Source/WebKit/NetworkProcess/PingLoad.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/NetworkProcess/PingLoad.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -29,6 +29,7 @@
 
 #include "NetworkDataTask.h"
 #include "NetworkResourceLoadParameters.h"
+#include <WebCore/ResourceError.h>
 
 namespace WebCore {
 class ContentSecurityPolicy;
@@ -68,6 +69,9 @@
     void preflightSuccess(WebCore::ResourceRequest&&);
 
     WebCore::SecurityOrigin& securityOrigin() const;
+
+    const WebCore::ResourceRequest& currentRequest() const;
+    void didFinish(const WebCore::ResourceError& = { });
     
     NetworkResourceLoadParameters m_parameters;
     WebCore::HTTPHeaderMap m_originalRequestHeaders; // Needed for CORS checks.
@@ -80,6 +84,7 @@
     bool m_isSimpleRequest { true };
     RedirectCompletionHandler m_redirectHandler;
     mutable std::unique_ptr<WebCore::ContentSecurityPolicy> m_contentSecurityPolicy;
+    std::optional<WebCore::ResourceRequest> m_lastRedirectionRequest;
 };
 
 }

Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp (220945 => 220946)


--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -135,9 +135,9 @@
         handler(filenames);
 }
 
-void NetworkProcessConnection::didFinishPingLoad(uint64_t pingLoadIdentifier)
+void NetworkProcessConnection::didFinishPingLoad(uint64_t pingLoadIdentifier, ResourceError&& error)
 {
-    WebProcess::singleton().webLoaderStrategy().didFinishPingLoad(pingLoadIdentifier);
+    WebProcess::singleton().webLoaderStrategy().didFinishPingLoad(pingLoadIdentifier, WTFMove(error));
 }
 
 #if ENABLE(SHAREABLE_RESOURCE)

Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h (220945 => 220946)


--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -73,7 +73,7 @@
     void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
 
     void didWriteBlobsToTemporaryFiles(uint64_t requestIdentifier, const Vector<String>& filenames);
-    void didFinishPingLoad(uint64_t pingLoadIdentifier);
+    void didFinishPingLoad(uint64_t pingLoadIdentifier, WebCore::ResourceError&&);
 
 #if ENABLE(SHAREABLE_RESOURCE)
     // Message handlers.

Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in (220945 => 220946)


--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in	2017-08-19 00:27:59 UTC (rev 220946)
@@ -27,5 +27,5 @@
 #endif
 
     DidWriteBlobsToTemporaryFiles(uint64_t requestIdentifier, Vector<String> filenames)
-    DidFinishPingLoad(uint64_t pingLoadIdentifier)
+    DidFinishPingLoad(uint64_t pingLoadIdentifier, WebCore::ResourceError error)
 }

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp (220945 => 220946)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -353,7 +353,7 @@
 
     auto pingLoadCompletionHandlers = WTFMove(m_pingLoadCompletionHandlers);
     for (auto& pingLoadCompletionHandler : pingLoadCompletionHandlers.values())
-        pingLoadCompletionHandler();
+        pingLoadCompletionHandler(internalError(URL()));
 }
 
 void WebLoaderStrategy::loadResourceSynchronously(NetworkingContext* context, unsigned long resourceLoadIdentifier, const ResourceRequest& request, StoredCredentials storedCredentials, ClientCredentialPolicy clientCredentialPolicy, ResourceError& error, ResourceResponse& response, Vector<char>& data)
@@ -396,13 +396,13 @@
     return ++identifier;
 }
 
-void WebLoaderStrategy::startPingLoad(NetworkingContext* networkingContext, ResourceRequest& request, const HTTPHeaderMap& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy* contentSecurityPolicy, const FetchOptions& options, WTF::Function<void()>&& completionHandler)
+void WebLoaderStrategy::startPingLoad(NetworkingContext* networkingContext, ResourceRequest& request, const HTTPHeaderMap& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy* contentSecurityPolicy, const FetchOptions& options, PingLoadCompletionHandler&& completionHandler)
 {
     // It's possible that call to createPingHandle might be made during initial empty Document creation before a NetworkingContext exists.
     // It is not clear that we should send ping loads during that process anyways.
     if (!networkingContext) {
         if (completionHandler)
-            completionHandler();
+            completionHandler(internalError(request.url()));
         return;
     }
 
@@ -429,10 +429,10 @@
     WebProcess::singleton().networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::LoadPing(WTFMove(loadParameters), originalRequestHeaders), 0);
 }
 
-void WebLoaderStrategy::didFinishPingLoad(uint64_t pingLoadIdentifier)
+void WebLoaderStrategy::didFinishPingLoad(uint64_t pingLoadIdentifier, ResourceError&& error)
 {
     if (auto completionHandler = m_pingLoadCompletionHandlers.take(pingLoadIdentifier))
-        completionHandler();
+        completionHandler(WTFMove(error));
 }
 
 void WebLoaderStrategy::storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer& data)

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h (220945 => 220946)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -59,8 +59,8 @@
     void suspendPendingRequests() final;
     void resumePendingRequests() final;
 
-    void startPingLoad(WebCore::NetworkingContext*, WebCore::ResourceRequest&, const WebCore::HTTPHeaderMap& originalRequestHeaders, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&, WTF::Function<void()>&& completionHandler) final;
-    void didFinishPingLoad(uint64_t pingLoadIdentifier);
+    void startPingLoad(WebCore::NetworkingContext*, WebCore::ResourceRequest&, const WebCore::HTTPHeaderMap& originalRequestHeaders, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&, PingLoadCompletionHandler&&) final;
+    void didFinishPingLoad(uint64_t pingLoadIdentifier, WebCore::ResourceError&&);
 
     void storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer&) final;
 
@@ -85,7 +85,7 @@
     
     HashMap<unsigned long, RefPtr<WebResourceLoader>> m_webResourceLoaders;
     HashMap<unsigned long, WebURLSchemeTaskProxy*> m_urlSchemeTasks;
-    HashMap<unsigned long, WTF::Function<void()>> m_pingLoadCompletionHandlers;
+    HashMap<unsigned long, PingLoadCompletionHandler> m_pingLoadCompletionHandlers;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKitLegacy/ChangeLog (220945 => 220946)


--- trunk/Source/WebKitLegacy/ChangeLog	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKitLegacy/ChangeLog	2017-08-19 00:27:59 UTC (rev 220946)
@@ -1,5 +1,20 @@
 2017-08-18  Chris Dumez  <[email protected]>
 
+        [Beacon] Improve error reporting
+        https://bugs.webkit.org/show_bug.cgi?id=175723
+
+        Reviewed by Darin Adler.
+
+        Have Ping loads such as beacons report errors via their completion handler.
+        The Beacon API is using this error to log a console message when beacon loads
+        fail, provided that the page is still alive.
+
+        * WebCoreSupport/WebResourceLoadScheduler.cpp:
+        (WebResourceLoadScheduler::startPingLoad):
+        * WebCoreSupport/WebResourceLoadScheduler.h:
+
+2017-08-18  Chris Dumez  <[email protected]>
+
         [Beacon] Add support for quota limitation
         https://bugs.webkit.org/show_bug.cgi?id=175443
         <rdar://problem/33729002>

Modified: trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp (220945 => 220946)


--- trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp	2017-08-19 00:27:59 UTC (rev 220946)
@@ -363,7 +363,7 @@
     return m_requestsLoading.size() >= (webResourceLoadScheduler().isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
 }
 
-void WebResourceLoadScheduler::startPingLoad(NetworkingContext* networkingContext, ResourceRequest& request, const HTTPHeaderMap&, Ref<SecurityOrigin>&&, WebCore::ContentSecurityPolicy*, const FetchOptions& options, WTF::Function<void()>&& completionHandler)
+void WebResourceLoadScheduler::startPingLoad(NetworkingContext* networkingContext, ResourceRequest& request, const HTTPHeaderMap&, Ref<SecurityOrigin>&&, WebCore::ContentSecurityPolicy*, const FetchOptions& options, PingLoadCompletionHandler&& completionHandler)
 {
     // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled.
     new PingHandle(networkingContext, request, options.credentials != FetchOptions::Credentials::Omit, PingHandle::UsesAsyncCallbacks::No, options.redirect == FetchOptions::Redirect::Follow, WTFMove(completionHandler));

Modified: trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h (220945 => 220946)


--- trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h	2017-08-19 00:27:29 UTC (rev 220945)
+++ trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h	2017-08-19 00:27:59 UTC (rev 220946)
@@ -59,7 +59,7 @@
     void suspendPendingRequests() final;
     void resumePendingRequests() final;
 
-    void startPingLoad(WebCore::NetworkingContext*, WebCore::ResourceRequest&, const WebCore::HTTPHeaderMap&, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&, WTF::Function<void()>&& completionHandler) final;
+    void startPingLoad(WebCore::NetworkingContext*, WebCore::ResourceRequest&, const WebCore::HTTPHeaderMap&, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&, PingLoadCompletionHandler&&) final;
 
     void storeDerivedDataToCache(const SHA1::Digest&, const String&, const String&, WebCore::SharedBuffer&) final { }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to