Diff
Modified: trunk/Source/WebCore/ChangeLog (184643 => 184644)
--- trunk/Source/WebCore/ChangeLog 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/ChangeLog 2015-05-20 17:56:17 UTC (rev 184644)
@@ -1,3 +1,53 @@
+2015-05-20 Alex Christensen <[email protected]>
+
+ [Content Extensions] Relax restrictions on triggers that match everything.
+ https://bugs.webkit.org/show_bug.cgi?id=145069
+
+ Reviewed by Benjamin Poulain.
+
+ Added API tests that cover the new functionality and test for correctness in behavior.
+
+ * contentextensions/CompiledContentExtension.cpp:
+ (WebCore::ContentExtensions::CompiledContentExtension::globalDisplayNoneSelectors):
+ * contentextensions/ContentExtensionCompiler.cpp:
+ (WebCore::ContentExtensions::addUniversalActionsToDFA):
+ (WebCore::ContentExtensions::compileRuleList):
+ Put universalActionsWithoutDomains into the DFA from filtersWithoutDomains and
+ put universalActionsWithDomains into the DFA from filtersWithDomains.
+ * contentextensions/ContentExtensionError.cpp:
+ (WebCore::ContentExtensions::contentExtensionErrorCategory):
+ * contentextensions/ContentExtensionError.h:
+ Remove error codes for errors that are not errors any more.
+ * contentextensions/ContentExtensionsBackend.cpp:
+ (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
+ * contentextensions/ContentExtensionsBackend.h:
+ * contentextensions/DFABytecode.h:
+ (WebCore::ContentExtensions::instructionSizeWithArguments):
+ * contentextensions/DFABytecodeCompiler.cpp:
+ (WebCore::ContentExtensions::set32Bits):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitJump):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValue):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValueRange):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::compileNode):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::compile):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitTestFlagsAndAppendAction): Deleted.
+ * contentextensions/DFABytecodeCompiler.h:
+ * contentextensions/DFABytecodeInterpreter.cpp:
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsFromDFARoot): Deleted.
+ * contentextensions/DFABytecodeInterpreter.h:
+ Add a new bytecode AppendActionDefaultStylesheet to mark actions that are css-display-none
+ that need to be put in the default stylesheet to be ignored or not as a whole.
+ css-display-none actions with flags or domain rules and css-display-none actions
+ after ignore-previous-rules actions are not to be in this precompiled stylesheet, but
+ they will be applied as needed per page. The precompiled stylesheet is already applied
+ if no ignore-previous-rules action is triggered.
+ * loader/ResourceLoadInfo.h:
+
2015-05-20 Youenn Fablet <[email protected]>
JS binding generator should create a member variable for each Promise attribute of an interface
Modified: trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/CompiledContentExtension.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -39,7 +39,7 @@
Vector<String> CompiledContentExtension::globalDisplayNoneSelectors(Vector<bool>& pagesUsed)
{
DFABytecodeInterpreter interpreter(filtersWithoutDomainsBytecode(), filtersWithoutDomainsBytecodeLength(), pagesUsed);
- DFABytecodeInterpreter::Actions actionLocations = interpreter.actionsFromDFARoot();
+ DFABytecodeInterpreter::Actions actionLocations = interpreter.actionsForDefaultStylesheetFromDFARoot();
Vector<Action> globalActions;
for (uint64_t actionLocation : actionLocations)
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -121,21 +121,24 @@
return actionLocations;
}
-typedef HashSet<uint64_t, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> UniversalActionLocationsSet;
+typedef HashSet<uint64_t, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> UniversalActionSet;
-static void addUniversalActionsToDFA(DFA& dfa, const UniversalActionLocationsSet& universalActionLocations)
+static void addUniversalActionsToDFA(DFA& dfa, const UniversalActionSet& universalActions)
{
- if (universalActionLocations.isEmpty())
+ if (universalActions.isEmpty())
return;
+ DFANode& root = dfa.nodes[dfa.root];
+ ASSERT(!root.actionsLength());
unsigned actionsStart = dfa.actions.size();
- dfa.actions.reserveCapacity(dfa.actions.size() + universalActionLocations.size());
- for (uint64_t actionLocation : universalActionLocations)
- dfa.actions.uncheckedAppend(actionLocation);
+ dfa.actions.reserveCapacity(dfa.actions.size() + universalActions.size());
+ for (uint64_t action : universalActions)
+ dfa.actions.uncheckedAppend(action);
unsigned actionsEnd = dfa.actions.size();
+
unsigned actionsLength = actionsEnd - actionsStart;
RELEASE_ASSERT_WITH_MESSAGE(actionsLength < std::numeric_limits<uint16_t>::max(), "Too many uncombined actions that match everything");
- dfa.nodes[dfa.root].setActions(actionsStart, static_cast<uint16_t>(actionsLength));
+ root.setActions(actionsStart, static_cast<uint16_t>(actionsLength));
}
std::error_code compileRuleList(ContentExtensionCompilationClient& client, String&& ruleList)
@@ -156,7 +159,8 @@
LOG_LARGE_STRUCTURES(actions, actions.capacity() * sizeof(SerializedActionByte));
actions.clear();
- UniversalActionLocationsSet universalActionLocations;
+ UniversalActionSet universalActionsWithoutDomains;
+ UniversalActionSet universalActionsWithDomains;
// FIXME: These don't all need to be in memory at the same time.
CombinedURLFilters filtersWithoutDomains;
@@ -169,6 +173,7 @@
for (unsigned ruleIndex = 0; ruleIndex < parsedRuleList.size(); ++ruleIndex) {
const ContentExtensionRule& contentExtensionRule = parsedRuleList[ruleIndex];
const Trigger& trigger = contentExtensionRule.trigger();
+ const Action& action = ""
ASSERT(trigger.urlFilter.length());
// High bits are used for flags. This should match how they are used in DFABytecodeCompiler::compileNode.
@@ -178,9 +183,12 @@
ASSERT(trigger.domainCondition == Trigger::DomainCondition::None);
status = filtersWithoutDomainParser.addPattern(trigger.urlFilter, trigger.urlFilterIsCaseSensitive, actionLocationAndFlags);
if (status == URLFilterParser::MatchesEverything) {
- if (ignorePreviousRulesSeen)
- return ContentExtensionError::RegexMatchesEverythingAfterIgnorePreviousRules;
- universalActionLocations.add(actionLocationAndFlags);
+ if (!ignorePreviousRulesSeen
+ && trigger.domainCondition == Trigger::DomainCondition::None
+ && action.type() == ActionType::CSSDisplayNoneSelector
+ && !trigger.flags)
+ actionLocationAndFlags |= DisplayNoneStyleSheetFlag;
+ universalActionsWithoutDomains.add(actionLocationAndFlags);
status = URLFilterParser::Ok;
}
if (status != URLFilterParser::Ok) {
@@ -196,8 +204,10 @@
}
status = filtersWithDomainParser.addPattern(trigger.urlFilter, trigger.urlFilterIsCaseSensitive, actionLocationAndFlags);
- if (status == URLFilterParser::MatchesEverything)
- return ContentExtensionError::RegexMatchesEverythingWithDomains;
+ if (status == URLFilterParser::MatchesEverything) {
+ universalActionsWithDomains.add(actionLocationAndFlags);
+ status = URLFilterParser::Ok;
+ }
if (status != URLFilterParser::Ok) {
dataLogF("Error while parsing %s: %s\n", trigger.urlFilter.utf8().data(), URLFilterParser::statusString(status).utf8().data());
return ContentExtensionError::JSONInvalidRegex;
@@ -207,7 +217,7 @@
}
ASSERT(status == URLFilterParser::Ok);
- if (contentExtensionRule.action().type() == ActionType::IgnorePreviousRules)
+ if (action.type() == ActionType::IgnorePreviousRules)
ignorePreviousRulesSeen = true;
}
LOG_LARGE_STRUCTURES(parsedRuleList, parsedRuleList.capacity() * sizeof(ContentExtensionRule)); // Doesn't include strings.
@@ -231,7 +241,7 @@
// FIXME: This can be tuned. More NFAs take longer to interpret, fewer use more memory and time to compile.
const unsigned maxNFASize = 50000;
- bool firstNFASeen = false;
+ bool firstNFAWithoutDomainsSeen = false;
// FIXME: Combine small NFAs to reduce the number of NFAs.
filtersWithoutDomains.processNFAs(maxNFASize, [&](NFA&& nfa) {
#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
@@ -252,9 +262,9 @@
#endif
ASSERT_WITH_MESSAGE(!dfa.nodes[dfa.root].hasActions(), "All actions on the DFA root should come from regular expressions that match everything.");
- if (!firstNFASeen) {
+ if (!firstNFAWithoutDomainsSeen) {
// Put all the universal actions on the first DFA.
- addUniversalActionsToDFA(dfa, universalActionLocations);
+ addUniversalActionsToDFA(dfa, universalActionsWithoutDomains);
}
Vector<DFABytecode> bytecode;
@@ -263,18 +273,18 @@
LOG_LARGE_STRUCTURES(bytecode, bytecode.capacity() * sizeof(uint8_t));
client.writeFiltersWithoutDomainsBytecode(WTF::move(bytecode));
- firstNFASeen = true;
+ firstNFAWithoutDomainsSeen = true;
});
ASSERT(filtersWithoutDomains.isEmpty());
- if (!firstNFASeen) {
+ if (!firstNFAWithoutDomainsSeen) {
// Our bytecode interpreter expects to have at least one DFA, so if we haven't seen any
// create a dummy one and add any universal actions.
NFA dummyNFA;
DFA dummyDFA = NFAToDFA::convert(dummyNFA);
- addUniversalActionsToDFA(dummyDFA, universalActionLocations);
+ addUniversalActionsToDFA(dummyDFA, universalActionsWithoutDomains);
Vector<DFABytecode> bytecode;
DFABytecodeCompiler compiler(dummyDFA, bytecode);
@@ -282,9 +292,10 @@
LOG_LARGE_STRUCTURES(bytecode, bytecode.capacity() * sizeof(uint8_t));
client.writeFiltersWithoutDomainsBytecode(WTF::move(bytecode));
}
- LOG_LARGE_STRUCTURES(universalActionLocations, universalActionLocations.capacity() * sizeof(unsigned));
- universalActionLocations.clear();
+ LOG_LARGE_STRUCTURES(universalAction, universalAction.capacity() * sizeof(unsigned));
+ universalActionsWithoutDomains.clear();
+ bool firstNFAWithDomainsSeen = false;
filtersWithDomains.processNFAs(maxNFASize, [&](NFA&& nfa) {
#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
dataLogF("filtersWithDomains NFA\n");
@@ -304,13 +315,38 @@
#endif
ASSERT_WITH_MESSAGE(!dfa.nodes[dfa.root].hasActions(), "Filters with domains that match everything are not allowed right now.");
+ if (!firstNFAWithDomainsSeen) {
+ // Put all the universal actions on the first DFA.
+ addUniversalActionsToDFA(dfa, universalActionsWithDomains);
+ }
+
Vector<DFABytecode> bytecode;
DFABytecodeCompiler compiler(dfa, bytecode);
compiler.compile();
LOG_LARGE_STRUCTURES(bytecode, bytecode.capacity() * sizeof(uint8_t));
client.writeFiltersWithDomainsBytecode(WTF::move(bytecode));
+
+ firstNFAWithDomainsSeen = true;
});
ASSERT(filtersWithDomains.isEmpty());
+
+ if (!firstNFAWithDomainsSeen) {
+ // Our bytecode interpreter expects to have at least one DFA, so if we haven't seen any
+ // create a dummy one and add any universal actions.
+
+ NFA dummyNFA;
+ DFA dummyDFA = NFAToDFA::convert(dummyNFA);
+
+ addUniversalActionsToDFA(dummyDFA, universalActionsWithDomains);
+
+ Vector<DFABytecode> bytecode;
+ DFABytecodeCompiler compiler(dummyDFA, bytecode);
+ compiler.compile();
+ LOG_LARGE_STRUCTURES(bytecode, bytecode.capacity() * sizeof(uint8_t));
+ client.writeFiltersWithDomainsBytecode(WTF::move(bytecode));
+ }
+ LOG_LARGE_STRUCTURES(universalActionsWithDomains, universalActionsWithDomains.capacity() * sizeof(unsigned));
+ universalActionsWithDomains.clear();
domainFilters.processNFAs(maxNFASize, [&](NFA&& nfa) {
#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionError.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -75,10 +75,6 @@
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.";
- case ContentExtensionError::RegexMatchesEverythingWithDomains:
- return "Regular expressions that match everything are not allowed with unless- or if-domain.";
case ContentExtensionError::JSONInvalidDomainList:
return "Invalid domain list.";
case ContentExtensionError::JSONDomainNotLowerCaseASCII:
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionError.h (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/ContentExtensionError.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionError.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -57,9 +57,6 @@
JSONInvalidActionType,
JSONInvalidCSSDisplayNoneActionType,
JSONInvalidRegex,
-
- RegexMatchesEverythingAfterIgnorePreviousRules,
- RegexMatchesEverythingWithDomains,
};
WEBCORE_EXPORT const std::error_category& contentExtensionErrorCategory();
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -146,16 +146,6 @@
}
}
if (!sawIgnorePreviousRules) {
- DFABytecodeInterpreter::Actions universalActions = withoutDomainsInterpreter.actionsFromDFARoot();
- for (uint64_t actionLocation : universalActions) {
- // FIXME: We shouldn't deserialize an action all the way if it is a css-display-none selector.
- Action action = "" actionsLength, static_cast<unsigned>(actionLocation));
- action.setExtensionIdentifier(contentExtension->identifier());
-
- // 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()));
finalActions.last().setExtensionIdentifier(contentExtension->identifier());
}
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.h (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -63,7 +63,7 @@
// - Internal WebCore Interface.
WEBCORE_EXPORT Vector<Action> actionsForResourceLoad(const ResourceLoadInfo&) const;
- StyleSheetContents* globalDisplayNoneStyleSheet(const String& identifier) const;
+ WEBCORE_EXPORT StyleSheetContents* globalDisplayNoneStyleSheet(const String& identifier) const;
void processContentExtensionRulesForLoad(ResourceRequest&, ResourceType, DocumentLoader& initiatingDocumentLoader);
Modified: trunk/Source/WebCore/contentextensions/DFABytecode.h (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/DFABytecode.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/DFABytecode.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -55,6 +55,7 @@
// AppendAction has one argument:
// The action to append (4 bytes).
AppendAction,
+ AppendActionDefaultStylesheet,
AppendActionWithIfDomain,
// TestFlagsAndAppendAction has two arguments:
@@ -76,20 +77,21 @@
switch (instruction) {
case DFABytecodeInstruction::CheckValueCaseSensitive:
case DFABytecodeInstruction::CheckValueCaseInsensitive:
- return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(unsigned);
+ return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(uint32_t);
case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
- return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(unsigned);
+ return sizeof(DFABytecodeInstruction) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t);
case DFABytecodeInstruction::AppendAction:
+ case DFABytecodeInstruction::AppendActionDefaultStylesheet:
case DFABytecodeInstruction::AppendActionWithIfDomain:
- return sizeof(DFABytecodeInstruction) + sizeof(unsigned);
+ return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
case DFABytecodeInstruction::TestFlagsAndAppendAction:
case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain:
- return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(unsigned);
+ return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
case DFABytecodeInstruction::Terminate:
return sizeof(DFABytecodeInstruction);
case DFABytecodeInstruction::Jump:
- return sizeof(DFABytecodeInstruction) + sizeof(unsigned);
+ return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
}
}
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -43,47 +43,50 @@
*reinterpret_cast<IntType*>(&bytecode[bytecode.size() - sizeof(IntType)]) = value;
}
-inline void set32Bits(Vector<DFABytecode>& bytecode, unsigned index, unsigned value)
+inline void set32Bits(Vector<DFABytecode>& bytecode, uint32_t index, uint32_t value)
{
- *reinterpret_cast<unsigned*>(&bytecode[index]) = value;
+ *reinterpret_cast<uint32_t*>(&bytecode[index]) = value;
}
-void DFABytecodeCompiler::emitAppendAction(unsigned action, bool ifDomain)
+void DFABytecodeCompiler::emitAppendAction(uint64_t action)
{
- if (ifDomain)
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionWithIfDomain);
- else
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendAction);
- append<unsigned>(m_bytecode, action);
+ // High bits are used to store flags. See compileRuleList.
+ if (action & 0xFFFF00000000) {
+ ASSERT(!(action & DisplayNoneStyleSheetFlag));
+ if (action & IfDomainFlag)
+ append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
+ else
+ append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendAction);
+ append<uint16_t>(m_bytecode, static_cast<uint16_t>(action >> 32));
+ append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
+ } else {
+ if (action & DisplayNoneStyleSheetFlag) {
+ RELEASE_ASSERT(!(action & IfDomainFlag));
+ append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionDefaultStylesheet);
+ } else if (action & IfDomainFlag)
+ append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionWithIfDomain);
+ else
+ append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendAction);
+ append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
+ }
}
-void DFABytecodeCompiler::emitTestFlagsAndAppendAction(uint16_t flags, unsigned action, bool ifDomain)
+void DFABytecodeCompiler::emitJump(uint32_t destinationNodeIndex)
{
- ASSERT(flags);
- if (ifDomain)
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
- else
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendAction);
- append<uint16_t>(m_bytecode, flags);
- append<unsigned>(m_bytecode, action);
-}
-
-void DFABytecodeCompiler::emitJump(unsigned destinationNodeIndex)
-{
append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::Jump);
m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
- append<unsigned>(m_bytecode, 0); // This value will be set when linking.
+ append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
}
-void DFABytecodeCompiler::emitCheckValue(uint8_t value, unsigned destinationNodeIndex, bool caseSensitive)
+void DFABytecodeCompiler::emitCheckValue(uint8_t value, uint32_t destinationNodeIndex, bool caseSensitive)
{
append<DFABytecodeInstruction>(m_bytecode, caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive);
append<uint8_t>(m_bytecode, value);
m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
- append<unsigned>(m_bytecode, 0); // This value will be set when linking.
+ append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
}
-void DFABytecodeCompiler::emitCheckValueRange(uint8_t lowValue, uint8_t highValue, unsigned destinationNodeIndex, bool caseSensitive)
+void DFABytecodeCompiler::emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t destinationNodeIndex, bool caseSensitive)
{
ASSERT_WITH_MESSAGE(lowValue < highValue, "The instruction semantic impose lowValue is strictly less than highValue.");
@@ -91,7 +94,7 @@
append<uint8_t>(m_bytecode, lowValue);
append<uint8_t>(m_bytecode, highValue);
m_linkRecords.append(std::make_pair(m_bytecode.size(), destinationNodeIndex));
- append<unsigned>(m_bytecode, 0); // This value will be set when linking.
+ append<uint32_t>(m_bytecode, 0); // This value will be set when linking.
}
void DFABytecodeCompiler::emitTerminate()
@@ -99,11 +102,11 @@
append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::Terminate);
}
-void DFABytecodeCompiler::compileNode(unsigned index, bool root)
+void DFABytecodeCompiler::compileNode(uint32_t index, bool root)
{
const DFANode& node = m_dfa.nodes[index];
if (node.isKilled()) {
- m_nodeStartOffsets[index] = std::numeric_limits<unsigned>::max();
+ m_nodeStartOffsets[index] = std::numeric_limits<uint32_t>::max();
return;
}
@@ -111,13 +114,8 @@
if (!root)
m_nodeStartOffsets[index] = m_bytecode.size();
- for (uint64_t action : node.actions(m_dfa)) {
- // High bits are used to store flags. A boolean is stored in the 48th bit. See compileRuleList.
- if (action & 0xFFFF00000000)
- emitTestFlagsAndAppendAction(static_cast<uint16_t>(action >> 32), static_cast<unsigned>(action), action & IfDomainFlag);
- else
- emitAppendAction(static_cast<unsigned>(action), action & IfDomainFlag);
- }
+ for (uint64_t action : node.actions(m_dfa))
+ emitAppendAction(action);
// If we jump to the root, we don't want to re-add its actions to a HashSet.
// We know we have already added them because the root is always compiled first and we always start interpreting at the beginning.
@@ -212,24 +210,24 @@
void DFABytecodeCompiler::compile()
{
// DFA header.
- unsigned startLocation = m_bytecode.size();
- append<unsigned>(m_bytecode, 0);
+ uint32_t startLocation = m_bytecode.size();
+ append<uint32_t>(m_bytecode, 0);
m_nodeStartOffsets.resize(m_dfa.nodes.size());
// Make sure the root is always at the beginning of the bytecode.
compileNode(m_dfa.root, true);
- for (unsigned i = 0; i < m_dfa.nodes.size(); i++) {
+ for (uint32_t i = 0; i < m_dfa.nodes.size(); i++) {
if (i != m_dfa.root)
compileNode(i, false);
}
// Link.
for (const auto& linkRecord : m_linkRecords) {
- unsigned offset = linkRecord.first;
- ASSERT(!(*reinterpret_cast<unsigned*>(&m_bytecode[offset])));
+ uint32_t offset = linkRecord.first;
+ ASSERT(!(*reinterpret_cast<uint32_t*>(&m_bytecode[offset])));
- unsigned target = m_nodeStartOffsets[linkRecord.second];
- RELEASE_ASSERT(target != std::numeric_limits<unsigned>::max());
+ uint32_t target = m_nodeStartOffsets[linkRecord.second];
+ RELEASE_ASSERT(target != std::numeric_limits<uint32_t>::max());
set32Bits(m_bytecode, offset, m_nodeStartOffsets[linkRecord.second]);
}
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -50,7 +50,7 @@
private:
struct Range {
- Range(uint8_t min, uint8_t max, unsigned destination, bool caseSensitive)
+ Range(uint8_t min, uint8_t max, uint32_t destination, bool caseSensitive)
: min(min)
, max(max)
, destination(destination)
@@ -59,28 +59,27 @@
}
uint8_t min;
uint8_t max;
- unsigned destination;
+ uint32_t destination;
bool caseSensitive;
};
- void compileNode(unsigned, bool root);
+ void compileNode(uint32_t, bool root);
void compileNodeTransitions(const DFANode&);
void compileCheckForRange(const Range&);
- void emitAppendAction(unsigned, bool ifDomain);
- void emitTestFlagsAndAppendAction(uint16_t flags, unsigned, bool ifDomain);
- void emitJump(unsigned destinationNodeIndex);
- void emitCheckValue(uint8_t value, unsigned destinationNodeIndex, bool caseSensitive);
- void emitCheckValueRange(uint8_t lowValue, uint8_t highValue, unsigned destinationNodeIndex, bool caseSensitive);
+ void emitAppendAction(uint64_t);
+ void emitJump(uint32_t destinationNodeIndex);
+ void emitCheckValue(uint8_t value, uint32_t destinationNodeIndex, bool caseSensitive);
+ void emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t destinationNodeIndex, bool caseSensitive);
void emitTerminate();
Vector<DFABytecode>& m_bytecode;
const DFA& m_dfa;
- Vector<unsigned> m_nodeStartOffsets;
+ Vector<uint32_t> m_nodeStartOffsets;
// The first value is the index in the bytecode buffer where the jump is to be written.
// The second value is the index of the node to jump to.
- Vector<std::pair<unsigned, unsigned>> m_linkRecords;
+ Vector<std::pair<uint32_t, uint32_t>> m_linkRecords;
};
} // namespace ContentExtensions
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -53,9 +53,12 @@
void DFABytecodeInterpreter::interpretAppendAction(unsigned& programCounter, Actions& actions, bool ifDomain)
{
ASSERT(getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendAction
- || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionWithIfDomain);
+ || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionWithIfDomain
+ || getBits<DFABytecodeInstruction>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed) == DFABytecodeInstruction::AppendActionDefaultStylesheet);
actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed)));
programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
+ ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfDomain));
+ ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet));
}
void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(unsigned& programCounter, uint16_t flags, Actions& actions, bool ifDomain)
@@ -65,9 +68,10 @@
if (flags & getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode), m_pagesUsed))
actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecode) + sizeof(uint16_t), m_pagesUsed)));
programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
+ ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain));
}
-DFABytecodeInterpreter::Actions DFABytecodeInterpreter::actionsFromDFARoot()
+DFABytecodeInterpreter::Actions DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot()
{
Actions actions;
@@ -77,12 +81,19 @@
while (programCounter < dfaBytecodeLength) {
DFABytecodeInstruction instruction = static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]);
- if (instruction == DFABytecodeInstruction::AppendAction)
+ if (instruction == DFABytecodeInstruction::AppendActionDefaultStylesheet)
interpretAppendAction(programCounter, actions, false);
+ else if (instruction == DFABytecodeInstruction::AppendAction)
+ programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
- else
+ else {
+ // actionsForDefaultStylesheetFromDFARoot should only be called on the DFA without domains,
+ // which should never have any actions with if-domain.
+ ASSERT(instruction != DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain);
+ ASSERT(instruction != DFABytecodeInstruction::AppendActionWithIfDomain);
break;
+ }
}
return actions;
}
@@ -102,12 +113,14 @@
unsigned dfaBytecodeLength = getBits<unsigned>(m_bytecode, m_bytecodeLength, programCounter, m_pagesUsed);
programCounter += sizeof(unsigned);
- // Skip the actions on the DFA root. These are accessed via actionsFromDFARoot.
+ // Skip the default stylesheet actions on the DFA root. These are accessed via actionsForDefaultStylesheetFromDFARoot.
if (!dfaStart) {
while (programCounter < dfaBytecodeLength) {
DFABytecodeInstruction instruction = static_cast<DFABytecodeInstruction>(m_bytecode[programCounter]);
- if (instruction == DFABytecodeInstruction::AppendAction)
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
+ if (instruction == DFABytecodeInstruction::AppendActionDefaultStylesheet)
+ programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet);
+ else if (instruction == DFABytecodeInstruction::AppendAction)
+ interpretAppendAction(programCounter, actions, false);
else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
interpretTestFlagsAndAppendAction(programCounter, flags, actions, false);
else
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h (184643 => 184644)
--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -60,7 +60,7 @@
typedef HashSet<uint64_t, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> Actions;
Actions interpret(const CString&, uint16_t flags);
- Actions actionsFromDFARoot();
+ Actions actionsForDefaultStylesheetFromDFARoot();
private:
void interpretAppendAction(unsigned& programCounter, Actions&, bool ifDomain);
Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.h (184643 => 184644)
--- trunk/Source/WebCore/loader/ResourceLoadInfo.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -56,8 +56,10 @@
// The first 32 bits of a uint64_t action are used for the action location.
// The next 16 bits are used for the flags (ResourceType and LoadType).
// The next bit is used to mark actions that are from a rule with an if-domain condition.
+// The next bit is used to mark actions that in the default stylesheet.
// The values -1 and -2 are used for removed and empty values in HashTables.
const uint64_t IfDomainFlag = 0x0001000000000000;
+const uint64_t DisplayNoneStyleSheetFlag = 0x0002000000000000;
ResourceType toResourceType(CachedResource::Type);
uint16_t readResourceType(const String&);
Modified: trunk/Source/WebKit2/ChangeLog (184643 => 184644)
--- trunk/Source/WebKit2/ChangeLog 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebKit2/ChangeLog 2015-05-20 17:56:17 UTC (rev 184644)
@@ -1,3 +1,13 @@
+2015-05-20 Alex Christensen <[email protected]>
+
+ [Content Extensions] Relax restrictions on triggers that match everything.
+ https://bugs.webkit.org/show_bug.cgi?id=145069
+
+ Reviewed by Benjamin Poulain.
+
+ * UIProcess/API/APIUserContentExtensionStore.h:
+ Increment version number to reflect changes in DFABytecode.
+
2015-05-20 Sungmann Cho <[email protected]>
Minor cleanups to PluginProcessProxy.
Modified: trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h (184643 => 184644)
--- trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h 2015-05-20 17:56:17 UTC (rev 184644)
@@ -51,7 +51,7 @@
// This should be incremented every time a functional change is made to the bytecode, file format, etc.
// to prevent crashing while loading old data.
- const static uint32_t CurrentContentExtensionFileVersion = 2;
+ const static uint32_t CurrentContentExtensionFileVersion = 3;
static UserContentExtensionStore& defaultStore();
Modified: trunk/Tools/ChangeLog (184643 => 184644)
--- trunk/Tools/ChangeLog 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Tools/ChangeLog 2015-05-20 17:56:17 UTC (rev 184644)
@@ -1,3 +1,14 @@
+2015-05-20 Alex Christensen <[email protected]>
+
+ [Content Extensions] Relax restrictions on triggers that match everything.
+ https://bugs.webkit.org/show_bug.cgi?id=145069
+
+ Reviewed by Benjamin Poulain.
+
+ * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+ (TestWebKitAPI::TEST_F):
+ Update and add tests for new possibilities with .*
+
2015-05-20 Rohit Kumar <[email protected]>
[EFL][Minibrowser] Hide URL bar on fullscreen mode for HTML elements and browser window in WebKit EFL Minibrowser
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (184643 => 184644)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2015-05-20 17:39:11 UTC (rev 184643)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2015-05-20 17:56:17 UTC (rev 184644)
@@ -743,6 +743,37 @@
EXPECT_STREQ(compilerError.category().name(), expectedError.category().name());
}
+TEST_F(ContentExtensionTest, MatchesEverything)
+{
+ // Only css-display-none rules with triggers that match everything, no domain rules, and no flags
+ // should go in the global display:none stylesheet. css-display-none rules with domain rules or flags
+ // are applied separately on pages where they apply.
+ auto backend1 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_TRUE(nullptr != backend1.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend1, mainDocumentRequest("http://webkit.org"), { }); // Selector is in global stylesheet.
+
+ auto backend2 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend2.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend2, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend2, mainDocumentRequest("http://w3c.org"), { });
+
+ auto backend3 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend3.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend3, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend3, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ auto backend4 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}}]");
+ EXPECT_EQ(nullptr, backend4.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend4, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend4, subResourceRequest("http://not_webkit.org", "http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ // css-display-none rules after ignore-previous-rules should not be put in the default stylesheet.
+ auto backend5 = makeBackend("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+}
+
TEST_F(ContentExtensionTest, InvalidJSON)
{
checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
@@ -803,10 +834,9 @@
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\":\".*\",\"if-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::RegexMatchesEverythingWithDomains);
- checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::RegexMatchesEverythingWithDomains);
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", { });
checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
ContentExtensions::ContentExtensionError::JSONInvalidRegex);
}