Changeset 220996 in webkit


Ignore:
Timestamp:
Aug 21, 2017 6:32:24 PM (7 years ago)
Author:
Chris Dumez
Message:

[Beacon] Content extensions should be able to intercept Beacon / Ping redirects
https://bugs.webkit.org/show_bug.cgi?id=175746
<rdar://problem/33946050>

Reviewed by Alex Christensen.

Source/WebCore:

Update PingLoad to process content extension rules upon redirect. This allows content
extensions to block and upgrade to HTTPS beacon / ping loads.

Because ping loads can outlive the WebProcess, the content extensions rules are passed
to the NetworkProcess when starting the Ping load. The PingLoad can then consult those
rules upon redirect, on the NetworkProcess side.

Tests: http/wpt/beacon/contentextensions/beacon-blocked.html

http/wpt/beacon/contentextensions/beacon-redirect-blocked.html

  • contentextensions/ContentExtensionActions.h:
  • contentextensions/ContentExtensionsBackend.cpp:

(WebCore::ContentExtensions::ContentExtensionsBackend::forEach):
(WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForPingLoad):

  • contentextensions/ContentExtensionsBackend.h:
  • page/Page.h:
  • page/UserContentProvider.cpp:

(WebCore::UserContentProvider::forEachContentExtension):

  • page/UserContentProvider.h:

Source/WebKit:

Update PingLoad to process content extension rules upon redirect. This allows content
extensions to block and upgrade to HTTPS beacon / ping loads.

Because ping loads can outlive the WebProcess, the content extensions rules are passed
to the NetworkProcess when starting the Ping load. The PingLoad can then consult those
rules upon redirect, on the NetworkProcess side.

  • NetworkProcess/NetworkResourceLoadParameters.cpp:

(WebKit::NetworkResourceLoadParameters::encode const):
(WebKit::NetworkResourceLoadParameters::decode):

  • NetworkProcess/NetworkResourceLoadParameters.h:
  • NetworkProcess/PingLoad.cpp:

(WebKit::PingLoad::willPerformHTTPRedirection):
(WebKit::PingLoad::contentExtensionsBackend):
(WebKit::PingLoad::processContentExtensionRulesForLoad):

  • NetworkProcess/PingLoad.h:
  • WebProcess/Network/WebLoaderStrategy.cpp:

(WebKit::WebLoaderStrategy::startPingLoad):

LayoutTests:

Add layout test coverage for blocking beacon loads via content extensions.

  • http/wpt/beacon/connect-src-beacon-redirect-blocked.sub-expected.txt:
  • http/wpt/beacon/connect-src-beacon-redirect-blocked.sub.html:
  • http/wpt/beacon/contentextensions/beacon-blocked-expected.txt: Added.
  • http/wpt/beacon/contentextensions/beacon-blocked.html: Added.
  • http/wpt/beacon/contentextensions/beacon-blocked.html.json: Added.
  • http/wpt/beacon/contentextensions/beacon-redirect-blocked-expected.txt: Added.
  • http/wpt/beacon/contentextensions/beacon-redirect-blocked.html: Added.
  • http/wpt/beacon/contentextensions/beacon-redirect-blocked.html.json: Added.
Location:
trunk
Files:
7 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r220987 r220996  
     12017-08-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [Beacon] Content extensions should be able to intercept Beacon / Ping redirects
     4        https://bugs.webkit.org/show_bug.cgi?id=175746
     5        <rdar://problem/33946050>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add layout test coverage for blocking beacon loads via content extensions.
     10
     11        * http/wpt/beacon/connect-src-beacon-redirect-blocked.sub-expected.txt:
     12        * http/wpt/beacon/connect-src-beacon-redirect-blocked.sub.html:
     13        * http/wpt/beacon/contentextensions/beacon-blocked-expected.txt: Added.
     14        * http/wpt/beacon/contentextensions/beacon-blocked.html: Added.
     15        * http/wpt/beacon/contentextensions/beacon-blocked.html.json: Added.
     16        * http/wpt/beacon/contentextensions/beacon-redirect-blocked-expected.txt: Added.
     17        * http/wpt/beacon/contentextensions/beacon-redirect-blocked.html: Added.
     18        * http/wpt/beacon/contentextensions/beacon-redirect-blocked.html.json: Added.
     19
    1202017-08-21  Matt Lewis  <jlewis3@apple.com>
    221
  • trunk/LayoutTests/http/wpt/beacon/connect-src-beacon-redirect-blocked.sub-expected.txt

    r220549 r220996  
     1CONSOLE MESSAGE: Beacon API cannot load http://127.0.0.1:8800/WebKit/beacon/resources/beacon-preflight.py?allowCors=1&cmd=put&id=2539e883-7dfb-4dde-a227-a41c670d5fe1&redirect_status=307&location=http%3A%2F%2F127.0.0.1%3A8800%2FWebKit%2Fbeacon%2Fresources%2Fbeacon-preflight.py%3FallowCors%3D1%26cmd%3Dput%26id%3D2539e883-7dfb-4dde-a227-a41c670d5fe1&count=1. Blocked by Content Security Policy
    12
    23PASS Redirect is blocked by CSP
  • trunk/LayoutTests/http/wpt/beacon/connect-src-beacon-redirect-blocked.sub.html

    r220549 r220996  
    3030function testCORSPreflightRedirectSuccess(what) {
    3131  var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR;
    32   var id = self.token();
     32  var id = "2539e883-7dfb-4dde-a227-a41c670d5fe1"; // Use a static token because the URL is logged.
    3333  var target = encodeURIComponent(testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id);
    3434
  • trunk/Source/WebCore/ChangeLog

    r220992 r220996  
     12017-08-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [Beacon] Content extensions should be able to intercept Beacon / Ping redirects
     4        https://bugs.webkit.org/show_bug.cgi?id=175746
     5        <rdar://problem/33946050>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Update PingLoad to process content extension rules upon redirect. This allows content
     10        extensions to block and upgrade to HTTPS beacon / ping loads.
     11
     12        Because ping loads can outlive the WebProcess, the content extensions rules are passed
     13        to the NetworkProcess when starting the Ping load. The PingLoad can then consult those
     14        rules upon redirect, on the NetworkProcess side.
     15
     16        Tests: http/wpt/beacon/contentextensions/beacon-blocked.html
     17               http/wpt/beacon/contentextensions/beacon-redirect-blocked.html
     18
     19        * contentextensions/ContentExtensionActions.h:
     20        * contentextensions/ContentExtensionsBackend.cpp:
     21        (WebCore::ContentExtensions::ContentExtensionsBackend::forEach):
     22        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForPingLoad):
     23        * contentextensions/ContentExtensionsBackend.h:
     24        * page/Page.h:
     25        * page/UserContentProvider.cpp:
     26        (WebCore::UserContentProvider::forEachContentExtension):
     27        * page/UserContentProvider.h:
     28
    1292017-08-21  Brady Eidson  <beidson@apple.com>
    230
  • trunk/Source/WebCore/contentextensions/ContentExtensionActions.h

    r204127 r220996  
    5252};
    5353
    54 void applyBlockedStatusToRequest(const BlockedStatus&, ResourceRequest&);
     54WEBCORE_EXPORT void applyBlockedStatusToRequest(const BlockedStatus&, ResourceRequest&);
    5555
    5656} // namespace ContentExtensions
  • trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp

    r219573 r220996  
    135135}
    136136
     137void ContentExtensionsBackend::forEach(const WTF::Function<void(const String&, ContentExtension&)>& apply)
     138{
     139    for (auto& pair : m_contentExtensions)
     140        apply(pair.key, pair.value);
     141}
     142
    137143StyleSheetContents* ContentExtensionsBackend::globalDisplayNoneStyleSheet(const String& identifier) const
    138144{
     
    214220}
    215221
     222BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForPingLoad(const URL& url, const URL& mainDocumentURL)
     223{
     224    if (m_contentExtensions.isEmpty())
     225        return { };
     226
     227    ResourceLoadInfo resourceLoadInfo = { url, mainDocumentURL, ResourceType::Raw };
     228    Vector<ContentExtensions::Action> actions = actionsForResourceLoad(resourceLoadInfo);
     229
     230    bool willBlockLoad = false;
     231    bool willBlockCookies = false;
     232    bool willMakeHTTPS = false;
     233    for (const auto& action : actions) {
     234        switch (action.type()) {
     235        case ContentExtensions::ActionType::BlockLoad:
     236            willBlockLoad = true;
     237            break;
     238        case ContentExtensions::ActionType::BlockCookies:
     239            willBlockCookies = true;
     240            break;
     241        case ContentExtensions::ActionType::MakeHTTPS:
     242            if ((url.protocolIs("http") || url.protocolIs("ws")) && (!url.port() || isDefaultPortForProtocol(url.port().value(), url.protocol())))
     243                willMakeHTTPS = true;
     244            break;
     245        case ContentExtensions::ActionType::CSSDisplayNoneSelector:
     246        case ContentExtensions::ActionType::CSSDisplayNoneStyleSheet:
     247            break;
     248        case ContentExtensions::ActionType::IgnorePreviousRules:
     249        case ContentExtensions::ActionType::InvalidAction:
     250            RELEASE_ASSERT_NOT_REACHED();
     251        }
     252    }
     253
     254    return { willBlockLoad, willBlockCookies, willMakeHTTPS };
     255}
     256
    216257const String& ContentExtensionsBackend::displayNoneCSSRule()
    217258{
  • trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.h

    r219573 r220996  
    6666
    6767    BlockedStatus processContentExtensionRulesForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
     68    WEBCORE_EXPORT BlockedStatus processContentExtensionRulesForPingLoad(const URL&, const URL& mainDocumentURL);
    6869
    6970    static const String& displayNoneCSSRule();
     71
     72    void forEach(const WTF::Function<void(const String&, ContentExtension&)>&);
    7073
    7174private:
  • trunk/Source/WebCore/page/Page.h

    r220887 r220996  
    505505    PluginInfoProvider& pluginInfoProvider();
    506506
    507     UserContentProvider& userContentProvider();
     507    WEBCORE_EXPORT UserContentProvider& userContentProvider();
    508508    WEBCORE_EXPORT void setUserContentProvider(Ref<UserContentProvider>&&);
    509509
  • trunk/Source/WebCore/page/UserContentProvider.cpp

    r219051 r220996  
    117117    return userContentExtensionBackend().actionsForResourceLoad(resourceLoadInfo);
    118118}
     119
     120void UserContentProvider::forEachContentExtension(const WTF::Function<void(const String&, ContentExtensions::ContentExtension&)>& apply, DocumentLoader& initiatingDocumentLoader)
     121{
     122    if (!contentExtensionsEnabled(initiatingDocumentLoader))
     123        return;
     124
     125    userContentExtensionBackend().forEach(apply);
     126}
     127
    119128#endif
    120129
  • trunk/Source/WebCore/page/UserContentProvider.h

    r218748 r220996  
    9393    ContentExtensions::BlockedStatus processContentExtensionRulesForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
    9494    Vector<ContentExtensions::Action> actionsForResourceLoad(const ResourceLoadInfo&, DocumentLoader& initiatingDocumentLoader);
     95    WEBCORE_EXPORT void forEachContentExtension(const WTF::Function<void(const String&, ContentExtensions::ContentExtension&)>&, DocumentLoader& initiatingDocumentLoader);
    9596#endif
    9697
  • trunk/Source/WebKit/ChangeLog

    r220995 r220996  
     12017-08-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [Beacon] Content extensions should be able to intercept Beacon / Ping redirects
     4        https://bugs.webkit.org/show_bug.cgi?id=175746
     5        <rdar://problem/33946050>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Update PingLoad to process content extension rules upon redirect. This allows content
     10        extensions to block and upgrade to HTTPS beacon / ping loads.
     11
     12        Because ping loads can outlive the WebProcess, the content extensions rules are passed
     13        to the NetworkProcess when starting the Ping load. The PingLoad can then consult those
     14        rules upon redirect, on the NetworkProcess side.
     15
     16        * NetworkProcess/NetworkResourceLoadParameters.cpp:
     17        (WebKit::NetworkResourceLoadParameters::encode const):
     18        (WebKit::NetworkResourceLoadParameters::decode):
     19        * NetworkProcess/NetworkResourceLoadParameters.h:
     20        * NetworkProcess/PingLoad.cpp:
     21        (WebKit::PingLoad::willPerformHTTPRedirection):
     22        (WebKit::PingLoad::contentExtensionsBackend):
     23        (WebKit::PingLoad::processContentExtensionRulesForLoad):
     24        * NetworkProcess/PingLoad.h:
     25        * WebProcess/Network/WebLoaderStrategy.cpp:
     26        (WebKit::WebLoaderStrategy::startPingLoad):
     27
    1282017-08-21  Adrian Perez de Castro  <aperez@igalia.com>
    229
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp

    r220888 r220996  
    8989    encoder.encodeEnum(mode);
    9090    encoder << cspResponseHeaders;
     91
     92#if ENABLE(CONTENT_EXTENSIONS)
     93    encoder << mainDocumentURL;
     94    encoder << contentRuleLists;
     95#endif
    9196}
    9297
     
    168173        return false;
    169174
     175#if ENABLE(CONTENT_EXTENSIONS)
     176    if (!decoder.decode(result.mainDocumentURL))
     177        return false;
     178
     179    if (!decoder.decode(result.contentRuleLists))
     180        return false;
     181#endif
     182
    170183    return true;
    171184}
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h

    r220888 r220996  
    2929#include "NetworkLoadParameters.h"
    3030#include "SandboxExtension.h"
     31#include "WebCompiledContentRuleListData.h"
    3132#include <WebCore/ContentSecurityPolicyResponseHeaders.h>
    3233#include <WebCore/FetchOptions.h>
     
    6061    WebCore::FetchOptions::Mode mode;
    6162    std::optional<WebCore::ContentSecurityPolicyResponseHeaders> cspResponseHeaders;
     63
     64#if ENABLE(CONTENT_EXTENSIONS)
     65    WebCore::URL mainDocumentURL;
     66    Vector<std::pair<String, WebCompiledContentRuleListData>> contentRuleLists;
     67#endif
    6268};
    6369
  • trunk/Source/WebKit/NetworkProcess/PingLoad.cpp

    r220946 r220996  
    3434#include "NetworkConnectionToWebProcess.h"
    3535#include "SessionTracker.h"
     36#include "WebCompiledContentRuleList.h"
    3637#include "WebErrors.h"
    3738#include <WebCore/ContentSecurityPolicy.h>
     
    103104void PingLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler)
    104105{
    105     m_lastRedirectionRequest = request;
    106 
    107106    RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - shouldFollowRedirects? %d", m_parameters.shouldFollowRedirects);
    108107    if (!m_parameters.shouldFollowRedirects) {
    109108        completionHandler({ });
    110         return;
    111     }
     109        didFinish(ResourceError { String(), 0, currentRequest().url(), ASCIILiteral("Not allowed to follow redirects"), ResourceError::Type::AccessControl });
     110        return;
     111    }
     112
     113#if ENABLE(CONTENT_EXTENSIONS)
     114    if (processContentExtensionRulesForLoad(request)) {
     115        RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - Redirect was blocked by content extensions");
     116        m_lastRedirectionRequest = request;
     117        completionHandler({ });
     118        didFinish(ResourceError { String(), 0, currentRequest().url(), ASCIILiteral("Blocked by content extension"), ResourceError::Type::AccessControl });
     119        return;
     120    }
     121#endif
     122
     123    m_lastRedirectionRequest = request;
    112124
    113125    if (auto* contentSecurityPolicy = this->contentSecurityPolicy()) {
     
    115127            RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - Redirect was blocked by CSP");
    116128            completionHandler({ });
     129            didFinish(ResourceError { String(), 0, currentRequest().url(), ASCIILiteral("Blocked by Content Security Policy"), ResourceError::Type::AccessControl });
    117130            return;
    118131        }
     
    297310}
    298311
     312#if ENABLE(CONTENT_EXTENSIONS)
     313
     314ContentExtensions::ContentExtensionsBackend& PingLoad::contentExtensionsBackend()
     315{
     316    if (!m_contentExtensionsBackend) {
     317        m_contentExtensionsBackend = std::make_unique<ContentExtensions::ContentExtensionsBackend>();
     318        for (auto& pair : m_parameters.contentRuleLists)
     319            m_contentExtensionsBackend->addContentExtension(pair.first, WebCompiledContentRuleList::create(WTFMove(pair.second)));
     320    }
     321    return *m_contentExtensionsBackend;
     322}
     323
     324// Returns true if we should block the load.
     325bool PingLoad::processContentExtensionRulesForLoad(ResourceRequest& request)
     326{
     327    auto status = contentExtensionsBackend().processContentExtensionRulesForPingLoad(request.url(), m_parameters.mainDocumentURL);
     328    applyBlockedStatusToRequest(status, request);
     329    return status.blockedLoad;
     330}
     331
     332#endif // ENABLE(CONTENT_EXTENSIONS)
     333
    299334} // namespace WebKit
    300335
  • trunk/Source/WebKit/NetworkProcess/PingLoad.h

    r220946 r220996  
    3030#include "NetworkDataTask.h"
    3131#include "NetworkResourceLoadParameters.h"
     32#include <WebCore/ContentExtensionsBackend.h>
    3233#include <WebCore/ResourceError.h>
    3334
     
    6970    void preflightSuccess(WebCore::ResourceRequest&&);
    7071
     72#if ENABLE(CONTENT_EXTENSIONS)
     73    WebCore::ContentExtensions::ContentExtensionsBackend& contentExtensionsBackend();
     74    bool processContentExtensionRulesForLoad(WebCore::ResourceRequest&);
     75#endif
     76
    7177    WebCore::SecurityOrigin& securityOrigin() const;
    7278
     
    8591    RedirectCompletionHandler m_redirectHandler;
    8692    mutable std::unique_ptr<WebCore::ContentSecurityPolicy> m_contentSecurityPolicy;
     93#if ENABLE(CONTENT_EXTENSIONS)
     94    std::unique_ptr<WebCore::ContentExtensions::ContentExtensionsBackend> m_contentExtensionsBackend;
     95#endif
    8796    std::optional<WebCore::ResourceRequest> m_lastRedirectionRequest;
    8897};
  • trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp

    r220957 r220996  
    3434#include "NetworkResourceLoadParameters.h"
    3535#include "SessionTracker.h"
     36#include "WebCompiledContentRuleList.h"
    3637#include "WebCoreArgumentCoders.h"
    3738#include "WebErrors.h"
     
    6263#include <WebCore/Settings.h>
    6364#include <WebCore/SubresourceLoader.h>
     65#include <WebCore/UserContentProvider.h>
    6466#include <pal/SessionID.h>
    6567#include <wtf/text/CString.h>
     
    434436    }
    435437
     438#if ENABLE(CONTENT_EXTENSIONS)
     439    loadParameters.mainDocumentURL = document->topDocument().url();
     440
     441    if (auto* documentLoader = frame.loader().documentLoader()) {
     442        if (auto* page = frame.page()) {
     443            page->userContentProvider().forEachContentExtension([&loadParameters](const String& identifier, ContentExtensions::ContentExtension& contentExtension) {
     444                loadParameters.contentRuleLists.append(std::make_pair(identifier, static_cast<const WebCompiledContentRuleList&>(contentExtension.compiledExtension()).data()));
     445            }, *documentLoader);
     446        }
     447    }
     448#endif
     449
    436450    if (completionHandler)
    437451        m_pingLoadCompletionHandlers.add(loadParameters.identifier, WTFMove(completionHandler));
Note: See TracChangeset for help on using the changeset viewer.