Diff
Modified: trunk/LayoutTests/ChangeLog (182167 => 182168)
--- trunk/LayoutTests/ChangeLog 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/LayoutTests/ChangeLog 2015-03-31 00:48:30 UTC (rev 182168)
@@ -1,3 +1,17 @@
+2015-03-30 Alex Christensen <[email protected]>
+
+ [Content Extensions] Correctly handle regular expressions matching everything
+ https://bugs.webkit.org/show_bug.cgi?id=143235
+
+ Reviewed by Benjamin Poulain.
+
+ * http/tests/contentextensions/css-display-none.html:
+ * http/tests/contentextensions/css-display-none.html.json:
+ Test multiple selectors with triggers that match everything.
+ * http/tests/contentextensions/whitelist-expected.txt: Added.
+ * http/tests/contentextensions/whitelist.html: Added.
+ * http/tests/contentextensions/whitelist.html.json: Added.
+
2015-03-30 Mark Lam <[email protected]>
REGRESSION (r181993): inspector-protocol/debugger/setBreakpoint-dfg-and-modify-local.html crashes.
Modified: trunk/LayoutTests/http/tests/contentextensions/css-display-none.html (182167 => 182168)
--- trunk/LayoutTests/http/tests/contentextensions/css-display-none.html 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/LayoutTests/http/tests/contentextensions/css-display-none.html 2015-03-31 00:48:30 UTC (rev 182168)
@@ -2,7 +2,8 @@
<meta charset="UTF-8"></meta>
</head>
<body>
-<p class="hidden_global">This text should not be visible once the global css selector is applied.</p>
+<p class="hidden_global1">This text should not be visible once the global css selector is applied.</p>
+<p class="hidden_global2">This text should not be visible once the global css selector is applied.</p>
<p class="hidden">This text should not be visible once the particular css selector is applied.</p>
<p class="hidden_Ž">This text should not be visible once the particular css selector with non-ascii characters is applied.</p>
<p class="not_hidden">This text should be visible.</p>
Modified: trunk/LayoutTests/http/tests/contentextensions/css-display-none.html.json (182167 => 182168)
--- trunk/LayoutTests/http/tests/contentextensions/css-display-none.html.json 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/LayoutTests/http/tests/contentextensions/css-display-none.html.json 2015-03-31 00:48:30 UTC (rev 182168)
@@ -20,10 +20,27 @@
{
"action": {
"type": "css-display-none",
- "selector": ".hidden_global"
+ "selector": ".hidden_global1"
},
"trigger": {
"url-filter": ".*"
}
+ },
+ {
+ "action": {
+ "type": "css-display-none",
+ "selector": ".hidden_global2"
+ },
+ "trigger": {
+ "url-filter": ".*"
+ }
+ },
+ {
+ "action": {
+ "type": "ignore-previous-rules"
+ },
+ "trigger": {
+ "url-filter": "never_used"
+ }
}
]
Added: trunk/LayoutTests/http/tests/contentextensions/whitelist-expected.txt (0 => 182168)
--- trunk/LayoutTests/http/tests/contentextensions/whitelist-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/contentextensions/whitelist-expected.txt 2015-03-31 00:48:30 UTC (rev 182168)
@@ -0,0 +1,7 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderText {#text} at (0,0) size 192x18
+ text run at (0,0) width 192: "This should load successfully."
Added: trunk/LayoutTests/http/tests/contentextensions/whitelist.html (0 => 182168)
--- trunk/LayoutTests/http/tests/contentextensions/whitelist.html (rev 0)
+++ trunk/LayoutTests/http/tests/contentextensions/whitelist.html 2015-03-31 00:48:30 UTC (rev 182168)
@@ -0,0 +1 @@
+This should load successfully.
Added: trunk/LayoutTests/http/tests/contentextensions/whitelist.html.json (0 => 182168)
--- trunk/LayoutTests/http/tests/contentextensions/whitelist.html.json (rev 0)
+++ trunk/LayoutTests/http/tests/contentextensions/whitelist.html.json 2015-03-31 00:48:30 UTC (rev 182168)
@@ -0,0 +1,18 @@
+[
+ {
+ "action": {
+ "type": "block"
+ },
+ "trigger": {
+ "url-filter": ".*"
+ }
+ },
+ {
+ "action": {
+ "type": "ignore-previous-rules"
+ },
+ "trigger": {
+ "url-filter": "whitelist"
+ }
+ }
+]
Modified: trunk/Source/WebCore/ChangeLog (182167 => 182168)
--- trunk/Source/WebCore/ChangeLog 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/ChangeLog 2015-03-31 00:48:30 UTC (rev 182168)
@@ -1,3 +1,38 @@
+2015-03-30 Alex Christensen <[email protected]>
+
+ [Content Extensions] Correctly handle regular expressions matching everything
+ https://bugs.webkit.org/show_bug.cgi?id=143235
+
+ Reviewed by Benjamin Poulain.
+
+ Test: http/tests/contentextensions/whitelist.html
+
+ * contentextensions/CompiledContentExtension.cpp:
+ (WebCore::ContentExtensions::CompiledContentExtension::globalDisplayNoneSelectors):
+ Global actions can have non-css actions. Only put the selectors into the list of selectors.
+ * contentextensions/ContentExtensionCompiler.cpp:
+ (WebCore::ContentExtensions::serializeSelector):
+ (WebCore::ContentExtensions::serializeActions):
+ Merge sequential css selectors with identical triggers (usually .*) into one action to reduce the number of actions.
+ (WebCore::ContentExtensions::compileRuleList):
+ Fail if a regular _expression_ matches everything after ignore-previous-rules.
+ * contentextensions/ContentExtensionError.cpp:
+ (WebCore::ContentExtensions::contentExtensionErrorCategory):
+ * contentextensions/ContentExtensionError.h:
+ Add more failure cases.
+ * contentextensions/ContentExtensionRule.h:
+ (WebCore::ContentExtensions::Trigger::operator==):
+ Allow comparing of Triggers to determine if sequential triggers are equal.
+ * contentextensions/ContentExtensionsBackend.cpp:
+ (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
+ Put non-css actions that match everything into the list of actions if ignore-previous-rules was not hit.
+ These actions will be out of order, but order only matters when determining if ignore-previous-rules, and this case is handled correctly.
+ * contentextensions/DFABytecodeInterpreter.cpp:
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsFromDFARoot):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+ Added an assertion that all actions that match everything should be in the first DFA root.
+ We should catch them all with URLFilterParser::MatchesEverything.
+
2015-03-30 Myles C. Maxfield <[email protected]>
Allow building on Windows without Cygwin
Modified: trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -47,8 +47,7 @@
Vector<String> selectors;
for (Action& action : globalActions) {
- ASSERT(action.type() == ActionType::CSSDisplayNoneSelector);
- if (action.stringArgument().length())
+ if (action.type() == ActionType::CSSDisplayNoneSelector)
selectors.append(action.stringArgument());
}
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -41,10 +41,33 @@
#include <wtf/CurrentTime.h>
#include <wtf/DataLog.h>
#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
namespace WebCore {
namespace ContentExtensions {
+static void serializeSelector(Vector<SerializedActionByte>& actions, const String& selector)
+{
+ // Append action type (1 byte).
+ actions.append(static_cast<SerializedActionByte>(ActionType::CSSDisplayNoneSelector));
+ // Append Selector length (4 bytes).
+ unsigned selectorLength = selector.length();
+ actions.resize(actions.size() + sizeof(unsigned));
+ *reinterpret_cast<unsigned*>(&actions[actions.size() - sizeof(unsigned)]) = selectorLength;
+ bool wideCharacters = !selector.is8Bit();
+ actions.append(wideCharacters);
+ // Append Selector.
+ if (wideCharacters) {
+ unsigned startIndex = actions.size();
+ actions.resize(actions.size() + sizeof(UChar) * selectorLength);
+ for (unsigned i = 0; i < selectorLength; ++i)
+ *reinterpret_cast<UChar*>(&actions[startIndex + i * sizeof(UChar)]) = selector[i];
+ } else {
+ for (unsigned i = 0; i < selectorLength; ++i)
+ actions.append(selector[i]);
+ }
+}
+
static Vector<unsigned> serializeActions(const Vector<ContentExtensionRule>& ruleList, Vector<SerializedActionByte>& actions)
{
ASSERT(!actions.size());
@@ -54,14 +77,33 @@
for (unsigned ruleIndex = 0; ruleIndex < ruleList.size(); ++ruleIndex) {
const ContentExtensionRule& rule = ruleList[ruleIndex];
+ // Consolidate css selectors with identical triggers.
+ if (rule.action().type() == ActionType::CSSDisplayNoneSelector) {
+ StringBuilder selector;
+ selector.append(rule.action().stringArgument());
+ actionLocations.append(actions.size());
+ for (unsigned i = ruleIndex + 1; i < ruleList.size(); i++) {
+ if (rule.trigger() == ruleList[i].trigger() && ruleList[i].action().type() == ActionType::CSSDisplayNoneSelector) {
+ actionLocations.append(actions.size());
+ ruleIndex++;
+ selector.append(',');
+ selector.append(ruleList[i].action().stringArgument());
+ } else
+ break;
+ }
+ serializeSelector(actions, selector.toString());
+ continue;
+ }
+
// Identical sequential actions should not be rewritten.
if (ruleIndex && rule.action() == ruleList[ruleIndex - 1].action()) {
actionLocations.append(actionLocations[ruleIndex - 1]);
continue;
}
+
actionLocations.append(actions.size());
-
switch (rule.action().type()) {
+ case ActionType::CSSDisplayNoneSelector:
case ActionType::CSSDisplayNoneStyleSheet:
case ActionType::InvalidAction:
RELEASE_ASSERT_NOT_REACHED();
@@ -71,30 +113,7 @@
case ActionType::IgnorePreviousRules:
actions.append(static_cast<SerializedActionByte>(rule.action().type()));
break;
-
- case ActionType::CSSDisplayNoneSelector: {
- const String& selector = rule.action().stringArgument();
- // Append action type (1 byte).
- actions.append(static_cast<SerializedActionByte>(ActionType::CSSDisplayNoneSelector));
- // Append Selector length (4 bytes).
- unsigned selectorLength = selector.length();
- actions.resize(actions.size() + sizeof(unsigned));
- *reinterpret_cast<unsigned*>(&actions[actions.size() - sizeof(unsigned)]) = selectorLength;
- bool wideCharacters = !selector.is8Bit();
- actions.append(wideCharacters);
- // Append Selector.
- if (wideCharacters) {
- for (unsigned i = 0; i < selectorLength; i++) {
- actions.resize(actions.size() + sizeof(UChar));
- *reinterpret_cast<UChar*>(&actions[actions.size() - sizeof(UChar)]) = selector[i];
- }
- } else {
- for (unsigned i = 0; i < selectorLength; i++)
- actions.append(selector[i]);
- }
- break;
}
- }
}
return actionLocations;
}
@@ -117,7 +136,7 @@
Vector<NFA> nfas;
nfas.append(NFA());
- bool nonUniversalActionSeen = false;
+ bool ignorePreviousRulesSeen = false;
for (unsigned ruleIndex = 0; ruleIndex < parsedRuleList.size(); ++ruleIndex) {
// FIXME: Tune this better and adjust ContentExtensionTest.MultiDFA accordingly.
@@ -135,16 +154,18 @@
URLFilterParser::ParseStatus status = urlFilterParser.addPattern(trigger.urlFilter, trigger.urlFilterIsCaseSensitive, actionLocationAndFlags);
if (status == URLFilterParser::MatchesEverything) {
- if (nonUniversalActionSeen)
- dataLogF("Trigger matching everything found not at beginning. This may cause incorrect behavior with ignore-previous-rules");
+ if (ignorePreviousRulesSeen)
+ return ContentExtensionError::RegexMatchesEverythingAfterIgnorePreviousRules;
universalActionLocations.append(actionLocationAndFlags);
- } else
- nonUniversalActionSeen = true;
+ }
if (status != URLFilterParser::Ok && status != URLFilterParser::MatchesEverything) {
dataLogF("Error while parsing %s: %s\n", trigger.urlFilter.utf8().data(), URLFilterParser::statusString(status).utf8().data());
- continue;
+ return ContentExtensionError::JSONInvalidRegex;
}
+
+ if (contentExtensionRule.action().type() == ActionType::IgnorePreviousRules)
+ ignorePreviousRulesSeen = true;
}
#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
@@ -172,6 +193,7 @@
dfa.debugPrintDot();
#endif
+ ASSERT_WITH_MESSAGE(!dfa.nodeAt(dfa.root()).actions.size(), "All actions on the DFA root should come from regular expressions that match everything.");
if (!i) {
// Put all the universal actions on the first DFA.
for (uint64_t actionLocation : universalActionLocations)
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -73,6 +73,10 @@
return "Invalid action type.";
case ContentExtensionError::JSONInvalidCSSDisplayNoneActionType:
return "Invalid css-display-none action type. Requires a selector.";
+ case ContentExtensionError::JSONInvalidRegex:
+ return "Invalid or unsupported regular _expression_.";
+ case ContentExtensionError::RegexMatchesEverythingAfterIgnorePreviousRules:
+ return "Regular expressions that match everything are only allowed before the first ignore-previous-rules.";
}
return std::string();
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionError.h (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/ContentExtensionError.h 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionError.h 2015-03-31 00:48:30 UTC (rev 182168)
@@ -53,6 +53,9 @@
JSONInvalidAction,
JSONInvalidActionType,
JSONInvalidCSSDisplayNoneActionType,
+ JSONInvalidRegex,
+
+ RegexMatchesEverythingAfterIgnorePreviousRules,
};
const std::error_category& contentExtensionErrorCategory();
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionRule.h (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/ContentExtensionRule.h 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionRule.h 2015-03-31 00:48:30 UTC (rev 182168)
@@ -45,6 +45,12 @@
String urlFilter;
bool urlFilterIsCaseSensitive { false };
ResourceFlags flags { 0 };
+ bool operator==(const Trigger& other) const
+ {
+ return urlFilter == other.urlFilter
+ && urlFilterIsCaseSensitive == other.urlFilterIsCaseSensitive
+ && flags == other.flags;
+ }
};
struct Action {
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -104,8 +104,17 @@
finalActions.append(action);
}
}
- if (!sawIgnorePreviousRules)
+ if (!sawIgnorePreviousRules) {
+ DFABytecodeInterpreter::Actions universalActions = interpreter.actionsFromDFARoot();
+ for (auto actionLocation : universalActions) {
+ Action action = "" actionsLength, actionLocation);
+
+ // CSS selectors were already compiled into a stylesheet using globalDisplayNoneSelectors.
+ if (action.type() != ActionType::CSSDisplayNoneSelector)
+ finalActions.append(action);
+ }
finalActions.append(Action(ActionType::CSSDisplayNoneStyleSheet, contentExtension->identifier()));
+ }
}
return finalActions;
}
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (182167 => 182168)
--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -47,6 +47,7 @@
// Skip first DFA header. All universal actions are in the first DFA root.
unsigned programCounter = sizeof(unsigned);
+
while (static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]) == DFABytecodeInstruction::AppendAction) {
universalActionLocations.add(static_cast<uint64_t>(getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode))));
programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
@@ -69,10 +70,11 @@
unsigned dfaBytecodeLength = getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter);
programCounter += sizeof(unsigned);
- // Skip the universal actions.
- // FIXME: Replace AppendAction with AppendActions to make this just one jump and make sure there aren't universal actions with flags.
- while (static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]) == DFABytecodeInstruction::AppendAction)
+ // Skip the actions on the DFA root. These are accessed via actionsFromDFARoot.
+ while (static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]) == DFABytecodeInstruction::AppendAction) {
+ ASSERT_WITH_MESSAGE(!dfaStart, "Triggers that match everything should only be in the first DFA.");
programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
+ }
// Interpret the bytecode from this DFA.
// This should always terminate if interpreting correctly compiled bytecode.
Modified: trunk/Tools/ChangeLog (182167 => 182168)
--- trunk/Tools/ChangeLog 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Tools/ChangeLog 2015-03-31 00:48:30 UTC (rev 182168)
@@ -1,3 +1,15 @@
+2015-03-30 Alex Christensen <[email protected]>
+
+ [Content Extensions] Correctly handle regular expressions matching everything
+ https://bugs.webkit.org/show_bug.cgi?id=143235
+
+ Reviewed by Benjamin Poulain.
+
+ * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+ (TestWebKitAPI::checkCompilerError):
+ (TestWebKitAPI::TEST_F):
+ Test ContentExtensionErrors.
+
2015-03-30 Alexey Proskuryakov <[email protected]>
DumpRenderTree should set NSWindowDisplayWithRunLoopObserver
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (182167 => 182168)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2015-03-31 00:43:49 UTC (rev 182167)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2015-03-31 00:48:30 UTC (rev 182168)
@@ -28,6 +28,7 @@
#include "PlatformUtilities.h"
#include <_javascript_Core/InitializeThreading.h>
#include <WebCore/ContentExtensionCompiler.h>
+#include <WebCore/ContentExtensionError.h>
#include <WebCore/ContentExtensionsBackend.h>
#include <WebCore/NFA.h>
#include <WebCore/ResourceLoadInfo.h>
@@ -573,6 +574,53 @@
testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
}
+void checkCompilerError(const char* json, ContentExtensions::ContentExtensionError expectedError)
+{
+ WebCore::ContentExtensions::CompiledContentExtensionData extensionData;
+ InMemoryContentExtensionCompilationClient client(extensionData);
+ std::error_code compilerError = ContentExtensions::compileRuleList(client, json);
+ EXPECT_EQ(compilerError.value(), static_cast<int>(expectedError));
+}
+
+TEST_F(ContentExtensionTest, InvalidJSON)
+{
+ checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
+ checkCompilerError("123", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnObject);
+ checkCompilerError("{}", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnArray);
+ // FIXME: Add unit test for JSONInvalidRule if that is possible to hit.
+ checkCompilerError("[]", ContentExtensions::ContentExtensionError::JSONContainsNoRules);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":5}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+
+ // FIXME: Add unit test for JSONInvalidObjectInTriggerFlagsArray if that is possible to hit.
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+
+ checkCompilerError("[{\"action\":5,\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidAction);
+ checkCompilerError("[{\"action\":{\"type\":\"invalid\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidActionType);
+ checkCompilerError("[{\"action\":{\"type\":\"css-display-none\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
+
+ checkCompilerError("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"webkit.org\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]",
+ ContentExtensions::ContentExtensionError::RegexMatchesEverythingAfterIgnorePreviousRules);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidRegex);
+}
+
static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
{
ContentExtensions::NFA nfa;