Changeset 194386 in webkit


Ignore:
Timestamp:
Dec 23, 2015 2:04:44 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Content blockers should be able to promote http to https
https://bugs.webkit.org/show_bug.cgi?id=148966

Patch by Chris Aljoudi <chris@chrismatic.io> and Alex Christensen <achristensen@webkit.org> on 2015-12-23
Reviewed by Benjamin Poulain.

Source/WebCore:

Test: http/tests/contentextensions/make-https.html

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

(WebCore::ContentExtensions::serializeActions):

  • contentextensions/ContentExtensionParser.cpp:

(WebCore::ContentExtensions::loadAction):

  • contentextensions/ContentExtensionRule.cpp:

(WebCore::ContentExtensions::Action::deserialize):
(WebCore::ContentExtensions::Action::deserializeType):
(WebCore::ContentExtensions::Action::serializedLength):

  • contentextensions/ContentExtensionsBackend.cpp:

(WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForLoad):

  • loader/cache/CachedResourceLoader.cpp:

(WebCore::CachedResourceLoader::requestResource):

  • platform/URL.cpp:

(WebCore::URL::isBlankURL):
(WebCore::defaultPortsMap):
(WebCore::defaultPortForProtocol):
(WebCore::isDefaultPortForProtocol):
(WebCore::portAllowed):

  • platform/URL.h:

Tools:

  • TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:

(WebCore::ContentExtensions::operator<<):
(TestWebKitAPI::TEST_F):

LayoutTests:

  • http/tests/contentextensions/make-https-expected.txt: Added.
  • http/tests/contentextensions/make-https.html: Added.
  • http/tests/contentextensions/make-https.html.json: Added.
Location:
trunk
Files:
3 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r194366 r194386  
     12015-12-23  Chris Aljoudi <chris@chrismatic.io> and Alex Christensen <achristensen@webkit.org>
     2
     3        Content blockers should be able to promote http to https
     4        https://bugs.webkit.org/show_bug.cgi?id=148966
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        * http/tests/contentextensions/make-https-expected.txt: Added.
     9        * http/tests/contentextensions/make-https.html: Added.
     10        * http/tests/contentextensions/make-https.html.json: Added.
     11
    1122015-12-22  Xabier Rodriguez Calvar  <calvaris@igalia.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r194380 r194386  
     12015-12-23  Chris Aljoudi <chris@chrismatic.io> and Alex Christensen <achristensen@webkit.org>
     2
     3        Content blockers should be able to promote http to https
     4        https://bugs.webkit.org/show_bug.cgi?id=148966
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        Test: http/tests/contentextensions/make-https.html
     9
     10        * contentextensions/ContentExtensionActions.h:
     11        * contentextensions/ContentExtensionCompiler.cpp:
     12        (WebCore::ContentExtensions::serializeActions):
     13        * contentextensions/ContentExtensionParser.cpp:
     14        (WebCore::ContentExtensions::loadAction):
     15        * contentextensions/ContentExtensionRule.cpp:
     16        (WebCore::ContentExtensions::Action::deserialize):
     17        (WebCore::ContentExtensions::Action::deserializeType):
     18        (WebCore::ContentExtensions::Action::serializedLength):
     19        * contentextensions/ContentExtensionsBackend.cpp:
     20        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForLoad):
     21        * loader/cache/CachedResourceLoader.cpp:
     22        (WebCore::CachedResourceLoader::requestResource):
     23        * platform/URL.cpp:
     24        (WebCore::URL::isBlankURL):
     25        (WebCore::defaultPortsMap):
     26        (WebCore::defaultPortForProtocol):
     27        (WebCore::isDefaultPortForProtocol):
     28        (WebCore::portAllowed):
     29        * platform/URL.h:
     30
    1312015-12-22  Andy Estes  <aestes@apple.com>
    232
  • trunk/Source/WebCore/contentextensions/ContentExtensionActions.h

    r190611 r194386  
    4141    CSSDisplayNoneStyleSheet,
    4242    IgnorePreviousRules,
     43    MakeHTTPS,
    4344    InvalidAction,
    4445};
  • trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp

    r187049 r194386  
    103103    Vector<unsigned> actionLocations;
    104104
    105     // Block and BlockCookies do not need to be distinguishable. The order in which they are executed it irrelevant
    106     // since Block is a strict superset of BlockCookies.
    107     // Similarily, Block is a superset of CSSDisplayNone, and BlockCookies is independent from CSSDisplayNone.
    108     //
    109     // The only distinguisher is "IgnorePreviousRules".
    110     //
    111     // The trigger's Flags do not need to be distinguishable either. The way we use them is filtering the actions
    112     // based on the flag *after* matching.
    113     //
    114     // To reduce the number of unique actions, we keep track of the various action, indexed by their flag.
    115     // We only need to create new ones when encountering a IgnorePreviousRules.
    116     HashMap<uint32_t, uint32_t, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> blockActionsMap;
    117     HashMap<uint32_t, uint32_t, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> blockCookiesActionsMap;
     105    // Order only matters because of IgnorePreviousRules. All other identical actions can be combined between each IgnorePreviousRules
     106    // and CSSDisplayNone strings can be combined if their triggers are identical.
     107    typedef HashMap<uint32_t, uint32_t, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> ActionMap;
     108    ActionMap blockLoadActionsMap;
     109    ActionMap blockCookiesActionsMap;
    118110    PendingDisplayNoneActionsMap cssDisplayNoneActionsMap;
    119     HashMap<uint32_t, uint32_t, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> ignorePreviousRuleActionsMap;
     111    ActionMap ignorePreviousRuleActionsMap;
     112    ActionMap makeHTTPSActionsMap;
    120113
    121114    for (unsigned ruleIndex = 0; ruleIndex < ruleList.size(); ++ruleIndex) {
     
    123116        ActionType actionType = rule.action().type();
    124117
    125         RELEASE_ASSERT(actionType == ActionType::CSSDisplayNoneSelector
    126             || actionType == ActionType::BlockLoad
    127             || actionType == ActionType::BlockCookies
    128             || actionType == ActionType::IgnorePreviousRules);
    129 
    130118        if (actionType == ActionType::IgnorePreviousRules) {
    131119            resolvePendingDisplayNoneActions(actions, actionLocations, cssDisplayNoneActionsMap);
    132120
    133             blockActionsMap.clear();
     121            blockLoadActionsMap.clear();
    134122            blockCookiesActionsMap.clear();
    135123            cssDisplayNoneActionsMap.clear();
     124            makeHTTPSActionsMap.clear();
    136125        } else
    137126            ignorePreviousRuleActionsMap.clear();
     
    151140        ResourceFlags flags = rule.trigger().flags;
    152141        unsigned actionLocation = std::numeric_limits<unsigned>::max();
     142       
     143        auto findOrMakeActionLocation = [&] (ActionMap& map)
     144        {
     145            const auto existingAction = map.find(flags);
     146            if (existingAction == map.end()) {
     147                actionLocation = actions.size();
     148                actions.append(static_cast<SerializedActionByte>(actionType));
     149                map.set(flags, actionLocation);
     150            } else
     151                actionLocation = existingAction->value;
     152        };
    153153
    154154        switch (actionType) {
     
    157157            RELEASE_ASSERT_NOT_REACHED();
    158158
    159         case ActionType::IgnorePreviousRules: {
    160             const auto existingAction = ignorePreviousRuleActionsMap.find(flags);
    161             if (existingAction == ignorePreviousRuleActionsMap.end()) {
    162                 actionLocation = actions.size();
    163                 actions.append(static_cast<SerializedActionByte>(rule.action().type()));
    164                 ignorePreviousRuleActionsMap.set(flags, actionLocation);
    165             } else
    166                 actionLocation = existingAction->value;
    167             break;
    168         }
    169159        case ActionType::CSSDisplayNoneSelector: {
    170160            const auto addResult = cssDisplayNoneActionsMap.add(rule.trigger(), PendingDisplayNoneActions());
     
    176166            break;
    177167        }
    178         case ActionType::BlockLoad: {
    179             const auto existingAction = blockActionsMap.find(flags);
    180             if (existingAction == blockActionsMap.end()) {
    181                 actionLocation = actions.size();
    182                 actions.append(static_cast<SerializedActionByte>(rule.action().type()));
    183                 blockActionsMap.set(flags, actionLocation);
    184             } else
    185                 actionLocation = existingAction->value;
     168        case ActionType::IgnorePreviousRules:
     169            findOrMakeActionLocation(ignorePreviousRuleActionsMap);
    186170            break;
    187         }
    188         case ActionType::BlockCookies: {
    189             const auto existingAction = blockCookiesActionsMap.find(flags);
    190             if (existingAction == blockCookiesActionsMap.end()) {
    191                 actionLocation = actions.size();
    192                 actions.append(static_cast<SerializedActionByte>(rule.action().type()));
    193                 blockCookiesActionsMap.set(flags, actionLocation);
    194             } else
    195                 actionLocation = existingAction->value;
     171        case ActionType::BlockLoad:
     172            findOrMakeActionLocation(blockLoadActionsMap);
    196173            break;
    197         }
     174        case ActionType::BlockCookies:
     175            findOrMakeActionLocation(blockCookiesActionsMap);
     176            break;
     177        case ActionType::MakeHTTPS:
     178            findOrMakeActionLocation(makeHTTPSActionsMap);
     179            break;
    198180        }
    199181
  • trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp

    r190602 r194386  
    217217        }
    218218        action = Action(ActionType::CSSDisplayNoneSelector, s);
     219    } else if (actionType == "make-https") {
     220        action = ActionType::MakeHTTPS;
    219221    } else
    220222        return ContentExtensionError::JSONInvalidActionType;
  • trunk/Source/WebCore/contentextensions/ContentExtensionRule.cpp

    r187049 r194386  
    5050    case ActionType::IgnorePreviousRules:
    5151        return Action(ActionType::IgnorePreviousRules, location);
     52    case ActionType::MakeHTTPS:
     53        return Action(ActionType::MakeHTTPS, location);
    5254    case ActionType::CSSDisplayNoneSelector: {
    5355        uint32_t headerLength = sizeof(ActionType) + sizeof(uint32_t) + sizeof(bool);
     
    8082    case ActionType::IgnorePreviousRules:
    8183    case ActionType::CSSDisplayNoneSelector:
     84    case ActionType::MakeHTTPS:
    8285        return type;
    8386    case ActionType::CSSDisplayNoneStyleSheet:
     
    9598    case ActionType::BlockLoad:
    9699    case ActionType::IgnorePreviousRules:
     100    case ActionType::MakeHTTPS:
    97101        return sizeof(ActionType);
    98102    case ActionType::CSSDisplayNoneSelector: {
  • trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp

    r190611 r194386  
    3737#include "ExtensionStyleSheets.h"
    3838#include "Frame.h"
     39#include "FrameLoaderClient.h"
    3940#include "MainFrame.h"
    4041#include "ResourceLoadInfo.h"
     
    190191            break;
    191192        }
     193        case ContentExtensions::ActionType::MakeHTTPS: {
     194            const URL originalURL = request.url();
     195            if (originalURL.protocolIs("http") && (!originalURL.hasPort() || isDefaultPortForProtocol(originalURL.port(), originalURL.protocol()))) {
     196                URL newURL = originalURL;
     197                newURL.setProtocol("https");
     198                if (originalURL.hasPort())
     199                    newURL.setPort(defaultPortForProtocol("https"));
     200                request.setURL(newURL);
     201
     202                if (resourceType == ResourceType::Document && initiatingDocumentLoader.isLoadingMainResource()) {
     203                    // This is to make sure the correct 'new' URL shows in the location bar.
     204                    initiatingDocumentLoader.request().setURL(newURL);
     205                    initiatingDocumentLoader.frameLoader()->client().dispatchDidChangeProvisionalURL();
     206                }
     207                if (currentDocument)
     208                    currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", originalURL.string(), " to ", newURL.string()));
     209            }
     210            break;
     211        }
    192212        case ContentExtensions::ActionType::IgnorePreviousRules:
    193213        case ContentExtensions::ActionType::InvalidAction:
  • trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp

    r194209 r194386  
    550550            return nullptr;
    551551        }
     552        url = request.resourceRequest().url(); // The content extension could have changed it from http to https.
     553        url = MemoryCache::removeFragmentIdentifierIfNeeded(url); // Might need to remove fragment identifier again.
    552554    }
    553555#endif
  • trunk/Source/WebCore/platform/URL.cpp

    r192100 r194386  
    3636#include <wtf/HashMap.h>
    3737#include <wtf/HexNumber.h>
     38#include <wtf/NeverDestroyed.h>
    3839#include <wtf/StdLibExtras.h>
    3940#include <wtf/text/CString.h>
     
    19901991}
    19911992
     1993typedef HashMap<String, unsigned short, CaseFoldingHash> DefaultPortsMap;
     1994static const DefaultPortsMap& defaultPortsMap()
     1995{
     1996    static NeverDestroyed<const DefaultPortsMap> defaultPortsMap(DefaultPortsMap({
     1997        { "http", 80 },
     1998        { "https", 443 },
     1999        { "ftp", 21 },
     2000        { "ftps", 990 }
     2001    }));
     2002    return defaultPortsMap.get();
     2003}
     2004unsigned short defaultPortForProtocol(const String& protocol)
     2005{
     2006    return defaultPortsMap().get(protocol);
     2007}
     2008
    19922009bool isDefaultPortForProtocol(unsigned short port, const String& protocol)
    19932010{
     
    19952012        return false;
    19962013
    1997     typedef HashMap<String, unsigned, CaseFoldingHash> DefaultPortsMap;
    1998     DEPRECATED_DEFINE_STATIC_LOCAL(DefaultPortsMap, defaultPorts, ());
    1999     if (defaultPorts.isEmpty()) {
    2000         defaultPorts.set("http", 80);
    2001         defaultPorts.set("https", 443);
    2002         defaultPorts.set("ftp", 21);
    2003         defaultPorts.set("ftps", 990);
    2004     }
    2005     return defaultPorts.get(protocol) == port;
     2014    return defaultPortForProtocol(protocol) == port;
    20062015}
    20072016
  • trunk/Source/WebCore/platform/URL.h

    r191487 r194386  
    247247WEBCORE_EXPORT bool protocolIsInHTTPFamily(const String& url);
    248248
     249unsigned short defaultPortForProtocol(const String& protocol);
    249250bool isDefaultPortForProtocol(unsigned short port, const String& protocol);
    250251bool portAllowed(const URL&); // Blacklist ports that should never be used for Web resources.
  • trunk/Tools/ChangeLog

    r194381 r194386  
     12015-12-23  Chris Aljoudi <chris@chrismatic.io> and Alex Christensen <achristensen@webkit.org>
     2
     3        Content blockers should be able to promote http to https
     4        https://bugs.webkit.org/show_bug.cgi?id=148966
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
     9        (WebCore::ContentExtensions::operator<<):
     10        (TestWebKitAPI::TEST_F):
     11
    1122015-12-22  Hunseop Jeong  <hs85.jeong@samsung.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp

    r186965 r194386  
    5151    switch (action) {
    5252    case ActionType::BlockLoad:
    53         return os << "ContentFilterAction::BlockLoad";
     53        return os << "ActionType::BlockLoad";
    5454    case ActionType::BlockCookies:
    55         return os << "ContentFilterAction::BlockCookies";
     55        return os << "ActionType::BlockCookies";
    5656    case ActionType::CSSDisplayNoneSelector:
    57         return os << "ContentFilterAction::CSSDisplayNone";
     57        return os << "ActionType::CSSDisplayNone";
    5858    case ActionType::CSSDisplayNoneStyleSheet:
    59         return os << "ContentFilterAction::CSSDisplayNoneStyleSheet";
     59        return os << "ActionType::CSSDisplayNoneStyleSheet";
    6060    case ActionType::IgnorePreviousRules:
    61         return os << "ContentFilterAction::IgnorePreviousRules";
     61        return os << "ActionType::IgnorePreviousRules";
     62    case ActionType::MakeHTTPS:
     63        return os << "ActionType::MakeHTTPS";
    6264    case ActionType::InvalidAction:
    63         return os << "ContentFilterAction::InvalidAction";
     65        return os << "ActionType::InvalidAction";
    6466    }
    6567}
     
    14391441    auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"A*D\"}},"
    14401442        "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"A*BA+\"}},"
    1441         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
     1443        "{\"action\":{\"type\":\"make-https\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
    14421444   
    14431445    testRequest(backend, mainDocumentRequest("http://webkit.org/D"), { ContentExtensions::ActionType::BlockLoad });
     
    14461448    testRequest(backend, mainDocumentRequest("http://webkit.org/ABA"), { }, true);
    14471449    testRequest(backend, mainDocumentRequest("http://webkit.org/ABAD"), { }, true);
    1448     testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::BlockCookies });
    1449     testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::BlockCookies });
    1450     testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::BlockCookies }, true);
    1451     testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::BlockCookies }, true);
    1452     testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
     1450    testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::MakeHTTPS });
     1451    testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::MakeHTTPS });
     1452    testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::MakeHTTPS }, true);
     1453    testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::MakeHTTPS }, true);
     1454    testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::MakeHTTPS, ContentExtensions::ActionType::BlockLoad });
    14531455}
    14541456   
Note: See TracChangeset for help on using the changeset viewer.