Diff
Modified: trunk/Source/WTF/ChangeLog (194949 => 194950)
--- trunk/Source/WTF/ChangeLog 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WTF/ChangeLog 2016-01-13 02:07:11 UTC (rev 194950)
@@ -1,3 +1,13 @@
+2016-01-08 Andy Estes <[email protected]>
+
+ [Content Filtering] Lazily load platform frameworks
+ https://bugs.webkit.org/show_bug.cgi?id=152881
+ rdar://problem/23270886
+
+ Reviewed by Brady Eidson.
+
+ * wtf/Platform.h: Moved definition of HAVE_NETWORK_EXTENSION to here from WebCore/platform/cocoa/NetworkExtensionContentFilter.h.
+
2016-01-12 Ryosuke Niwa <[email protected]>
Add a build flag for custom element
Modified: trunk/Source/WTF/wtf/Platform.h (194949 => 194950)
--- trunk/Source/WTF/wtf/Platform.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WTF/wtf/Platform.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -531,6 +531,7 @@
#define HAVE_SEC_KEYCHAIN 1
#if CPU(X86_64)
+#define HAVE_NETWORK_EXTENSION 1
#define USE_PLUGIN_HOST_PROCESS 1
#endif
@@ -544,6 +545,7 @@
#if PLATFORM(IOS)
+#define HAVE_NETWORK_EXTENSION 1
#define HAVE_READLINE 1
#if USE(APPLE_INTERNAL_SDK)
#define USE_CFNETWORK 1
Modified: trunk/Source/WebCore/ChangeLog (194949 => 194950)
--- trunk/Source/WebCore/ChangeLog 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/ChangeLog 2016-01-13 02:07:11 UTC (rev 194950)
@@ -1,3 +1,96 @@
+2016-01-08 Andy Estes <[email protected]>
+
+ [Content Filtering] Lazily load platform frameworks
+ https://bugs.webkit.org/show_bug.cgi?id=152881
+ rdar://problem/23270886
+
+ Reviewed by Brady Eidson.
+
+ On Cocoa platforms, ContentFilter soft-links two frameworks that perform the underlying filtering operations.
+ There is a one-time cost associated with the soft-linking, and the current design requires all clients to pay
+ this cost whether or not they ever load a resource that is subject to filtering.
+
+ Addressed this by deferring the loading of frameworks until it is known that a resource will require filtering.
+ It is rather simple to defer the soft-linking at the PlatformContentFilter level, but doing this alone would
+ mean that every CachedRawResourceClient callback would be routed through ContentFilter, even in the very common
+ case where both platform content filters are disabled. This is because checking if a platform content filter is
+ enabled involves loading its framework, so creating a ContentFilter (which DocumentLoader will add as the
+ CachedRawResource client in place of itself) cannot be avoided by checking that all its platform content filters
+ are disabled.
+
+ Resolved this by inverting the relationship between ContentFilter and DocumentLoader. Instead of ContentFilter
+ being the CachedRawResource's client and forwarding callbacks to DocumentLoader when one or more platform
+ filters are enabled, DocumentLoader is now always the client and it forwards callbacks to ContentFilter.
+ ContentFilter then returns a boolean value indicating whether or not DocumentLoader should proceed with each
+ callback.
+
+ New API test: ContentFiltering.LazilyLoadPlatformFrameworks
+
+ * loader/ContentFilter.cpp:
+ (WebCore::ContentFilter::create): Renamed from createIfEnabled(). Since the enabled check causes frameworks to
+ be loaded, the check is skipped here and all types are always created.
+ (WebCore::ContentFilter::continueAfterWillSendRequest): Renamed from willSendRequest(). Renamed requestCopy to
+ originalRequest, and only created it for logging purposes. Since the copy was only used for logging purposes,
+ request is now modified directly. Returned false if request is null.
+ (WebCore::ContentFilter::continueAfterResponseReceived): Renamed from responseReceived(). Stopped asserting that
+ resource is non-null, since it will be null in the case of substitute data loads. Stopped asserting that m_state
+ is not Initialized, since that state was removed and the function can now be called in all states. Only logged
+ if m_state is Filtering. Returned false if m_state is Blocked.
+ (WebCore::ContentFilter::continueAfterDataReceived): Renamed from dataReceived(). Stopped asserting that
+ resource is non-null and that m_state is Initialized, and moved the logging, for the same reasons as above.
+ Returned false if m_state is Filtering or Blocked.
+ (WebCore::ContentFilter::continueAfterNotifyFinished): Renamed from notifyFinished(). Stopped asserting that
+ resource is non-null and that m_state is not Initialized, and moved the logging, for the same reasons as above.
+ If m_state is not Blocked at this point, set m_state to Allowed in order for deliverResourceData() to not get
+ caught in continueAfterDataReceived(). Returned false if m_state is Blocked or Stopped after delivering data.
+ (WebCore::ContentFilter::createIfEnabled): Renamed to create().
+ (WebCore::ContentFilter::~ContentFilter): Stopped removing ourself as m_mainResource's client.
+ (WebCore::ContentFilter::willSendRequest): Renamed to continueAfterWillSendRequest().
+ (WebCore::ContentFilter::startFilteringMainResource): Stopped adding ourself as m_mainResource's client. Stopped
+ asserting that m_state is not Initialized and instead returned early if m_state is not Stopped.
+ (WebCore::ContentFilter::stopFilteringMainResource): Stopped removing ourself as m_mainResource's client.
+ (WebCore::ContentFilter::responseReceived): Renamed to continueAfterResponseReceived().
+ (WebCore::ContentFilter::dataReceived): Renamed to continueAfterDataReceived().
+ (WebCore::ContentFilter::redirectReceived): Removed. DocumentLoader now calls continueAfterWillSendRequest()
+ directly on redirects.
+ (WebCore::ContentFilter::notifyFinished): Renamed to continueAfterNotifyFinished().
+ (WebCore::ContentFilter::didDecide): Instead of calling DocumentLoader::contentFilterDidDecide(), called
+ DocumentLoader::contentFilterDidBlock() when m_state is Blocked.
+ (WebCore::ContentFilter::deliverResourceData): Asserted that m_state is Allowed.
+ * loader/ContentFilter.h: Stopped inheriting from CachedRawResourceClient. Redeclared the
+ CachedRawResourceClient virtual functions as the continue* functions mentioned above. Made State enum private
+ and removed Initialized. Initialized m_state to Stopped and removed its getter.
+ (WebCore::ContentFilter::type): Returned a ContentFilter::Type that does not include an enabled function.
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::notifyFinished): Returned early if ContentFilter::continueAfterNotifyFinished()
+ returned false.
+ (WebCore::DocumentLoader::willSendRequest): Called ContentFilter::continueAfterWillSendRequest() even for
+ redirects, since ContentFilter is no longer a CachedRawResourceClient and so will no longer receive
+ redirectReceived(). Returned early if continueAfterWillSendRequest() returns false.
+ (WebCore::DocumentLoader::responseReceived): Returned early if ContentFilter::continueAfterResponseReceived()
+ returned false.
+ (WebCore::DocumentLoader::dataReceived): Ditto for ContentFilter::continueAfterDataReceived().
+ (WebCore::DocumentLoader::startLoadingMainResource): Called ContentFilter::create(), not createIfEnabled().
+ (WebCore::DocumentLoader::becomeMainResourceClient): Called ContentFilter::startFilteringMainResource() even if
+ m_state is not Initialized. Added ourself as a client of m_mainResource unconditionally.
+ (WebCore::DocumentLoader::contentFilterDidBlock): Renamed from contentFilterDidDecide. Removed assertions and
+ the early return when m_state is Allowed, since the state is guaranteed to be Blocked.
+ (WebCore::DocumentLoader::contentFilterDidDecide): Renamed to contentFilterDidBlock.
+ * platform/cocoa/NetworkExtensionContentFilter.h: Moved definition of HAVE_NETWORK_EXTENSION to Platform.h so
+ that this file doesn't need to become a Private header. Made enabled() private, and declared initialize().
+ * platform/cocoa/NetworkExtensionContentFilter.mm:
+ (WebCore::NetworkExtensionContentFilter::initialize): Added a function to lazily initialize the object.
+ (WebCore::NetworkExtensionContentFilter::willSendRequest): For the modern NEFilterSource, checked if it is
+ enabled only after checking if the request is HTTP(S). If both checks pass, then called initialize().
+ (WebCore::NetworkExtensionContentFilter::responseReceived): Ditto for the legacy NEFilterSource.
+ * platform/cocoa/ParentalControlsContentFilter.h: Made enabled() private.
+ * platform/cocoa/ParentalControlsContentFilter.mm:
+ (WebCore::ParentalControlsContentFilter::responseReceived): Checked if WebFilterEvaluator is enabled only after
+ checking if the response is from a protocol that can be handled.
+ * testing/MockContentFilter.cpp:
+ (WebCore::MockContentFilter::willSendRequest): Immediately set m_status to Status::Allowed if !enabled().
+ * testing/MockContentFilter.h: Made enabled() private.
+
2016-01-12 Commit Queue <[email protected]>
Unreviewed, rolling out r194926 and r194928.
Modified: trunk/Source/WebCore/loader/ContentFilter.cpp (194949 => 194950)
--- trunk/Source/WebCore/loader/ContentFilter.cpp 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/loader/ContentFilter.cpp 2016-01-13 02:07:11 UTC (rev 194950)
@@ -59,13 +59,10 @@
return types;
}
-std::unique_ptr<ContentFilter> ContentFilter::createIfEnabled(DocumentLoader& documentLoader)
+std::unique_ptr<ContentFilter> ContentFilter::create(DocumentLoader& documentLoader)
{
Container filters;
for (auto& type : types()) {
- if (!type.enabled())
- continue;
-
auto filter = type.create();
ASSERT(filter);
filters.append(WTFMove(filter));
@@ -88,48 +85,41 @@
ContentFilter::~ContentFilter()
{
LOG(ContentFiltering, "Destroying ContentFilter.\n");
- if (!m_mainResource)
- return;
- ASSERT(m_mainResource->hasClient(this));
- m_mainResource->removeClient(this);
}
-void ContentFilter::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
+bool ContentFilter::continueAfterWillSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
{
LOG(ContentFiltering, "ContentFilter received request for <%s> with redirect response from <%s>.\n", request.url().string().ascii().data(), redirectResponse.url().string().ascii().data());
- ResourceRequest requestCopy { request };
- ASSERT(m_state == State::Initialized || m_state == State::Filtering);
- forEachContentFilterUntilBlocked([&requestCopy, &redirectResponse](PlatformContentFilter& contentFilter) {
- contentFilter.willSendRequest(requestCopy, redirectResponse);
- if (contentFilter.didBlockData())
- requestCopy = ResourceRequest();
+#if !LOG_DISABLED
+ ResourceRequest originalRequest { request };
+#endif
+ ASSERT(m_state == State::Stopped || m_state == State::Filtering);
+ forEachContentFilterUntilBlocked([&request, &redirectResponse](PlatformContentFilter& contentFilter) {
+ contentFilter.willSendRequest(request, redirectResponse);
});
+ if (m_state == State::Blocked)
+ request = ResourceRequest();
#if !LOG_DISABLED
- if (request != requestCopy)
- LOG(ContentFiltering, "ContentFilter changed request url to <%s>.\n", requestCopy.url().string().ascii().data());
+ if (request != originalRequest)
+ LOG(ContentFiltering, "ContentFilter changed request url to <%s>.\n", originalRequest.url().string().ascii().data());
#endif
- request = requestCopy;
+ return !request.isNull();
}
void ContentFilter::startFilteringMainResource(CachedRawResource& resource)
{
+ if (m_state != State::Stopped)
+ return;
+
LOG(ContentFiltering, "ContentFilter will start filtering main resource at <%s>.\n", resource.url().string().ascii().data());
- ASSERT(m_state == State::Initialized);
m_state = State::Filtering;
ASSERT(!m_mainResource);
m_mainResource = &resource;
- ASSERT(!m_mainResource->hasClient(this));
- m_mainResource->addClient(this);
}
void ContentFilter::stopFilteringMainResource()
{
m_state = State::Stopped;
- if (!m_mainResource)
- return;
-
- ASSERT(m_mainResource->hasClient(this));
- m_mainResource->removeClient(this);
m_mainResource = nullptr;
}
@@ -157,83 +147,61 @@
return m_blockingContentFilter->unblockRequestDeniedScript();
}
-void ContentFilter::responseReceived(CachedResource* resource, const ResourceResponse& response)
+bool ContentFilter::continueAfterResponseReceived(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_UNUSED(resource, resource == m_mainResource);
if (m_state == State::Filtering) {
+ LOG(ContentFiltering, "ContentFilter received response from <%s>.\n", response.url().string().ascii().data());
forEachContentFilterUntilBlocked([&response](PlatformContentFilter& contentFilter) {
contentFilter.responseReceived(response);
});
}
- if (m_state != State::Blocked)
- m_documentLoader.responseReceived(resource, response);
+ return m_state != State::Blocked;
}
-void ContentFilter::dataReceived(CachedResource* resource, const char* data, int length)
+bool ContentFilter::continueAfterDataReceived(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());
if (m_state == State::Filtering) {
+ LOG(ContentFiltering, "ContentFilter received %d bytes of data from <%s>.\n", length, resource->url().string().ascii().data());
forEachContentFilterUntilBlocked([data, length](PlatformContentFilter& contentFilter) {
contentFilter.addData(data, length);
});
if (m_state == State::Allowed)
deliverResourceData(*resource);
- return;
+ return false;
}
- if (m_state == State::Allowed)
- m_documentLoader.dataReceived(resource, data, length);
+ return m_state != State::Blocked;
}
-void ContentFilter::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
+bool ContentFilter::continueAfterNotifyFinished(CachedResource* resource)
{
- ASSERT(resource);
ASSERT(resource == m_mainResource);
- ASSERT(m_state != State::Initialized);
- if (m_state == State::Filtering)
- willSendRequest(request, redirectResponse);
+ if (resource->errorOccurred())
+ return true;
- 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());
-
- if (resource->errorOccurred()) {
- m_documentLoader.notifyFinished(resource);
- return;
- }
-
if (m_state == State::Filtering) {
+ LOG(ContentFiltering, "ContentFilter will finish filtering main resource at <%s>.\n", resource->url().string().ascii().data());
forEachContentFilterUntilBlocked([](PlatformContentFilter& contentFilter) {
contentFilter.finishedAddingData();
});
- if (m_state != State::Blocked)
+ if (m_state != State::Blocked) {
+ m_state = State::Allowed;
deliverResourceData(*resource);
-
+ }
+
if (m_state == State::Stopped)
- return;
+ return false;
}
- if (m_state != State::Blocked)
- m_documentLoader.notifyFinished(resource);
+ return m_state != State::Blocked;
}
void ContentFilter::forEachContentFilterUntilBlocked(std::function<void(PlatformContentFilter&)> function)
@@ -267,11 +235,13 @@
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();
+ if (m_state == State::Blocked)
+ m_documentLoader.contentFilterDidBlock();
}
void ContentFilter::deliverResourceData(CachedResource& resource)
{
+ ASSERT(m_state == State::Allowed);
ASSERT(resource.dataBufferingPolicy() == BufferData);
if (auto* resourceBuffer = resource.resourceBuffer())
m_documentLoader.dataReceived(&resource, resourceBuffer->data(), resourceBuffer->size());
Modified: trunk/Source/WebCore/loader/ContentFilter.h (194949 => 194950)
--- trunk/Source/WebCore/loader/ContentFilter.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/loader/ContentFilter.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -28,7 +28,6 @@
#if ENABLE(CONTENT_FILTERING)
-#include "CachedRawResourceClient.h"
#include "CachedResourceHandle.h"
#include <functional>
#include <wtf/Vector.h>
@@ -39,39 +38,43 @@
class ContentFilterUnblockHandler;
class DocumentLoader;
class PlatformContentFilter;
+class ResourceRequest;
+class ResourceResponse;
class SharedBuffer;
-class ContentFilter final : private CachedRawResourceClient {
+class ContentFilter {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(ContentFilter);
public:
template <typename T> static void addType() { types().append(type<T>()); }
- static std::unique_ptr<ContentFilter> createIfEnabled(DocumentLoader&);
- ~ContentFilter() override;
+ static std::unique_ptr<ContentFilter> create(DocumentLoader&);
+ ~ContentFilter();
static const char* urlScheme() { return "x-apple-content-filter"; }
- void willSendRequest(ResourceRequest&, const ResourceResponse&);
void startFilteringMainResource(CachedRawResource&);
void stopFilteringMainResource();
+ bool continueAfterWillSendRequest(ResourceRequest&, const ResourceResponse&);
+ bool continueAfterResponseReceived(CachedResource*, const ResourceResponse&);
+ bool continueAfterDataReceived(CachedResource*, const char* data, int length);
+ bool continueAfterNotifyFinished(CachedResource*);
+
+ ContentFilterUnblockHandler unblockHandler() const;
+ Ref<SharedBuffer> replacementData() const;
+ String unblockRequestDeniedScript() const;
+
+private:
enum class State {
- Initialized,
+ Stopped,
Filtering,
Allowed,
Blocked,
- Stopped
};
- State state() const { return m_state; }
- ContentFilterUnblockHandler unblockHandler() const;
- Ref<SharedBuffer> replacementData() const;
- String unblockRequestDeniedScript() const;
-private:
struct Type {
- const std::function<bool()> enabled;
const std::function<std::unique_ptr<PlatformContentFilter>()> create;
};
template <typename T> static Type type();
@@ -81,14 +84,6 @@
friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, DocumentLoader&);
ContentFilter(Container, DocumentLoader&);
- // CachedRawResourceClient
- void responseReceived(CachedResource*, const ResourceResponse&) override;
- void dataReceived(CachedResource*, const char* data, int length) override;
- void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) override;
-
- // CachedResourceClient
- void notifyFinished(CachedResource*) override;
-
void forEachContentFilterUntilBlocked(std::function<void(PlatformContentFilter&)>);
void didDecide(State);
void deliverResourceData(CachedResource&);
@@ -97,14 +92,14 @@
DocumentLoader& m_documentLoader;
CachedResourceHandle<CachedRawResource> m_mainResource;
PlatformContentFilter* m_blockingContentFilter { nullptr };
- State m_state { State::Initialized };
+ State m_state { State::Stopped };
};
template <typename T>
ContentFilter::Type ContentFilter::type()
{
static_assert(std::is_base_of<PlatformContentFilter, T>::value, "Type must be a PlatformContentFilter.");
- return { T::enabled, T::create };
+ return { T::create };
}
} // namespace WebCore
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (194949 => 194950)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2016-01-13 02:07:11 UTC (rev 194950)
@@ -370,6 +370,11 @@
void DocumentLoader::notifyFinished(CachedResource* resource)
{
+#if ENABLE(CONTENT_FILTERING)
+ if (m_contentFilter && !m_contentFilter->continueAfterNotifyFinished(resource))
+ return;
+#endif
+
ASSERT_UNUSED(resource, m_mainResource == resource);
ASSERT(m_mainResource);
if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
@@ -540,11 +545,8 @@
}
#if ENABLE(CONTENT_FILTERING)
- if (m_contentFilter && redirectResponse.isNull()) {
- m_contentFilter->willSendRequest(newRequest, redirectResponse);
- if (newRequest.isNull())
- return;
- }
+ if (m_contentFilter && !m_contentFilter->continueAfterWillSendRequest(newRequest, redirectResponse))
+ return;
#endif
setRequest(newRequest);
@@ -606,6 +608,11 @@
void DocumentLoader::responseReceived(CachedResource* resource, const ResourceResponse& response)
{
+#if ENABLE(CONTENT_FILTERING)
+ if (m_contentFilter && !m_contentFilter->continueAfterResponseReceived(resource, response))
+ return;
+#endif
+
ASSERT_UNUSED(resource, m_mainResource == resource);
Ref<DocumentLoader> protect(*this);
bool willLoadFallback = m_applicationCacheHost->maybeLoadFallbackForMainResponse(request(), response);
@@ -873,6 +880,11 @@
void DocumentLoader::dataReceived(CachedResource* resource, const char* data, int length)
{
+#if ENABLE(CONTENT_FILTERING)
+ if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(resource, data, length))
+ return;
+#endif
+
ASSERT(data);
ASSERT(length);
ASSERT_UNUSED(resource, resource == m_mainResource);
@@ -1418,7 +1430,7 @@
return;
#if ENABLE(CONTENT_FILTERING)
- m_contentFilter = !m_originalSubstituteDataWasValid ? ContentFilter::createIfEnabled(*this) : nullptr;
+ m_contentFilter = !m_substituteData.isValid() ? ContentFilter::create(*this) : nullptr;
#endif
// FIXME: Is there any way the extra fields could have not been added by now?
@@ -1624,11 +1636,8 @@
void DocumentLoader::becomeMainResourceClient()
{
#if ENABLE(CONTENT_FILTERING)
- if (m_contentFilter && m_contentFilter->state() == ContentFilter::State::Initialized) {
- // ContentFilter will synthesize CachedRawResourceClient callbacks.
+ if (m_contentFilter)
m_contentFilter->startFilteringMainResource(*m_mainResource);
- return;
- }
#endif
m_mainResource->addClient(this);
}
@@ -1666,13 +1675,9 @@
frameLoader()->client().contentFilterDidBlockLoad(WTFMove(unblockHandler));
}
-void DocumentLoader::contentFilterDidDecide()
+void DocumentLoader::contentFilterDidBlock()
{
- using State = ContentFilter::State;
ASSERT(m_contentFilter);
- ASSERT(m_contentFilter->state() == State::Blocked || m_contentFilter->state() == State::Allowed);
- if (m_contentFilter->state() == State::Allowed)
- return;
installContentFilterUnblockHandler(*m_contentFilter);
Modified: trunk/Source/WebCore/loader/DocumentLoader.h (194949 => 194950)
--- trunk/Source/WebCore/loader/DocumentLoader.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/loader/DocumentLoader.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -349,7 +349,7 @@
#if ENABLE(CONTENT_FILTERING)
friend class ContentFilter;
void installContentFilterUnblockHandler(ContentFilter&);
- void contentFilterDidDecide();
+ void contentFilterDidBlock();
#endif
Frame* m_frame;
Modified: trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h (194949 => 194950)
--- trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -32,8 +32,6 @@
#include <wtf/OSObjectPtr.h>
#include <wtf/RetainPtr.h>
-#define HAVE_NETWORK_EXTENSION PLATFORM(IOS) || (PLATFORM(MAC) && CPU(X86_64))
-
enum NEFilterSourceStatus : NSInteger;
OBJC_CLASS NEFilterSource;
@@ -41,11 +39,12 @@
namespace WebCore {
+class URL;
+
class NetworkExtensionContentFilter final : public PlatformContentFilter {
friend std::unique_ptr<NetworkExtensionContentFilter> std::make_unique<NetworkExtensionContentFilter>();
public:
- static bool enabled();
static std::unique_ptr<NetworkExtensionContentFilter> create();
void willSendRequest(ResourceRequest&, const ResourceResponse&) override;
@@ -58,7 +57,10 @@
ContentFilterUnblockHandler unblockHandler() const override;
private:
+ static bool enabled();
+
NetworkExtensionContentFilter();
+ void initialize(const URL* = nullptr);
void handleDecision(NEFilterSourceStatus, NSData *replacementData);
NEFilterSourceStatus m_status;
Modified: trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm (194949 => 194950)
--- trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -65,24 +65,36 @@
NetworkExtensionContentFilter::NetworkExtensionContentFilter()
: m_status { NEFilterSourceStatusNeedsMoreData }
- , m_queue { adoptOSObject(dispatch_queue_create("com.apple.WebCore.NEFilterSourceQueue", DISPATCH_QUEUE_SERIAL)) }
- , m_semaphore { adoptOSObject(dispatch_semaphore_create(0)) }
+{
+}
+
+void NetworkExtensionContentFilter::initialize(const URL* url)
+{
+ ASSERT(!m_queue);
+ ASSERT(!m_semaphore);
+ ASSERT(!m_neFilterSource);
+ m_queue = adoptOSObject(dispatch_queue_create("com.apple.WebCore.NEFilterSourceQueue", DISPATCH_QUEUE_SERIAL));
+ m_semaphore = adoptOSObject(dispatch_semaphore_create(0));
#if HAVE(MODERN_NE_FILTER_SOURCE)
- , m_neFilterSource { adoptNS([allocNEFilterSourceInstance() initWithDecisionQueue:m_queue.get()]) }
+ ASSERT_UNUSED(url, !url);
+ m_neFilterSource = adoptNS([allocNEFilterSourceInstance() initWithDecisionQueue:m_queue.get()]);
+#else
+ ASSERT_ARG(url, url);
+ m_neFilterSource = adoptNS([allocNEFilterSourceInstance() initWithURL:*url direction:NEFilterSourceDirectionInbound socketIdentifier:0]);
#endif
-{
- ASSERT([getNEFilterSourceClass() filterRequired]);
}
void NetworkExtensionContentFilter::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
{
#if HAVE(MODERN_NE_FILTER_SOURCE)
ASSERT(!request.isNull());
- if (!request.url().protocolIsInHTTPFamily()) {
+ if (!request.url().protocolIsInHTTPFamily() || !enabled()) {
m_status = NEFilterSourceStatusPass;
return;
}
+ initialize();
+
if (!redirectResponse.isNull()) {
responseReceived(redirectResponse);
if (!needsMoreData())
@@ -125,8 +137,12 @@
}
#if !HAVE(MODERN_NE_FILTER_SOURCE)
- ASSERT(!m_neFilterSource);
- m_neFilterSource = adoptNS([allocNEFilterSourceInstance() initWithURL:response.url() direction:NEFilterSourceDirectionInbound socketIdentifier:0]);
+ if (!enabled()) {
+ m_status = NEFilterSourceStatusPass;
+ return;
+ }
+
+ initialize(&response.url());
#else
[m_neFilterSource receivedResponse:response.nsURLResponse() decisionHandler:[this](NEFilterSourceStatus status, NSDictionary *decisionInfo) {
handleDecision(status, replacementDataFromDecisionInfo(decisionInfo));
Modified: trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h (194949 => 194950)
--- trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -39,7 +39,6 @@
friend std::unique_ptr<ParentalControlsContentFilter> std::make_unique<ParentalControlsContentFilter>();
public:
- static bool enabled();
static std::unique_ptr<ParentalControlsContentFilter> create();
void willSendRequest(ResourceRequest&, const ResourceResponse&) override { }
@@ -52,6 +51,8 @@
ContentFilterUnblockHandler unblockHandler() const override;
private:
+ static bool enabled();
+
ParentalControlsContentFilter();
void updateFilterState();
Modified: trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm (194949 => 194950)
--- trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -56,7 +56,6 @@
ParentalControlsContentFilter::ParentalControlsContentFilter()
: m_filterState { kWFEStateBuffering }
{
- ASSERT([getWebFilterEvaluatorClass() isManagedSession]);
}
static inline bool canHandleResponse(const ResourceResponse& response)
@@ -72,7 +71,7 @@
{
ASSERT(!m_webFilterEvaluator);
- if (!canHandleResponse(response)) {
+ if (!canHandleResponse(response) || !enabled()) {
m_filterState = kWFEStateAllowed;
return;
}
Modified: trunk/Source/WebCore/testing/MockContentFilter.cpp (194949 => 194950)
--- trunk/Source/WebCore/testing/MockContentFilter.cpp 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/testing/MockContentFilter.cpp 2016-01-13 02:07:11 UTC (rev 194950)
@@ -70,6 +70,11 @@
void MockContentFilter::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
{
+ if (!enabled()) {
+ m_status = Status::Allowed;
+ return;
+ }
+
if (redirectResponse.isNull())
maybeDetermineStatus(DecisionPoint::AfterWillSendRequest);
else
Modified: trunk/Source/WebCore/testing/MockContentFilter.h (194949 => 194950)
--- trunk/Source/WebCore/testing/MockContentFilter.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Source/WebCore/testing/MockContentFilter.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -36,7 +36,6 @@
public:
static void ensureInstalled();
- static bool enabled();
static std::unique_ptr<MockContentFilter> create();
void willSendRequest(ResourceRequest&, const ResourceResponse&) override;
@@ -56,6 +55,8 @@
Blocked
};
+ static bool enabled();
+
MockContentFilter() = default;
void maybeDetermineStatus(MockContentFilterSettings::DecisionPoint);
Modified: trunk/Tools/ChangeLog (194949 => 194950)
--- trunk/Tools/ChangeLog 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/ChangeLog 2016-01-13 02:07:11 UTC (rev 194950)
@@ -1,3 +1,47 @@
+2016-01-08 Andy Estes <[email protected]>
+
+ [Content Filtering] Lazily load platform frameworks
+ https://bugs.webkit.org/show_bug.cgi?id=152881
+ rdar://problem/23270886
+
+ Reviewed by Brady Eidson.
+
+ Added an API test that verifies that the Parental Controls and Network Extension frameworks are loaded at the
+ expected times. The test verifies that they are not loaded after creating a WKWebView, loading an HTML string,
+ loading NSData, loading a file, or loading from a custom protocol. It verifies that Network Extension on Mac/iOS
+ and Parental Controls on iOS are loaded after an HTTP request. It finally verifies that Parental Controls on Mac
+ is loaded after an HTTPS request.
+
+ To accomplish this, TestProtocol was generalized to allow tests to specify the scheme they wish to use.
+ Other tests that used TestProtocol were updated to account for this change. TestProtocol was removed from
+ WebKit2.PreventImageLoadWithAutoResizingTest, which didn't actually need to use it. ContentFiltering tests were
+ also re-enabled on iOS after mistakenly being disabled by r188892.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/CustomProtocolsSyncXHRTest.mm:
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h: Added.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html: Added.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm:
+ (TEST):
+ (downloadTest):
+ (-[LazilyLoadPlatformFrameworksController init]):
+ (-[LazilyLoadPlatformFrameworksController webView]):
+ (-[LazilyLoadPlatformFrameworksController expectParentalControlsLoaded:networkExtensionLoaded:]):
+ (-[LazilyLoadPlatformFrameworksController webView:didFinishNavigation:]):
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm:
+ (-[ContentFilteringPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+ (-[ContentFilteringPlugIn observeValueForKeyPath:ofObject:change:context:]):
+ (-[ContentFilteringPlugIn checkIfPlatformFrameworksAreLoaded:]):
+ * TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm:
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm:
+ (TestWebKitAPI::TEST): Deleted.
+ * TestWebKitAPI/cocoa/TestProtocol.h:
+ * TestWebKitAPI/cocoa/TestProtocol.mm:
+ (+[TestProtocol registerWithScheme:]):
+ (+[TestProtocol unregister]):
+
2016-01-12 Dewei Zhu <[email protected]>
Fix the Sunpider converage in slow device.
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-01-13 02:07:11 UTC (rev 194950)
@@ -278,6 +278,7 @@
A14FC5881B8991BF00D107EB /* ContentFiltering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A14FC5861B8991B600D107EB /* ContentFiltering.mm */; };
A14FC58B1B89927100D107EB /* ContentFilteringPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = A14FC5891B89927100D107EB /* ContentFilteringPlugIn.mm */; };
A14FC5901B8AE36F00D107EB /* TestProtocol.mm in Sources */ = {isa = PBXBuildFile; fileRef = A14FC58E1B8AE36500D107EB /* TestProtocol.mm */; };
+ A16F66BA1C40EB4F00BD4D24 /* ContentFiltering.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */; };
A1C4FB6E1BACCE50003742D0 /* QuickLook.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1C4FB6C1BACCE50003742D0 /* QuickLook.mm */; };
A1C4FB731BACD1CA003742D0 /* pages.pages in Copy Resources */ = {isa = PBXBuildFile; fileRef = A1C4FB721BACD1B7003742D0 /* pages.pages */; };
A1DF74321C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1DF74301C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm */; };
@@ -378,6 +379,7 @@
dstPath = TestWebKitAPI.resources;
dstSubfolderSpec = 7;
files = (
+ A16F66BA1C40EB4F00BD4D24 /* ContentFiltering.html in Copy Resources */,
CDC8E4941BC6F10800594FEC /* video-with-audio.html in Copy Resources */,
CDC8E4951BC6F10800594FEC /* video-with-audio.mp4 in Copy Resources */,
CDC8E4961BC6F10800594FEC /* video-without-audio.html in Copy Resources */,
@@ -671,6 +673,8 @@
A14FC5891B89927100D107EB /* ContentFilteringPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContentFilteringPlugIn.mm; sourceTree = "<group>"; };
A14FC58D1B8AE36500D107EB /* TestProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestProtocol.h; path = cocoa/TestProtocol.h; sourceTree = "<group>"; };
A14FC58E1B8AE36500D107EB /* TestProtocol.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestProtocol.mm; path = cocoa/TestProtocol.mm; sourceTree = "<group>"; };
+ A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ContentFiltering.html; sourceTree = "<group>"; };
+ A18AA8CC1C3FA218009B2B97 /* ContentFiltering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentFiltering.h; sourceTree = "<group>"; };
A1A4FE5D18DD3DB700B5EA8A /* Download.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Download.mm; sourceTree = "<group>"; };
A1C4FB6C1BACCE50003742D0 /* QuickLook.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QuickLook.mm; sourceTree = "<group>"; };
A1C4FB721BACD1B7003742D0 /* pages.pages */ = {isa = PBXFileReference; lastKnownFileType = file; name = pages.pages; path = ios/pages.pages; sourceTree = SOURCE_ROOT; };
@@ -928,10 +932,12 @@
1ABC3DEC1899BE55004F0626 /* WebKit2 Cocoa */ = {
isa = PBXGroup;
children = (
+ A16F66B81C40E9E100BD4D24 /* Resources */,
7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */,
2DD355351BD08378005DF4A7 /* AutoLayoutIntegration.mm */,
A13EBBAC1B87436F00097110 /* BundleParameters.mm */,
A13EBBAE1B87436F00097110 /* BundleParametersPlugIn.mm */,
+ A18AA8CC1C3FA218009B2B97 /* ContentFiltering.h */,
A14FC5861B8991B600D107EB /* ContentFiltering.mm */,
A14FC5891B89927100D107EB /* ContentFilteringPlugIn.mm */,
A1A4FE5D18DD3DB700B5EA8A /* Download.mm */,
@@ -1020,6 +1026,14 @@
path = cocoa/WebProcessPlugIn;
sourceTree = "<group>";
};
+ A16F66B81C40E9E100BD4D24 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
A1C4FB6F1BACCEFA003742D0 /* Resources */ = {
isa = PBXGroup;
children = (
Modified: trunk/Tools/TestWebKitAPI/Tests/CustomProtocolsSyncXHRTest.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/CustomProtocolsSyncXHRTest.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/Tests/CustomProtocolsSyncXHRTest.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -48,8 +48,7 @@
TEST(WebKit2CustomProtocolsTest, SyncXHR)
{
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol registerWithScheme:@"http"];
RetainPtr<WKProcessGroup> processGroup = adoptNS([[WKProcessGroup alloc] init]);
RetainPtr<WKBrowsingContextGroup> browsingContextGroup = adoptNS([[WKBrowsingContextGroup alloc] initWithIdentifier:@"TestIdentifier"]);
@@ -69,8 +68,7 @@
WKPageLoadURL(wkView.get().pageRef, Util::createURLForResource("custom-protocol-sync-xhr", "html"));
TestWebKitAPI::Util::run(&testFinished);
- [NSURLProtocol unregisterClass:[TestProtocol class]];
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol unregister];
}
} // namespace TestWebKitAPI
Copied: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h (from rev 194935, trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.h) (0 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@protocol ContentFilteringProtocol <NSObject>
+- (void)checkIfPlatformFrameworksAreLoaded:(void (^)(BOOL parentalControlsLoaded, BOOL networkExtensionLoaded))completionHandler;
+@end
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html (0 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html 2016-01-13 02:07:11 UTC (rev 194950)
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+PASS
+</body>
+</html>
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -25,17 +25,19 @@
#import "config.h"
-#if WK_API_ENABLED && PLATFORM(MAC)
+#if WK_API_ENABLED
+#import "ContentFiltering.h"
#import "MockContentFilterSettings.h"
#import "PlatformUtilities.h"
#import "TestProtocol.h"
#import "WKWebViewConfigurationExtras.h"
-#import <WebKit/WKBrowsingContextController.h>
#import <WebKit/WKNavigationDelegatePrivate.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/_WKDownloadDelegate.h>
+#import <WebKit/_WKRemoteObjectInterface.h>
+#import <WebKit/_WKRemoteObjectRegistry.h>
#import <wtf/RetainPtr.h>
using Decision = WebCore::MockContentFilterSettings::Decision;
@@ -118,8 +120,7 @@
TEST(ContentFiltering, URLAfterServerRedirect)
{
@autoreleasepool {
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol registerWithScheme:@"http"];
auto configuration = configurationWithContentFilterSettings(Decision::Allow, DecisionPoint::AfterAddData);
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
@@ -128,8 +129,7 @@
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect?pass"]]];
TestWebKitAPI::Util::run(&isDone);
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
- [NSURLProtocol unregisterClass:[TestProtocol class]];
+ [TestProtocol unregister];
}
}
@@ -172,8 +172,7 @@
static void downloadTest(Decision decision, DecisionPoint decisionPoint)
{
@autoreleasepool {
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol registerWithScheme:@"http"];
auto configuration = configurationWithContentFilterSettings(decision, decisionPoint);
auto downloadDelegate = adoptNS([[ContentFilteringDownloadDelegate alloc] init]);
@@ -193,8 +192,7 @@
EXPECT_EQ(downloadShouldStart, downloadDidStart);
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
- [NSURLProtocol unregisterClass:[TestProtocol class]];
+ [TestProtocol unregister];
}
}
@@ -258,4 +256,107 @@
downloadTest(Decision::Block, DecisionPoint::Never);
}
+@interface LazilyLoadPlatformFrameworksController : NSObject <WKNavigationDelegate>
+@property (nonatomic, readonly) WKWebView *webView;
+- (void)expectParentalControlsLoaded:(BOOL)parentalControlsShouldBeLoaded networkExtensionLoaded:(BOOL)networkExtensionShouldBeLoaded;
+@end
+
+@implementation LazilyLoadPlatformFrameworksController {
+ RetainPtr<WKWebView> _webView;
+ RetainPtr<id <ContentFilteringProtocol>> _remoteObjectProxy;
+}
+
+- (instancetype)init
+{
+ if (!(self = [super init]))
+ return nil;
+
+ WKWebViewConfiguration *configuration = [WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"ContentFilteringPlugIn"];
+ _webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
+ [_webView setNavigationDelegate:self];
+
+ _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(ContentFilteringProtocol)];
+ _remoteObjectProxy = [[_webView _remoteObjectRegistry] remoteObjectProxyWithInterface:interface];
+
+ return self;
+}
+
+- (WKWebView *)webView
+{
+ return _webView.get();
+}
+
+- (void)expectParentalControlsLoaded:(BOOL)parentalControlsShouldBeLoaded networkExtensionLoaded:(BOOL)networkExtensionShouldBeLoaded
+{
+ isDone = false;
+ [_remoteObjectProxy checkIfPlatformFrameworksAreLoaded:^(BOOL parentalControlsLoaded, BOOL networkExtensionLoaded) {
+#if HAVE(PARENTAL_CONTROLS)
+ EXPECT_EQ(static_cast<bool>(parentalControlsShouldBeLoaded), static_cast<bool>(parentalControlsLoaded));
+#endif
+#if HAVE(NETWORK_EXTENSION)
+ EXPECT_EQ(static_cast<bool>(networkExtensionShouldBeLoaded), static_cast<bool>(networkExtensionLoaded));
+#endif
+ isDone = true;
+ }];
+ TestWebKitAPI::Util::run(&isDone);
+}
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+ isDone = true;
+}
+
+@end
+
+TEST(ContentFiltering, LazilyLoadPlatformFrameworks)
+{
+ @autoreleasepool {
+ auto controller = adoptNS([[LazilyLoadPlatformFrameworksController alloc] init]);
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:NO];
+
+ isDone = false;
+ [[controller webView] loadHTMLString:@"PASS" baseURL:[NSURL URLWithString:@"about:blank"]];
+ TestWebKitAPI::Util::run(&isDone);
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:NO];
+
+ isDone = false;
+ [[controller webView] loadData:[NSData dataWithBytes:"PASS" length:4] MIMEType:@"text/html" characterEncodingName:@"UTF-8" baseURL:[NSURL URLWithString:@"about:blank"]];
+ TestWebKitAPI::Util::run(&isDone);
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:NO];
+
+ isDone = false;
+ NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"ContentFiltering" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+ [[controller webView] loadFileURL:fileURL allowingReadAccessToURL:fileURL];
+ TestWebKitAPI::Util::run(&isDone);
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:NO];
+
+ isDone = false;
+ [TestProtocol registerWithScheme:@"custom"];
+ [[controller webView] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"custom://test"]]];
+ TestWebKitAPI::Util::run(&isDone);
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:NO];
+ [TestProtocol unregister];
+
+ isDone = false;
+ [TestProtocol registerWithScheme:@"http"];
+ [[controller webView] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://test"]]];
+ TestWebKitAPI::Util::run(&isDone);
+#if PLATFORM(MAC)
+ [controller expectParentalControlsLoaded:NO networkExtensionLoaded:YES];
+#else
+ [controller expectParentalControlsLoaded:YES networkExtensionLoaded:YES];
+#endif
+ [TestProtocol unregister];
+
+#if PLATFORM(MAC)
+ isDone = false;
+ [TestProtocol registerWithScheme:@"https"];
+ [[controller webView] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://test"]]];
+ TestWebKitAPI::Util::run(&isDone);
+ [controller expectParentalControlsLoaded:YES networkExtensionLoaded:YES];
+ [TestProtocol unregister];
+#endif
+ }
+}
+
#endif // WK_API_ENABLED
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFilteringPlugIn.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -27,8 +27,13 @@
#if WK_API_ENABLED
+#import "ContentFiltering.h"
#import "MockContentFilterSettings.h"
#import <WebKit/WKWebProcessPlugIn.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextControllerPrivate.h>
+#import <WebKit/_WKRemoteObjectInterface.h>
+#import <WebKit/_WKRemoteObjectRegistry.h>
+#import <mach-o/dyld.h>
using MockContentFilterSettings = WebCore::MockContentFilterSettings;
using Decision = MockContentFilterSettings::Decision;
@@ -73,7 +78,7 @@
@end
-@interface ContentFilteringPlugIn : NSObject <WKWebProcessPlugIn>
+@interface ContentFilteringPlugIn : NSObject <ContentFilteringProtocol, WKWebProcessPlugIn>
@end
@implementation ContentFilteringPlugIn {
@@ -88,6 +93,12 @@
[plugInController.parameters addObserver:self forKeyPath:NSStringFromClass([MockContentFilterEnabler class]) options:NSKeyValueObservingOptionInitial context:NULL];
}
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
+{
+ _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(ContentFilteringProtocol)];
+ [[browserContextController _remoteObjectRegistry] registerExportedObject:self interface:interface];
+}
+
- (void)dealloc
{
[[_plugInController parameters] removeObserver:self forKeyPath:NSStringFromClass([MockContentFilterEnabler class])];
@@ -97,10 +108,24 @@
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
id contentFilterEnabler = [object valueForKeyPath:keyPath];
- ASSERT([contentFilterEnabler isKindOfClass:[MockContentFilterEnabler class]]);
+ ASSERT(!contentFilterEnabler || [contentFilterEnabler isKindOfClass:[MockContentFilterEnabler class]]);
_contentFilterEnabler = contentFilterEnabler;
}
+- (void)checkIfPlatformFrameworksAreLoaded:(void (^)(BOOL parentalControlsLoaded, BOOL networkExtensionLoaded))completionHandler
+{
+ bool parentalControlsLoaded = false;
+#if HAVE(PARENTAL_CONTROLS)
+ parentalControlsLoaded = NSVersionOfRunTimeLibrary("WebContentAnalysis") != -1;
+#endif
+
+ bool networkExtensionLoaded = false;
+#if HAVE(NETWORK_EXTENSION)
+ networkExtensionLoaded = NSVersionOfRunTimeLibrary("NetworkExtension") != -1;
+#endif
+ completionHandler(parentalControlsLoaded, networkExtensionLoaded);
+}
+
@end
#endif // WK_API_ENABLED
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsTest.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -70,8 +70,7 @@
TEST(WebKit2CustomProtocolsTest, MainResource)
{
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol registerWithScheme:@"http"];
RetainPtr<WKProcessGroup> processGroup = adoptNS([[WKProcessGroup alloc] init]);
RetainPtr<WKBrowsingContextGroup> browsingContextGroup = adoptNS([[WKBrowsingContextGroup alloc] initWithIdentifier:@"TestIdentifier"]);
@@ -81,8 +80,7 @@
[[wkView browsingContextController] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@://redirect?test", [TestProtocol scheme]]]]];
Util::run(&testFinished);
- [NSURLProtocol unregisterClass:[TestProtocol class]];
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
+ [TestProtocol unregister];
}
} // namespace TestWebKitAPI
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -32,7 +32,6 @@
#import "PlatformUtilities.h"
#import "PlatformWebView.h"
#import "TestBrowsingContextLoadDelegate.h"
-#import "TestProtocol.h"
#import <WebKit/WKViewPrivate.h>
#if WK_API_ENABLED && PLATFORM(MAC)
@@ -43,9 +42,6 @@
TEST(WebKit2, PreventImageLoadWithAutoResizingTest)
{
- [NSURLProtocol registerClass:[TestProtocol class]];
- [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
-
WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("DenyWillSendRequestTest"));
PlatformWebView webView(context.get());
@@ -56,8 +52,6 @@
[webView.platformView().browsingContextController loadHTMLString:@"<html><body style='background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFZJREFUeF59z4EJADEIQ1F36k7u5E7ZKXeUQPACJ3wK7UNokVxVk9kHnQH7bY9hbDyDhNXgjpRLqFlo4M2GgfyJHhjq8V4agfrgPQX3JtJQGbofmCHgA/nAKks+JAjFAAAAAElFTkSuQmCC);'></body></html>" baseURL:[NSURL URLWithString:@"about:blank"]];
Util::run(&testFinished);
- [NSURLProtocol unregisterClass:[TestProtocol class]];
- [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
}
} // namespace TestWebKitAPI
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.h (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.h 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.h 2016-01-13 02:07:11 UTC (rev 194950)
@@ -28,6 +28,8 @@
@interface TestProtocol : NSURLProtocol {
}
++ (void)registerWithScheme:(NSString *)scheme;
++ (void)unregister;
+ (NSString *)scheme;
@end
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.mm (194949 => 194950)
--- trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.mm 2016-01-13 01:41:48 UTC (rev 194949)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestProtocol.mm 2016-01-13 02:07:11 UTC (rev 194950)
@@ -26,11 +26,10 @@
#import "config.h"
#import "TestProtocol.h"
+#import <WebKit/WKBrowsingContextController.h>
#import <wtf/RetainPtr.h>
-// Even though NSURLProtocol is capable of generating redirect responses for any protocol, WebCore asserts if a redirect is not in the http family.
-// See http://webkit.org/b/147870 for details.
-static NSString *testScheme = @"http";
+static NSString *testScheme;
@implementation TestProtocol
@@ -54,6 +53,25 @@
return testScheme;
}
++ (void)registerWithScheme:(NSString *)scheme
+{
+ testScheme = [scheme retain];
+ [NSURLProtocol registerClass:[self class]];
+#if WK_API_ENABLED
+ [WKBrowsingContextController registerSchemeForCustomProtocol:testScheme];
+#endif
+}
+
++ (void)unregister
+{
+#if WK_API_ENABLED
+ [WKBrowsingContextController unregisterSchemeForCustomProtocol:testScheme];
+#endif
+ [NSURLProtocol unregisterClass:[self class]];
+ [testScheme release];
+ testScheme = nil;
+}
+
- (void)startLoading
{
NSURL *requestURL = self.request.URL;