WebKit Bugzilla
Attachment 349793 Details for
Bug 188871
: Implement safe browsing in WebKit
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188871-20180914131700.patch (text/plain), 102.29 KB, created by
Alex Christensen
on 2018-09-14 13:17:02 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Alex Christensen
Created:
2018-09-14 13:17:02 PDT
Size:
102.29 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 235954) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,27 @@ >+2018-09-14 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * loader/DocumentLoader.cpp: >+ (WebCore::DocumentLoader::willSendRequest): >+ (WebCore::DocumentLoader::continueAfterContentPolicy): >+ (WebCore::DocumentLoader::stopLoadingForPolicyChange): >+ * loader/DocumentLoader.h: >+ * loader/EmptyClients.cpp: >+ (WebCore::EmptyFrameLoaderClient::unsafeURLError): >+ * loader/EmptyFrameLoaderClient.h: >+ * loader/FrameLoader.cpp: >+ (WebCore::FrameLoader::continueLoadAfterNavigationPolicy): >+ * loader/FrameLoaderClient.h: >+ * loader/FrameLoaderTypes.h: >+ * loader/PolicyChecker.cpp: >+ (WebCore::PolicyChecker::checkNavigationPolicy): >+ (WebCore::PolicyChecker::checkNewWindowPolicy): >+ * loader/PolicyChecker.h: >+ > 2018-09-11 Simon Fraser <simon.fraser@apple.com> > > Make GraphicsLayers ref-counted, so their tree can persist when disconnected from RenderLayerBackings >Index: Source/WebCore/loader/DocumentLoader.cpp >=================================================================== >--- Source/WebCore/loader/DocumentLoader.cpp (revision 235954) >+++ Source/WebCore/loader/DocumentLoader.cpp (working copy) >@@ -637,8 +637,18 @@ void DocumentLoader::willSendRequest(Res > // We handle suspension by navigating forward to about:blank, which leaves us setup to navigate back to resume. > request = { blankURL() }; > break; >+ case ShouldContinue::UnsafeURL: { >+ auto error = frameLoader()->client().unsafeURLError(this->request()); >+ stopLoadingForPolicyChange(ResourceError(error)); >+ auto* frameLoader = this->frameLoader(); >+ if (!frameLoader) >+ break; >+ frameLoader->client().dispatchDidStartProvisionalLoad(); >+ frameLoader->client().dispatchDidFailProvisionalLoad(error); >+ break; >+ } > case ShouldContinue::No: >- stopLoadingForPolicyChange(); >+ stopLoadingForPolicyChange(interruptedForPolicyChangeError()); > break; > case ShouldContinue::Yes: > break; >@@ -881,7 +891,7 @@ void DocumentLoader::continueAfterConten > if (!frameLoader()->client().canShowMIMEType(m_response.mimeType()) || isRemoteWebArchive(*this)) { > frameLoader()->policyChecker().cannotShowMIMEType(m_response); > // Check reachedTerminalState since the load may have already been canceled inside of _handleUnimplementablePolicyWithErrorCode::. >- stopLoadingForPolicyChange(); >+ stopLoadingForPolicyChange(interruptedForPolicyChangeError()); > return; > } > break; >@@ -916,13 +926,14 @@ void DocumentLoader::continueAfterConten > static_cast<ResourceLoader*>(mainResourceLoader())->didFail(interruptedForPolicyChangeError()); > return; > } >+ case PolicyAction::UnsafeURL: > case PolicyAction::Suspend: > // It is invalid to get a Suspend policy based on navigation response. > RELEASE_ASSERT_NOT_REACHED(); > case PolicyAction::Ignore: > if (ResourceLoader* mainResourceLoader = this->mainResourceLoader()) > InspectorInstrumentation::continueWithPolicyIgnore(*m_frame, mainResourceLoader->identifier(), *this, m_response); >- stopLoadingForPolicyChange(); >+ stopLoadingForPolicyChange(interruptedForPolicyChangeError()); > return; > } > >@@ -980,9 +991,8 @@ ResourceError DocumentLoader::interrupte > return frameLoader()->client().interruptedForPolicyChangeError(request()); > } > >-void DocumentLoader::stopLoadingForPolicyChange() >+void DocumentLoader::stopLoadingForPolicyChange(ResourceError&& error) > { >- ResourceError error = interruptedForPolicyChangeError(); > error.setType(ResourceError::Type::Cancellation); > cancelMainResourceLoad(error); > } >Index: Source/WebCore/loader/DocumentLoader.h >=================================================================== >--- Source/WebCore/loader/DocumentLoader.h (revision 235954) >+++ Source/WebCore/loader/DocumentLoader.h (working copy) >@@ -384,7 +384,7 @@ private: > #endif > void continueAfterContentPolicy(PolicyAction); > >- void stopLoadingForPolicyChange(); >+ void stopLoadingForPolicyChange(ResourceError&&); > ResourceError interruptedForPolicyChangeError() const; > > #if HAVE(RUNLOOP_TIMER) >Index: Source/WebCore/loader/EmptyClients.cpp >=================================================================== >--- Source/WebCore/loader/EmptyClients.cpp (revision 235954) >+++ Source/WebCore/loader/EmptyClients.cpp (working copy) >@@ -441,6 +441,11 @@ void EmptyChromeClient::showShareSheet(S > { > } > >+ResourceError EmptyFrameLoaderClient::unsafeURLError(const ResourceRequest&) >+{ >+ return { }; >+} >+ > PAL::SessionID EmptyFrameLoaderClient::sessionID() const > { > return PAL::SessionID::defaultSessionID(); >Index: Source/WebCore/loader/EmptyFrameLoaderClient.h >=================================================================== >--- Source/WebCore/loader/EmptyFrameLoaderClient.h (revision 235954) >+++ Source/WebCore/loader/EmptyFrameLoaderClient.h (working copy) >@@ -121,6 +121,7 @@ class WEBCORE_EXPORT EmptyFrameLoaderCli > > ResourceError cancelledError(const ResourceRequest&) final { return { ResourceError::Type::Cancellation }; } > ResourceError blockedError(const ResourceRequest&) final { return { }; } >+ ResourceError unsafeURLError(const ResourceRequest&) final; > ResourceError blockedByContentBlockerError(const ResourceRequest&) final { return { }; } > ResourceError cannotShowURLError(const ResourceRequest&) final { return { }; } > ResourceError interruptedForPolicyChangeError(const ResourceRequest&) final { return { }; } >Index: Source/WebCore/loader/FrameLoader.cpp >=================================================================== >--- Source/WebCore/loader/FrameLoader.cpp (revision 235954) >+++ Source/WebCore/loader/FrameLoader.cpp (working copy) >@@ -3286,7 +3286,10 @@ void FrameLoader::continueLoadAfterNavig > bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false; > > bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid(); >- bool canContinue = shouldContinue != ShouldContinue::No && shouldClose() && !urlIsDisallowed; >+ bool canContinue = shouldContinue != ShouldContinue::No >+ && shouldContinue != ShouldContinue::UnsafeURL >+ && shouldClose() >+ && !urlIsDisallowed; > > if (!canContinue) { > // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we >@@ -3295,6 +3298,11 @@ void FrameLoader::continueLoadAfterNavig > if (m_quickRedirectComing) > clientRedirectCancelledOrFinished(false); > >+ if (shouldContinue == ShouldContinue::UnsafeURL) { >+ m_client.dispatchDidStartProvisionalLoad(); >+ m_client.dispatchDidFailProvisionalLoad(m_client.unsafeURLError(request)); >+ } >+ > setPolicyDocumentLoader(nullptr); > checkCompleted(); > checkLoadComplete(); >Index: Source/WebCore/loader/FrameLoaderClient.h >=================================================================== >--- Source/WebCore/loader/FrameLoaderClient.h (revision 235954) >+++ Source/WebCore/loader/FrameLoaderClient.h (working copy) >@@ -240,6 +240,7 @@ public: > > virtual ResourceError cancelledError(const ResourceRequest&) = 0; > virtual ResourceError blockedError(const ResourceRequest&) = 0; >+ virtual ResourceError unsafeURLError(const ResourceRequest&) = 0; > virtual ResourceError blockedByContentBlockerError(const ResourceRequest&) = 0; > virtual ResourceError cannotShowURLError(const ResourceRequest&) = 0; > virtual ResourceError interruptedForPolicyChangeError(const ResourceRequest&) = 0; >Index: Source/WebCore/loader/FrameLoaderTypes.h >=================================================================== >--- Source/WebCore/loader/FrameLoaderTypes.h (revision 235954) >+++ Source/WebCore/loader/FrameLoaderTypes.h (working copy) >@@ -45,6 +45,7 @@ enum class PolicyAction { > Download, > Ignore, > Suspend, >+ UnsafeURL, > }; > > enum class ReloadOption { >@@ -173,7 +174,8 @@ template<> struct EnumTraits<WebCore::Po > WebCore::PolicyAction::Use, > WebCore::PolicyAction::Download, > WebCore::PolicyAction::Ignore, >- WebCore::PolicyAction::Suspend >+ WebCore::PolicyAction::Suspend, >+ WebCore::PolicyAction::UnsafeURL > >; > }; > >Index: Source/WebCore/loader/PolicyChecker.cpp >=================================================================== >--- Source/WebCore/loader/PolicyChecker.cpp (revision 235954) >+++ Source/WebCore/loader/PolicyChecker.cpp (working copy) >@@ -180,6 +180,8 @@ void PolicyChecker::checkNavigationPolic > return function({ }, nullptr, ShouldContinue::No); > case PolicyAction::Suspend: > return function({ }, nullptr, ShouldContinue::ForSuspension); >+ case PolicyAction::UnsafeURL: >+ return function({ }, nullptr, ShouldContinue::UnsafeURL); > case PolicyAction::Use: > if (!m_frame.loader().client().canHandleRequest(request)) { > handleUnimplementablePolicy(m_frame.loader().client().cannotShowURLError(request)); >@@ -209,8 +211,9 @@ void PolicyChecker::checkNewWindowPolicy > case PolicyAction::Ignore: > function({ }, nullptr, { }, { }, ShouldContinue::No); > return; >+ case PolicyAction::UnsafeURL: > case PolicyAction::Suspend: >- // It is invalid to get a "Suspend" policy for new windows, as the old document is not going away. >+ // It is invalid to get a "Suspend" or "UnsafeURL" policy for new windows, as the old document is not going away. > RELEASE_ASSERT_NOT_REACHED(); > case PolicyAction::Use: > function(request, makeWeakPtr(formState.get()), frameName, navigationAction, ShouldContinue::Yes); >Index: Source/WebCore/loader/PolicyChecker.h >=================================================================== >--- Source/WebCore/loader/PolicyChecker.h (revision 235954) >+++ Source/WebCore/loader/PolicyChecker.h (working copy) >@@ -56,7 +56,8 @@ class ResourceResponse; > enum class ShouldContinue { > Yes, > No, >- ForSuspension >+ ForSuspension, >+ UnsafeURL, > }; > > enum class PolicyDecisionMode { Synchronous, Asynchronous }; >Index: Source/WebKit/ChangeLog >=================================================================== >--- Source/WebKit/ChangeLog (revision 235954) >+++ Source/WebKit/ChangeLog (working copy) >@@ -1,3 +1,73 @@ >+2018-09-14 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * NetworkProcess/NetworkDataTaskBlob.cpp: >+ (WebKit::NetworkDataTaskBlob::dispatchDidReceiveResponse): >+ * NetworkProcess/capture/NetworkDataTaskReplay.cpp: >+ (WebKit::NetworkCapture::NetworkDataTaskReplay::didReceiveResponse): >+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm: >+ (toNSURLSessionResponseDisposition): >+ * Shared/API/APIObject.h: >+ * Shared/Cocoa/APIObject.mm: >+ (API::Object::newObject): >+ * Shared/WebErrors.cpp: >+ (WebKit::unsafeURLError): >+ * Shared/WebErrors.h: >+ * Shared/WebPreferences.yaml: >+ * UIProcess/API/APINavigationClient.h: >+ (API::NavigationClient::areYouSureYouWantToNavigateToUnsafeURL): >+ (API::NavigationClient::webViewDetectedUnsafeContent): >+ * UIProcess/API/C/mac/WKContextPrivateMac.mm: >+ (WKContextHandlesSafeBrowsing): >+ * UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h: >+ * UIProcess/API/Cocoa/WKPreferences.mm: >+ (-[WKPreferences _safeBrowsingEnabled]): >+ (-[WKPreferences _setSafeBrowsingEnabled:]): >+ * UIProcess/API/Cocoa/WKPreferencesPrivate.h: >+ * UIProcess/API/Cocoa/_WKUnsafeURLInfo.h: Added. >+ * UIProcess/API/Cocoa/_WKUnsafeURLInfo.mm: Added. >+ (-[_WKUnsafeURLInfo dealloc]): >+ (-[_WKUnsafeURLInfo safeBrowsingProvider]): >+ (-[_WKUnsafeURLInfo URL]): >+ (-[_WKUnsafeURLInfo isPhishing]): >+ (-[_WKUnsafeURLInfo isMalware]): >+ (-[_WKUnsafeURLInfo isUnwantedSoftware]): >+ (-[_WKUnsafeURLInfo isKnownToBeUnsafe]): >+ (-[_WKUnsafeURLInfo _apiObject]): >+ * UIProcess/API/Cocoa/_WKUnsafeURLInfoInternal.h: Added. >+ * UIProcess/Cocoa/NavigationState.h: >+ * UIProcess/Cocoa/NavigationState.mm: >+ (WebKit::NavigationState::setNavigationDelegate): >+ (WebKit::toSafeBrowsingAction): >+ (WebKit::toUnsafeContentAction): >+ (WebKit::NavigationState::NavigationClient::areYouSureYouWantToNavigateToUnsafeURL): >+ (WebKit::NavigationState::NavigationClient::webViewDetectedUnsafeContent): >+ * UIProcess/Cocoa/WebPageProxyCocoa.mm: >+ (WebKit::WebPageProxy::beginSafeBrowsingCheck): >+ * UIProcess/SafeBrowsingResult.h: >+ (WebKit::SafeBrowsingResult::create): >+ * UIProcess/WebFramePolicyListenerProxy.cpp: >+ (WebKit::WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults): >+ * UIProcess/WebFramePolicyListenerProxy.h: >+ * UIProcess/WebFrameProxy.cpp: >+ (WebKit::WebFrameProxy::setUpPolicyListenerProxy): >+ * UIProcess/WebFrameProxy.h: >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::decidePolicyForNavigationAction): >+ (WebKit::WebPageProxy::decidePolicyForNewWindowAction): >+ (WebKit::WebPageProxy::decidePolicyForResponse): >+ * WebKit.xcodeproj/project.pbxproj: >+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp: >+ (WebKit::WebFrameLoaderClient::dispatchDidStartProvisionalLoad): >+ (WebKit::WebFrameLoaderClient::unsafeURLError): >+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.h: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::SandboxExtensionTracker::didStartProvisionalLoad): >+ > 2018-09-12 Sihui Liu <sihui_liu@apple.com> > > Move IndexedDB to Network Process >Index: Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp (revision 235954) >+++ Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp (working copy) >@@ -316,8 +316,9 @@ void NetworkDataTaskBlob::dispatchDidRec > m_buffer.resize(bufferSize); > read(); > break; >+ case PolicyAction::UnsafeURL: > case PolicyAction::Suspend: >- LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now"); >+ LOG_ERROR("PolicyAction::Suspend or UnsafeURL encountered - Treating as PolicyAction::Ignore for now"); > FALLTHROUGH; > case PolicyAction::Ignore: > break; >Index: Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp (revision 235954) >+++ Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp (working copy) >@@ -252,8 +252,9 @@ void NetworkDataTaskReplay::didReceiveRe > case WebCore::PolicyAction::Use: > enqueueEventHandler(); > break; >+ case WebCore::PolicyAction::UnsafeURL: > case WebCore::PolicyAction::Suspend: >- LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now"); >+ LOG_ERROR("PolicyAction::Suspend or UnsafeURL encountered - Treating as PolicyAction::Ignore for now"); > FALLTHROUGH; > case WebCore::PolicyAction::Ignore: > complete(); >Index: Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm >=================================================================== >--- Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (revision 235954) >+++ Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (working copy) >@@ -57,8 +57,9 @@ using namespace WebKit; > static NSURLSessionResponseDisposition toNSURLSessionResponseDisposition(WebCore::PolicyAction disposition) > { > switch (disposition) { >+ case WebCore::PolicyAction::UnsafeURL: > case WebCore::PolicyAction::Suspend: >- LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now"); >+ LOG_ERROR("PolicyAction::Suspend or UnsafeURL encountered - Treating as PolicyAction::Ignore for now"); > FALLTHROUGH; > case WebCore::PolicyAction::Ignore: > return NSURLSessionResponseCancel; >Index: Source/WebKit/Shared/WebErrors.cpp >=================================================================== >--- Source/WebKit/Shared/WebErrors.cpp (revision 235954) >+++ Source/WebKit/Shared/WebErrors.cpp (working copy) >@@ -42,6 +42,13 @@ ResourceError blockedError(const Resourc > return ResourceError(API::Error::webKitPolicyErrorDomain(), API::Error::Policy::CannotUseRestrictedPort, request.url(), WEB_UI_STRING("Not allowed to use restricted network port", "WebKitErrorCannotUseRestrictedPort description")); > } > >+ResourceError unsafeURLError(const ResourceRequest& request) >+{ >+ // FIXME: Add this to the Web UI Strings. >+ // FIXME: Add a new WKError type for this. >+ return ResourceError(API::Error::webKitPolicyErrorDomain(), API::Error::Policy::CannotUseRestrictedPort, request.url(), WEB_UI_STRING("This is unsafe.", "WebKitErrorUnsafeURL description")); >+} >+ > ResourceError blockedByContentBlockerError(const ResourceRequest& request) > { > return ResourceError(API::Error::webKitPolicyErrorDomain(), API::Error::Policy::FrameLoadBlockedByContentBlocker, request.url(), WEB_UI_STRING("The URL was blocked by a content blocker", "WebKitErrorBlockedByContentBlocker description")); >Index: Source/WebKit/Shared/WebErrors.h >=================================================================== >--- Source/WebKit/Shared/WebErrors.h (revision 235954) >+++ Source/WebKit/Shared/WebErrors.h (working copy) >@@ -38,6 +38,7 @@ namespace WebKit { > > WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&); > WebCore::ResourceError blockedError(const WebCore::ResourceRequest&); >+WebCore::ResourceError unsafeURLError(const WebCore::ResourceRequest&); > WebCore::ResourceError blockedByContentBlockerError(const WebCore::ResourceRequest&); > WebCore::ResourceError cannotShowURLError(const WebCore::ResourceRequest&); > WebCore::ResourceError interruptedForPolicyChangeError(const WebCore::ResourceRequest&); >Index: Source/WebKit/Shared/WebPreferences.yaml >=================================================================== >--- Source/WebKit/Shared/WebPreferences.yaml (revision 235954) >+++ Source/WebKit/Shared/WebPreferences.yaml (working copy) >@@ -42,6 +42,11 @@ DatabasesEnabled: > defaultValue: true > webcoreBinding: custom > >+SafeBrowsingEnabled: >+ type: bool >+ defaultValue: true >+ webcoreBinding: none >+ > XSSAuditorEnabled: > type: bool > defaultValue: true >Index: Source/WebKit/Shared/API/APIObject.h >=================================================================== >--- Source/WebKit/Shared/API/APIObject.h (revision 235954) >+++ Source/WebKit/Shared/API/APIObject.h (working copy) >@@ -151,6 +151,7 @@ public: > RunJavaScriptAlertResultListener, > RunJavaScriptConfirmResultListener, > RunJavaScriptPromptResultListener, >+ SafeBrowsingResult, > TextChecker, > URLSchemeTask, > UserContentController, >Index: Source/WebKit/Shared/Cocoa/APIObject.mm >=================================================================== >--- Source/WebKit/Shared/Cocoa/APIObject.mm (revision 235954) >+++ Source/WebKit/Shared/Cocoa/APIObject.mm (working copy) >@@ -78,6 +78,7 @@ > #import "_WKInspectorInternal.h" > #import "_WKInternalDebugFeatureInternal.h" > #import "_WKProcessPoolConfigurationInternal.h" >+#import "_WKUnsafeURLInfoInternal.h" > #import "_WKUserContentWorldInternal.h" > #import "_WKUserInitiatedActionInternal.h" > #import "_WKUserStyleSheetInternal.h" >@@ -269,6 +270,10 @@ void* Object::newObject(size_t size, Typ > wrapper = [WKBrowsingContextGroup alloc]; > break; > >+ case Type::SafeBrowsingResult: >+ wrapper = [_WKUnsafeURLInfo alloc]; >+ break; >+ > case Type::SecurityOrigin: > wrapper = [WKSecurityOrigin alloc]; > break; >Index: Source/WebKit/UIProcess/SafeBrowsingResult.h >=================================================================== >--- Source/WebKit/UIProcess/SafeBrowsingResult.h (revision 235954) >+++ Source/WebKit/UIProcess/SafeBrowsingResult.h (working copy) >@@ -25,6 +25,7 @@ > > #pragma once > >+#include "APIObject.h" > #include <WebCore/URL.h> > #include <wtf/text/WTFString.h> > >@@ -32,12 +33,14 @@ OBJC_CLASS SSBServiceLookupResult; > > namespace WebKit { > >-class SafeBrowsingResult { >+class SafeBrowsingResult : public API::ObjectImpl<API::Object::Type::SafeBrowsingResult> { > public: > #if HAVE(SAFE_BROWSING) >- SafeBrowsingResult(WebCore::URL&&, SSBServiceLookupResult *); >+ static Ref<SafeBrowsingResult> create(WebCore::URL&& url, SSBServiceLookupResult *result) >+ { >+ return adoptRef(*new SafeBrowsingResult(WTFMove(url), result)); >+ } > #endif >- SafeBrowsingResult() = default; > > const WebCore::URL& url() const { return m_url; } > const String& provider() const { return m_provider; } >@@ -47,6 +50,9 @@ public: > bool isKnownToBeUnsafe() const { return m_isKnownToBeUnsafe; } > > private: >+#if HAVE(SAFE_BROWSING) >+ SafeBrowsingResult(WebCore::URL&&, SSBServiceLookupResult *); >+#endif > WebCore::URL m_url; > String m_provider; > bool m_isPhishing { false }; >Index: Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp >=================================================================== >--- Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp (revision 235954) >+++ Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp (working copy) >@@ -45,7 +45,7 @@ WebFramePolicyListenerProxy::WebFramePol > > WebFramePolicyListenerProxy::~WebFramePolicyListenerProxy() = default; > >-void WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults(Vector<SafeBrowsingResult>&& safeBrowsingResults) >+void WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults(Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) > { > ASSERT(!m_safeBrowsingResults); > if (m_policyResult) { >Index: Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h >=================================================================== >--- Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h (revision 235954) >+++ Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h (working copy) >@@ -47,7 +47,7 @@ enum class ShouldExpectSafeBrowsingResul > class WebFramePolicyListenerProxy : public API::ObjectImpl<API::Object::Type::FramePolicyListener> { > public: > >- using Reply = CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<SafeBrowsingResult>&&)>; >+ using Reply = CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&&)>; > static Ref<WebFramePolicyListenerProxy> create(Reply&& reply, ShouldExpectSafeBrowsingResult expect) > { > return adoptRef(*new WebFramePolicyListenerProxy(WTFMove(reply), expect)); >@@ -58,13 +58,13 @@ public: > void download(); > void ignore(); > >- void didReceiveSafeBrowsingResults(Vector<SafeBrowsingResult>&&); >+ void didReceiveSafeBrowsingResults(Vector<Ref<SafeBrowsingResult>>&&); > > private: > WebFramePolicyListenerProxy(Reply&&, ShouldExpectSafeBrowsingResult); > > std::optional<std::pair<RefPtr<API::WebsitePolicies>, ProcessSwapRequestedByClient>> m_policyResult; >- std::optional<Vector<SafeBrowsingResult>> m_safeBrowsingResults; >+ std::optional<Vector<Ref<SafeBrowsingResult>>> m_safeBrowsingResults; > Reply m_reply; > }; > >Index: Source/WebKit/UIProcess/WebFrameProxy.cpp >=================================================================== >--- Source/WebKit/UIProcess/WebFrameProxy.cpp (revision 235954) >+++ Source/WebKit/UIProcess/WebFrameProxy.cpp (working copy) >@@ -177,11 +177,11 @@ void WebFrameProxy::didChangeTitle(const > m_title = title; > } > >-WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<SafeBrowsingResult>&&)>&& completionHandler, ShouldExpectSafeBrowsingResult expect) >+WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&&)>&& completionHandler, ShouldExpectSafeBrowsingResult expect) > { > if (m_activeListener) > m_activeListener->ignore(); >- m_activeListener = WebFramePolicyListenerProxy::create([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (WebCore::PolicyAction action, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<SafeBrowsingResult>&& safeBrowsingResults) mutable { >+ m_activeListener = WebFramePolicyListenerProxy::create([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (WebCore::PolicyAction action, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) mutable { > completionHandler(action, policies, processSwapRequestedByClient, WTFMove(safeBrowsingResults)); > m_activeListener = nullptr; > }, expect); >Index: Source/WebKit/UIProcess/WebFrameProxy.h >=================================================================== >--- Source/WebKit/UIProcess/WebFrameProxy.h (revision 235954) >+++ Source/WebKit/UIProcess/WebFrameProxy.h (working copy) >@@ -117,7 +117,7 @@ public: > void didSameDocumentNavigation(const WebCore::URL&); // eg. anchor navigation, session state change. > void didChangeTitle(const String&); > >- WebFramePolicyListenerProxy& setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<SafeBrowsingResult>&&)>&&, ShouldExpectSafeBrowsingResult); >+ WebFramePolicyListenerProxy& setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&&)>&&, ShouldExpectSafeBrowsingResult); > > #if ENABLE(CONTENT_FILTERING) > void contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler contentFilterUnblockHandler) { m_contentFilterUnblockHandler = WTFMove(contentFilterUnblockHandler); } >Index: Source/WebKit/UIProcess/WebPageProxy.cpp >=================================================================== >--- Source/WebKit/UIProcess/WebPageProxy.cpp (revision 235954) >+++ Source/WebKit/UIProcess/WebPageProxy.cpp (working copy) >@@ -4029,29 +4029,78 @@ void WebPageProxy::decidePolicyForNaviga > UNUSED_PARAM(newNavigationID); > #endif > >- auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frame = makeRef(*frame), sender = sender.copyRef(), navigation] (WebCore::PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<SafeBrowsingResult>&&) mutable { >- // FIXME: do something with the SafeBrowsingResults. >+ if (!m_preferences->safeBrowsingEnabled()) >+ shouldSkipSafeBrowsingCheck = ShouldSkipSafeBrowsingCheck::Yes; > >- std::optional<WebsitePoliciesData> data; >- if (policies) { >- data = policies->data(); >- if (policies->websiteDataStore()) >- changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore()); >- } >+ auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frame = makeRef(*frame), sender = WTFMove(sender), navigation] (WebCore::PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) mutable { >+ >+ auto completionHandler = [this, protectedThis = protectedThis.copyRef(), frame = frame.copyRef(), sender = WTFMove(sender), navigation = WTFMove(navigation), policies = makeRefPtr(policies), processSwapRequestedByClient] (WebCore::PolicyAction policyAction) mutable { >+ std::optional<WebsitePoliciesData> data; >+ if (policies) { >+ data = policies->data(); >+ if (policies->websiteDataStore()) >+ changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore()); >+ } > >- if (policyAction == PolicyAction::Use && frame->isMainFrame()) { >- auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, processSwapRequestedByClient, policyAction); >- >- if (proposedProcess.ptr() != &process()) { >- LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), proposedProcess->processIdentifier(), navigation->navigationID(), navigation->loggingString()); >+ if (policyAction == PolicyAction::Use && frame->isMainFrame()) { >+ auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, processSwapRequestedByClient, policyAction); > >- RunLoop::main().dispatch([this, protectedThis = WTFMove(protectedThis), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable { >- continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess)); >- }); >+ if (proposedProcess.ptr() != &process()) { >+ LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), proposedProcess->processIdentifier(), navigation->navigationID(), navigation->loggingString()); >+ >+ RunLoop::main().dispatch([this, protectedThis = WTFMove(protectedThis), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable { >+ continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess)); >+ }); >+ } >+ } >+ >+ receivedPolicyDecision(policyAction, navigation.get(), WTFMove(data), WTFMove(sender)); >+ }; >+ >+ auto isUnsafe = [] (const SafeBrowsingResult& result) { >+ return result.isPhishing() >+ || result.isMalware() >+ || result.isUnwantedSoftware() >+ || result.isKnownToBeUnsafe(); >+ }; >+ >+ for (auto& result : safeBrowsingResults) { >+ if (m_navigationClient && isUnsafe(result)) { >+ if (frame->isMainFrame()) { >+ m_navigationClient->areYouSureYouWantToNavigateToUnsafeURL(*this, result, [completionHandler = WTFMove(completionHandler)] (SafeBrowsingAction action) mutable { >+ switch (action) { >+ case SafeBrowsingAction::ContinueToUnsafePage: >+ completionHandler(PolicyAction::Use); >+ break; >+ case SafeBrowsingAction::PretendToFailProvisionalLoad: >+ completionHandler(PolicyAction::UnsafeURL); >+ break; >+ case SafeBrowsingAction::CancelNavigation: >+ completionHandler(PolicyAction::Ignore); >+ break; >+ } >+ }); >+ } else { >+ m_navigationClient->webViewDetectedUnsafeContent(*this, result, [this, protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)] (UnsafeContentAction action) mutable { >+ switch (action) { >+ case UnsafeContentAction::ResumeBusinessAsUsual: >+ completionHandler(PolicyAction::Use); >+ break; >+ case UnsafeContentAction::IveTakenCareOfIt: >+ completionHandler(PolicyAction::Ignore); >+ break; >+ case UnsafeContentAction::TerminateProcess: >+ completionHandler(PolicyAction::Ignore); >+ m_process->requestTermination(ProcessTerminationReason::RequestedByClient); >+ break; >+ } >+ }); >+ } >+ return; > } > } >+ completionHandler(policyAction); > >- receivedPolicyDecision(policyAction, navigation.get(), WTFMove(data), WTFMove(sender)); > }, shouldSkipSafeBrowsingCheck == ShouldSkipSafeBrowsingCheck::Yes ? ShouldExpectSafeBrowsingResult::No : ShouldExpectSafeBrowsingResult::Yes)); > if (shouldSkipSafeBrowsingCheck == ShouldSkipSafeBrowsingCheck::No) > beginSafeBrowsingCheck(request.url(), listener); >@@ -4100,7 +4149,7 @@ void WebPageProxy::decidePolicyForNewWin > MESSAGE_CHECK(frame); > MESSAGE_CHECK_URL(request.url()); > >- auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), listenerID, frameID] (WebCore::PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<SafeBrowsingResult>&& safeBrowsingResults) mutable { >+ auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), listenerID, frameID] (WebCore::PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) mutable { > // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away. > RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No); > ASSERT_UNUSED(safeBrowsingResults, safeBrowsingResults.isEmpty()); >@@ -4136,7 +4185,7 @@ void WebPageProxy::decidePolicyForRespon > MESSAGE_CHECK_URL(response.url()); > > RefPtr<API::Navigation> navigation = navigationID ? &m_navigationState->navigation(navigationID) : nullptr; >- auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation)] (WebCore::PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<SafeBrowsingResult>&& safeBrowsingResults) mutable { >+ auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation)] (WebCore::PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) mutable { > // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away. > RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No); > ASSERT_UNUSED(safeBrowsingResults, safeBrowsingResults.isEmpty()); >Index: Source/WebKit/UIProcess/API/APINavigationClient.h >=================================================================== >--- Source/WebKit/UIProcess/API/APINavigationClient.h (revision 235954) >+++ Source/WebKit/UIProcess/API/APINavigationClient.h (working copy) >@@ -47,6 +47,7 @@ struct SecurityOriginData; > namespace WebKit { > class AuthenticationChallengeProxy; > class QuickLookDocumentData; >+class SafeBrowsingResult; > class WebBackForwardListItem; > class WebFramePolicyListenerProxy; > class WebFrameProxy; >@@ -54,6 +55,8 @@ class WebPageProxy; > class WebProtectionSpace; > struct NavigationActionData; > struct WebNavigationDataStore; >+enum class SafeBrowsingAction : uint8_t { ContinueToUnsafePage, CancelNavigation, PretendToFailProvisionalLoad }; >+enum class UnsafeContentAction : uint8_t { ResumeBusinessAsUsual, IveTakenCareOfIt, TerminateProcess }; > } > > namespace API { >@@ -96,6 +99,8 @@ public: > virtual RefPtr<Data> webCryptoMasterKey(WebKit::WebPageProxy&) { return nullptr; } > > virtual RefPtr<String> signedPublicKeyAndChallengeString(WebKit::WebPageProxy&, unsigned keySizeIndex, const RefPtr<String>& challengeString, const WebCore::URL&) { return nullptr; } >+ virtual void areYouSureYouWantToNavigateToUnsafeURL(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::SafeBrowsingAction)>&& completionHandler) { completionHandler(WebKit::SafeBrowsingAction::PretendToFailProvisionalLoad); } >+ virtual void webViewDetectedUnsafeContent(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::UnsafeContentAction)>&& completionHandler) { completionHandler(WebKit::UnsafeContentAction::TerminateProcess); } > > #if USE(QUICK_LOOK) > virtual void didStartLoadForQuickLookDocumentInMainFrame(const WTF::String& fileName, const WTF::String& uti) { } >Index: Source/WebKit/UIProcess/API/C/mac/WKContextPrivateMac.mm >=================================================================== >--- Source/WebKit/UIProcess/API/C/mac/WKContextPrivateMac.mm (revision 235954) >+++ Source/WebKit/UIProcess/API/C/mac/WKContextPrivateMac.mm (working copy) >@@ -173,5 +173,5 @@ bool WKContextShouldSuggestBlockWebGL() > > bool WKContextHandlesSafeBrowsing() > { >- return false; >+ return true; > } >Index: Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h (revision 235954) >+++ Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h (working copy) >@@ -31,6 +31,7 @@ > > #if WK_API_ENABLED > >+@class _WKUnsafeURLInfo; > @class _WKWebsitePolicies; > > #if !TARGET_OS_IPHONE >@@ -55,6 +56,16 @@ typedef NS_ENUM(NSInteger, _WKProcessTer > _WKProcessTerminationReasonCrash, > } WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > >+typedef NS_ENUM(NSInteger, _WKUnsafeURLAction) { >+ _WKUnsafeURLActionLoadUnsafeURL, >+ _WKUnsafeURLActionCancelNavigation, >+} WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >+ >+typedef NS_ENUM(NSInteger, _WKUnsafeContentAction) { >+ _WKUnsafeContentActionResumeBusinessAsUsual, >+ _WKUnsafeContentActionIveTakenCareOfIt, >+} WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >+ > static const WKNavigationActionPolicy _WKNavigationActionPolicyDownload = (WKNavigationActionPolicy)(WKNavigationActionPolicyAllow + 1); > static const WKNavigationActionPolicy WK_API_AVAILABLE(macosx(10.11), ios(9.0)) _WKNavigationActionPolicyAllowWithoutTryingAppLink = (WKNavigationActionPolicy)(_WKNavigationActionPolicyDownload + 1); > static const WKNavigationActionPolicy WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)) _WKNavigationActionPolicyAllowInNewProcess = (WKNavigationActionPolicy)(_WKNavigationActionPolicyAllowWithoutTryingAppLink + 1); >@@ -65,6 +76,8 @@ static const WKNavigationResponsePolicy > > @optional > >+- (void)_webView:(WKWebView *)webView attemptedToLoadUnsafeURL:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeURLAction))decisionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >+- (void)_webView:(WKWebView *)webView detectedUnsafeContent:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeContentAction))decisionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didFailProvisionalLoadInSubframe:(WKFrameInfo *)subframe withError:(NSError *)error; > > - (void)_webView:(WKWebView *)webView willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)delay; >Index: Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (revision 235954) >+++ Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (working copy) >@@ -130,6 +130,16 @@ - (void)setJavaScriptCanOpenWindowsAutom > _preferences->setJavaScriptCanOpenWindowsAutomatically(javaScriptCanOpenWindowsAutomatically); > } > >+- (BOOL)_safeBrowsingEnabled >+{ >+ return _preferences->safeBrowsingEnabled(); >+} >+ >+- (void)_setSafeBrowsingEnabled:(BOOL)enabled >+{ >+ _preferences->setSafeBrowsingEnabled(enabled); >+} >+ > - (BOOL)_storageAccessPromptsEnabled > { > return _preferences->storageAccessPromptsEnabled(); >Index: Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (revision 235954) >+++ Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (working copy) >@@ -110,6 +110,7 @@ typedef NS_ENUM(NSInteger, _WKEditableLi > @property (nonatomic, setter=_setApplePayCapabilityDisclosureAllowed:) BOOL _applePayCapabilityDisclosureAllowed WK_API_AVAILABLE(macosx(10.12), ios(10.0)); > > @property (nonatomic, setter=_setLoadsImagesAutomatically:) BOOL _loadsImagesAutomatically WK_API_AVAILABLE(macosx(10.13), ios(11.0)); >+@property (nonatomic, setter=_setSafeBrowsingEnabled:) BOOL _safeBrowsingEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > > @property (nonatomic, setter=_setPeerConnectionEnabled:) BOOL _peerConnectionEnabled WK_API_AVAILABLE(macosx(10.13.4), ios(11.3)); > @property (nonatomic, setter=_setMediaDevicesEnabled:) BOOL _mediaDevicesEnabled WK_API_AVAILABLE(macosx(10.13), ios(11.0)); >Index: Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.h (nonexistent) >+++ Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.h (working copy) >@@ -0,0 +1,52 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#import <WebKit/WKFoundation.h> >+ >+#if WK_API_ENABLED >+ >+#import <Foundation/Foundation.h> >+ >+NS_ASSUME_NONNULL_BEGIN >+ >+WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)) >+@interface _WKUnsafeURLInfo : NSObject >+ >+- (instancetype)init NS_UNAVAILABLE; >+ >+@property (nonatomic, readonly, copy) NSString *safeBrowsingProvider; >+ >+@property (nonatomic, readonly, nullable, copy) NSURL *URL; >+ >+@property (nonatomic, readonly) BOOL isPhishing; >+@property (nonatomic, readonly) BOOL isMalware; >+@property (nonatomic, readonly) BOOL isUnwantedSoftware; >+@property (nonatomic, readonly) BOOL isKnownToBeUnsafe; >+ >+@end >+ >+NS_ASSUME_NONNULL_END >+ >+#endif >Index: Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.mm >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.mm (nonexistent) >+++ Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfo.mm (working copy) >@@ -0,0 +1,79 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#import "config.h" >+#import "_WKUnsafeURLInfoInternal.h" >+ >+#if WK_API_ENABLED >+ >+@implementation _WKUnsafeURLInfo >+ >+- (void)dealloc >+{ >+ _info->~SafeBrowsingResult(); >+ >+ [super dealloc]; >+} >+ >+- (NSString *)safeBrowsingProvider >+{ >+ return _info->provider(); >+} >+ >+- (NSURL *)URL >+{ >+ return _info->url(); >+} >+ >+- (BOOL)isPhishing >+{ >+ return _info->isPhishing(); >+} >+ >+- (BOOL)isMalware >+{ >+ return _info->isMalware(); >+} >+ >+- (BOOL)isUnwantedSoftware >+{ >+ return _info->isUnwantedSoftware(); >+} >+ >+- (BOOL)isKnownToBeUnsafe >+{ >+ return _info->isKnownToBeUnsafe(); >+} >+ >+#pragma mark WKObject protocol implementation >+ >+- (API::Object&)_apiObject >+{ >+ return *_info; >+} >+ >+@end >+ >+#endif >Index: Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfoInternal.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfoInternal.h (nonexistent) >+++ Source/WebKit/UIProcess/API/Cocoa/_WKUnsafeURLInfoInternal.h (working copy) >@@ -0,0 +1,47 @@ >+/* >+ * Copyright (C) 2015-2018 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. >+ */ >+ >+#import "_WKUnsafeURLInfo.h" >+ >+#if WK_API_ENABLED >+ >+#import "SafeBrowsingResult.h" >+#import "WKObject.h" >+ >+namespace WebKit { >+ >+template<> struct WrapperTraits<WebKit::SafeBrowsingResult> { >+ using WrapperClass = _WKUnsafeURLInfo; >+}; >+ >+} >+ >+@interface _WKUnsafeURLInfo () <WKObject> { >+@package >+ API::ObjectStorage<WebKit::SafeBrowsingResult> _info; >+} >+@end >+ >+#endif // WK_API_ENABLED >Index: Source/WebKit/UIProcess/Cocoa/NavigationState.h >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/NavigationState.h (revision 235954) >+++ Source/WebKit/UIProcess/Cocoa/NavigationState.h (working copy) >@@ -105,6 +105,8 @@ private: > void didFinishNavigation(WebPageProxy&, API::Navigation*, API::Object*) override; > void didFailNavigationWithError(WebPageProxy&, WebFrameProxy&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override; > void didSameDocumentNavigation(WebPageProxy&, API::Navigation*, SameDocumentNavigationType, API::Object*) override; >+ void areYouSureYouWantToNavigateToUnsafeURL(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::SafeBrowsingAction)>&&) final; >+ void webViewDetectedUnsafeContent(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::UnsafeContentAction)>&&) final; > > void renderingProgressDidChange(WebPageProxy&, WebCore::LayoutMilestones) override; > >@@ -216,6 +218,8 @@ private: > bool webViewWillSnapshotBackForwardListItem : 1; > bool webViewNavigationGestureSnapshotWasRemoved : 1; > bool webViewURLContentRuleListIdentifiersNotifications : 1; >+ bool webViewAttemptedToLoadUnsafeURLDecisionHandler : 1; >+ bool webViewDetectedUnsafeContent : 1; > #if USE(QUICK_LOOK) > bool webViewDidStartLoadForQuickLookDocumentInMainFrame : 1; > bool webViewDidFinishLoadForQuickLookDocumentInMainFrame : 1; >Index: Source/WebKit/UIProcess/Cocoa/NavigationState.mm >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/NavigationState.mm (revision 235954) >+++ Source/WebKit/UIProcess/Cocoa/NavigationState.mm (working copy) >@@ -39,6 +39,7 @@ > #import "Logging.h" > #import "NavigationActionData.h" > #import "PageLoadState.h" >+#import "SafeBrowsingResult.h" > #import "WKBackForwardListInternal.h" > #import "WKBackForwardListItemInternal.h" > #import "WKFrameInfoInternal.h" >@@ -64,6 +65,7 @@ > #import "_WKFrameHandleInternal.h" > #import "_WKRenderingProgressEventsInternal.h" > #import "_WKSameDocumentNavigationTypeInternal.h" >+#import "_WKUnsafeURLInfoInternal.h" > #import "_WKWebsitePoliciesInternal.h" > #import <WebCore/Credential.h> > #import <WebCore/SSLKeyGenerator.h> >@@ -141,6 +143,8 @@ void NavigationState::setNavigationDeleg > m_navigationDelegate = delegate; > > m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandler = [delegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]; >+ m_navigationDelegateMethods.webViewAttemptedToLoadUnsafeURLDecisionHandler = [delegate respondsToSelector:@selector(_webView:attemptedToLoadUnsafeURL:decisionHandler:)]; >+ m_navigationDelegateMethods.webViewDetectedUnsafeContent = [delegate respondsToSelector:@selector(_webView:detectedUnsafeContent:decisionHandler:)]; > m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandlerWebsitePolicies = [delegate respondsToSelector:@selector(_webView:decidePolicyForNavigationAction:decisionHandler:)]; > m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionUserInfoDecisionHandlerWebsitePolicies = [delegate respondsToSelector:@selector(_webView:decidePolicyForNavigationAction:userInfo:decisionHandler:)]; > m_navigationDelegateMethods.webViewDecidePolicyForNavigationResponseDecisionHandler = [delegate respondsToSelector:@selector(webView:decidePolicyForNavigationResponse:decisionHandler:)]; >@@ -425,6 +429,62 @@ void NavigationState::NavigationClient:: > }).get()]; > } > >+static WebKit::SafeBrowsingAction toSafeBrowsingAction(_WKUnsafeURLAction action) >+{ >+ switch (action) { >+ case _WKUnsafeURLActionLoadUnsafeURL: >+ return WebKit::SafeBrowsingAction::ContinueToUnsafePage; >+ case _WKUnsafeURLActionCancelNavigation: >+ return WebKit::SafeBrowsingAction::CancelNavigation; >+ } >+} >+ >+static WebKit::UnsafeContentAction toUnsafeContentAction(_WKUnsafeContentAction action) >+{ >+ switch (action) { >+ case _WKUnsafeContentActionResumeBusinessAsUsual: >+ return WebKit::UnsafeContentAction::ResumeBusinessAsUsual; >+ case _WKUnsafeContentActionIveTakenCareOfIt: >+ return WebKit::UnsafeContentAction::IveTakenCareOfIt; >+ } >+} >+ >+void NavigationState::NavigationClient::areYouSureYouWantToNavigateToUnsafeURL(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult& info, CompletionHandler<void(WebKit::SafeBrowsingAction)>&& completionHandler) >+{ >+ if (!m_navigationState.m_navigationDelegateMethods.webViewAttemptedToLoadUnsafeURLDecisionHandler) >+ return completionHandler(WebKit::SafeBrowsingAction::PretendToFailProvisionalLoad); >+ >+ auto delegate = m_navigationState.m_navigationDelegate.get(); >+ if (!delegate) >+ return completionHandler(WebKit::SafeBrowsingAction::PretendToFailProvisionalLoad); >+ >+ auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:attemptedToLoadUnsafeURL:decisionHandler:)); >+ [(id <WKNavigationDelegatePrivate>)delegate _webView:m_navigationState.m_webView attemptedToLoadUnsafeURL:wrapper(info) decisionHandler:BlockPtr<void(_WKUnsafeURLAction)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (_WKUnsafeURLAction action) mutable { >+ if (checker->completionHandlerHasBeenCalled()) >+ return; >+ checker->didCallCompletionHandler(); >+ completionHandler(toSafeBrowsingAction(action)); >+ }).get()]; >+} >+ >+void NavigationState::NavigationClient::webViewDetectedUnsafeContent(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult& info, CompletionHandler<void(WebKit::UnsafeContentAction)>&& completionHandler) >+{ >+ if (!m_navigationState.m_navigationDelegateMethods.webViewDetectedUnsafeContent) >+ return completionHandler(WebKit::UnsafeContentAction::TerminateProcess); >+ >+ auto delegate = m_navigationState.m_navigationDelegate.get(); >+ if (!delegate) >+ return completionHandler(WebKit::UnsafeContentAction::TerminateProcess); >+ >+ auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:detectedUnsafeContent:decisionHandler:)); >+ [(id <WKNavigationDelegatePrivate>)delegate _webView:m_navigationState.m_webView detectedUnsafeContent:wrapper(info) decisionHandler:BlockPtr<void(_WKUnsafeContentAction)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (_WKUnsafeContentAction action) mutable { >+ if (checker->completionHandlerHasBeenCalled()) >+ return; >+ checker->didCallCompletionHandler(); >+ completionHandler(toUnsafeContentAction(action)); >+ }).get()]; >+} >+ > bool NavigationState::NavigationClient::didChangeBackForwardList(WebPageProxy&, WebBackForwardListItem* added, const Vector<Ref<WebBackForwardListItem>>& removed) > { > if (!m_navigationState.m_navigationDelegateMethods.webViewBackForwardListItemAddedRemoved) >Index: Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm (revision 235954) >+++ Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm (working copy) >@@ -85,10 +85,10 @@ void WebPageProxy::beginSafeBrowsingChec > } > > NSArray<SSBServiceLookupResult *> *results = [result serviceLookupResults]; >- Vector<SafeBrowsingResult> resultsVector; >+ Vector<Ref<SafeBrowsingResult>> resultsVector; > resultsVector.reserveInitialCapacity([results count]); > for (SSBServiceLookupResult *result in results) >- resultsVector.uncheckedAppend({ URL(url), result }); >+ resultsVector.uncheckedAppend(SafeBrowsingResult::create(URL(url), result)); > listener->didReceiveSafeBrowsingResults(WTFMove(resultsVector)); > }); > }).get()]; >Index: Source/WebKit/WebKit.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebKit/WebKit.xcodeproj/project.pbxproj (revision 235954) >+++ Source/WebKit/WebKit.xcodeproj/project.pbxproj (working copy) >@@ -1052,6 +1052,9 @@ > 5C298DA01C3DF02100470AFE /* PendingDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C298D9E1C3DEF2900470AFE /* PendingDownload.h */; }; > 5C4B9D8B210A8CCF008F14D1 /* UndoOrRedo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4B9D8A210A8C46008F14D1 /* UndoOrRedo.h */; }; > 5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 5C882837214AEDF000F45C65 /* _WKUnsafeURLInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C882834214AEDEA00F45C65 /* _WKUnsafeURLInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 5C882838214AEDF400F45C65 /* _WKUnsafeURLInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C882836214AEDEA00F45C65 /* _WKUnsafeURLInfo.mm */; }; >+ 5C882839214AEDF700F45C65 /* _WKUnsafeURLInfoInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C882835214AEDEA00F45C65 /* _WKUnsafeURLInfoInternal.h */; }; > 5C8DD3801FE4521600F2A556 /* WebsiteAutoplayPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8DD37F1FE4519200F2A556 /* WebsiteAutoplayPolicy.h */; }; > 5C9E56831DF7F1B300C9EE33 /* WKWebsitePolicies.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C9E56811DF7F05500C9EE33 /* WKWebsitePolicies.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 5CA9854A210BEB640057EB6B /* SafeBrowsingResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CA98549210BEB5A0057EB6B /* SafeBrowsingResult.h */; }; >@@ -3431,6 +3434,9 @@ > 5C7C88DC1D0F41A0009D2F6D /* WebSocketProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebSocketProvider.h; path = Network/WebSocketProvider.h; sourceTree = "<group>"; }; > 5C84CF901F96AC4E00B6705A /* NetworkSessionCreationParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSessionCreationParameters.h; sourceTree = "<group>"; }; > 5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingDownload.cpp; sourceTree = "<group>"; }; >+ 5C882834214AEDEA00F45C65 /* _WKUnsafeURLInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUnsafeURLInfo.h; sourceTree = "<group>"; }; >+ 5C882835214AEDEA00F45C65 /* _WKUnsafeURLInfoInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUnsafeURLInfoInternal.h; sourceTree = "<group>"; }; >+ 5C882836214AEDEA00F45C65 /* _WKUnsafeURLInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKUnsafeURLInfo.mm; sourceTree = "<group>"; }; > 5C8DD37C1FE4501100F2A556 /* APIWebsitePolicies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIWebsitePolicies.h; sourceTree = "<group>"; }; > 5C8DD37D1FE4501100F2A556 /* APIWebsitePolicies.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIWebsitePolicies.cpp; sourceTree = "<group>"; }; > 5C8DD37F1FE4519200F2A556 /* WebsiteAutoplayPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebsiteAutoplayPolicy.h; sourceTree = "<group>"; }; >@@ -5982,6 +5988,9 @@ > 2D6B371918A967AD0042AE80 /* _WKThumbnailView.h */, > 2D6B371A18A967AD0042AE80 /* _WKThumbnailView.mm */, > 2DACE64D18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h */, >+ 5C882834214AEDEA00F45C65 /* _WKUnsafeURLInfo.h */, >+ 5C882836214AEDEA00F45C65 /* _WKUnsafeURLInfo.mm */, >+ 5C882835214AEDEA00F45C65 /* _WKUnsafeURLInfoInternal.h */, > 7C2413011AACFA7500A58C15 /* _WKUserContentExtensionStore.h */, > 7C2413001AACFA7500A58C15 /* _WKUserContentExtensionStore.mm */, > 7C2413041AACFA9C00A58C15 /* _WKUserContentExtensionStoreInternal.h */, >@@ -8777,6 +8786,8 @@ > 1A002D43196B337000B9AD44 /* _WKSessionStateInternal.h in Headers */, > 2D6B371B18A967AD0042AE80 /* _WKThumbnailView.h in Headers */, > 2DACE64E18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h in Headers */, >+ 5C882837214AEDF000F45C65 /* _WKUnsafeURLInfo.h in Headers */, >+ 5C882839214AEDF700F45C65 /* _WKUnsafeURLInfoInternal.h in Headers */, > 7C2413031AACFA7500A58C15 /* _WKUserContentExtensionStore.h in Headers */, > 7C2413051AACFA9C00A58C15 /* _WKUserContentExtensionStoreInternal.h in Headers */, > 7CA3793E1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h in Headers */, >@@ -10652,6 +10663,7 @@ > isa = PBXSourcesBuildPhase; > buildActionMask = 2147483647; > files = ( >+ 5C882838214AEDF400F45C65 /* _WKUnsafeURLInfo.mm in Sources */, > 2D92A784212B6AB100F493FD /* ActivityAssertion.cpp in Sources */, > 2D92A77B212B6A7100F493FD /* ArgumentCoders.cpp in Sources */, > 2DEB1D2E2127473600933906 /* ArgumentCodersCF.cpp in Sources */, >Index: Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp >=================================================================== >--- Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (revision 235954) >+++ Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (working copy) >@@ -472,17 +472,20 @@ void WebFrameLoaderClient::dispatchDidSt > webPage->findController().hideFindUI(); > webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame); > >- WebDocumentLoader& provisionalLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader()); >- auto& url = provisionalLoader.url(); >+ auto provisionalLoader = static_cast<WebDocumentLoader*>(m_frame->coreFrame()->loader().provisionalDocumentLoader()); >+ if (!provisionalLoader) >+ provisionalLoader = static_cast<WebDocumentLoader*>(m_frame->coreFrame()->loader().policyDocumentLoader()); >+ >+ auto& url = provisionalLoader->url(); > RefPtr<API::Object> userData; > > // Notify the bundle client. > webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(*webPage, *m_frame, userData); > >- auto& unreachableURL = provisionalLoader.unreachableURL(); >+ auto& unreachableURL = provisionalLoader->unreachableURL(); > > // Notify the UIProcess. >- webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader.navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); >+ webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader->navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); > } > > static constexpr unsigned maxTitleLength = 1000; // Closest power of 10 above the W3C recommendation for Title length. >@@ -1175,7 +1178,12 @@ ResourceError WebFrameLoaderClient::canc > { > return WebKit::cancelledError(request); > } >- >+ >+ResourceError WebFrameLoaderClient::unsafeURLError(const ResourceRequest& request) >+{ >+ return WebKit::unsafeURLError(request); >+} >+ > ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request) > { > return WebKit::blockedError(request); >Index: Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h >=================================================================== >--- Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h (revision 235954) >+++ Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h (working copy) >@@ -160,6 +160,7 @@ private: > > WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError blockedError(const WebCore::ResourceRequest&) final; >+ WebCore::ResourceError unsafeURLError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError blockedByContentBlockerError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError cannotShowURLError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError interruptedForPolicyChangeError(const WebCore::ResourceRequest&) final; >Index: Source/WebKit/WebProcess/WebPage/WebPage.cpp >=================================================================== >--- Source/WebKit/WebProcess/WebPage/WebPage.cpp (revision 235954) >+++ Source/WebKit/WebProcess/WebPage/WebPage.cpp (working copy) >@@ -4129,7 +4129,12 @@ void WebPage::SandboxExtensionTracker::d > if (!m_provisionalSandboxExtension) > return; > >- ASSERT(!m_provisionalSandboxExtension || frame->coreFrame()->loader().provisionalDocumentLoader()->url().isLocalFile()); >+#if !ASSERT_DISABLED >+ auto* documentLoader = frame->coreFrame()->loader().provisionalDocumentLoader(); >+ if (!documentLoader) >+ documentLoader = frame->coreFrame()->loader().policyDocumentLoader(); >+ ASSERT(!m_provisionalSandboxExtension || documentLoader->url().isLocalFile()); >+#endif > > m_provisionalSandboxExtension->consume(); > } >Index: Source/WebKitLegacy/mac/ChangeLog >=================================================================== >--- Source/WebKitLegacy/mac/ChangeLog (revision 235957) >+++ Source/WebKitLegacy/mac/ChangeLog (working copy) >@@ -1,3 +1,14 @@ >+2018-09-14 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebCoreSupport/WebFrameLoaderClient.h: >+ * WebCoreSupport/WebFrameLoaderClient.mm: >+ (WebFrameLoaderClient::unsafeURLError): >+ > 2018-09-12 Alex Christensen <achristensen@webkit.org> > > Fix an internal build after r235935 >Index: Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h >=================================================================== >--- Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h (revision 235954) >+++ Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h (working copy) >@@ -164,6 +164,7 @@ private: > > WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError blockedError(const WebCore::ResourceRequest&) final; >+ WebCore::ResourceError unsafeURLError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError blockedByContentBlockerError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError cannotShowURLError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError interruptedForPolicyChangeError(const WebCore::ResourceRequest&) final; >Index: Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm >=================================================================== >--- Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm (revision 235954) >+++ Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm (working copy) >@@ -1149,7 +1149,12 @@ ResourceError WebFrameLoaderClient::canc > { > return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()]; > } >- >+ >+ResourceError WebFrameLoaderClient::unsafeURLError(const ResourceRequest&) >+{ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ > ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request) > { > return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()]; >Index: Source/WebKitLegacy/win/ChangeLog >=================================================================== >--- Source/WebKitLegacy/win/ChangeLog (revision 235954) >+++ Source/WebKitLegacy/win/ChangeLog (working copy) >@@ -1,3 +1,14 @@ >+2018-09-14 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebCoreSupport/WebFrameLoaderClient.cpp: >+ (WebFrameLoaderClient::unsafeURLError): >+ * WebCoreSupport/WebFrameLoaderClient.h: >+ > 2018-09-12 Fujii Hironori <Hironori.Fujii@sony.com> > > [Win][Clang][WebKitLegacy] error: 'static' is invalid in friend declarations >Index: Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp >=================================================================== >--- Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp (revision 235954) >+++ Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp (working copy) >@@ -825,6 +825,11 @@ ResourceError WebFrameLoaderClient::canc > return ResourceError(String(WebURLErrorDomain), -999, request.url(), String("Cancelled")); > } > >+ResourceError WebFrameLoaderClient::unsafeURLError(const ResourceRequest&) >+{ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ > ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request) > { > return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotUseRestrictedPort, request.url(), WEB_UI_STRING("Not allowed to use restricted network port", "WebKitErrorCannotUseRestrictedPort description")); >Index: Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h >=================================================================== >--- Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h (revision 235954) >+++ Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h (working copy) >@@ -145,6 +145,7 @@ public: > > WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&) override; > WebCore::ResourceError blockedError(const WebCore::ResourceRequest&) override; >+ WebCore::ResourceError unsafeURLError(const WebCore::ResourceRequest&) final; > WebCore::ResourceError blockedByContentBlockerError(const WebCore::ResourceRequest&) override; > WebCore::ResourceError cannotShowURLError(const WebCore::ResourceRequest&) override; > WebCore::ResourceError interruptedForPolicyChangeError(const WebCore::ResourceRequest&) override; >Index: Tools/ChangeLog >=================================================================== >--- Tools/ChangeLog (revision 236016) >+++ Tools/ChangeLog (working copy) >@@ -1,3 +1,43 @@ >+2018-09-14 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * MiniBrowser/mac/SettingsController.m: >+ * MiniBrowser/mac/WK2BrowserWindowController.m: >+ (unsafeURLType): >+ (-[WK2BrowserWindowController _webView:attemptedToLoadUnsafeURL:decisionHandler:]): >+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: >+ * TestWebKitAPI/Tests/WebKit/simple-alert.html: Added. >+ * TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm: >+ (toString): >+ (-[CallbackRecorder webView:decidePolicyForNavigationAction:decisionHandler:]): >+ (-[CallbackRecorder webView:decidePolicyForNavigationResponse:decisionHandler:]): >+ (-[CallbackRecorder webView:didStartProvisionalNavigation:]): >+ (-[CallbackRecorder webView:didReceiveServerRedirectForProvisionalNavigation:]): >+ (-[CallbackRecorder webView:didFailProvisionalNavigation:withError:]): >+ (-[CallbackRecorder webView:didCommitNavigation:]): >+ (-[CallbackRecorder webView:didFinishNavigation:]): >+ (-[CallbackRecorder webView:didFailNavigation:withError:]): >+ (-[CallbackRecorder webView:didReceiveAuthenticationChallenge:completionHandler:]): >+ (-[CallbackRecorder _webView:webContentProcessDidTerminateWithReason:]): >+ (-[TestLookupContext lookUpURL:completionHandler:]): >+ (initializeTestContext): >+ (resourceURL): >+ (safeResult): >+ (phishingResult): >+ (checkBackForwardList): >+ (checkNavigationCallbacks): >+ (webViewWith): >+ (appendIframe): >+ (TEST): >+ (-[ImplementNewCallbacks _webView:attemptedToLoadUnsafeURL:decisionHandler:]): >+ (-[ImplementNewCallbacks _webView:detectedUnsafeContent:decisionHandler:]): >+ (-[ImplementNewCallbacks webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]): >+ (-[SafeBrowsingNavigationDelegate webView:didFinishNavigation:]): Deleted. >+ > 2018-09-14 Ryan Haddad <ryanhaddad@apple.com> > > bots should pass --clobber-old-results to run-webkit-tests >Index: Tools/MiniBrowser/mac/SettingsController.m >=================================================================== >--- Tools/MiniBrowser/mac/SettingsController.m (revision 235954) >+++ Tools/MiniBrowser/mac/SettingsController.m (working copy) >@@ -35,7 +35,7 @@ > #import <WebKit/_WKInternalDebugFeature.h> > #endif > >-static NSString * const defaultURL = @"http://www.webkit.org/"; >+static NSString * const defaultURL = @"http://testsafebrowsing.appspot.com/"; > static NSString * const DefaultURLPreferenceKey = @"DefaultURL"; > > static NSString * const UseWebKit2ByDefaultPreferenceKey = @"UseWebKit2ByDefault"; >Index: Tools/MiniBrowser/mac/WK2BrowserWindowController.m >=================================================================== >--- Tools/MiniBrowser/mac/WK2BrowserWindowController.m (revision 235954) >+++ Tools/MiniBrowser/mac/WK2BrowserWindowController.m (working copy) >@@ -32,7 +32,7 @@ > #import "SettingsController.h" > #import <WebKit/WKFrameInfo.h> > #import <WebKit/WKNavigationActionPrivate.h> >-#import <WebKit/WKNavigationDelegate.h> >+#import <WebKit/WKNavigationDelegatePrivate.h> > #import <WebKit/WKPage.h> > #import <WebKit/WKPreferencesPrivate.h> > #import <WebKit/WKUIDelegate.h> >@@ -44,6 +44,7 @@ > #import <WebKit/_WKIconLoadingDelegate.h> > #import <WebKit/_WKInspector.h> > #import <WebKit/_WKLinkIconParameters.h> >+#import <WebKit/_WKUnsafeURLInfo.h> > #import <WebKit/_WKUserInitiatedAction.h> > > static void* keyValueObservingContext = &keyValueObservingContext; >@@ -725,6 +726,32 @@ - (void)webViewWebContentProcessDidTermi > [self reload:nil]; > } > >+static const char* unsafeURLType(_WKUnsafeURLInfo *info) >+{ >+ if (info.isPhishing) >+ return "phishing"; >+ if (info.isMalware) >+ return "malware"; >+ if (info.isUnwantedSoftware) >+ return "unwanted software"; >+ return "unsafe"; >+} >+ >+- (void)_webView:(WKWebView *)webView attemptedToLoadUnsafeURL:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeURLAction))decisionHandler >+{ >+ NSAlert* alert = [[NSAlert alloc] init]; >+ >+ [alert setMessageText:@"Unsafe URL warning"]; >+ [alert setInformativeText:[NSString stringWithFormat:@"Are you sure you want to do this? <%@> has been determined to be %s.", info.URL, unsafeURLType(info)]]; >+ [alert addButtonWithTitle:@"Let's not go there"]; >+ [alert addButtonWithTitle:@"I know I'm doing risky things"]; >+ >+ [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse response) { >+ decisionHandler(response == NSAlertFirstButtonReturn ? _WKUnsafeURLActionCancelNavigation : _WKUnsafeURLActionLoadUnsafeURL); >+ [alert release]; >+ }]; >+} >+ > - (void)_webView:(WKWebView *)webView renderingProgressDidChange:(_WKRenderingProgressEvents)progressEvents > { > if (progressEvents & _WKRenderingProgressEventFirstLayout) >Index: Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >=================================================================== >--- Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (revision 235954) >+++ Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (working copy) >@@ -41,7 +41,6 @@ > 0F139E791A42457000F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; }; > 0F2C20B81DCD545000542D9E /* Time.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C20B71DCD544800542D9E /* Time.cpp */; }; > 0F30CB5C1FCE1796004B5323 /* ConcurrentPtrHashSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */; }; >- 4909EE3A2D09480C88982D56 /* Markable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC79F168BE454E579E417B05 /* Markable.cpp */; }; > 0F3B94A71A77267400DE3272 /* WKWebViewEvaluateJavaScript.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */; }; > 0F4FFA9E1ED3AA8500F7111F /* SnapshotViaRenderInContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F4FFA9D1ED3AA8500F7111F /* SnapshotViaRenderInContext.mm */; }; > 0F5651F71FCE4DDC00310FBC /* NoHistoryItemScrollToFragment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F5651F61FCE4DDB00310FBC /* NoHistoryItemScrollToFragment.mm */; }; >@@ -174,6 +173,7 @@ > 46C519E81D3563FD00DAA51A /* LocalStorageNullEntries.localstorage-shm in Copy Resources */ = {isa = PBXBuildFile; fileRef = 46C519E41D35629600DAA51A /* LocalStorageNullEntries.localstorage-shm */; }; > 46E66A901F0D75590026D83C /* WKWebViewDiagnosticLogging.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46E66A8F1F0D75590026D83C /* WKWebViewDiagnosticLogging.mm */; }; > 46E816F81E79E29C00375ADC /* RestoreStateAfterTermination.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46E816F71E79E29100375ADC /* RestoreStateAfterTermination.mm */; }; >+ 4909EE3A2D09480C88982D56 /* Markable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC79F168BE454E579E417B05 /* Markable.cpp */; }; > 4BFDFFA71314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDFFA61314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp */; }; > 510477721D298DDD009747EB /* IDBDeleteRecovery.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5104776F1D298D85009747EB /* IDBDeleteRecovery.sqlite3 */; }; > 510477731D298DDD009747EB /* IDBDeleteRecovery.sqlite3-shm in Copy Resources */ = {isa = PBXBuildFile; fileRef = 510477701D298D85009747EB /* IDBDeleteRecovery.sqlite3-shm */; }; >@@ -290,6 +290,7 @@ > 5CB3CE391FA1697F00C3A2D6 /* WKWebViewConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB3CE381FA1691700C3A2D6 /* WKWebViewConfiguration.mm */; }; > 5CB40B4E1F4B98D3007DC7B9 /* UIDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB40B4D1F4B98BE007DC7B9 /* UIDelegate.mm */; }; > 5CB5B3C21FFC55CF00C27BB0 /* FrameHandleSerialization.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB5B3BD1FFC517E00C27BB0 /* FrameHandleSerialization.mm */; }; >+ 5CC23876214C412D00A28705 /* simple-alert.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5CC23875214C410D00A28705 /* simple-alert.html */; }; > 5CCB10E1213457D300AC5AF0 /* ResponsivenessTimer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB10E02134579D00AC5AF0 /* ResponsivenessTimer.mm */; }; > 5CCB10E2213457D500AC5AF0 /* ResponsivenessTimerDoesntFireEarly.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB10DD2134579C00AC5AF0 /* ResponsivenessTimerDoesntFireEarly.mm */; }; > 5CCB10E3213457D800AC5AF0 /* RestoreSessionStateWithoutNavigation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB10DE2134579D00AC5AF0 /* RestoreSessionStateWithoutNavigation.mm */; }; >@@ -934,7 +935,6 @@ > dstPath = TestWebKitAPI.resources; > dstSubfolderSpec = 7; > files = ( >- C944160021430E8900B1EDDA /* audio-with-controls.html in Copy Resources */, > 1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */, > 379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */, > 1C2B81871C8925A000A5529F /* Ahem.ttf in Copy Resources */, >@@ -951,6 +951,7 @@ > 7C9ED98B17A19F4B00E4DC33 /* attributedStringStrikethrough.html in Copy Resources */, > 37137E4B21124D01002BEEA4 /* AttrStyle.html in Copy Resources */, > CD9E292E1C90C33F000BB800 /* audio-only.html in Copy Resources */, >+ C944160021430E8900B1EDDA /* audio-with-controls.html in Copy Resources */, > CD57779C211CE91F001B371E /* audio-with-web-audio.html in Copy Resources */, > 76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */, > F41AB99F1EF4696B0083FA08 /* autofocus-contenteditable.html in Copy Resources */, >@@ -1164,6 +1165,7 @@ > F4FC077720F013B600CA043C /* significant-text-milestone.html in Copy Resources */, > C9B4AD2A1ECA6EBE00F5FEA0 /* silence-long.m4a in Copy Resources */, > 1ADBEFE3130C6AA100D61D19 /* simple-accelerated-compositing.html in Copy Resources */, >+ 5CC23876214C412D00A28705 /* simple-alert.html in Copy Resources */, > C0ADBE9612FCA79B00D2C129 /* simple-form.html in Copy Resources */, > 33DC8912141955FE00747EF7 /* simple-iframe.html in Copy Resources */, > BCAA485614A0444C0088FAC4 /* simple-tall.html in Copy Resources */, >@@ -1238,7 +1240,6 @@ > 0F17BBD415AF6C4D007AB753 /* WebCoreStatisticsWithNoWebProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreStatisticsWithNoWebProcess.cpp; sourceTree = "<group>"; }; > 0F2C20B71DCD544800542D9E /* Time.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Time.cpp; sourceTree = "<group>"; }; > 0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcurrentPtrHashSet.cpp; sourceTree = "<group>"; }; >- EC79F168BE454E579E417B05 /* Markable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Markable.cpp; sourceTree = "<group>"; }; > 0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewEvaluateJavaScript.mm; sourceTree = "<group>"; }; > 0F4FFA9D1ED3AA8500F7111F /* SnapshotViaRenderInContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SnapshotViaRenderInContext.mm; sourceTree = "<group>"; }; > 0F4FFAA01ED3D0DE00F7111F /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; >@@ -1587,6 +1588,7 @@ > 5CB3CE381FA1691700C3A2D6 /* WKWebViewConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewConfiguration.mm; sourceTree = "<group>"; }; > 5CB40B4D1F4B98BE007DC7B9 /* UIDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIDelegate.mm; sourceTree = "<group>"; }; > 5CB5B3BD1FFC517E00C27BB0 /* FrameHandleSerialization.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameHandleSerialization.mm; sourceTree = "<group>"; }; >+ 5CC23875214C410D00A28705 /* simple-alert.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "simple-alert.html"; sourceTree = "<group>"; }; > 5CCB10DD2134579C00AC5AF0 /* ResponsivenessTimerDoesntFireEarly.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResponsivenessTimerDoesntFireEarly.mm; sourceTree = "<group>"; }; > 5CCB10DE2134579D00AC5AF0 /* RestoreSessionStateWithoutNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RestoreSessionStateWithoutNavigation.mm; sourceTree = "<group>"; }; > 5CCB10DF2134579D00AC5AF0 /* ShouldGoToBackForwardListItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShouldGoToBackForwardListItem.mm; sourceTree = "<group>"; }; >@@ -2021,6 +2023,7 @@ > E4A757D3178AEA5B00B5D7A4 /* Deque.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Deque.cpp; sourceTree = "<group>"; }; > E4C9ABC71B3DB1710040A987 /* RunLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RunLoop.cpp; sourceTree = "<group>"; }; > E5036F77211BC22800BFDBE2 /* color-drop.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "color-drop.html"; sourceTree = "<group>"; }; >+ EC79F168BE454E579E417B05 /* Markable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Markable.cpp; sourceTree = "<group>"; }; > ECA680CD1E68CC0900731D20 /* StringUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StringUtilities.mm; sourceTree = "<group>"; }; > F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; }; > F407FE381F1D0DE60017CF25 /* enormous.svg */ = {isa = PBXFileReference; lastKnownFileType = text; path = enormous.svg; sourceTree = "<group>"; }; >@@ -2621,7 +2624,6 @@ > A16F66B81C40E9E100BD4D24 /* Resources */ = { > isa = PBXGroup; > children = ( >- C94415FF21430B6700B1EDDA /* audio-with-controls.html */, > C25CCA0C1E5140E50026CB8A /* AllAhem.svg */, > F4A9202E1FEE34C800F59590 /* apple-data-url.html */, > F47D30EB1ED28619000482E1 /* apple.gif */, >@@ -2630,6 +2632,7 @@ > 5C9E59401D3EB1DE00E3C62E /* ApplicationCache.db-wal */, > F4856CA21E6498A8009D7EE7 /* attachment-element.html */, > 3760C4F221124BD000233ACC /* AttrStyle.html */, >+ C94415FF21430B6700B1EDDA /* audio-with-controls.html */, > CD57779A211CE6B7001B371E /* audio-with-web-audio.html */, > F41AB9981EF4692C0083FA08 /* autofocus-contenteditable.html */, > 93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */, >@@ -3138,6 +3141,7 @@ > 7A66BDB71EAF150100CCC924 /* set-long-title.html */, > CEBABD481B71687C0051210A /* should-open-external-schemes.html */, > 1ADBEFBC130C6A0100D61D19 /* simple-accelerated-compositing.html */, >+ 5CC23875214C410D00A28705 /* simple-alert.html */, > C0ADBE8412FCA6B600D2C129 /* simple-form.html */, > 33DC890E1419539300747EF7 /* simple-iframe.html */, > BCAA485514A021640088FAC4 /* simple-tall.html */, >Index: Tools/TestWebKitAPI/Tests/WebKit/simple-alert.html >=================================================================== >--- Tools/TestWebKitAPI/Tests/WebKit/simple-alert.html (nonexistent) >+++ Tools/TestWebKitAPI/Tests/WebKit/simple-alert.html (working copy) >@@ -0,0 +1 @@ >+<script> alert("simple-alert.html loaded") </script> >Index: Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm >=================================================================== >--- Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm (revision 235954) >+++ Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm (working copy) >@@ -30,20 +30,117 @@ > #import "ClassMethodSwizzler.h" > #import "PlatformUtilities.h" > #import "TestWKWebView.h" >-#import <WebKit/WKNavigationDelegate.h> >+#import <WebKit/WKNavigationDelegatePrivate.h> >+#import <WebKit/WKPreferencesPrivate.h> > #import <WebKit/WKWebViewPrivate.h> >+#import <WebKit/WebKit.h> >+#import <WebKit/_WKUnsafeURLInfo.h> >+#import <wtf/BlockPtr.h> > #import <wtf/RetainPtr.h> >+#import <wtf/text/WTFString.h> > >-static bool done; >+enum class Callback { >+ NavigationAction, >+ NavigationResponse, >+ StartProvisionalNavigation, >+ ReceiveServerRedirect, >+ FailProvisionalNavigation, >+ CommitNavigation, >+ FinishNavigation, >+ FailNavigation, >+ AuthenticationChallenge, >+ Terminate, >+ UnsafeURL, >+ UnsafeContent, >+}; >+ >+static const char* toString(Callback c) >+{ >+ switch (c) { >+ case Callback::NavigationAction: >+ return "NavigationAction"; >+ case Callback::NavigationResponse: >+ return "NavigationResponse"; >+ case Callback::StartProvisionalNavigation: >+ return "StartProvisionalNavigation"; >+ case Callback::ReceiveServerRedirect: >+ return "ReceiveServerRedirect"; >+ case Callback::FailProvisionalNavigation: >+ return "FailProvisionalNavigation"; >+ case Callback::CommitNavigation: >+ return "CommitNavigation"; >+ case Callback::FinishNavigation: >+ return "FinishNavigation"; >+ case Callback::FailNavigation: >+ return "FailNavigation"; >+ case Callback::AuthenticationChallenge: >+ return "AuthenticationChallenge"; >+ case Callback::Terminate: >+ return "Terminate"; >+ case Callback::UnsafeURL: >+ return "UnsafeURL"; >+ case Callback::UnsafeContent: >+ return "UnsafeContent"; >+ } >+ return "Unrecognized Callback"; >+} >+ >+static bool navigationFinished; >+static bool processTerminated; >+static Vector<Callback> callbacks; > >-@interface SafeBrowsingNavigationDelegate : NSObject <WKNavigationDelegate> >+@interface CallbackRecorder : NSObject <WKNavigationDelegate, WKUIDelegate> > @end > >-@implementation SafeBrowsingNavigationDelegate >+@implementation CallbackRecorder > >-- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation >+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler > { >- done = true; >+ callbacks.append(Callback::NavigationAction); >+ decisionHandler(WKNavigationActionPolicyAllow); >+} >+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler >+{ >+ callbacks.append(Callback::NavigationResponse); >+ decisionHandler(WKNavigationResponsePolicyAllow); >+} >+- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation >+{ >+ callbacks.append(Callback::StartProvisionalNavigation); >+} >+- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation >+{ >+ callbacks.append(Callback::ReceiveServerRedirect); >+} >+- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error >+{ >+ callbacks.append(Callback::FailProvisionalNavigation); >+ navigationFinished = true; >+} >+- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation >+{ >+ callbacks.append(Callback::CommitNavigation); >+} >+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation >+{ >+ callbacks.append(Callback::FinishNavigation); >+ navigationFinished = true; >+} >+- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error >+{ >+ callbacks.append(Callback::FailNavigation); >+ navigationFinished = true; >+} >+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * credential))completionHandler >+{ >+ callbacks.append(Callback::AuthenticationChallenge); >+ completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); >+} >+- (void)_webView:(WKWebView *)webView webContentProcessDidTerminateWithReason:(_WKProcessTerminationReason)reason >+{ >+ EXPECT_EQ(reason, _WKProcessTerminationReasonRequestedByClient); >+ callbacks.append(Callback::Terminate); >+ processTerminated = true; > } > > @end >@@ -126,6 +223,8 @@ - (NSArray<TestServiceLookupResult *> *) > > @end > >+static Vector<std::pair<RetainPtr<NSURL>, RetainPtr<TestServiceLookupResult>>> lookupBehavior; >+ > @interface TestLookupContext : NSObject > @end > >@@ -139,23 +238,264 @@ + (TestLookupContext *)sharedLookupConte > > - (void)lookUpURL:(NSURL *)URL completionHandler:(void (^)(TestLookupResult *, NSError *))completionHandler > { >- completionHandler([TestLookupResult resultWithResults:@[[TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:YES malware:NO unwantedSoftware:NO knownToBeUnsafe:NO]]], nil); >+ for (auto pair : lookupBehavior) { >+ if ([pair.first isEqual:URL]) >+ return completionHandler([TestLookupResult resultWithResults:@[pair.second.get()]], nil); >+ } >+ EXPECT_FALSE(true); >+ completionHandler(nil, nil); > } > > @end > >-TEST(WebKit, SafeBrowsing) >+static void initializeTestContext(Vector<std::pair<RetainPtr<NSURL>, RetainPtr<TestServiceLookupResult>>>&& behavior) >+{ >+ static TestWebKitAPI::ClassMethodSwizzler swizzler(objc_getClass("SSBLookupContext"), @selector(sharedLookupContext), [TestLookupContext methodForSelector:@selector(sharedLookupContext)]); >+ lookupBehavior = WTFMove(behavior); >+ callbacks.clear(); >+} >+ >+static RetainPtr<NSURL> resourceURL(String&& resource) >+{ >+ return [[NSBundle mainBundle] URLForResource:resource withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+} >+ >+static RetainPtr<TestServiceLookupResult> safeResult() >+{ >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:NO malware:NO unwantedSoftware:NO knownToBeUnsafe:NO]; >+} >+ >+static RetainPtr<TestServiceLookupResult> phishingResult() >+{ >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:YES malware:NO unwantedSoftware:NO knownToBeUnsafe:NO]; >+} >+/* >+static RetainPtr<TestServiceLookupResult> malwareResult() >+{ >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:NO malware:YES unwantedSoftware:NO knownToBeUnsafe:NO]; >+} >+ >+static RetainPtr<TestServiceLookupResult> unwantedSoftwareResult() > { >- TestWebKitAPI::ClassMethodSwizzler swizzler(objc_getClass("SSBLookupContext"), @selector(sharedLookupContext), [TestLookupContext methodForSelector:@selector(sharedLookupContext)]); >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:NO malware:NO unwantedSoftware:YES knownToBeUnsafe:NO]; >+} > >- auto navigationDelegate = adoptNS([[SafeBrowsingNavigationDelegate alloc] init]); >+static RetainPtr<TestServiceLookupResult> resultKnownToBeUnsafe() >+{ >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:NO malware:NO unwantedSoftware:NO knownToBeUnsafe:YES]; >+} >+*/ >+static void checkBackForwardList(const RetainPtr<WKWebView>& view, Vector<String>&& back, String current, Vector<String>&& forward) >+{ >+ auto compareItems = [] (WKBackForwardListItem *a, const String& b) { >+ if (!a && b.isNull()) >+ return; >+ EXPECT_STREQ(a.URL.absoluteString.UTF8String, [[NSBundle mainBundle] URLForResource:b withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"].absoluteString.UTF8String); >+ }; >+ auto compareArrays = [&] (NSArray<WKBackForwardListItem *> *a, const Vector<String>& b) { >+ EXPECT_EQ(a.count, b.size()); >+ if (a.count == b.size()) { >+ for (size_t i = 0; i < b.size(); ++i) >+ compareItems(a[i], b[i]); >+ } >+ }; >+ compareArrays(view.get().backForwardList.backList, back); >+ compareItems(view.get().backForwardList.currentItem, current); >+ compareArrays(view.get().backForwardList.forwardList, forward); >+} >+ >+static void checkNavigationCallbacks(Vector<Callback>&& expected) >+{ >+ if (expected != callbacks) { >+ EXPECT_FALSE(true); >+ WTFLogAlways("Callbacks did not match. Expected:"); >+ for (auto& callback : expected) >+ WTFLogAlways("Callback::%s,", toString(callback)); >+ WTFLogAlways("Actual:"); >+ for (auto& callback : callbacks) >+ WTFLogAlways("Callback::%s,", toString(callback)); >+ } >+ callbacks.clear(); >+} >+ >+template<typename Delegate> RetainPtr<WKWebView> webViewWith() >+{ >+ static auto delegate = adoptNS([[Delegate alloc] init]); > auto webView = adoptNS([[WKWebView alloc] init]); >- [webView setNavigationDelegate:navigationDelegate.get()]; >- [webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]]; >+ [webView setNavigationDelegate:delegate.get()]; >+ [webView setUIDelegate:delegate.get()]; >+ return webView; >+} >+ >+static NSString *appendIframe(const char* name) >+{ >+ return [NSString stringWithFormat:@"var iframe = document.createElement('iframe'); iframe.src = '%s.html'; document.body.appendChild(iframe)", name]; >+} >+ >+TEST(SafeBrowsing, Compatibility) >+{ >+ auto simpleURL = resourceURL("simple"); >+ auto simple2URL = resourceURL("simple2"); >+ initializeTestContext({ >+ { simple2URL, safeResult() }, >+ { simpleURL, phishingResult() }, >+ }); >+ auto webView = webViewWith<CallbackRecorder>(); >+ [webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView, { }, { }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::FailProvisionalNavigation >+ }); >+ >+ navigationFinished = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:simple2URL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+ [webView evaluateJavaScript:appendIframe("simple") completionHandler:nil]; >+ TestWebKitAPI::Util::run(&processTerminated); >+ checkBackForwardList(webView, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::Terminate, >+ }); >+} >+ >+static _WKUnsafeURLAction urlAction; >+static _WKUnsafeContentAction contentAction; >+static bool detectedUnsafeContent; >+static bool receivedAlert; >+ >+@interface ImplementNewCallbacks : CallbackRecorder >+@end >+ >+@implementation ImplementNewCallbacks >+ >+- (void)_webView:(WKWebView *)webView attemptedToLoadUnsafeURL:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeURLAction))decisionHandler >+{ >+ callbacks.append(Callback::UnsafeURL); >+ decisionHandler(urlAction); >+ if (urlAction == _WKUnsafeURLActionCancelNavigation) >+ navigationFinished = true; >+} > >- // FIXME: Check that the loading happens as expected once we do something with safe browsing results. >+- (void)_webView:(WKWebView *)webView detectedUnsafeContent:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeContentAction))decisionHandler >+{ >+ callbacks.append(Callback::UnsafeContent); >+ decisionHandler(contentAction); >+ detectedUnsafeContent = true; >+} > >- TestWebKitAPI::Util::run(&done); >+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler >+{ >+ EXPECT_STREQ(message.UTF8String, "simple-alert.html loaded"); >+ completionHandler(); >+ receivedAlert = true; >+} >+ >+@end >+ >+TEST(SafeBrowsing, ImplementNewCallbacks) >+{ >+ auto simpleURL = resourceURL("simple"); >+ auto simple2URL = resourceURL("simple2"); >+ auto simpleAlertURL = resourceURL("simple-alert"); >+ initializeTestContext({ >+ { simple2URL, safeResult() }, >+ { simpleAlertURL, phishingResult() }, >+ { simpleURL, phishingResult() }, >+ }); >+ >+ { >+ auto webView1 = webViewWith<ImplementNewCallbacks>(); >+ urlAction = _WKUnsafeURLActionLoadUnsafeURL; >+ [webView1 loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView1, { }, { "simple" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::UnsafeURL, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+ >+ navigationFinished = false; >+ auto webView2 = webViewWith<ImplementNewCallbacks>(); >+ urlAction = _WKUnsafeURLActionCancelNavigation; >+ [webView2 loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView2, { }, { }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::UnsafeURL, >+ }); >+ } >+ >+ navigationFinished = false; >+ >+ { >+ auto webView3 = webViewWith<ImplementNewCallbacks>(); >+ contentAction = _WKUnsafeContentActionResumeBusinessAsUsual; >+ [webView3 loadRequest:[NSURLRequest requestWithURL:simple2URL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView3, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+ [webView3 evaluateJavaScript:appendIframe("simple-alert") completionHandler:nil]; >+ TestWebKitAPI::Util::run(&receivedAlert); >+ checkBackForwardList(webView3, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::UnsafeContent, >+ Callback::NavigationResponse, >+ }); >+ } >+ >+ navigationFinished = false; >+ receivedAlert = false; >+ >+ { >+ auto webView4 = webViewWith<ImplementNewCallbacks>(); >+ contentAction = _WKUnsafeContentActionIveTakenCareOfIt; >+ [webView4 loadRequest:[NSURLRequest requestWithURL:simple2URL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView4, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+ [webView4 evaluateJavaScript:appendIframe("simple-alert") completionHandler:nil]; >+ __block bool verifiedIFrameDidNotLoad = false; >+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), dispatch_get_main_queue(), ^{ >+ EXPECT_FALSE(receivedAlert); >+ verifiedIFrameDidNotLoad = true; >+ }); >+ TestWebKitAPI::Util::run(&verifiedIFrameDidNotLoad); >+ checkBackForwardList(webView4, { }, { "simple2" }, { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::UnsafeContent, >+ }); >+ } > } > > @interface NullLookupContext : NSObject >@@ -167,7 +507,7 @@ + (NullLookupContext *)sharedLookupConte > } > @end > >-TEST(WebKit, NoSafeBrowsing) >+TEST(SafeBrowsing, BaseSystemMissingFramework) > { > TestWebKitAPI::ClassMethodSwizzler swizzler(objc_getClass("SSBLookupContext"), @selector(sharedLookupContext), [NullLookupContext methodForSelector:@selector(sharedLookupContext)]); > auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188871
:
347880
|
347888
|
347904
|
349327
|
349334
|
349462
|
349793
|
350060
|
350071
|
350738
|
350808
|
350813
|
350826
|
350872
|
352850
|
353655
|
353711
|
353715
|
353740
|
353776
|
353780
|
353792
|
353870
|
353915
|
353918
|
353928