blob: 398e74c231127705b6ca037edd753d1434edf92c [file] [log] [blame]
/*
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(CONTENT_EXTENSIONS)
#include "ContentExtensionActions.h"
#include "ResourceLoadInfo.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
namespace ContentExtensions {
// A ContentExtensionRule is the smallest unit in a ContentExtension.
//
// It is composed of a trigger and an action. The trigger defines on what kind of content this extension should apply.
// The action defines what to perform on that content.
struct Trigger {
String urlFilter;
bool urlFilterIsCaseSensitive { false };
bool topURLConditionIsCaseSensitive { false };
ResourceFlags flags { 0 };
Vector<String> conditions;
enum class ConditionType {
None,
IfDomain,
UnlessDomain,
IfTopURL,
UnlessTopURL,
};
ConditionType conditionType { ConditionType::None };
WEBCORE_EXPORT Trigger isolatedCopy() const;
~Trigger()
{
ASSERT(conditions.isEmpty() == (conditionType == ConditionType::None));
if (topURLConditionIsCaseSensitive)
ASSERT(conditionType == ConditionType::IfTopURL || conditionType == ConditionType::UnlessTopURL);
}
bool isEmpty() const
{
return urlFilter.isEmpty()
&& !urlFilterIsCaseSensitive
&& !topURLConditionIsCaseSensitive
&& !flags
&& conditions.isEmpty()
&& conditionType == ConditionType::None;
}
bool operator==(const Trigger& other) const
{
return urlFilter == other.urlFilter
&& urlFilterIsCaseSensitive == other.urlFilterIsCaseSensitive
&& topURLConditionIsCaseSensitive == other.topURLConditionIsCaseSensitive
&& flags == other.flags
&& conditions == other.conditions
&& conditionType == other.conditionType;
}
};
struct TriggerHash {
static unsigned hash(const Trigger& trigger)
{
unsigned hash = trigger.urlFilterIsCaseSensitive ? 10619863 : 40960001;
if (!trigger.urlFilter.isNull())
hash ^= StringHash::hash(trigger.urlFilter);
hash = WTF::pairIntHash(hash, DefaultHash<ResourceFlags>::Hash::hash(trigger.flags));
for (const String& condition : trigger.conditions)
hash ^= StringHash::hash(condition);
hash ^= 1 << static_cast<unsigned>(trigger.conditionType);
return hash;
}
static bool equal(const Trigger& a, const Trigger& b)
{
return a == b;
}
static const bool safeToCompareToEmptyOrDeleted = false;
};
struct TriggerHashTraits : public WTF::CustomHashTraits<Trigger> {
static const bool emptyValueIsZero = false;
static const bool hasIsEmptyValueFunction = true;
static void constructDeletedValue(Trigger& trigger)
{
new (NotNull, std::addressof(trigger.urlFilter)) String(WTF::HashTableDeletedValue);
}
static bool isDeletedValue(const Trigger& trigger)
{
return trigger.urlFilter.isHashTableDeletedValue();
}
static Trigger emptyValue()
{
return Trigger();
}
static bool isEmptyValue(const Trigger& trigger)
{
return trigger.isEmpty();
}
};
struct Action {
Action(ActionType type, const String& stringArgument, uint32_t actionID = std::numeric_limits<uint32_t>::max())
: m_type(type)
, m_actionID(actionID)
, m_stringArgument(stringArgument)
{
ASSERT(hasStringArgument(type));
}
Action(ActionType type, uint32_t actionID = std::numeric_limits<uint32_t>::max())
: m_type(type)
, m_actionID(actionID)
{
ASSERT(!hasStringArgument(type));
}
Action(Action&&) = default;
bool operator==(const Action& other) const
{
return m_type == other.m_type
&& m_actionID == other.m_actionID
&& m_stringArgument == other.m_stringArgument;
}
static Action deserialize(const SerializedActionByte* actions, const uint32_t actionsLength, uint32_t location);
static ActionType deserializeType(const SerializedActionByte* actions, const uint32_t actionsLength, uint32_t location);
static uint32_t serializedLength(const SerializedActionByte* actions, const uint32_t actionsLength, uint32_t location);
ActionType type() const { return m_type; }
uint32_t actionID() const { return m_actionID; }
const String& stringArgument() const { return m_stringArgument; }
WEBCORE_EXPORT Action isolatedCopy() const;
private:
ActionType m_type;
uint32_t m_actionID;
String m_stringArgument;
};
class ContentExtensionRule {
public:
WEBCORE_EXPORT ContentExtensionRule(Trigger&&, Action&&);
const Trigger& trigger() const { return m_trigger; }
const Action& action() const { return m_action; }
ContentExtensionRule isolatedCopy() const
{
return { m_trigger.isolatedCopy(), m_action.isolatedCopy() };
}
bool operator==(const ContentExtensionRule& other) const
{
return m_trigger == other.m_trigger && m_action == other.m_action;
}
private:
Trigger m_trigger;
Action m_action;
};
} // namespace ContentExtensions
} // namespace WebCore
#endif // ENABLE(CONTENT_EXTENSIONS)