Diff
Modified: trunk/LayoutTests/ChangeLog (181790 => 181791)
--- trunk/LayoutTests/ChangeLog 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/LayoutTests/ChangeLog 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1,5 +1,24 @@
2015-03-19 Andy Estes <[email protected]>
+ [Content Filtering] Add tests for unblock requests
+ https://bugs.webkit.org/show_bug.cgi?id=142900
+
+ Reviewed by Andreas Kling.
+
+ Taught contentfiltering.js how to perform an unblock request test, and added tests for both allowed and blocked requests.
+
+ * contentfiltering/allow-after-unblock-request-expected.html: Added.
+ * contentfiltering/allow-after-unblock-request.html: Added.
+ * contentfiltering/block-after-unblock-request-expected.html: Added.
+ * contentfiltering/block-after-unblock-request.html: Added.
+ * contentfiltering/resources/contentfiltering.js:
+ (testContentFiltering): Added an argument specifying if the decision applies to the initial load or the unblock request.
+ (_doTest): When testing unblock handling, navigate the test iframe to settings.unblockRequestURL when the error page is displayed.
+ If the unblock is denied, the test harness will call window.unblockRequestDenied(). If the unblock is successful,
+ the iframe will reload, which we detect by listening for its load event.
+
+2015-03-19 Andy Estes <[email protected]>
+
[Content Filtering] Give contentfiltering tests a _javascript_ harness
https://bugs.webkit.org/show_bug.cgi?id=142899
Added: trunk/LayoutTests/contentfiltering/allow-after-unblock-request-expected.html (0 => 181791)
--- trunk/LayoutTests/contentfiltering/allow-after-unblock-request-expected.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/allow-after-unblock-request-expected.html 2015-03-20 08:42:59 UTC (rev 181791)
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src=""
Added: trunk/LayoutTests/contentfiltering/allow-after-unblock-request.html (0 => 181791)
--- trunk/LayoutTests/contentfiltering/allow-after-unblock-request.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/allow-after-unblock-request.html 2015-03-20 08:42:59 UTC (rev 181791)
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+var internals = window.internals;
+if (internals) {
+ var settings = internals.mockContentFilterSettings;
+ testContentFiltering(/* decisionPoint */settings.DECISION_POINT_AFTER_FINISHED_ADDING_DATA, /* decision */settings.DECISION_ALLOW, /* decideAfterUnblockRequest */true);
+}
+</script>
Added: trunk/LayoutTests/contentfiltering/block-after-unblock-request-expected.html (0 => 181791)
--- trunk/LayoutTests/contentfiltering/block-after-unblock-request-expected.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/block-after-unblock-request-expected.html 2015-03-20 08:42:59 UTC (rev 181791)
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src=""
Added: trunk/LayoutTests/contentfiltering/block-after-unblock-request.html (0 => 181791)
--- trunk/LayoutTests/contentfiltering/block-after-unblock-request.html (rev 0)
+++ trunk/LayoutTests/contentfiltering/block-after-unblock-request.html 2015-03-20 08:42:59 UTC (rev 181791)
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+var internals = window.internals;
+if (internals) {
+ var settings = internals.mockContentFilterSettings;
+ testContentFiltering(/* decisionPoint */settings.DECISION_POINT_AFTER_FINISHED_ADDING_DATA, /* decision */settings.DECISION_BLOCK, /* decideAfterUnblockRequest */true);
+}
+</script>
Modified: trunk/LayoutTests/contentfiltering/resources/contentfiltering.js (181790 => 181791)
--- trunk/LayoutTests/contentfiltering/resources/contentfiltering.js 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/LayoutTests/contentfiltering/resources/contentfiltering.js 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1,22 +1,37 @@
-function _doTest(decisionPoint, decision)
+function _doTest(decisionPoint, decision, decideAfterUnblockRequest)
{
var settings = window.internals.mockContentFilterSettings;
settings.enabled = true;
settings.decisionPoint = decisionPoint;
- settings.decision = decision;
+ settings.decision = (decideAfterUnblockRequest ? settings.DECISION_BLOCK : decision);
var blockedStringText = (decision === settings.DECISION_ALLOW ? "FAIL" : "PASS");
- settings.blockedString = "<!DOCTYPE html><body>" + blockedStringText;
+ if (decideAfterUnblockRequest) {
+ settings.unblockRequestDecision = decision;
+ settings.blockedString = "<!DOCTYPE html><script>function unblockRequestDenied() { window.top.postMessage('unblockrequestdenied', '*'); }</script><body>" + blockedStringText;
+ } else
+ settings.blockedString = "<!DOCTYPE html><body>" + blockedStringText;
+ var isUnblocking = false;
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.addEventListener("load", function(event) {
- window.testRunner.notifyDone();
+ if (isUnblocking || !decideAfterUnblockRequest) {
+ window.testRunner.notifyDone();
+ return;
+ }
+
+ isUnblocking = true;
+ window.addEventListener("message", function(event) {
+ if (event.data ="" "unblockrequestdenied")
+ window.testRunner.notifyDone();
+ }, false);
+ iframe.contentDocument.location = settings.unblockRequestURL;
}, false);
iframe.src = "" html><body>" + (blockedStringText === "FAIL" ? "PASS" : "FAIL");
}
-function testContentFiltering(decisionPoint, decision)
+function testContentFiltering(decisionPoint, decision, decideAfterUnblockRequest)
{
if (!window.internals) {
console.log("This test requires window.internals");
@@ -30,6 +45,6 @@
window.testRunner.waitUntilDone();
window.addEventListener("load", function(event) {
- _doTest(decisionPoint, decision);
+ _doTest(decisionPoint, decision, decideAfterUnblockRequest);
}, false);
}
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (181790 => 181791)
--- trunk/Source/WebCore/ChangeLog 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/ChangeLog 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1,3 +1,99 @@
+2015-03-19 Andy Estes <[email protected]>
+
+ [Content Filtering] Add tests for unblock requests
+ https://bugs.webkit.org/show_bug.cgi?id=142900
+
+ Reviewed by Andreas Kling.
+
+ Currently the iOS Parental Controls content filter has a mechanism for requesting that a page be unblocked.
+ WebKit implements this by listening for navigations originating from the filter's error page to a special URL,
+ and requesting the page be unblocked via platform API, which might cause UI to be displayed. If the unblock is
+ successful then we schedule a reload of the frame in order to display the unblocked document.
+
+ NetworkExtension also supports unblock requests, so in preparation for adopting its API, this patch allows
+ content filters to specify their own unblock request method, teaches MockContentFilter to provide such a method,
+ and writes tests to cover both allowed and denied unblock requests.
+
+ The content filter that blocks a load creates a ContentFilterUnblockHandler, passing it a lambda that is executed
+ when a navigation matches the filter's special unblock URL. Filters can also specify that a script be executed in
+ the context of its error page if the unblock is denied.
+
+ All platform content filters can handle unblock requests like this with the exception of iOS Parental Controls in WebKit2.
+ Since UI can be displayed by the system in this case, the request must be made from within the UI process. Therefore the
+ existing method is retained of serializing a WebFilterEvaluator and intercepting navigation policy calls in the UI process.
+
+ Tests: contentfiltering/allow-after-unblock-request.html
+ contentfiltering/block-after-unblock-request.html
+
+ * bindings/js/JSMockContentFilterSettingsCustom.cpp:
+ (WebCore::JSMockContentFilterSettings::decisionPoint): Added some using statements for clarity.
+ (WebCore::JSMockContentFilterSettings::setDecisionPoint): Ditto.
+ (WebCore::toJSValue): Returns a JSValue from a Decision.
+ (WebCore::toDecision): Returns a Decision from a JSValue.
+ (WebCore::JSMockContentFilterSettings::decision): Used toJSValue.
+ (WebCore::JSMockContentFilterSettings::setDecision): Used toDecision.
+ (WebCore::JSMockContentFilterSettings::unblockRequestDecision): Used toJSValue.
+ (WebCore::JSMockContentFilterSettings::setUnblockRequestDecision): Used toDecision.
+ * loader/ContentFilter.cpp:
+ (WebCore::ContentFilter::createIfNeeded): Passed a reference to the owning DocumentLoader.
+ (WebCore::ContentFilter::ContentFilter): Ditto.
+ (WebCore::ContentFilter::unblockHandler): If the unblockHandler requests that a script be executed when an
+ unblock request is denied, create a wrapper unblockHandler that executes that script in m_documentLoader's frame.
+ * loader/ContentFilter.h:
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::responseReceived): Passed this to ContentFilter::createIfNeeded.
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::prepareForLoadStart): Called PolicyChecker::prepareForLoadStart.
+ * loader/PolicyChecker.cpp:
+ (WebCore::PolicyChecker::prepareForLoadStart): Reset m_contentFilterUnblockHandler.
+ (WebCore::PolicyChecker::checkNavigationPolicy): Moved logic to here from WebKit1's WebFrameLoaderClient.
+ Placing it here allows it to be shared between WebKit1 and WebKit2 (when the unblock handler does not need to
+ be called in the UI process).
+ * loader/PolicyChecker.h:
+ (WebCore::PolicyChecker::setContentFilterUnblockHandler): Added.
+ * page/Frame.h: Made Frame ThreadSafeRefCounted, since RefPtr<Frames> are captured in lambdas that can be
+ copied by background threads managed by the underlying platform.
+ * platform/ContentFilterUnblockHandler.h:
+ (WebCore::ContentFilterUnblockHandler::unblockURLScheme): Returned the Apple content filter scheme.
+ (WebCore::ContentFilterUnblockHandler::unblockURLHost): Returned the unblock URL host.
+ (WebCore::ContentFilterUnblockHandler::clear): Deleted.
+ * platform/PlatformContentFilter.h:
+ (WebCore::PlatformContentFilter::unblockRequestDeniedScript): Returned the unblock request denied script.
+ * platform/cocoa/ContentFilterUnblockHandlerCocoa.mm:
+ (WebCore::ContentFilterUnblockHandler::ContentFilterUnblockHandler): Added a constructor that takes an
+ unblockURLHost and a UnblockRequesterFunction. Added an alternate constructor for iOS Parental Controls on
+ WebKit2 that takes an unblockURLHost and a WebFilterEvaluator.
+ (WebCore::ContentFilterUnblockHandler::needsUIProcess): Returned true if m_webFilterEvaluator is non-null.
+ (WebCore::ContentFilterUnblockHandler::encode): Encoded m_unblockURLHost in addition to m_webFilterEvaluator.
+ (WebCore::ContentFilterUnblockHandler::decode): Decoded m_unblockURLHost in addition to m_webFilterEvaluator.
+ (WebCore::ContentFilterUnblockHandler::canHandleRequest): Returned true if there is a either a m_unblockRequester
+ or a m_webFilterEvaluator and the request's host and scheme match those of the unblock request URL.
+ (WebCore::dispatchToMainThread): Added a helper to dispatch a block to the main thread. Then if the web thread
+ is enabled on iOS, dispatch it there.
+ (WebCore::ContentFilterUnblockHandler::requestUnblockAsync): Renamed from handleUnblockRequestAndDispatchIfSuccessful.
+ Requested an unblock using either m_unblockRequester or m_webFilterEvaluator, then called decisionHandler with the response.
+ (WebCore::scheme): Moved to ContentFilterUnblockHandler::unblockURLScheme.
+ (WebCore::ContentFilterUnblockHandler::handleUnblockRequestAndDispatchIfSuccessful): Renamed to requestUnblockAsync.
+ * platform/cocoa/ParentalControlsContentFilter.mm:
+ (WebCore::ParentalControlsContentFilter::unblockHandler): Returned an unblock handler using the WebFilterEvaluator constructor.
+ * testing/MockContentFilter.cpp: Added using statments for clarity.
+ (WebCore::settings): Added a helper to get MockContentFilterSettings::singleton().
+ (WebCore::MockContentFilter::canHandleResponse): Used the helper.
+ (WebCore::MockContentFilter::MockContentFilter): Took advantage of the using statements.
+ (WebCore::MockContentFilter::addData): Ditto.
+ (WebCore::MockContentFilter::finishedAddingData): Ditto.
+ (WebCore::MockContentFilter::unblockHandler): Returned a ContentFilterUnblockHandler that checks settings() for its decision.
+ (WebCore::MockContentFilter::unblockRequestDeniedScript): Returned the script to execute in MockContentFilter's
+ error page when an unblock request is denied.
+ (WebCore::MockContentFilter::maybeDetermineStatus): Took advantage of settings() and using statements.
+ * testing/MockContentFilterSettings.cpp:
+ (WebCore::MockContentFilterSettings::unblockRequestURL): Constructed a static unblock URL and returned it.
+ * testing/MockContentFilterSettings.h:
+ (WebCore::MockContentFilterSettings::unblockURLHost): Returned the filter's unblock URL host.
+ (WebCore::MockContentFilterSettings::unblockRequestDecision): Returns the decision to make for an unblock request.
+ (WebCore::MockContentFilterSettings::setUnblockRequestDecision): Sets the decision to make for an unblock request.
+ * testing/MockContentFilterSettings.idl: Added the unblockRequestDecision and unblockRequestURL attributes.
+
2015-03-20 Carlos Garcia Campos <[email protected]>
[GTK] Crash due to empty drag image during drag-and-drop
Modified: trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp (181790 => 181791)
--- trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -35,6 +35,9 @@
namespace WebCore {
+using Decision = MockContentFilterSettings::Decision;
+using DecisionPoint = MockContentFilterSettings::DecisionPoint;
+
// Must be kept in sync with values in MockContentFilterSettings.idl.
const uint8_t decisionPointAfterResponse = 0;
const uint8_t decisionPointAfterAddData = 1;
@@ -42,22 +45,22 @@
const uint8_t decisionAllow = 0;
const uint8_t decisionBlock = 1;
-JSC::JSValue JSMockContentFilterSettings::decisionPoint(JSC::ExecState*) const
+JSValue JSMockContentFilterSettings::decisionPoint(ExecState*) const
{
switch (impl().decisionPoint()) {
- case MockContentFilterSettings::DecisionPoint::AfterResponse:
+ case DecisionPoint::AfterResponse:
return jsNumber(decisionPointAfterResponse);
- case MockContentFilterSettings::DecisionPoint::AfterAddData:
+ case DecisionPoint::AfterAddData:
return jsNumber(decisionPointAfterAddData);
- case MockContentFilterSettings::DecisionPoint::AfterFinishedAddingData:
+ case DecisionPoint::AfterFinishedAddingData:
return jsNumber(decisionPointAfterFinishedAddingData);
}
ASSERT_NOT_REACHED();
- return { };
+ return jsUndefined();
}
-void JSMockContentFilterSettings::setDecisionPoint(JSC::ExecState* exec, JSC::JSValue value)
+void JSMockContentFilterSettings::setDecisionPoint(ExecState* exec, JSValue value)
{
uint8_t nativeValue { toUInt8(exec, value, EnforceRange) };
if (exec->hadException())
@@ -65,50 +68,77 @@
switch (nativeValue) {
case decisionPointAfterResponse:
- impl().setDecisionPoint(MockContentFilterSettings::DecisionPoint::AfterResponse);
+ impl().setDecisionPoint(DecisionPoint::AfterResponse);
return;
case decisionPointAfterAddData:
- impl().setDecisionPoint(MockContentFilterSettings::DecisionPoint::AfterAddData);
+ impl().setDecisionPoint(DecisionPoint::AfterAddData);
return;
case decisionPointAfterFinishedAddingData:
- impl().setDecisionPoint(MockContentFilterSettings::DecisionPoint::AfterFinishedAddingData);
+ impl().setDecisionPoint(DecisionPoint::AfterFinishedAddingData);
return;
- default:
- throwTypeError(exec, String::format("%u is not a valid decisionPoint value.", nativeValue));
}
+
+ throwTypeError(exec, String::format("%u is not a valid decisionPoint value.", nativeValue));
}
-JSC::JSValue JSMockContentFilterSettings::decision(JSC::ExecState*) const
+static inline JSValue toJSValue(Decision decision)
{
- switch (impl().decision()) {
- case MockContentFilterSettings::Decision::Allow:
+ switch (decision) {
+ case Decision::Allow:
return jsNumber(decisionAllow);
- case MockContentFilterSettings::Decision::Block:
+ case Decision::Block:
return jsNumber(decisionBlock);
}
ASSERT_NOT_REACHED();
- return { };
+ return jsUndefined();
}
-void JSMockContentFilterSettings::setDecision(JSC::ExecState* exec, JSC::JSValue value)
+static inline Decision toDecision(ExecState* exec, JSValue value)
{
uint8_t nativeValue { toUInt8(exec, value, EnforceRange) };
if (exec->hadException())
- return;
+ return Decision::Allow;
switch (nativeValue) {
case decisionAllow:
- impl().setDecision(MockContentFilterSettings::Decision::Allow);
- return;
+ return Decision::Allow;
case decisionBlock:
- impl().setDecision(MockContentFilterSettings::Decision::Block);
- return;
- default:
- throwTypeError(exec, String::format("%u is not a valid decision value.", nativeValue));
+ return Decision::Block;
}
+
+ throwTypeError(exec, String::format("%u is not a valid decision value.", nativeValue));
+ return Decision::Allow;
}
+JSValue JSMockContentFilterSettings::decision(ExecState*) const
+{
+ return toJSValue(impl().decision());
+}
+
+void JSMockContentFilterSettings::setDecision(ExecState* exec, JSValue value)
+{
+ Decision decision { toDecision(exec, value) };
+ if (exec->hadException())
+ return;
+
+ impl().setDecision(decision);
+}
+
+JSValue JSMockContentFilterSettings::unblockRequestDecision(ExecState*) const
+{
+ return toJSValue(impl().unblockRequestDecision());
+}
+
+void JSMockContentFilterSettings::setUnblockRequestDecision(ExecState* exec, JSValue value)
+{
+ Decision unblockRequestDecision { toDecision(exec, value) };
+ if (exec->hadException())
+ return;
+
+ impl().setUnblockRequestDecision(unblockRequestDecision);
+}
+
}; // namespace WebCore
#endif // ENABLE(CONTENT_FILTERING)
Modified: trunk/Source/WebCore/loader/ContentFilter.cpp (181790 => 181791)
--- trunk/Source/WebCore/loader/ContentFilter.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/ContentFilter.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -28,9 +28,14 @@
#if ENABLE(CONTENT_FILTERING)
+#include "DocumentLoader.h"
+#include "Frame.h"
#include "NetworkExtensionContentFilter.h"
#include "ParentalControlsContentFilter.h"
+#include "ScriptController.h"
+#include <bindings/ScriptValue.h>
#include <wtf/NeverDestroyed.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -47,7 +52,7 @@
return types;
}
-std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(const ResourceResponse& response)
+std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(const ResourceResponse& response, DocumentLoader& documentLoader)
{
Container filters;
for (auto& type : types()) {
@@ -58,11 +63,12 @@
if (filters.isEmpty())
return nullptr;
- return std::make_unique<ContentFilter>(WTF::move(filters));
+ return std::make_unique<ContentFilter>(WTF::move(filters), documentLoader);
}
-ContentFilter::ContentFilter(Container contentFilters)
+ContentFilter::ContentFilter(Container contentFilters, DocumentLoader& documentLoader)
: m_contentFilters { WTF::move(contentFilters) }
+ , m_documentLoader { documentLoader }
{
ASSERT(!m_contentFilters.isEmpty());
}
@@ -121,13 +127,32 @@
{
ASSERT(didBlockData());
+ PlatformContentFilter* blockingFilter = nullptr;
for (auto& contentFilter : m_contentFilters) {
- if (contentFilter->didBlockData())
- return contentFilter->unblockHandler();
+ if (contentFilter->didBlockData()) {
+ blockingFilter = contentFilter.get();
+ break;
+ }
}
+ ASSERT(blockingFilter);
- ASSERT_NOT_REACHED();
- return { };
+ StringCapture unblockRequestDeniedScript { blockingFilter->unblockRequestDeniedScript() };
+ if (unblockRequestDeniedScript.string().isEmpty())
+ return blockingFilter->unblockHandler();
+
+ // It would be a layering violation for the unblock handler to access its frame,
+ // so we will execute the unblock denied script on its behalf.
+ ContentFilterUnblockHandler unblockHandler { blockingFilter->unblockHandler() };
+ RefPtr<Frame> frame { m_documentLoader.frame() };
+ return ContentFilterUnblockHandler {
+ unblockHandler.unblockURLHost(), [unblockHandler, frame, unblockRequestDeniedScript](ContentFilterUnblockHandler::DecisionHandlerFunction decisionHandler) {
+ unblockHandler.requestUnblockAsync([decisionHandler, frame, unblockRequestDeniedScript](bool unblocked) {
+ decisionHandler(unblocked);
+ if (!unblocked && frame)
+ frame->script().executeScript(unblockRequestDeniedScript.string());
+ });
+ }
+ };
}
} // namespace WebCore
Modified: trunk/Source/WebCore/loader/ContentFilter.h (181790 => 181791)
--- trunk/Source/WebCore/loader/ContentFilter.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/ContentFilter.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -33,12 +33,13 @@
namespace WebCore {
+class DocumentLoader;
class ResourceResponse;
class ContentFilter final : public PlatformContentFilter {
public:
template <typename T> static void addType() { types().append(type<T>()); }
- static std::unique_ptr<ContentFilter> createIfNeeded(const ResourceResponse&);
+ static std::unique_ptr<ContentFilter> createIfNeeded(const ResourceResponse&, DocumentLoader&);
void addData(const char* data, int length) override;
void finishedAddingData() override;
@@ -56,10 +57,11 @@
WEBCORE_EXPORT static Vector<Type>& types();
using Container = Vector<std::unique_ptr<PlatformContentFilter>>;
- friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&);
- explicit ContentFilter(Container);
+ friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, DocumentLoader&);
+ explicit ContentFilter(Container, DocumentLoader&);
Container m_contentFilters;
+ DocumentLoader& m_documentLoader;
};
template <typename T>
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (181790 => 181791)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -663,7 +663,7 @@
#endif
#if ENABLE(CONTENT_FILTERING)
- m_contentFilter = ContentFilter::createIfNeeded(response);
+ m_contentFilter = ContentFilter::createIfNeeded(response, *this);
#endif
frameLoader()->policyChecker().checkContentPolicy(m_response, [this](PolicyAction policy) {
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (181790 => 181791)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1124,6 +1124,7 @@
void FrameLoader::prepareForLoadStart()
{
+ policyChecker().prepareForLoadStart();
m_progressTracker->progressStarted();
m_client.dispatchDidStartProvisionalLoad();
Modified: trunk/Source/WebCore/loader/PolicyChecker.cpp (181790 => 181791)
--- trunk/Source/WebCore/loader/PolicyChecker.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/PolicyChecker.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -56,6 +56,13 @@
{
}
+void PolicyChecker::prepareForLoadStart()
+{
+#if ENABLE(CONTENT_FILTERING)
+ m_contentFilterUnblockHandler = { };
+#endif
+}
+
void PolicyChecker::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function)
{
checkNavigationPolicy(newRequest, m_frame.loader().activeDocumentLoader(), nullptr, WTF::move(function));
@@ -105,6 +112,17 @@
}
#endif
+#if ENABLE(CONTENT_FILTERING)
+ if (m_contentFilterUnblockHandler.canHandleRequest(request)) {
+ RefPtr<Frame> frame { &m_frame };
+ m_contentFilterUnblockHandler.requestUnblockAsync([frame](bool unblocked) {
+ if (unblocked)
+ frame->loader().reload();
+ });
+ continueAfterNavigationPolicy(PolicyIgnore);
+ }
+#endif
+
m_delegateIsDecidingNavigationPolicy = true;
m_frame.loader().client().dispatchDecidePolicyForNavigationAction(action, request, formState, [this](PolicyAction action) {
continueAfterNavigationPolicy(action);
Modified: trunk/Source/WebCore/loader/PolicyChecker.h (181790 => 181791)
--- trunk/Source/WebCore/loader/PolicyChecker.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/loader/PolicyChecker.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -36,6 +36,10 @@
#include <wtf/PassRefPtr.h>
#include <wtf/text/WTFString.h>
+#if ENABLE(CONTENT_FILTERING)
+#include "ContentFilterUnblockHandler.h"
+#endif
+
namespace WebCore {
class DocumentLoader;
@@ -50,6 +54,7 @@
public:
explicit PolicyChecker(Frame&);
+ void prepareForLoadStart();
void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction);
void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction);
void checkNewWindowPolicy(const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, NewWindowPolicyDecisionFunction);
@@ -74,6 +79,10 @@
// the heart to hack on all the platforms to make that happen right now.
void continueLoadAfterWillSubmitForm(PolicyAction);
+#if ENABLE(CONTENT_FILTERING)
+ void setContentFilterUnblockHandler(ContentFilterUnblockHandler unblockHandler) { m_contentFilterUnblockHandler = WTF::move(unblockHandler); }
+#endif
+
private:
void continueAfterNavigationPolicy(PolicyAction);
void continueAfterNewWindowPolicy(PolicyAction);
@@ -91,6 +100,10 @@
// on navigation action delegate callbacks.
FrameLoadType m_loadType;
PolicyCallback m_callback;
+
+#if ENABLE(CONTENT_FILTERING)
+ ContentFilterUnblockHandler m_contentFilterUnblockHandler;
+#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/page/Frame.h (181790 => 181791)
--- trunk/Source/WebCore/page/Frame.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/page/Frame.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -36,7 +36,7 @@
#include "ScrollTypes.h"
#include "UserScriptTypes.h"
#include <memory>
-#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
#if PLATFORM(IOS)
#include "ViewportArguments.h"
@@ -113,7 +113,7 @@
};
typedef unsigned LayerTreeFlags;
- class Frame : public RefCounted<Frame> {
+ class Frame : public ThreadSafeRefCounted<Frame> {
public:
WEBCORE_EXPORT static Ref<Frame> create(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
Modified: trunk/Source/WebCore/platform/ContentFilterUnblockHandler.h (181790 => 181791)
--- trunk/Source/WebCore/platform/ContentFilterUnblockHandler.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/platform/ContentFilterUnblockHandler.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -30,10 +30,13 @@
#include <functional>
#include <wtf/RetainPtr.h>
+#include <wtf/text/WTFString.h>
-OBJC_CLASS NSKeyedArchiver;
-OBJC_CLASS NSKeyedUnarchiver;
+OBJC_CLASS NSCoder;
+
+#if PLATFORM(IOS)
OBJC_CLASS WebFilterEvaluator;
+#endif
namespace WebCore {
@@ -41,19 +44,31 @@
class ContentFilterUnblockHandler {
public:
- ContentFilterUnblockHandler() = default;
- explicit ContentFilterUnblockHandler(WebFilterEvaluator *evaluator) : m_webFilterEvaluator { evaluator } { }
+ using DecisionHandlerFunction = std::function<void(bool unblocked)>;
+ using UnblockRequesterFunction = std::function<void(DecisionHandlerFunction)>;
- void clear() { m_webFilterEvaluator = nullptr; }
- WEBCORE_EXPORT void encode(NSKeyedArchiver *) const;
- WEBCORE_EXPORT static bool decode(NSKeyedUnarchiver *, ContentFilterUnblockHandler&);
+ static const char* unblockURLScheme() { return "x-apple-content-filter"; }
+ ContentFilterUnblockHandler() = default;
+ WEBCORE_EXPORT ContentFilterUnblockHandler(String unblockURLHost, UnblockRequesterFunction);
#if PLATFORM(IOS)
- WEBCORE_EXPORT bool handleUnblockRequestAndDispatchIfSuccessful(const ResourceRequest&, std::function<void()>);
+ ContentFilterUnblockHandler(String unblockURLHost, RetainPtr<WebFilterEvaluator>);
#endif
+ WEBCORE_EXPORT bool needsUIProcess() const;
+ WEBCORE_EXPORT void encode(NSCoder *) const;
+ WEBCORE_EXPORT static bool decode(NSCoder *, ContentFilterUnblockHandler&);
+ WEBCORE_EXPORT bool canHandleRequest(const ResourceRequest&) const;
+ WEBCORE_EXPORT void requestUnblockAsync(DecisionHandlerFunction) const;
+
+ const String& unblockURLHost() const { return m_unblockURLHost; }
+
private:
+ String m_unblockURLHost;
+ UnblockRequesterFunction m_unblockRequester;
+#if PLATFORM(IOS)
RetainPtr<WebFilterEvaluator> m_webFilterEvaluator;
+#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/PlatformContentFilter.h (181790 => 181791)
--- trunk/Source/WebCore/platform/PlatformContentFilter.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/platform/PlatformContentFilter.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -48,6 +48,7 @@
virtual bool didBlockData() const = 0;
virtual const char* getReplacementData(int& length) const = 0;
virtual ContentFilterUnblockHandler unblockHandler() const = 0;
+ virtual String unblockRequestDeniedScript() const { return emptyString(); }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/cocoa/ContentFilterUnblockHandlerCocoa.mm (181790 => 181791)
--- trunk/Source/WebCore/platform/cocoa/ContentFilterUnblockHandlerCocoa.mm 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/platform/cocoa/ContentFilterUnblockHandlerCocoa.mm 2015-03-20 08:42:59 UTC (rev 181791)
@@ -28,62 +28,118 @@
#if ENABLE(CONTENT_FILTERING)
+#import "BlockExceptions.h"
#import "ResourceRequest.h"
+
+#if PLATFORM(IOS)
#import "SoftLinking.h"
+#import "WebCoreThreadRun.h"
#import "WebFilterEvaluatorSPI.h"
-#import <objc/runtime.h>
SOFT_LINK_PRIVATE_FRAMEWORK(WebContentAnalysis);
SOFT_LINK_CLASS(WebContentAnalysis, WebFilterEvaluator);
+static NSString * const webFilterEvaluatorKey { @"webFilterEvaluator" };
+#endif
+
+static NSString * const unblockURLHostKey { @"unblockURLHost" };
+
namespace WebCore {
-static NSString * const platformContentFilterKey = @"platformContentFilter";
+ContentFilterUnblockHandler::ContentFilterUnblockHandler(String unblockURLHost, UnblockRequesterFunction unblockRequester)
+ : m_unblockURLHost { WTF::move(unblockURLHost) }
+ , m_unblockRequester { WTF::move(unblockRequester) }
+{
+}
-void ContentFilterUnblockHandler::encode(NSKeyedArchiver *archiver) const
+#if PLATFORM(IOS)
+ContentFilterUnblockHandler::ContentFilterUnblockHandler(String unblockURLHost, RetainPtr<WebFilterEvaluator> evaluator)
+ : m_unblockURLHost { WTF::move(unblockURLHost) }
+ , m_webFilterEvaluator { WTF::move(evaluator) }
{
- if ([getWebFilterEvaluatorClass() conformsToProtocol:@protocol(NSSecureCoding)])
- [archiver encodeObject:m_webFilterEvaluator.get() forKey:platformContentFilterKey];
}
+#endif
-bool ContentFilterUnblockHandler::decode(NSKeyedUnarchiver *unarchiver, ContentFilterUnblockHandler& unblockHandler)
+bool ContentFilterUnblockHandler::needsUIProcess() const
{
- @try {
- if ([getWebFilterEvaluatorClass() conformsToProtocol:@protocol(NSSecureCoding)])
- unblockHandler.m_webFilterEvaluator = (WebFilterEvaluator *)[unarchiver decodeObjectOfClass:getWebFilterEvaluatorClass() forKey:platformContentFilterKey];
- return true;
- } @catch (NSException *exception) {
- LOG_ERROR("The platform content filter being decoded is not a WebFilterEvaluator.");
- }
-
+#if PLATFORM(IOS)
+ return m_webFilterEvaluator;
+#else
return false;
+#endif
}
+void ContentFilterUnblockHandler::encode(NSCoder *coder) const
+{
+ ASSERT_ARG(coder, coder.allowsKeyedCoding && coder.requiresSecureCoding);
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ [coder encodeObject:m_unblockURLHost forKey:unblockURLHostKey];
#if PLATFORM(IOS)
-static inline const char* scheme()
+ [coder encodeObject:m_webFilterEvaluator.get() forKey:webFilterEvaluatorKey];
+#endif
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+bool ContentFilterUnblockHandler::decode(NSCoder *coder, ContentFilterUnblockHandler& unblockHandler)
{
- return "x-apple-content-filter";
+ ASSERT_ARG(coder, coder.allowsKeyedCoding && coder.requiresSecureCoding);
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ unblockHandler.m_unblockURLHost = [coder decodeObjectOfClass:[NSString class] forKey:unblockURLHostKey];
+#if PLATFORM(IOS)
+ unblockHandler.m_webFilterEvaluator = [coder decodeObjectOfClass:getWebFilterEvaluatorClass() forKey:webFilterEvaluatorKey];
+#endif
+ return true;
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return false;
}
-bool ContentFilterUnblockHandler::handleUnblockRequestAndDispatchIfSuccessful(const ResourceRequest& request, std::function<void()> function)
+bool ContentFilterUnblockHandler::canHandleRequest(const ResourceRequest& request) const
{
- if (!m_webFilterEvaluator)
+ if (!m_unblockRequester) {
+#if PLATFORM(IOS)
+ if (!m_webFilterEvaluator)
+ return false;
+#else
return false;
+#endif
+ }
- if (!request.url().protocolIs(scheme()))
- return false;
+ return request.url().protocolIs(unblockURLScheme()) && equalIgnoringCase(request.url().host(), m_unblockURLHost);
+}
- if (!equalIgnoringCase(request.url().host(), "unblock"))
- return false;
+static inline void dispatchToMainThread(void (^block)())
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+#if PLATFORM(IOS)
+ WebThreadRun(block);
+#else
+ block();
+#endif
+ });
+}
- [m_webFilterEvaluator unblockWithCompletion:^(BOOL unblocked, NSError *) {
- if (unblocked)
- function();
- }];
- return true;
-}
+void ContentFilterUnblockHandler::requestUnblockAsync(DecisionHandlerFunction decisionHandler) const
+{
+#if PLATFORM(IOS)
+ if (m_webFilterEvaluator) {
+ [m_webFilterEvaluator unblockWithCompletion:[decisionHandler](BOOL unblocked, NSError *) {
+ dispatchToMainThread([decisionHandler, unblocked] {
+ decisionHandler(unblocked);
+ });
+ }];
+ return;
+ }
#endif
+ if (m_unblockRequester) {
+ m_unblockRequester([decisionHandler](bool unblocked) {
+ dispatchToMainThread([decisionHandler, unblocked] {
+ decisionHandler(unblocked);
+ });
+ });
+ }
+}
+
} // namespace WebCore
#endif // PLATFORM(IOS) && ENABLE(CONTENT_FILTERING)
Modified: trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm (181790 => 181791)
--- trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm 2015-03-20 08:42:59 UTC (rev 181791)
@@ -93,7 +93,11 @@
ContentFilterUnblockHandler ParentalControlsContentFilter::unblockHandler() const
{
- return ContentFilterUnblockHandler { m_webFilterEvaluator.get() };
+#if PLATFORM(IOS)
+ return ContentFilterUnblockHandler { "unblock", m_webFilterEvaluator };
+#else
+ return { };
+#endif
}
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/MockContentFilter.cpp (181790 => 181791)
--- trunk/Source/WebCore/testing/MockContentFilter.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/testing/MockContentFilter.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -34,6 +34,9 @@
namespace WebCore {
+using Decision = MockContentFilterSettings::Decision;
+using DecisionPoint = MockContentFilterSettings::DecisionPoint;
+
void MockContentFilter::ensureInstalled()
{
static std::once_flag onceFlag;
@@ -42,9 +45,14 @@
});
}
+static inline MockContentFilterSettings& settings()
+{
+ return MockContentFilterSettings::singleton();
+}
+
bool MockContentFilter::canHandleResponse(const ResourceResponse&)
{
- return MockContentFilterSettings::singleton().enabled();
+ return settings().enabled();
}
std::unique_ptr<MockContentFilter> MockContentFilter::create(const ResourceResponse& response)
@@ -54,18 +62,18 @@
MockContentFilter::MockContentFilter(const ResourceResponse&)
{
- maybeDetermineStatus(MockContentFilterSettings::DecisionPoint::AfterResponse);
+ maybeDetermineStatus(DecisionPoint::AfterResponse);
}
void MockContentFilter::addData(const char* data, int length)
{
m_replacementData.append(data, length);
- maybeDetermineStatus(MockContentFilterSettings::DecisionPoint::AfterAddData);
+ maybeDetermineStatus(DecisionPoint::AfterAddData);
}
void MockContentFilter::finishedAddingData()
{
- maybeDetermineStatus(MockContentFilterSettings::DecisionPoint::AfterFinishedAddingData);
+ maybeDetermineStatus(DecisionPoint::AfterFinishedAddingData);
}
bool MockContentFilter::needsMoreData() const
@@ -86,20 +94,34 @@
ContentFilterUnblockHandler MockContentFilter::unblockHandler() const
{
- return { };
+ using DecisionHandlerFunction = ContentFilterUnblockHandler::DecisionHandlerFunction;
+
+ return ContentFilterUnblockHandler {
+ MockContentFilterSettings::unblockURLHost(), [](DecisionHandlerFunction decisionHandler) {
+ bool shouldAllow { settings().unblockRequestDecision() == Decision::Allow };
+ if (shouldAllow)
+ settings().setDecision(Decision::Allow);
+ decisionHandler(shouldAllow);
+ }
+ };
}
-void MockContentFilter::maybeDetermineStatus(MockContentFilterSettings::DecisionPoint decisionPoint)
+String MockContentFilter::unblockRequestDeniedScript() const
{
- if (m_status != Status::NeedsMoreData || decisionPoint != MockContentFilterSettings::singleton().decisionPoint())
+ return ASCIILiteral("unblockRequestDenied()");
+}
+
+void MockContentFilter::maybeDetermineStatus(DecisionPoint decisionPoint)
+{
+ if (m_status != Status::NeedsMoreData || decisionPoint != settings().decisionPoint())
return;
- m_status = MockContentFilterSettings::singleton().decision() == MockContentFilterSettings::Decision::Allow ? Status::Allowed : Status::Blocked;
+ m_status = settings().decision() == Decision::Allow ? Status::Allowed : Status::Blocked;
if (m_status != Status::Blocked)
return;
m_replacementData.clear();
- const CString utf8BlockedString = MockContentFilterSettings::singleton().blockedString().utf8();
+ const CString utf8BlockedString = settings().blockedString().utf8();
m_replacementData.append(utf8BlockedString.data(), utf8BlockedString.length());
}
Modified: trunk/Source/WebCore/testing/MockContentFilter.h (181790 => 181791)
--- trunk/Source/WebCore/testing/MockContentFilter.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/testing/MockContentFilter.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -45,6 +45,7 @@
bool didBlockData() const override;
const char* getReplacementData(int& length) const override;
ContentFilterUnblockHandler unblockHandler() const override;
+ String unblockRequestDeniedScript() const override;
private:
enum class Status {
Modified: trunk/Source/WebCore/testing/MockContentFilterSettings.cpp (181790 => 181791)
--- trunk/Source/WebCore/testing/MockContentFilterSettings.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/testing/MockContentFilterSettings.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -28,6 +28,8 @@
#if ENABLE(CONTENT_FILTERING)
+#include "ContentFilterUnblockHandler.h"
+#include <mutex>
#include <wtf/NeverDestroyed.h>
namespace WebCore {
@@ -43,6 +45,18 @@
singleton() = MockContentFilterSettings();
}
+const String& MockContentFilterSettings::unblockRequestURL() const
+{
+ static LazyNeverDestroyed<String> unblockRequestURL;
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [] {
+ unblockRequestURL.construct(ContentFilterUnblockHandler::unblockURLScheme());
+ unblockRequestURL.get().append("://");
+ unblockRequestURL.get().append(unblockURLHost());
+ });
+ return unblockRequestURL;
+}
+
}; // namespace WebCore
#endif // ENABLE(CONTENT_FILTERING)
Modified: trunk/Source/WebCore/testing/MockContentFilterSettings.h (181790 => 181791)
--- trunk/Source/WebCore/testing/MockContentFilterSettings.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/testing/MockContentFilterSettings.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -32,8 +32,8 @@
namespace WebCore {
class MockContentFilterSettings {
- WTF_MAKE_FAST_ALLOCATED;
friend class NeverDestroyed<MockContentFilterSettings>;
+
public:
enum class DecisionPoint {
AfterResponse,
@@ -48,6 +48,7 @@
static MockContentFilterSettings& singleton();
static void reset();
+ static const char* unblockURLHost() { return "mock-unblock"; }
// Trick the generated bindings into thinking we're RefCounted.
void ref() { }
@@ -65,6 +66,11 @@
Decision decision() const { return m_decision; }
void setDecision(Decision decision) { m_decision = decision; }
+ Decision unblockRequestDecision() const { return m_unblockRequestDecision; }
+ void setUnblockRequestDecision(Decision unblockRequestDecision) { m_unblockRequestDecision = unblockRequestDecision; }
+
+ const String& unblockRequestURL() const;
+
private:
MockContentFilterSettings() = default;
MockContentFilterSettings(const MockContentFilterSettings&) = delete;
@@ -73,6 +79,7 @@
bool m_enabled { false };
DecisionPoint m_decisionPoint { DecisionPoint::AfterResponse };
Decision m_decision { Decision::Allow };
+ Decision m_unblockRequestDecision { Decision::Block };
String m_blockedString;
};
Modified: trunk/Source/WebCore/testing/MockContentFilterSettings.idl (181790 => 181791)
--- trunk/Source/WebCore/testing/MockContentFilterSettings.idl 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebCore/testing/MockContentFilterSettings.idl 2015-03-20 08:42:59 UTC (rev 181791)
@@ -39,4 +39,7 @@
const octet DECISION_ALLOW = 0;
const octet DECISION_BLOCK = 1;
[Custom] attribute octet decision;
+ [Custom] attribute octet unblockRequestDecision;
+
+ readonly attribute DOMString unblockRequestURL;
};
Modified: trunk/Source/WebKit/mac/ChangeLog (181790 => 181791)
--- trunk/Source/WebKit/mac/ChangeLog 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit/mac/ChangeLog 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1,3 +1,17 @@
+2015-03-19 Andy Estes <[email protected]>
+
+ [Content Filtering] Add tests for unblock requests
+ https://bugs.webkit.org/show_bug.cgi?id=142900
+
+ Reviewed by Andreas Kling.
+
+ * WebCoreSupport/WebFrameLoaderClient.mm:
+ (WebFrameLoaderClient::dispatchDidStartProvisionalLoad): This now happens in PolicyChecker.
+ (WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction): Ditto.
+ * WebView/WebFrame.mm:
+ (-[WebFrame _contentFilterDidHandleNavigationAction:]): Deleted.
+ * WebView/WebFrameInternal.h: Removed contentFilterUnblockHandler from WebFramePrivate.
+
2015-03-19 Enrica Casucci <[email protected]>
<attachment> should put URLs on the pasteboard so that Finder can accept drops.
Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm (181790 => 181791)
--- trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm 2015-03-20 08:42:59 UTC (rev 181791)
@@ -151,6 +151,10 @@
#import <WebCore/RuntimeApplicationChecksIOS.h>
#endif
+#if ENABLE(CONTENT_FILTERING)
+#import <WebCore/PolicyChecker.h>
+#endif
+
using namespace WebCore;
using namespace HTMLNames;
@@ -665,7 +669,6 @@
{
ASSERT(!m_webFrame->_private->provisionalURL);
m_webFrame->_private->provisionalURL = core(m_webFrame.get())->loader().provisionalDocumentLoader()->url().string();
- m_webFrame->_private->contentFilterUnblockHandler.clear();
WebView *webView = getWebView(m_webFrame.get());
#if !PLATFORM(IOS)
@@ -880,11 +883,6 @@
void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, FramePolicyFunction function)
{
- if ([m_webFrame _contentFilterDidHandleNavigationAction:request]) {
- function(PolicyIgnore);
- return;
- }
-
WebView *webView = getWebView(m_webFrame.get());
[[webView _policyDelegateForwarder] webView:webView
decidePolicyForNavigationAction:actionDictionary(action, formState)
@@ -2242,10 +2240,12 @@
}
#endif
+#if ENABLE(CONTENT_FILTERING)
void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
{
- m_webFrame->_private->contentFilterUnblockHandler = WTF::move(unblockHandler);
+ core(m_webFrame.get())->loader().policyChecker().setContentFilterUnblockHandler(WTF::move(unblockHandler));
}
+#endif
@implementation WebFramePolicyListener
Modified: trunk/Source/WebKit/mac/WebView/WebFrame.mm (181790 => 181791)
--- trunk/Source/WebKit/mac/WebView/WebFrame.mm 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit/mac/WebView/WebFrame.mm 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1002,20 +1002,6 @@
_private->coreFrame->loader().documentLoader()->commitData((const char *)[data bytes], [data length]);
}
-- (BOOL)_contentFilterDidHandleNavigationAction:(const WebCore::ResourceRequest &)request
-{
-#if PLATFORM(IOS)
- RetainPtr<WebFrame> retainedMainFrame = [[self webView] mainFrame];
- return _private->contentFilterUnblockHandler.handleUnblockRequestAndDispatchIfSuccessful(request, [retainedMainFrame] {
- WebThreadRun(^ {
- [retainedMainFrame reload];
- });
- });
-#else
- return NO;
-#endif
-}
-
@end
@implementation WebFrame (WebPrivate)
Modified: trunk/Source/WebKit/mac/WebView/WebFrameInternal.h (181790 => 181791)
--- trunk/Source/WebKit/mac/WebView/WebFrameInternal.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit/mac/WebView/WebFrameInternal.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -30,7 +30,6 @@
#import "WebFramePrivate.h"
#import "WebPreferencesPrivate.h"
-#import <WebCore/ContentFilterUnblockHandler.h>
#import <WebCore/EditAction.h>
#import <WebCore/FrameLoaderTypes.h>
#import <WebCore/FrameSelection.h>
@@ -92,7 +91,6 @@
#if PLATFORM(IOS)
BOOL isCommitting;
#endif
- WebCore::ContentFilterUnblockHandler contentFilterUnblockHandler;
}
@end
@@ -184,8 +182,6 @@
- (void)_commitData:(NSData *)data;
-- (BOOL)_contentFilterDidHandleNavigationAction:(const WebCore::ResourceRequest&)request;
-
@end
@interface NSObject (WebInternalFrameLoadDelegate)
Modified: trunk/Source/WebKit2/ChangeLog (181790 => 181791)
--- trunk/Source/WebKit2/ChangeLog 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/ChangeLog 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1,3 +1,26 @@
+2015-03-19 Andy Estes <[email protected]>
+
+ [Content Filtering] Add tests for unblock requests
+ https://bugs.webkit.org/show_bug.cgi?id=142900
+
+ Reviewed by Andreas Kling.
+
+ * UIProcess/Cocoa/WebPageProxyCocoa.mm:
+ (WebKit::WebPageProxy::contentFilterDidBlockLoadForFrame): Called WebFrameProxy::contentFilterDidBlockLoad.
+ * UIProcess/WebFrameProxy.cpp:
+ (WebKit::WebFrameProxy::didStartProvisionalLoad): Assigned a default-constructed ContentFilterUnblockHandler instead of calling clear().
+ (WebKit::WebFrameProxy::didHandleContentFilterUnblockNavigation): Renamed from contentFilterDidHandleNavigationAction.
+ Updated to use ContentFilterUnblockHandler's new API.
+ (WebKit::WebFrameProxy::contentFilterDidHandleNavigationAction): Deleted.
+ * UIProcess/WebFrameProxy.h:
+ (WebKit::WebFrameProxy::contentFilterDidBlockLoad): Renamed from setContentFilterUnblockHandler.
+ (WebKit::WebFrameProxy::setContentFilterUnblockHandler): Deleted.
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::decidePolicyForNavigationAction): Called WebFrameProxy::didHandleContentFilterUnblockNavigation.
+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+ (WebKit::WebFrameLoaderClient::contentFilterDidBlockLoad): If the unblock handler needs the UI process,
+ send WebPageProxy::ContentFilterDidBlockLoadForFrame. Oterwise, call PolicyChecker::setContentFilterUnblockHandler.
+
2015-03-20 Zan Dobersek <[email protected]>
[GTK] Properly guard X11-specific code in BackingStore::createBackend()
Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebPageProxyCocoa.mm (181790 => 181791)
--- trunk/Source/WebKit2/UIProcess/Cocoa/WebPageProxyCocoa.mm 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebPageProxyCocoa.mm 2015-03-20 08:42:59 UTC (rev 181791)
@@ -75,7 +75,7 @@
void WebPageProxy::contentFilterDidBlockLoadForFrame(const WebCore::ContentFilterUnblockHandler& unblockHandler, uint64_t frameID)
{
if (WebFrameProxy* frame = m_process->webFrame(frameID))
- frame->setContentFilterUnblockHandler(unblockHandler);
+ frame->contentFilterDidBlockLoad(unblockHandler);
}
}
Modified: trunk/Source/WebKit2/UIProcess/WebFrameProxy.cpp (181790 => 181791)
--- trunk/Source/WebKit2/UIProcess/WebFrameProxy.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/UIProcess/WebFrameProxy.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -128,7 +128,7 @@
{
m_frameLoadState.didStartProvisionalLoad(url);
#if ENABLE(CONTENT_FILTERING)
- m_contentFilterUnblockHandler.clear();
+ m_contentFilterUnblockHandler = { };
#endif
}
@@ -234,16 +234,18 @@
}
#if ENABLE(CONTENT_FILTERING)
-bool WebFrameProxy::contentFilterDidHandleNavigationAction(const WebCore::ResourceRequest& request)
+bool WebFrameProxy::didHandleContentFilterUnblockNavigation(const WebCore::ResourceRequest& request)
{
-#if PLATFORM(IOS)
- RefPtr<WebPageProxy> retainedPage = m_page;
- return m_contentFilterUnblockHandler.handleUnblockRequestAndDispatchIfSuccessful(request, [retainedPage] {
- retainedPage->reload(false);
+ if (!m_contentFilterUnblockHandler.canHandleRequest(request))
+ return false;
+
+ RefPtr<WebPageProxy> page { m_page };
+ ASSERT(page);
+ m_contentFilterUnblockHandler.requestUnblockAsync([page](bool unblocked) {
+ if (unblocked)
+ page->reload(false);
});
-#else
- return false;
-#endif
+ return true;
}
#endif
Modified: trunk/Source/WebKit2/UIProcess/WebFrameProxy.h (181790 => 181791)
--- trunk/Source/WebKit2/UIProcess/WebFrameProxy.h 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/UIProcess/WebFrameProxy.h 2015-03-20 08:42:59 UTC (rev 181791)
@@ -123,8 +123,8 @@
WebFormSubmissionListenerProxy& setUpFormSubmissionListenerProxy(uint64_t listenerID);
#if ENABLE(CONTENT_FILTERING)
- void setContentFilterUnblockHandler(WebCore::ContentFilterUnblockHandler contentFilterUnblockHandler) { m_contentFilterUnblockHandler = WTF::move(contentFilterUnblockHandler); }
- bool contentFilterDidHandleNavigationAction(const WebCore::ResourceRequest&);
+ void contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler contentFilterUnblockHandler) { m_contentFilterUnblockHandler = WTF::move(contentFilterUnblockHandler); }
+ bool didHandleContentFilterUnblockNavigation(const WebCore::ResourceRequest&);
#endif
private:
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (181790 => 181791)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -3092,7 +3092,7 @@
}
#if ENABLE(CONTENT_FILTERING)
- if (frame->contentFilterDidHandleNavigationAction(request)) {
+ if (frame->didHandleContentFilterUnblockNavigation(request)) {
receivedPolicyAction = true;
policyAction = PolicyIgnore;
return;
Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (181790 => 181791)
--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2015-03-20 08:35:33 UTC (rev 181790)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2015-03-20 08:42:59 UTC (rev 181791)
@@ -1648,7 +1648,12 @@
#if ENABLE(CONTENT_FILTERING)
void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
{
- if (WebPage* webPage = m_frame->page())
+ if (!unblockHandler.needsUIProcess()) {
+ m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTF::move(unblockHandler));
+ return;
+ }
+
+ if (WebPage* webPage { m_frame->page() })
webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
}
#endif