MockContentFilter.cpp [plain text]
#include "config.h"
#include "MockContentFilter.h"
#if ENABLE(CONTENT_FILTERING)
#include "ContentFilter.h"
#include "ContentFilterUnblockHandler.h"
#include "Logging.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "SharedBuffer.h"
#include <mutex>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
namespace WebCore {
using Decision = MockContentFilterSettings::Decision;
using DecisionPoint = MockContentFilterSettings::DecisionPoint;
void MockContentFilter::ensureInstalled()
{
static std::once_flag onceFlag;
std::call_once(onceFlag, []{
ContentFilter::addType<MockContentFilter>();
});
}
static inline MockContentFilterSettings& settings()
{
return MockContentFilterSettings::singleton();
}
bool MockContentFilter::enabled()
{
bool enabled = settings().enabled();
LOG(ContentFiltering, "MockContentFilter is %s.\n", enabled ? "enabled" : "not enabled");
return enabled;
}
std::unique_ptr<MockContentFilter> MockContentFilter::create()
{
return std::make_unique<MockContentFilter>();
}
void MockContentFilter::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
{
if (redirectResponse.isNull())
maybeDetermineStatus(DecisionPoint::AfterWillSendRequest);
else
maybeDetermineStatus(DecisionPoint::AfterRedirect);
if (m_status == Status::NeedsMoreData)
return;
String modifiedRequestURLString { settings().modifiedRequestURL() };
if (modifiedRequestURLString.isEmpty())
return;
URL modifiedRequestURL { request.url(), modifiedRequestURLString };
if (!modifiedRequestURL.isValid()) {
LOG(ContentFiltering, "MockContentFilter failed to convert %s to a WebCore::URL.\n", modifiedRequestURL.string().ascii().data());
return;
}
request.setURL(modifiedRequestURL);
}
void MockContentFilter::responseReceived(const ResourceResponse&)
{
maybeDetermineStatus(DecisionPoint::AfterResponse);
}
void MockContentFilter::addData(const char*, int)
{
maybeDetermineStatus(DecisionPoint::AfterAddData);
}
void MockContentFilter::finishedAddingData()
{
maybeDetermineStatus(DecisionPoint::AfterFinishedAddingData);
}
bool MockContentFilter::needsMoreData() const
{
return m_status == Status::NeedsMoreData;
}
bool MockContentFilter::didBlockData() const
{
return m_status == Status::Blocked;
}
Ref<SharedBuffer> MockContentFilter::replacementData() const
{
ASSERT(didBlockData());
return adoptRef(*SharedBuffer::create(m_replacementData.data(), m_replacementData.size()).leakRef());
}
ContentFilterUnblockHandler MockContentFilter::unblockHandler() const
{
ASSERT(didBlockData());
using DecisionHandlerFunction = ContentFilterUnblockHandler::DecisionHandlerFunction;
return ContentFilterUnblockHandler {
MockContentFilterSettings::unblockURLHost(), [](DecisionHandlerFunction decisionHandler) {
bool shouldAllow { settings().unblockRequestDecision() == Decision::Allow };
if (shouldAllow)
settings().setDecision(Decision::Allow);
LOG(ContentFiltering, "MockContentFilter %s the unblock request.\n", shouldAllow ? "allowed" : "did not allow");
decisionHandler(shouldAllow);
}
};
}
String MockContentFilter::unblockRequestDeniedScript() const
{
return ASCIILiteral("unblockRequestDenied()");
}
void MockContentFilter::maybeDetermineStatus(DecisionPoint decisionPoint)
{
if (m_status != Status::NeedsMoreData || decisionPoint != settings().decisionPoint())
return;
LOG(ContentFiltering, "MockContentFilter stopped buffering with status %u at decision point %u.\n", m_status, decisionPoint);
m_status = settings().decision() == Decision::Allow ? Status::Allowed : Status::Blocked;
if (m_status != Status::Blocked)
return;
m_replacementData.clear();
const CString utf8BlockedString = settings().blockedString().utf8();
m_replacementData.append(utf8BlockedString.data(), utf8BlockedString.length());
}
}
#endif // ENABLE(CONTENT_FILTERING)