Diff
Modified: trunk/LayoutTests/ChangeLog (189192 => 189193)
--- trunk/LayoutTests/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/LayoutTests/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,18 @@
+2015-08-26 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Added tests for what happens if the content filter does not make a decision when the load finishes.
+
+ * contentfiltering/allow-never-expected.html: Added.
+ * contentfiltering/allow-never.html: Added.
+ * contentfiltering/block-never-expected.html: Added.
+ * contentfiltering/block-never.html: Added.
+ * contentfiltering/resources/contentfiltering.js:
+
2015-08-31 Zalan Bujtas <[email protected]>
Repaint cleanup:
Added: trunk/LayoutTests/contentfiltering/allow-never-expected.html (0 => 189193)
--- trunk/LayoutTests/contentfiltering/allow-never-expected.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/allow-never-expected.html 2015-08-31 23:27:20 UTC (rev 189193)
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src=""
Added: trunk/LayoutTests/contentfiltering/allow-never.html (0 => 189193)
--- trunk/LayoutTests/contentfiltering/allow-never.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/allow-never.html 2015-08-31 23:27:20 UTC (rev 189193)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+if (window.internals) {
+ var settings = window.internals.mockContentFilterSettings;
+ testContentFiltering(/* decisionPoint */settings.DECISION_POINT_NEVER, /* decision */settings.DECISION_ALLOW);
+}
+</script>
Added: trunk/LayoutTests/contentfiltering/block-never-expected.html (0 => 189193)
--- trunk/LayoutTests/contentfiltering/block-never-expected.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/block-never-expected.html 2015-08-31 23:27:20 UTC (rev 189193)
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src=""
Added: trunk/LayoutTests/contentfiltering/block-never.html (0 => 189193)
--- trunk/LayoutTests/contentfiltering/block-never.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/block-never.html 2015-08-31 23:27:20 UTC (rev 189193)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+if (window.internals) {
+ var settings = window.internals.mockContentFilterSettings;
+ testContentFiltering(/* decisionPoint */settings.DECISION_POINT_NEVER, /* decision */settings.DECISION_BLOCK);
+}
+</script>
Modified: trunk/LayoutTests/contentfiltering/resources/contentfiltering.js (189192 => 189193)
--- trunk/LayoutTests/contentfiltering/resources/contentfiltering.js 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/LayoutTests/contentfiltering/resources/contentfiltering.js 2015-08-31 23:27:20 UTC (rev 189193)
@@ -5,7 +5,12 @@
settings.decisionPoint = decisionPoint;
settings.decision = (decideAfterUnblockRequest ? settings.DECISION_BLOCK : decision);
- var blockedStringText = (decision === settings.DECISION_ALLOW ? "FAIL" : "PASS");
+ var blockedStringText;
+ if (decisionPoint === settings.DECISION_POINT_NEVER || decision === settings.DECISION_ALLOW)
+ blockedStringText = "FAIL";
+ else
+ blockedStringText = "PASS";
+
if (decideAfterUnblockRequest) {
settings.unblockRequestDecision = decision;
settings.blockedString = "<!DOCTYPE html><script>function unblockRequestDenied() { window.top.postMessage('unblockrequestdenied', '*'); }</script><body>" + blockedStringText;
Modified: trunk/Source/WebCore/ChangeLog (189192 => 189193)
--- trunk/Source/WebCore/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,94 @@
+2015-08-26 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Prior to this change, ContentFilter would hide from DocumentLoader all CachedRawResourceClient callbacks until
+ a decision was made, then replay the missed callbacks. This approach interacted poorly with some features of
+ the loader, notably appcache and downloads. In the case of appcache, DocumentLoader might not have a chance to
+ check for substitute data until the original load has finished, wasting bandwidth, and might receive duplicate
+ or out-of-order callbacks. In the case of downloads, it would often be too late to convert the existing
+ connection to a download, leading to restarted downloads or outright failures.
+
+ Bandaids were put in place for these issues in r188150, r188486, and r188851 to fix crashes or serious
+ regressions in behavior, but these weren't complete fixes. They did not solve any of the duplicate data loading
+ problems, and they did not make downloads work reliably in all cases.
+
+ This patch rolls out the bandaids (but keeps their tests) and replaces them with a more robust fix. Instead of
+ hiding callbacks from DocumentLoader, ContentFilter now delivers willSendRequest(), redirectReceived(), and
+ responseReceived() to DocumentLoader immediately, and cancels filtering if DocumentLoader decides to ignore the
+ load, download it, or load substitute data. ContentFilter continues to buffer incoming data to prevent partial
+ rendering of blocked content.
+
+ The existing tests for r188150 and r188851 were kept, the test for r188486 was rewritten to be specific to
+ content filtering, and new tests were added to cover the case where ContentFilter is still undecided after a
+ load finishes.
+
+ Tests: contentfiltering/allow-never.html
+ contentfiltering/block-never.html
+ ContentFiltering.AllowDownloadAfterAddData
+ ContentFiltering.AllowDownloadAfterFinishedAddingData
+ ContentFiltering.AllowDownloadAfterRedirect
+ ContentFiltering.AllowDownloadAfterResponse
+ ContentFiltering.AllowDownloadAfterWillSendRequest
+ ContentFiltering.AllowDownloadNever
+ ContentFiltering.BlockDownloadAfterAddData
+ ContentFiltering.BlockDownloadAfterFinishedAddingData
+ ContentFiltering.BlockDownloadAfterRedirect
+ ContentFiltering.BlockDownloadAfterResponse
+ ContentFiltering.BlockDownloadAfterWillSendRequest
+ ContentFiltering.BlockDownloadNever
+
+ * bindings/js/JSMockContentFilterSettingsCustom.cpp:
+ (WebCore::JSMockContentFilterSettings::decisionPoint): Taught to handle DecisionPoint::Never, and rewrote to
+ not need a set of const uint8_ts that mirror the DecisionPoint enum.
+ (WebCore::JSMockContentFilterSettings::setDecisionPoint): Ditto.
+ (WebCore::toJSValue): Rewrote to not need a set of const uint8_ts that mirror the Decision enum.
+ (WebCore::toDecision): Ditto.
+ * loader/ContentFilter.cpp:
+ (WebCore::ContentFilter::createIfEnabled): Renamed from createIfNeeded, and changed to take a DocumentLoader&
+ instead of a DecisionFunction.
+ (WebCore::ContentFilter::ContentFilter):
+ (WebCore::ContentFilter::responseReceived): If m_state != Blocked after filtering, call DocumentLoader::responseReceived().
+ (WebCore::ContentFilter::dataReceived): If m_state == Allowed after filtering, deliver buffered data to DocumentLoader.
+ If no filtering was necessary, call DocumentLoader::dataReceived() directly.
+ (WebCore::ContentFilter::redirectReceived): If m_state != Blocked after filtering, call DocumentLoader::redirectReceived().
+ (WebCore::ContentFilter::notifyFinished): If an error occured, call DocumentLoader::notifyFinished() immediately and return.
+ If m_state != Blocked after filtering, deliver buffered data to DocumentLoader and call DocumentLoader::notifyFinished().
+ If no filtering was necessary and m_state != Blocked, call DocumentLoader::notifyFinished() directly.
+ (WebCore::ContentFilter::didDecide): Called DocumentLoader::contentFilterDidDecide() instead of m_decisionFunction().
+ (WebCore::ContentFilter::deliverResourceData): Added a helper function to deliver buffered data to DocumentLoader.
+ (WebCore::ContentFilter::createIfNeeded): Renamed to createIfEnabled().
+ * loader/ContentFilter.h:
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::DocumentLoader):
+ (WebCore::DocumentLoader::willSendRequest): Stopped asserting that redirectResponse is null and made it part of
+ the if condition instead, since willSendRequest() will now be called on redirects when there is an active ContentFilter.
+ (WebCore::DocumentLoader::startLoadingMainResource): Called becomeMainResourceClient() instead of becomeMainResourceClientIfFilterAllows().
+ (WebCore::DocumentLoader::becomeMainResourceClient): Renamed from becomeMainResourceClientIfFilterAllows().
+ Only called ContentFilter::startFilteringMainResource() if the filter state is Initialized, since ContentFilter
+ might have already made a decision in willSendRequest().
+ (WebCore::DocumentLoader::contentFilterDidDecide): Stopped deleting m_contentFilter, since it will continue to deliver callbacks
+ even after making a decision. Fixed a bug where we were creating two copies of ContentFilter's replacement data.
+ (WebCore::DocumentLoader::syntheticRedirectReceived): Deleted.
+ (WebCore::DocumentLoader::becomeMainResourceClientIfFilterAllows): Renamed to becomeMainResourceClient().
+ * loader/DocumentLoader.h:
+ * loader/EmptyClients.h:
+ * loader/FrameLoaderClient.h:
+ * loader/ResourceLoader.cpp:
+ (WebCore::ResourceLoader::willSendRequestInternal): Removed part of r188851.
+ * loader/SubresourceLoader.cpp:
+ (WebCore::SubresourceLoader::didReceiveResponse): Removed part of r188486.
+ * loader/SubresourceLoader.h:
+ * loader/cache/CachedRawResource.cpp:
+ (WebCore::CachedRawResource::didAddClient): Removed part of r188150.
+ * loader/cache/CachedRawResourceClient.h:
+ (WebCore::CachedRawResourceClient::syntheticRedirectReceived): Removed part of r188150.
+ * testing/MockContentFilterSettings.h: Defined DecisionPoint::Never.
+ * testing/MockContentFilterSettings.idl: Defined DECISION_POINT_NEVER.
+
2015-08-31 Chris Dumez <[email protected]>
Unreviewed, rebaseline bindings tests after r189184.
Modified: trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp (189192 => 189193)
--- trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -38,28 +38,17 @@
using Decision = MockContentFilterSettings::Decision;
using DecisionPoint = MockContentFilterSettings::DecisionPoint;
-// Must be kept in sync with values in MockContentFilterSettings.idl.
-const uint8_t decisionPointAfterWillSendRequest = 0;
-const uint8_t decisionPointAfterRedirect = 1;
-const uint8_t decisionPointAfterResponse = 2;
-const uint8_t decisionPointAfterAddData = 3;
-const uint8_t decisionPointAfterFinishedAddingData = 4;
-const uint8_t decisionAllow = 0;
-const uint8_t decisionBlock = 1;
-
JSValue JSMockContentFilterSettings::decisionPoint(ExecState*) const
{
- switch (impl().decisionPoint()) {
+ DecisionPoint decisionPoint = impl().decisionPoint();
+ switch (decisionPoint) {
case DecisionPoint::AfterWillSendRequest:
- return jsNumber(decisionPointAfterWillSendRequest);
case DecisionPoint::AfterRedirect:
- return jsNumber(decisionPointAfterRedirect);
case DecisionPoint::AfterResponse:
- return jsNumber(decisionPointAfterResponse);
case DecisionPoint::AfterAddData:
- return jsNumber(decisionPointAfterAddData);
case DecisionPoint::AfterFinishedAddingData:
- return jsNumber(decisionPointAfterFinishedAddingData);
+ case DecisionPoint::Never:
+ return jsNumber(static_cast<uint8_t>(decisionPoint));
}
ASSERT_NOT_REACHED();
@@ -72,22 +61,16 @@
if (exec->hadException())
return;
- switch (nativeValue) {
- case decisionPointAfterWillSendRequest:
- impl().setDecisionPoint(DecisionPoint::AfterWillSendRequest);
+ DecisionPoint decisionPoint { static_cast<DecisionPoint>(nativeValue) };
+ switch (decisionPoint) {
+ case DecisionPoint::AfterWillSendRequest:
+ case DecisionPoint::AfterRedirect:
+ case DecisionPoint::AfterResponse:
+ case DecisionPoint::AfterAddData:
+ case DecisionPoint::AfterFinishedAddingData:
+ case DecisionPoint::Never:
+ impl().setDecisionPoint(decisionPoint);
return;
- case decisionPointAfterRedirect:
- impl().setDecisionPoint(DecisionPoint::AfterRedirect);
- return;
- case decisionPointAfterResponse:
- impl().setDecisionPoint(DecisionPoint::AfterResponse);
- return;
- case decisionPointAfterAddData:
- impl().setDecisionPoint(DecisionPoint::AfterAddData);
- return;
- case decisionPointAfterFinishedAddingData:
- impl().setDecisionPoint(DecisionPoint::AfterFinishedAddingData);
- return;
}
throwTypeError(exec, String::format("%u is not a valid decisionPoint value.", nativeValue));
@@ -97,9 +80,8 @@
{
switch (decision) {
case Decision::Allow:
- return jsNumber(decisionAllow);
case Decision::Block:
- return jsNumber(decisionBlock);
+ return jsNumber(static_cast<uint8_t>(decision));
}
ASSERT_NOT_REACHED();
@@ -112,11 +94,11 @@
if (exec->hadException())
return Decision::Allow;
- switch (nativeValue) {
- case decisionAllow:
- return Decision::Allow;
- case decisionBlock:
- return Decision::Block;
+ Decision decision { static_cast<Decision>(nativeValue) };
+ switch (decision) {
+ case Decision::Allow:
+ case Decision::Block:
+ return decision;
}
throwTypeError(exec, String::format("%u is not a valid decision value.", nativeValue));
Modified: trunk/Source/WebCore/loader/ContentFilter.cpp (189192 => 189193)
--- trunk/Source/WebCore/loader/ContentFilter.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/ContentFilter.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -30,6 +30,7 @@
#include "CachedRawResource.h"
#include "ContentFilterUnblockHandler.h"
+#include "DocumentLoader.h"
#include "Logging.h"
#include "NetworkExtensionContentFilter.h"
#include "ParentalControlsContentFilter.h"
@@ -58,7 +59,7 @@
return types;
}
-std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(DecisionFunction decisionFunction)
+std::unique_ptr<ContentFilter> ContentFilter::createIfEnabled(DocumentLoader& documentLoader)
{
Container filters;
for (auto& type : types()) {
@@ -73,12 +74,12 @@
if (filters.isEmpty())
return nullptr;
- return std::make_unique<ContentFilter>(WTF::move(filters), WTF::move(decisionFunction));
+ return std::make_unique<ContentFilter>(WTF::move(filters), documentLoader);
}
-ContentFilter::ContentFilter(Container contentFilters, DecisionFunction decisionFunction)
+ContentFilter::ContentFilter(Container contentFilters, DocumentLoader& documentLoader)
: m_contentFilters { WTF::move(contentFilters) }
- , m_decisionFunction { WTF::move(decisionFunction) }
+ , m_documentLoader { documentLoader }
{
LOG(ContentFiltering, "Creating ContentFilter with %zu platform content filter(s).\n", m_contentFilters.size());
ASSERT(!m_contentFilters.isEmpty());
@@ -147,39 +148,78 @@
void ContentFilter::responseReceived(CachedResource* resource, const ResourceResponse& response)
{
+ ASSERT(resource);
+ ASSERT(resource == m_mainResource);
+ ASSERT(m_state != State::Initialized);
LOG(ContentFiltering, "ContentFilter received response from <%s>.\n", response.url().string().ascii().data());
- ASSERT(m_state == State::Filtering);
- ASSERT_UNUSED(resource, resource == m_mainResource.get());
- forEachContentFilterUntilBlocked([&response](PlatformContentFilter& contentFilter) {
- contentFilter.responseReceived(response);
- });
+
+ if (m_state == State::Filtering) {
+ forEachContentFilterUntilBlocked([&response](PlatformContentFilter& contentFilter) {
+ contentFilter.responseReceived(response);
+ });
+ }
+
+ if (m_state != State::Blocked)
+ m_documentLoader.responseReceived(resource, response);
}
void ContentFilter::dataReceived(CachedResource* resource, const char* data, int length)
{
+ ASSERT(resource);
+ ASSERT(resource == m_mainResource);
+ ASSERT(m_state != State::Initialized);
LOG(ContentFiltering, "ContentFilter received %d bytes of data from <%s>.\n", length, resource->url().string().ascii().data());
- ASSERT(m_state == State::Filtering);
- ASSERT_UNUSED(resource, resource == m_mainResource.get());
- forEachContentFilterUntilBlocked([data, length](PlatformContentFilter& contentFilter) {
- contentFilter.addData(data, length);
- });
+
+ if (m_state == State::Filtering) {
+ forEachContentFilterUntilBlocked([data, length](PlatformContentFilter& contentFilter) {
+ contentFilter.addData(data, length);
+ });
+
+ if (m_state == State::Allowed)
+ deliverResourceData(*resource);
+ return;
+ }
+
+ if (m_state == State::Allowed)
+ m_documentLoader.dataReceived(resource, data, length);
}
void ContentFilter::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
- ASSERT(m_state == State::Filtering);
- ASSERT_UNUSED(resource, resource == m_mainResource.get());
- willSendRequest(request, redirectResponse);
+ ASSERT(resource);
+ ASSERT(resource == m_mainResource);
+ ASSERT(m_state != State::Initialized);
+
+ if (m_state == State::Filtering)
+ willSendRequest(request, redirectResponse);
+
+ if (m_state != State::Blocked)
+ m_documentLoader.redirectReceived(resource, request, redirectResponse);
}
void ContentFilter::notifyFinished(CachedResource* resource)
{
+ ASSERT(resource);
+ ASSERT(resource == m_mainResource);
+ ASSERT(m_state != State::Initialized);
LOG(ContentFiltering, "ContentFilter will finish filtering main resource at <%s>.\n", resource->url().string().ascii().data());
- ASSERT(m_state == State::Filtering);
- ASSERT_UNUSED(resource, resource == m_mainResource.get());
- forEachContentFilterUntilBlocked([](PlatformContentFilter& contentFilter) {
- contentFilter.finishedAddingData();
- });
+
+ if (resource->errorOccurred()) {
+ m_documentLoader.notifyFinished(resource);
+ return;
+ }
+
+ if (m_state == State::Filtering) {
+ forEachContentFilterUntilBlocked([](PlatformContentFilter& contentFilter) {
+ contentFilter.finishedAddingData();
+ });
+
+ if (m_state != State::Blocked)
+ deliverResourceData(*resource);
+ }
+
+ if (m_state != State::Blocked)
+ m_documentLoader.notifyFinished(resource);
}
void ContentFilter::forEachContentFilterUntilBlocked(std::function<void(PlatformContentFilter&)> function)
@@ -213,10 +253,14 @@
ASSERT(state == State::Allowed || state == State::Blocked);
LOG(ContentFiltering, "ContentFilter decided load should be %s for main resource at <%s>.\n", state == State::Allowed ? "allowed" : "blocked", m_mainResource ? m_mainResource->url().string().ascii().data() : "");
m_state = state;
+ m_documentLoader.contentFilterDidDecide();
+}
- // Calling m_decisionFunction might delete |this|.
- if (m_decisionFunction)
- m_decisionFunction();
+void ContentFilter::deliverResourceData(CachedResource& resource)
+{
+ ASSERT(resource.dataBufferingPolicy() == BufferData);
+ const SharedBuffer& resourceBuffer = *resource.resourceBuffer();
+ m_documentLoader.dataReceived(&resource, resourceBuffer.data(), resourceBuffer.size());
}
} // namespace WebCore
Modified: trunk/Source/WebCore/loader/ContentFilter.h (189192 => 189193)
--- trunk/Source/WebCore/loader/ContentFilter.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/ContentFilter.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -37,6 +37,7 @@
class CachedRawResource;
class ContentFilterUnblockHandler;
+class DocumentLoader;
class PlatformContentFilter;
class SharedBuffer;
@@ -47,8 +48,7 @@
public:
template <typename T> static void addType() { types().append(type<T>()); }
- using DecisionFunction = std::function<void()>;
- static std::unique_ptr<ContentFilter> createIfNeeded(DecisionFunction);
+ static std::unique_ptr<ContentFilter> createIfEnabled(DocumentLoader&);
~ContentFilter() override;
static const char* urlScheme() { return "x-apple-content-filter"; }
@@ -76,8 +76,8 @@
WEBCORE_EXPORT static Vector<Type>& types();
using Container = Vector<std::unique_ptr<PlatformContentFilter>>;
- friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, DecisionFunction&&);
- ContentFilter(Container, DecisionFunction);
+ friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, DocumentLoader&);
+ ContentFilter(Container, DocumentLoader&);
// CachedRawResourceClient
void responseReceived(CachedResource*, const ResourceResponse&) override;
@@ -89,9 +89,10 @@
void forEachContentFilterUntilBlocked(std::function<void(PlatformContentFilter&)>);
void didDecide(State);
+ void deliverResourceData(CachedResource&);
const Container m_contentFilters;
- const DecisionFunction m_decisionFunction;
+ DocumentLoader& m_documentLoader;
CachedResourceHandle<CachedRawResource> m_mainResource;
PlatformContentFilter* m_blockingContentFilter { nullptr };
State m_state { State::Initialized };
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (189192 => 189193)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -142,7 +142,7 @@
, m_subresourceLoadersArePageCacheAcceptable(false)
, m_applicationCacheHost(std::make_unique<ApplicationCacheHost>(*this))
#if ENABLE(CONTENT_FILTERING)
- , m_contentFilter(!substituteData.isValid() ? ContentFilter::createIfNeeded(std::bind(&DocumentLoader::contentFilterDidDecide, this)) : nullptr)
+ , m_contentFilter(!substituteData.isValid() ? ContentFilter::createIfEnabled(*this) : nullptr)
#endif
{
}
@@ -489,14 +489,6 @@
willSendRequest(request, redirectResponse);
}
-void DocumentLoader::syntheticRedirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse, bool& shouldContinue)
-{
- redirectReceived(resource, request, redirectResponse);
-
- // If we will soon remove our reference to the CachedRawResource in favor of a SubstituteData load, we don't want to continue receiving synthetic CachedRawResource callbacks.
- shouldContinue = !m_substituteData.isValid();
-}
-
void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
// Note that there are no asserts here as there are for the other callbacks. This is due to the
@@ -544,8 +536,7 @@
}
#if ENABLE(CONTENT_FILTERING)
- if (m_contentFilter) {
- ASSERT(redirectResponse.isNull());
+ if (m_contentFilter && redirectResponse.isNull()) {
m_contentFilter->willSendRequest(newRequest, redirectResponse);
if (newRequest.isNull())
return;
@@ -1462,11 +1453,7 @@
frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, request, ResourceResponse());
}
-#if ENABLE(CONTENT_FILTERING)
- becomeMainResourceClientIfFilterAllows();
-#else
- m_mainResource->addClient(this);
-#endif
+ becomeMainResourceClient();
// A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
if (mainResourceLoader())
@@ -1604,6 +1591,18 @@
return m_shouldOpenExternalURLsPolicy;
}
+void DocumentLoader::becomeMainResourceClient()
+{
+#if ENABLE(CONTENT_FILTERING)
+ if (m_contentFilter && m_contentFilter->state() == ContentFilter::State::Initialized) {
+ // ContentFilter will synthesize CachedRawResourceClient callbacks.
+ m_contentFilter->startFilteringMainResource(*m_mainResource);
+ return;
+ }
+#endif
+ m_mainResource->addClient(this);
+}
+
#if ENABLE(CONTENT_EXTENSIONS)
void DocumentLoader::addPendingContentExtensionSheet(const String& identifier, StyleSheetContents& sheet)
{
@@ -1620,16 +1619,6 @@
#endif
#if ENABLE(CONTENT_FILTERING)
-void DocumentLoader::becomeMainResourceClientIfFilterAllows()
-{
- ASSERT(m_mainResource);
- if (m_contentFilter) {
- ASSERT(m_contentFilter->state() == ContentFilter::State::Initialized);
- m_contentFilter->startFilteringMainResource(*m_mainResource);
- } else
- m_mainResource->addClient(this);
-}
-
void DocumentLoader::installContentFilterUnblockHandler(ContentFilter& contentFilter)
{
ContentFilterUnblockHandler unblockHandler { contentFilter.unblockHandler() };
@@ -1652,21 +1641,17 @@
using State = ContentFilter::State;
ASSERT(m_contentFilter);
ASSERT(m_contentFilter->state() == State::Blocked || m_contentFilter->state() == State::Allowed);
- std::unique_ptr<ContentFilter> contentFilter;
- std::swap(contentFilter, m_contentFilter);
- if (contentFilter->state() == State::Allowed) {
- if (m_mainResource)
- m_mainResource->addClient(this);
+ if (m_contentFilter->state() == State::Allowed)
return;
- }
- installContentFilterUnblockHandler(*contentFilter);
+ installContentFilterUnblockHandler(*m_contentFilter);
URL blockedURL;
blockedURL.setProtocol(ContentFilter::urlScheme());
blockedURL.setHost(ASCIILiteral("blocked-page"));
- ResourceResponse response(URL(), ASCIILiteral("text/html"), contentFilter->replacementData()->size(), ASCIILiteral("UTF-8"));
- SubstituteData substituteData { contentFilter->replacementData(), documentURL(), response, SubstituteData::SessionHistoryVisibility::Hidden };
+ auto replacementData = m_contentFilter->replacementData();
+ ResourceResponse response(URL(), ASCIILiteral("text/html"), replacementData->size(), ASCIILiteral("UTF-8"));
+ SubstituteData substituteData { adoptRef(&replacementData.leakRef()), documentURL(), response, SubstituteData::SessionHistoryVisibility::Hidden };
frame()->navigationScheduler().scheduleSubstituteDataLoad(blockedURL, substituteData);
}
#endif
Modified: trunk/Source/WebCore/loader/DocumentLoader.h (189192 => 189193)
--- trunk/Source/WebCore/loader/DocumentLoader.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/DocumentLoader.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -307,7 +307,6 @@
void finishedLoading(double finishTime);
void mainReceivedError(const ResourceError&);
WEBCORE_EXPORT virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) override;
- WEBCORE_EXPORT virtual void syntheticRedirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&, bool& /* shouldContinue */) override;
WEBCORE_EXPORT virtual void responseReceived(CachedResource*, const ResourceResponse&) override;
WEBCORE_EXPORT virtual void dataReceived(CachedResource*, const char* data, int length) override;
WEBCORE_EXPORT virtual void notifyFinished(CachedResource*) override;
@@ -339,9 +338,10 @@
void clearMainResource();
void cancelPolicyCheckIfNeeded();
+ void becomeMainResourceClient();
#if ENABLE(CONTENT_FILTERING)
- void becomeMainResourceClientIfFilterAllows();
+ friend class ContentFilter;
void installContentFilterUnblockHandler(ContentFilter&);
void contentFilterDidDecide();
#endif
Modified: trunk/Source/WebCore/loader/EmptyClients.h (189192 => 189193)
--- trunk/Source/WebCore/loader/EmptyClients.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/EmptyClients.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -272,7 +272,7 @@
virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int) override { return false; }
virtual void dispatchDidHandleOnloadEvents() override { }
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(const URL&) override { }
+ virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() override { }
virtual void dispatchDidCancelClientRedirect() override { }
virtual void dispatchWillPerformClientRedirect(const URL&, double, double) override { }
virtual void dispatchDidChangeLocationWithinPage() override { }
Modified: trunk/Source/WebCore/loader/FrameLoaderClient.h (189192 => 189193)
--- trunk/Source/WebCore/loader/FrameLoaderClient.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/FrameLoaderClient.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -154,7 +154,7 @@
virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) = 0;
virtual void dispatchDidHandleOnloadEvents() = 0;
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(const URL&) = 0;
+ virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() = 0;
virtual void dispatchDidChangeProvisionalURL() { }
virtual void dispatchDidCancelClientRedirect() = 0;
virtual void dispatchWillPerformClientRedirect(const URL&, double interval, double fireDate) = 0;
Modified: trunk/Source/WebCore/loader/ResourceLoader.cpp (189192 => 189193)
--- trunk/Source/WebCore/loader/ResourceLoader.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/ResourceLoader.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -372,7 +372,7 @@
if (isRedirect) {
auto& redirectURL = request.url();
if (!m_documentLoader->isCommitted())
- frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad(redirectURL);
+ frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad();
if (redirectURL.protocolIsData()) {
// Handle data URL decoding locally.
Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (189192 => 189193)
--- trunk/Source/WebCore/loader/SubresourceLoader.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/SubresourceLoader.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -207,8 +207,6 @@
// anything including removing the last reference to this object; one example of this is 3266216.
Ref<SubresourceLoader> protect(*this);
- TemporaryChange<bool> callingDidReceiveResponse(m_callingDidReceiveResponse, true);
-
if (shouldIncludeCertificateInfo())
response.includeCertificateInfo();
Modified: trunk/Source/WebCore/loader/SubresourceLoader.h (189192 => 189193)
--- trunk/Source/WebCore/loader/SubresourceLoader.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/SubresourceLoader.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -58,8 +58,6 @@
virtual const ResourceRequest& iOSOriginalRequest() const override { return m_iOSOriginalRequest; }
#endif
- bool callingDidReceiveResponse() const { return m_callingDidReceiveResponse; }
-
private:
SubresourceLoader(Frame*, CachedResource*, const ResourceLoaderOptions&);
@@ -126,7 +124,6 @@
bool m_loadingMultipartContent;
SubresourceLoaderState m_state;
std::unique_ptr<RequestCountTracker> m_requestCountTracker;
- bool m_callingDidReceiveResponse { false };
};
}
Modified: trunk/Source/WebCore/loader/cache/CachedRawResource.cpp (189192 => 189193)
--- trunk/Source/WebCore/loader/cache/CachedRawResource.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/cache/CachedRawResource.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -132,9 +132,8 @@
for (size_t i = 0; i < redirectCount; i++) {
RedirectPair redirect = m_redirectChain[i];
ResourceRequest request(redirect.m_request);
- bool shouldContinue = true;
- client->syntheticRedirectReceived(this, request, redirect.m_redirectResponse, shouldContinue);
- if (!hasClient(c) || !shouldContinue)
+ client->redirectReceived(this, request, redirect.m_redirectResponse);
+ if (!hasClient(c))
return;
}
ASSERT(redirectCount == m_redirectChain.size());
Modified: trunk/Source/WebCore/loader/cache/CachedRawResourceClient.h (189192 => 189193)
--- trunk/Source/WebCore/loader/cache/CachedRawResourceClient.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/loader/cache/CachedRawResourceClient.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -41,10 +41,6 @@
virtual void responseReceived(CachedResource*, const ResourceResponse&) { }
virtual void dataReceived(CachedResource*, const char* /* data */, int /* length */) { }
virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) { }
-
- // In response to a redirect, some clients wish to receive no futher callbacks, but cannot immediately remove themselves as a client.
- // Those clients can express their desire to recieve no futher callbacks by setting shouldContinue to false.
- virtual void syntheticRedirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& response, bool& /* shouldContinue */) { redirectReceived(resource, request, response); }
#if USE(SOUP)
virtual char* getOrCreateReadBuffer(CachedResource*, size_t /* requestedSize */, size_t& /* actualSize */) { return 0; }
#endif
Modified: trunk/Source/WebCore/testing/MockContentFilterSettings.h (189192 => 189193)
--- trunk/Source/WebCore/testing/MockContentFilterSettings.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/testing/MockContentFilterSettings.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -40,7 +40,8 @@
AfterRedirect,
AfterResponse,
AfterAddData,
- AfterFinishedAddingData
+ AfterFinishedAddingData,
+ Never
};
enum class Decision {
Modified: trunk/Source/WebCore/testing/MockContentFilterSettings.idl (189192 => 189193)
--- trunk/Source/WebCore/testing/MockContentFilterSettings.idl 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebCore/testing/MockContentFilterSettings.idl 2015-08-31 23:27:20 UTC (rev 189193)
@@ -37,6 +37,7 @@
const octet DECISION_POINT_AFTER_RESPONSE = 2;
const octet DECISION_POINT_AFTER_ADD_DATA = 3;
const octet DECISION_POINT_AFTER_FINISHED_ADDING_DATA = 4;
+ const octet DECISION_POINT_NEVER = 5;
[Custom] attribute octet decisionPoint;
const octet DECISION_ALLOW = 0;
Modified: trunk/Source/WebKit/mac/ChangeLog (189192 => 189193)
--- trunk/Source/WebKit/mac/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/mac/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,17 @@
+2015-08-26 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Deleted parts of r188486 and r188851.
+
+ * WebCoreSupport/WebFrameLoaderClient.h:
+ * WebCoreSupport/WebFrameLoaderClient.mm:
+ (WebFrameLoaderClient::convertMainResourceLoadToDownload):
+ (WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad):
+
2015-08-31 Chris Dumez <[email protected]>
Range.detach() / NodeIterator.detach() should be no-ops as per the latest DOM specification
Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h (189192 => 189193)
--- trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -96,7 +96,7 @@
virtual NSCachedURLResponse* willCacheResponse(WebCore::DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const override;
virtual void dispatchDidHandleOnloadEvents() override;
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(const WebCore::URL&) override;
+ virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() override;
virtual void dispatchDidCancelClientRedirect() override;
virtual void dispatchWillPerformClientRedirect(const WebCore::URL&, double interval, double fireDate) override;
virtual void dispatchDidChangeLocationWithinPage() override;
Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm (189192 => 189193)
--- trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm 2015-08-31 23:27:20 UTC (rev 189193)
@@ -288,7 +288,7 @@
WebView *webView = getWebView(m_webFrame.get());
SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
- if (!mainResourceLoader || !mainResourceLoader->callingDidReceiveResponse()) {
+ if (!mainResourceLoader) {
// The resource has already been cached, or the conversion is being attmpted when not calling SubresourceLoader::didReceiveResponse().
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -578,9 +578,9 @@
CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
}
-void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad(const URL& url)
+void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
{
- m_webFrame->_private->provisionalURL = url.string();
+ m_webFrame->_private->provisionalURL = core(m_webFrame.get())->loader().provisionalDocumentLoader()->url().string();
WebView *webView = getWebView(m_webFrame.get());
WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
Modified: trunk/Source/WebKit/win/ChangeLog (189192 => 189193)
--- trunk/Source/WebKit/win/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/win/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,16 @@
+2015-08-27 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Deleted part of r188851.
+
+ * WebCoreSupport/WebFrameLoaderClient.cpp:
+ (WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad):
+ * WebCoreSupport/WebFrameLoaderClient.h:
+
2015-08-31 Chris Dumez <[email protected]>
Range.detach() / NodeIterator.detach() should be no-ops as per the latest DOM specification
Modified: trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp (189192 => 189193)
--- trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -330,7 +330,7 @@
frameLoadDelegatePriv->didHandleOnloadEventsForFrame(webView, m_webFrame);
}
-void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad(const URL&)
+void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
{
WebView* webView = m_webFrame->webView();
COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
Modified: trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h (189192 => 189193)
--- trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -77,7 +77,7 @@
virtual bool shouldCacheResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse&, const unsigned char* data, unsigned long long length);
virtual void dispatchDidHandleOnloadEvents() override;
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(const WebCore::URL&) override;
+ virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() override;
virtual void dispatchDidCancelClientRedirect() override;
virtual void dispatchWillPerformClientRedirect(const WebCore::URL&, double interval, double fireDate) override;
virtual void dispatchDidChangeLocationWithinPage() override;
Modified: trunk/Source/WebKit2/ChangeLog (189192 => 189193)
--- trunk/Source/WebKit2/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit2/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,18 @@
+2015-08-26 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Deleted parts of r188486 and r188851.
+
+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+ (WebKit::WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad):
+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+ * WebProcess/WebPage/WebFrame.cpp:
+ (WebKit::WebFrame::convertMainResourceLoadToDownload):
+
2015-08-31 Chris Dumez <[email protected]>
Range.detach() / NodeIterator.detach() should be no-ops as per the latest DOM specification
Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (189192 => 189193)
--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -278,20 +278,21 @@
webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(webPage, m_frame);
}
-void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad(const URL& url)
+void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
{
WebPage* webPage = m_frame->page();
if (!webPage)
return;
WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
+ const String& url = ""
RefPtr<API::Object> userData;
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(webPage, m_frame, userData);
// Notify the UIProcess.
- webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), url.string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), url, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidChangeProvisionalURL()
Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h (189192 => 189193)
--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h 2015-08-31 23:27:20 UTC (rev 189193)
@@ -79,7 +79,7 @@
virtual bool dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int length) override;
virtual void dispatchDidHandleOnloadEvents() override;
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(const WebCore::URL&) override;
+ virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() override;
virtual void dispatchDidChangeProvisionalURL() override;
virtual void dispatchDidCancelClientRedirect() override;
virtual void dispatchWillPerformClientRedirect(const WebCore::URL&, double interval, double fireDate) override;
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp (189192 => 189193)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp 2015-08-31 23:27:20 UTC (rev 189193)
@@ -283,7 +283,7 @@
// This can happen if there is no loader because the main resource is in the WebCore memory cache,
// or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
uint64_t mainResourceLoadIdentifier;
- if (mainResourceLoader && mainResourceLoader->callingDidReceiveResponse())
+ if (mainResourceLoader)
mainResourceLoadIdentifier = mainResourceLoader->identifier();
else
mainResourceLoadIdentifier = 0;
@@ -293,7 +293,7 @@
}
#endif
- if (!mainResourceLoader || !mainResourceLoader->callingDidReceiveResponse()) {
+ if (!mainResourceLoader) {
// The main resource has already been loaded. Start a new download instead.
webProcess.downloadManager().startDownload(policyDownloadID, request);
return;
Modified: trunk/Tools/ChangeLog (189192 => 189193)
--- trunk/Tools/ChangeLog 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/ChangeLog 2015-08-31 23:27:20 UTC (rev 189193)
@@ -1,3 +1,49 @@
+2015-08-26 Andy Estes <[email protected]>
+
+ [Content Filtering] Determine navigation and content policy before continuing to filter a load
+ https://bugs.webkit.org/show_bug.cgi?id=148506
+
+ Reviewed by Brady Eidson.
+
+ Added download API tests covering every decision and decision point.
+ Removed _WKDownload.AsynchronousDownloadPolicy in favor of these new tests.
+
+ * TestWebKitAPI/Configurations/Base.xcconfig: Added $(BUILT_PRODUCTS_DIR)/WebCoreTestSupport to the header search path.
+ * TestWebKitAPI/Configurations/WebProcessPlugIn.xcconfig: Removed it from here.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/BundleParametersPlugIn.mm:
+ (-[BundleParametersPlugIn observeValueForKeyPath:ofObject:change:context:]): Called -valueForKeyPath:, which
+ returns an id, instead of -valueForKey:, which always returns an NSString even if the object is of another type.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm: Added a class that can send a MockContentFilter
+ decision and decision point as a bundle parameter.
+ (+[MockContentFilterEnabler supportsSecureCoding]):
+ (-[MockContentFilterEnabler copyWithZone:]):
+ (-[MockContentFilterEnabler initWithCoder:]):
+ (-[MockContentFilterEnabler initWithDecision:decisionPoint:]):
+ (-[MockContentFilterEnabler encodeWithCoder:]):
+ (configurationWithContentFilterSettings): Added a helper function to create a WKWebViewConfiguration with MockConentFilter settings.
+ (TEST): Renamed ContentFiltering.ServerRedirect to ContentFiltering.URLAfterServerRedirect.
+ (-[BecomeDownloadDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Decided _WKNavigationResponsePolicyBecomeDownload.
+ (-[BecomeDownloadDelegate webView:didFailProvisionalNavigation:withError:]): Set isDone to true.
+ (-[BecomeDownloadDelegate webView:didFinishNavigation:]): Ditto.
+ (-[ContentFilteringDownloadDelegate _downloadDidStart:]): Set downloadDidStart to true.
+ (downloadTest): Added a helper function to test downloads with a given decision and decision point.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm: Added a corresponding bundle class that decodes
+ the MockContentFilter decision and decision point, and sets these values in the MockContentFilterSettings
+ singleton. This class is duplicated in the bundle to prevent TestWebKitAPI from having to link to WebCoreTestSupport.
+ (+[MockContentFilterEnabler supportsSecureCoding]):
+ (-[MockContentFilterEnabler copyWithZone:]):
+ (-[MockContentFilterEnabler initWithCoder:]):
+ (-[MockContentFilterEnabler dealloc]):
+ (-[MockContentFilterEnabler encodeWithCoder:]):
+ (-[ContentFilteringPlugIn webProcessPlugIn:initializeWithObject:]): Start observing changes to the MockContentFilterEnabler key path.
+ (-[ContentFilteringPlugIn dealloc]): Stop observing.
+ (-[ContentFilteringPlugIn observeValueForKeyPath:ofObject:change:context:]): Store a MockContentFilterEnabler in _contentFilterEnabler.
+ (+[ServerRedirectPlugIn initialize]): Deleted.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm:
+ (-[AsynchronousDownloadNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Deleted.
+ (-[AsynchronousDownloadDelegate _downloadDidStart:]): Deleted.
+ (TEST): Deleted.
+
2015-08-31 Filip Pizlo <[email protected]>
Skip slow lock tests on Windows/debug
Modified: trunk/Tools/TestWebKitAPI/Configurations/Base.xcconfig (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Configurations/Base.xcconfig 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Configurations/Base.xcconfig 2015-08-31 23:27:20 UTC (rev 189193)
@@ -24,7 +24,7 @@
CLANG_CXX_LANGUAGE_STANDARD = gnu++0x;
CLANG_CXX_LIBRARY = libc++;
CLANG_WARN_CXX0X_EXTENSIONS = NO;
-HEADER_SEARCH_PATHS = ${BUILT_PRODUCTS_DIR}/usr/local/include $(WEBCORE_PRIVATE_HEADERS_DIR)/ForwardingHeaders $(WEBCORE_PRIVATE_HEADERS_DIR)/icu;
+HEADER_SEARCH_PATHS = ${BUILT_PRODUCTS_DIR}/usr/local/include $(WEBCORE_PRIVATE_HEADERS_DIR)/ForwardingHeaders $(WEBCORE_PRIVATE_HEADERS_DIR)/icu $(BUILT_PRODUCTS_DIR)/WebCoreTestSupport;
FRAMEWORK_SEARCH_PATHS = $(FRAMEWORK_SEARCH_PATHS_$(PLATFORM_NAME));
FRAMEWORK_SEARCH_PATHS_macosx = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks;
Modified: trunk/Tools/TestWebKitAPI/Configurations/WebProcessPlugIn.xcconfig (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Configurations/WebProcessPlugIn.xcconfig 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Configurations/WebProcessPlugIn.xcconfig 2015-08-31 23:27:20 UTC (rev 189193)
@@ -27,7 +27,6 @@
PRODUCT_NAME = TestWebKitAPI;
EXECUTABLE_SUFFIX = .bundle;
WRAPPER_EXTENSION = wkbundle;
-HEADER_SEARCH_PATHS = $(inherited) $(BUILT_PRODUCTS_DIR)/WebCoreTestSupport;
OTHER_LDFLAGS = $(inherited) -framework _javascript_Core -framework WebKit -lWebCoreTestSupport;
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = "@loader_path/../../..";
LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = "@loader_path/..";
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleParametersPlugIn.mm (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleParametersPlugIn.mm 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleParametersPlugIn.mm 2015-08-31 23:27:20 UTC (rev 189193)
@@ -64,7 +64,7 @@
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
JSContext *jsContext = [[_browserContextController mainFrame] jsContextForWorld:[WKWebProcessPlugInScriptWorld normalWorld]];
- [jsContext setObject:[object valueForKey:keyPath] forKeyedSubscript:keyPath];
+ [jsContext setObject:[object valueForKeyPath:keyPath] forKeyedSubscript:keyPath];
}
@end
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm 2015-08-31 23:27:20 UTC (rev 189193)
@@ -27,16 +27,72 @@
#if WK_API_ENABLED && PLATFORM(MAC)
+#import "MockContentFilterSettings.h"
#import "PlatformUtilities.h"
#import "TestProtocol.h"
#import "WKWebViewConfigurationExtras.h"
#import <WebKit/WKBrowsingContextController.h>
-#import <WebKit/WKNavigationDelegate.h>
+#import <WebKit/WKNavigationDelegatePrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebView.h>
+#import <WebKit/_WKDownloadDelegate.h>
#import <wtf/RetainPtr.h>
+using Decision = WebCore::MockContentFilterSettings::Decision;
+using DecisionPoint = WebCore::MockContentFilterSettings::DecisionPoint;
+
static bool isDone;
+@interface MockContentFilterEnabler : NSObject <NSCopying, NSSecureCoding>
+- (instancetype)initWithDecision:(Decision)decision decisionPoint:(DecisionPoint)decisionPoint;
+@end
+
+@implementation MockContentFilterEnabler {
+ Decision _decision;
+ DecisionPoint _decisionPoint;
+}
+
++ (BOOL)supportsSecureCoding
+{
+ return YES;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ return [self retain];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder
+{
+ return [super init];
+}
+
+- (instancetype)initWithDecision:(Decision)decision decisionPoint:(DecisionPoint)decisionPoint
+{
+ if (!(self = [super init]))
+ return nil;
+
+ _decision = decision;
+ _decisionPoint = decisionPoint;
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ [coder encodeInt:static_cast<int>(_decision) forKey:@"Decision"];
+ [coder encodeInt:static_cast<int>(_decisionPoint) forKey:@"DecisionPoint"];
+}
+
+@end
+
+static RetainPtr<WKWebViewConfiguration> configurationWithContentFilterSettings(Decision decision, DecisionPoint decisionPoint)
+{
+ auto configuration = retainPtr([WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"ContentFilteringPlugIn"]);
+ auto contentFilterEnabler = adoptNS([[MockContentFilterEnabler alloc] initWithDecision:decision decisionPoint:decisionPoint]);
+ [[configuration processPool] _setObject:contentFilterEnabler.get() forBundleParameter:NSStringFromClass([MockContentFilterEnabler class])];
+ return configuration;
+}
+
@interface ServerRedirectNavigationDelegate : NSObject <WKNavigationDelegate>
@end
@@ -59,20 +115,144 @@
@end
-TEST(ContentFiltering, ServerRedirect)
+TEST(ContentFiltering, URLAfterServerRedirect)
{
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+ @autoreleasepool {
+ [NSURLProtocol registerClass:[TestProtocol class]];
+ [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
- auto configuration = retainPtr([WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"ServerRedirectPlugIn"]);
- auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
- auto navigationDelegate = adoptNS([[ServerRedirectNavigationDelegate alloc] init]);
- [webView setNavigationDelegate:navigationDelegate.get()];
- [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect?pass"]]];
- TestWebKitAPI::Util::run(&isDone);
+ auto configuration = configurationWithContentFilterSettings(Decision::Allow, DecisionPoint::AfterAddData);
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+ auto navigationDelegate = adoptNS([[ServerRedirectNavigationDelegate alloc] init]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect?pass"]]];
+ TestWebKitAPI::Util::run(&isDone);
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
- [NSURLProtocol unregisterClass:[TestProtocol class]];
+ [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
+ [NSURLProtocol unregisterClass:[TestProtocol class]];
+ }
}
+@interface BecomeDownloadDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation BecomeDownloadDelegate
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+ decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
+}
+
+- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
+{
+ isDone = true;
+}
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+ isDone = true;
+}
+
+@end
+
+static bool downloadDidStart;
+
+@interface ContentFilteringDownloadDelegate : NSObject <_WKDownloadDelegate>
+@end
+
+@implementation ContentFilteringDownloadDelegate
+
+- (void)_downloadDidStart:(_WKDownload *)download
+{
+ downloadDidStart = true;
+}
+
+@end
+
+static void downloadTest(Decision decision, DecisionPoint decisionPoint)
+{
+ @autoreleasepool {
+ [NSURLProtocol registerClass:[TestProtocol class]];
+ [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+
+ auto configuration = configurationWithContentFilterSettings(decision, decisionPoint);
+ auto downloadDelegate = adoptNS([[ContentFilteringDownloadDelegate alloc] init]);
+ [[configuration processPool] _setDownloadDelegate:downloadDelegate.get()];
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+ auto navigationDelegate = adoptNS([[BecomeDownloadDelegate alloc] init]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect/?download"]]];
+
+ isDone = false;
+ downloadDidStart = false;
+ TestWebKitAPI::Util::run(&isDone);
+
+ const bool downloadShouldStart = decision == Decision::Allow || decisionPoint > DecisionPoint::AfterResponse;
+ EXPECT_EQ(downloadShouldStart, downloadDidStart);
+
+ [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
+ [NSURLProtocol unregisterClass:[TestProtocol class]];
+ }
+}
+
+TEST(ContentFiltering, AllowDownloadAfterWillSendRequest)
+{
+ downloadTest(Decision::Allow, DecisionPoint::AfterWillSendRequest);
+}
+
+TEST(ContentFiltering, BlockDownloadAfterWillSendRequest)
+{
+ downloadTest(Decision::Block, DecisionPoint::AfterWillSendRequest);
+}
+
+TEST(ContentFiltering, AllowDownloadAfterRedirect)
+{
+ downloadTest(Decision::Allow, DecisionPoint::AfterRedirect);
+}
+
+TEST(ContentFiltering, BlockDownloadAfterRedirect)
+{
+ downloadTest(Decision::Block, DecisionPoint::AfterRedirect);
+}
+
+TEST(ContentFiltering, AllowDownloadAfterResponse)
+{
+ downloadTest(Decision::Allow, DecisionPoint::AfterResponse);
+}
+
+TEST(ContentFiltering, BlockDownloadAfterResponse)
+{
+ downloadTest(Decision::Block, DecisionPoint::AfterResponse);
+}
+
+TEST(ContentFiltering, AllowDownloadAfterAddData)
+{
+ downloadTest(Decision::Allow, DecisionPoint::AfterAddData);
+}
+
+TEST(ContentFiltering, BlockDownloadAfterAddData)
+{
+ downloadTest(Decision::Block, DecisionPoint::AfterAddData);
+}
+
+TEST(ContentFiltering, AllowDownloadAfterFinishedAddingData)
+{
+ downloadTest(Decision::Allow, DecisionPoint::AfterFinishedAddingData);
+}
+
+TEST(ContentFiltering, BlockDownloadAfterFinishedAddingData)
+{
+ downloadTest(Decision::Block, DecisionPoint::AfterFinishedAddingData);
+}
+
+TEST(ContentFiltering, AllowDownloadNever)
+{
+ downloadTest(Decision::Allow, DecisionPoint::Never);
+}
+
+TEST(ContentFiltering, BlockDownloadNever)
+{
+ downloadTest(Decision::Block, DecisionPoint::Never);
+}
+
#endif // WK_API_ENABLED
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm 2015-08-31 23:27:20 UTC (rev 189193)
@@ -30,22 +30,77 @@
#import "MockContentFilterSettings.h"
#import <WebKit/WKWebProcessPlugIn.h>
-@interface ServerRedirectPlugIn : NSObject <WKWebProcessPlugIn>
+using MockContentFilterSettings = WebCore::MockContentFilterSettings;
+using Decision = MockContentFilterSettings::Decision;
+using DecisionPoint = MockContentFilterSettings::DecisionPoint;
+
+@interface MockContentFilterEnabler : NSObject <NSCopying, NSSecureCoding>
@end
-@implementation ServerRedirectPlugIn
+@implementation MockContentFilterEnabler
-+ (void)initialize
++ (BOOL)supportsSecureCoding
{
- using MockContentFilterSettings = WebCore::MockContentFilterSettings;
- using Decision = MockContentFilterSettings::Decision;
- using DecisionPoint = MockContentFilterSettings::DecisionPoint;
- MockContentFilterSettings& settings = MockContentFilterSettings::singleton();
+ return YES;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ return [self retain];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder
+{
+ if (!(self = [super init]))
+ return nil;
+
+ auto& settings = MockContentFilterSettings::singleton();
settings.setEnabled(true);
- settings.setDecision(Decision::Allow);
- settings.setDecisionPoint(DecisionPoint::AfterAddData);
+ settings.setDecision(static_cast<Decision>([decoder decodeIntForKey:@"Decision"]));
+ settings.setDecisionPoint(static_cast<DecisionPoint>([decoder decodeIntForKey:@"DecisionPoint"]));
+ return self;
}
+- (void)dealloc
+{
+ MockContentFilterSettings::singleton().setEnabled(false);
+ [super dealloc];
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+}
+
@end
+@interface ContentFilteringPlugIn : NSObject <WKWebProcessPlugIn>
+@end
+
+@implementation ContentFilteringPlugIn {
+ RetainPtr<MockContentFilterEnabler> _contentFilterEnabler;
+ RetainPtr<WKWebProcessPlugInController> _plugInController;
+}
+
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController initializeWithObject:(id)initializationObject
+{
+ ASSERT(!_plugInController);
+ _plugInController = plugInController;
+ [plugInController.parameters addObserver:self forKeyPath:NSStringFromClass([MockContentFilterEnabler class]) options:NSKeyValueObservingOptionInitial context:NULL];
+}
+
+- (void)dealloc
+{
+ [[_plugInController parameters] removeObserver:self forKeyPath:NSStringFromClass([MockContentFilterEnabler class])];
+ [super dealloc];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ id contentFilterEnabler = [object valueForKeyPath:keyPath];
+ ASSERT([contentFilterEnabler isKindOfClass:[MockContentFilterEnabler class]]);
+ _contentFilterEnabler = contentFilterEnabler;
+}
+
+@end
+
#endif // WK_API_ENABLED
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm (189192 => 189193)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm 2015-08-31 23:13:13 UTC (rev 189192)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm 2015-08-31 23:27:20 UTC (rev 189193)
@@ -265,34 +265,5 @@
TestWebKitAPI::Util::run(&isDone);
}
-@interface AsynchronousDownloadNavigationDelegate : NSObject <WKNavigationDelegate>
-@end
-
-@implementation AsynchronousDownloadNavigationDelegate
-- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
-{
- dispatch_async(dispatch_get_main_queue(), ^ {
- decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
- });
-}
-@end
-
-@interface AsynchronousDownloadDelegate : NSObject <_WKDownloadDelegate>
-@end
-
-@implementation AsynchronousDownloadDelegate
-
-- (void)_downloadDidStart:(_WKDownload *)download
-{
- isDone = true;
-}
-
-@end
-
-TEST(_WKDownload, AsynchronousDownloadPolicy)
-{
- runTest(adoptNS([[AsynchronousDownloadNavigationDelegate alloc] init]).get(), adoptNS([[AsynchronousDownloadDelegate alloc] init]).get(), sourceURL);
-}
-
#endif
#endif