blob: 787dbd705443ab502254c02eea8dc87156daca48 [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/Hasher.h>
#include <wtf/text/WTFString.h>
namespace WebCore::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 topURLFilterIsCaseSensitive { false };
bool frameURLFilterIsCaseSensitive { false };
ResourceFlags flags { 0 };
Vector<String> conditions;
WEBCORE_EXPORT Trigger isolatedCopy() const &;
WEBCORE_EXPORT Trigger isolatedCopy() &&;
void checkValidity()
{
auto actionCondition = static_cast<ActionCondition>(flags & ActionConditionMask);
ASSERT_UNUSED(actionCondition, conditions.isEmpty() == (actionCondition == ActionCondition::None));
if (topURLFilterIsCaseSensitive)
ASSERT(actionCondition == ActionCondition::IfTopURL || actionCondition == ActionCondition::UnlessTopURL);
if (frameURLFilterIsCaseSensitive)
ASSERT(actionCondition == ActionCondition::IfFrameURL);
}
bool isEmpty() const
{
return urlFilter.isEmpty()
&& !urlFilterIsCaseSensitive
&& !topURLFilterIsCaseSensitive
&& !frameURLFilterIsCaseSensitive
&& !flags
&& conditions.isEmpty();
}
bool operator==(const Trigger& other) const
{
return urlFilter == other.urlFilter
&& urlFilterIsCaseSensitive == other.urlFilterIsCaseSensitive
&& topURLFilterIsCaseSensitive == other.topURLFilterIsCaseSensitive
&& frameURLFilterIsCaseSensitive == other.frameURLFilterIsCaseSensitive
&& flags == other.flags
&& conditions == other.conditions;
}
};
inline void add(Hasher& hasher, const Trigger& trigger)
{
add(hasher, trigger.urlFilterIsCaseSensitive, trigger.urlFilter, trigger.flags, trigger.conditions);
}
struct TriggerHash {
static unsigned hash(const Trigger& trigger)
{
return computeHash(trigger);
}
static bool equal(const Trigger& a, const Trigger& b)
{
return a == b;
}
static const bool safeToCompareToEmptyOrDeleted = false;
};
struct TriggerHashTraits : public WTF::CustomHashTraits<Trigger> {
static constexpr bool emptyValueIsZero = false;
static constexpr 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(ActionData&& data)
: m_data(WTFMove(data)) { }
bool operator==(const Action& other) const { return m_data == other.m_data; }
bool operator!=(const Action& other) const { return !(*this == other); }
const ActionData& data() const { return m_data; }
WEBCORE_EXPORT Action isolatedCopy() const &;
WEBCORE_EXPORT Action isolatedCopy() &&;
private:
ActionData m_data;
};
struct DeserializedAction : public Action {
static DeserializedAction deserialize(Span<const uint8_t>, uint32_t location);
static size_t serializedLength(Span<const uint8_t>, uint32_t location);
uint32_t actionID() const { return m_actionID; }
private:
DeserializedAction(uint32_t actionID, ActionData&& data)
: Action(WTFMove(data))
, m_actionID(actionID) { }
const uint32_t m_actionID;
};
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() }; }
ContentExtensionRule isolatedCopy() && { return { WTFMove(m_trigger).isolatedCopy(), WTFMove(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 WebCore::ContentExtensions
#endif // ENABLE(CONTENT_EXTENSIONS)