WebKit Bugzilla
Attachment 349462 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-20180911145311.patch (text/plain), 111.24 KB, created by
Alex Christensen
on 2018-09-11 14:53:12 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Alex Christensen
Created:
2018-09-11 14:53:12 PDT
Size:
111.24 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 235912) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,19 @@ >+2018-09-11 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Covered by new API tests. >+ >+ * dom/Document.cpp: >+ (WebCore::loadURLWithoutSafeBrowsingCheck): >+ (WebCore::Document::injectLoadURLWithoutSafeBrowsingCheck): >+ * dom/Document.h: >+ The safe browsing warning needs a special ability to load a URL but bypass the safe browsing check >+ when the user clicks to ignore the safe browsing warning. >+ > 2018-09-11 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > Shrink size of ResourseResponseBase >Index: Source/WebCore/dom/Document.cpp >=================================================================== >--- Source/WebCore/dom/Document.cpp (revision 235912) >+++ Source/WebCore/dom/Document.cpp (working copy) >@@ -72,6 +72,7 @@ > #include "FontFaceSet.h" > #include "FormController.h" > #include "Frame.h" >+#include "FrameLoadRequest.h" > #include "FrameLoader.h" > #include "FrameLoaderClient.h" > #include "FrameView.h" >@@ -112,6 +113,7 @@ > #include "IntersectionObserver.h" > #include "JSCustomElementInterface.h" > #include "JSDOMPromiseDeferred.h" >+#include "JSDocument.h" > #include "JSLazyEventListener.h" > #include "KeyboardEvent.h" > #include "KeyframeEffectReadOnly.h" >@@ -224,6 +226,7 @@ > #include "XPathNSResolver.h" > #include "XPathResult.h" > #include <JavaScriptCore/ConsoleMessage.h> >+#include <JavaScriptCore/IdentifierInlines.h> > #include <JavaScriptCore/RegularExpression.h> > #include <JavaScriptCore/ScriptCallStack.h> > #include <JavaScriptCore/VM.h> >@@ -1991,6 +1994,34 @@ bool Document::needsStyleRecalc() const > return false; > } > >+static JSC::EncodedJSValue JSC_HOST_CALL loadURLWithoutSafeBrowsingCheck(JSC::ExecState* exec) >+{ >+ if (!exec->argumentCount()) >+ return { }; >+ auto url = URL(URL(), exec->argument(0).getString(exec)); >+ if (!url.isValid()) >+ return { }; >+ >+ auto* globalObject = JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); >+ auto* document = downcast<Document>(globalObject->scriptExecutionContext()); >+ auto* frame = document->frame(); >+ if (!frame) >+ return { }; >+ >+ FrameLoadRequest request { *document, document->securityOrigin(), ResourceRequest(URL(URL(), url), frame->loader().outgoingReferrer()), { }, LockHistory::Yes, LockBackForwardList::Yes, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Suppress, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown }; >+ request.setShouldSkipSafeBrowsingCheck(ShouldSkipSafeBrowsingCheck::Yes); >+ frame->loader().load(WTFMove(request)); >+ return { }; >+} >+ >+void Document::injectLoadURLWithoutSafeBrowsingCheck() >+{ >+ auto* exec = execState(); >+ JSC::JSLockHolder loc(exec->vm()); >+ auto* globalObject = JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); >+ globalObject->putDirectNativeFunction(exec->vm(), globalObject, JSC::Identifier::fromString(exec, "loadURLWithoutSafeBrowsingCheck"), 1, loadURLWithoutSafeBrowsingCheck, JSC::NoIntrinsic, 0); >+} >+ > static bool isSafeToUpdateStyleOrLayout(const Document& document) > { > bool isSafeToExecuteScript = ScriptDisallowedScope::InMainThread::isScriptAllowed(); >Index: Source/WebCore/dom/Document.h >=================================================================== >--- Source/WebCore/dom/Document.h (revision 235912) >+++ Source/WebCore/dom/Document.h (working copy) >@@ -1494,6 +1494,8 @@ public: > void setAsRunningUserScripts() { m_isRunningUserScripts = true; } > bool isRunningUserScripts() const { return m_isRunningUserScripts; } > >+ WEBCORE_EXPORT void injectLoadURLWithoutSafeBrowsingCheck(); >+ > protected: > enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 }; > Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0); >Index: Source/WebKit/ChangeLog >=================================================================== >--- Source/WebKit/ChangeLog (revision 235912) >+++ Source/WebKit/ChangeLog (working copy) >@@ -1,3 +1,82 @@ >+2018-09-11 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This makes WebKit show a warning page if the SafeBrowsing framework has determined that we are >+ navigating to an unsafe URL, such as phishing or malware. API should allow the >+ WKWebViewConfiguration to disable this or the WKUIDelegate to change its behavior. >+ >+ * Resources/SafeBrowsingLocalizedStrings.js: Added. >+ * Resources/SafeBrowsingWarning.html: Added. >+ * Shared/API/APIObject.h: >+ * Shared/Cocoa/APIObject.mm: >+ (API::Object::newObject): >+ * Shared/WebPreferences.yaml: >+ Add a new preference so apps can disable safe browsing checks if desired. >+ * UIProcess/API/APIUIClient.h: >+ (API::UIClient::handleSafeBrowsingWarning): >+ * UIProcess/API/C/mac/WKContextPrivateMac.mm: >+ (WKContextHandlesSafeBrowsing): >+ * UIProcess/API/Cocoa/WKPreferences.mm: >+ (-[WKPreferences _safeBrowsingEnabled]): >+ (-[WKPreferences _setSafeBrowsingEnabled:]): >+ * UIProcess/API/Cocoa/WKPreferencesPrivate.h: >+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.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/UIDelegate.h: >+ * UIProcess/Cocoa/UIDelegate.mm: >+ (WebKit::UIDelegate::setDelegate): >+ (WebKit::toSafeBrowsingAction): >+ (WebKit::UIDelegate::UIClient::handleSafeBrowsingWarning): >+ * UIProcess/Cocoa/WebPageProxyCocoa.mm: >+ (WebKit::detailsURL): >+ (WebKit::learnMoreURL): >+ (WebKit::reportAnErrorURL): >+ (WebKit::providerName): >+ (WebKit::alertType): >+ (WebKit::variableDeclarations): >+ (WebKit::WebPageProxy::safeBrowsingWarningHTML): >+ (WebKit::WebPageProxy::beginSafeBrowsingCheck): >+ Generate the safe browsing warning if needed. >+ * 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): >+ If the WKNavigationDelegate has decided to continue with this navigation but the SafeBrowsing framework >+ says it's unsafe, call a new WKUIDelegate(Private for now) to let the application decide what to do and >+ inform the application that such has happened. The default behavior is to show a warning which allows >+ the user to go back or click through. Other options are to cancel the navigation or skip the warning. >+ (WebKit::WebPageProxy::decidePolicyForNewWindowAction): >+ (WebKit::WebPageProxy::decidePolicyForResponse): >+ (WebKit::WebPageProxy::beginSafeBrowsingCheck): >+ (WebKit::WebPageProxy::safeBrowsingWarningHTML): >+ * UIProcess/WebPageProxy.h: >+ * WebKit.xcodeproj/project.pbxproj: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::loadAlternateHTML): >+ (WebKit::WebPage::didFinishLoad): >+ Inject the function to bypass the safe browsing warning only if we have just loaded the safe browsing warning. >+ * WebProcess/WebPage/WebPage.h: >+ > 2018-09-11 Myles C. Maxfield <mmaxfield@apple.com> > > Crash under PlatformPopupMenuData::encode when interacting with a select menu that has variable fonts >Index: Source/WebKit/SourcesCocoa.txt >=================================================================== >--- Source/WebKit/SourcesCocoa.txt (revision 235912) >+++ Source/WebKit/SourcesCocoa.txt (working copy) >@@ -245,6 +245,7 @@ UIProcess/API/Cocoa/_WKProcessPoolConfig > UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm > UIProcess/API/Cocoa/_WKSessionState.mm > UIProcess/API/Cocoa/_WKThumbnailView.mm >+UIProcess/API/Cocoa/_WKUnsafeURLInfo.mm > UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm > UIProcess/API/Cocoa/_WKUserContentFilter.mm > UIProcess/API/Cocoa/_WKUserContentWorld.mm >Index: Source/WebKit/Resources/SafeBrowsingLocalizedStrings.js >=================================================================== >--- Source/WebKit/Resources/SafeBrowsingLocalizedStrings.js (nonexistent) >+++ Source/WebKit/Resources/SafeBrowsingLocalizedStrings.js (working copy) >@@ -0,0 +1,32 @@ >+var localizedStrings = { >+"Close Page": "Close Page", >+"Deceptive Website Warning": "Deceptive Website Warning", >+"Go Back": "Go Back", >+"If you believe this website is safe, you can %report-an-error%. Or, if you understand the risks involved, you can %bypass-link%.": "If you believe this website is safe, you can %report-an-error%. Or, if you understand the risks involved, you can %bypass-link%.", >+"If you understand the risks involved, you can %visit-this-site-link%.": "If you understand the risks involved, you can %visit-this-site-link%.", >+"If you understand the risks involved, you can %visit-this-unsafe-site-link%.": "If you understand the risks involved, you can %visit-this-unsafe-site-link%.", >+"Ignore Warning": "Ignore Warning", >+"Learn moreâ¦": "Learn moreâ¦", >+"Malware Website Warning": "Malware Website Warning", >+"Phishing websites are designed to trick you into disclosing personal or financial information, usually by creating a copy of a legitimate website, such as a bankâs.": "Phishing websites are designed to trick you into disclosing personal or financial information, usually by creating a copy of a legitimate website, such as a bankâs.", >+"Possible Phishing Website": "Possible Phishing Website", >+"Show Details": "Show Details", >+"The address for the website youâre visiting contains a username or password. This may be a âphishingâ website.": "The address for the website youâre visiting contains a username or password. This may be a âphishingâ website.", >+"This website may attempt to install dangerous software, which could harm your computer or steal your personal or financial information, like passwords, photos, or credit cards.": "This website may attempt to install dangerous software, which could harm your computer or steal your personal or financial information, like passwords, photos, or credit cards.", >+"This website may try to trick you into doing something dangerous, like installing software or disclosing personal or financial information, like passwords, phone numbers, or credit cards.": "This website may try to trick you into doing something dangerous, like installing software or disclosing personal or financial information, like passwords, phone numbers, or credit cards.", >+"This website may try to trick you into installing software that harms your browsing experience, like changing your settings without your permission or showing you unwanted ads. Once installed, it may be difficult to remove.": "This website may try to trick you into installing software that harms your browsing experience, like changing your settings without your permission or showing you unwanted ads. Once installed, it may be difficult to remove.", >+"This website was detected as containing harmful software by â%@â.": "This website was detected as containing harmful software by â%@â.", >+"This website was detected as containing malicious software by â%@â.": "This website was detected as containing malicious software by â%@â.", >+"This website was reported as a deceptive website by â%@â.": "This website was reported as a deceptive website by â%@â.", >+"Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust.": "Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust.", >+"Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust. %phishing-learn-more%": "Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust. %phishing-learn-more%", >+"Warnings are shown for websites where harmful software has been detected.": "Warnings are shown for websites where harmful software has been detected.", >+"Warnings are shown for websites where harmful software has been detected. You can check %the-status-of-site% on the %safeBrowsingProvider% diagnostic page.": "Warnings are shown for websites where harmful software has been detected. You can check %the-status-of-site% on the %safeBrowsingProvider% diagnostic page.", >+"Warnings are shown for websites where malicious software has been detected.": "Warnings are shown for websites where malicious software has been detected.", >+"Warnings are shown for websites where malicious software has been detected. You can check the %status-link% on the %safeBrowsingProvider% diagnostic page.": "Warnings are shown for websites where malicious software has been detected. You can check the %status-link% on the %safeBrowsingProvider% diagnostic page.", >+"Website With Harmful Software Warning": "Website With Harmful Software Warning", >+"malware status of â%site%â": "malware status of â%site%â", >+"report an error": "report an error", >+"the status of â%site%â": "the status of â%site%â", >+"visit this unsafe website": "visit this unsafe website", >+}; >Index: Source/WebKit/Resources/SafeBrowsingWarning.html >=================================================================== >--- Source/WebKit/Resources/SafeBrowsingWarning.html (nonexistent) >+++ Source/WebKit/Resources/SafeBrowsingWarning.html (working copy) >@@ -0,0 +1,722 @@ >+<!-- >+ Copyright (C) 2010-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. >+ 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of >+ its contributors may be used to endorse or promote products derived >+ from this software without specific prior written permission. >+ >+ THIS SOFTWARE IS PROVIDED BY APPLE 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 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. >+ --> >+ >+<style> >+body { >+ --font-color: #434343; >+ --compact-font-color: white; >+ --red-color: #fc3d39; >+ --blue-color: rgb(0, 122, 255); >+ --horizontal-padding: 32px; >+ --compact-horizontal-padding: 20px; >+ --border-radius: 6px; >+ --ios-border-radius: 10px; >+} >+ >+* { >+ padding: 0; >+ margin: 0; >+} >+ >+body:not(.ios) * { >+ font-family: -apple-system-font; >+} >+ >+html, body { >+ height: 100%; >+ width: 100%; >+} >+ >+body { >+ font-size: 13px; >+ background: var(--red-color); >+ cursor: default; >+ -webkit-user-select: none; >+} >+ >+#title { >+ overflow: hidden; >+ padding-top: 3px; >+} >+ >+.alert { >+ background-color: white; >+ min-width: 320px; >+ max-width: 672px; >+ position: relative; >+ margin: 0 auto; >+ padding-top: 28px; >+ border-radius: var(--border-radius); >+ box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.2); >+} >+ >+.alert-body .phishing, >+.alert-body .malware, >+.alert-body .unwantedSoftware, >+.alert-body .userinfo { >+ display: none; >+} >+ >+.alert-body { >+ margin: 21px 0 0 0; >+ padding-left: var(--horizontal-padding); >+ padding-right: var(--horizontal-padding); >+ padding-bottom: 24px; >+ color: var(--font-color); >+} >+ >+.alert-body p:first-of-type { >+ margin-bottom: 15px; >+ margin-top: 20px; >+} >+ >+.alert-body p:last-of-type { >+ margin-bottom: 0; >+} >+ >+.bottom-bar { >+ margin-top: 1.3em; >+ height: 22px; >+} >+ >+.bottom-bar button { >+ float: right; >+ font-size: 13px; >+ line-height: 21px; >+ min-width: 90px; >+ margin: 0 4px; >+ vertical-align: bottom; >+ padding: 0 12px; >+} >+ >+.bottom-bar .details { >+ float: left; >+} >+ >+.bottom-bar .details a { >+ cursor: pointer; >+ font-size: 14px; >+ margin-top: 2px; >+} >+ >+#details { >+ display: none; >+ padding: 22px var(--horizontal-padding) 10px var(--horizontal-padding); >+ border-top: 1px solid rgb(217, 217, 217); >+ color: var(--font-color); >+ background-color: rgb(243, 243, 243); >+ border-bottom-left-radius: var(--border-radius); >+ border-bottom-right-radius: var(--border-radius); >+} >+ >+.bottom-bar.goBack .closePage, .bottom-bar.closePage .goBack, #ignoreWarning { >+ display: none; >+} >+ >+a { >+ color: inherit; >+ text-decoration: underline; >+ cursor: pointer; >+} >+ >+#exclamation { >+ float: left; >+ width: 30px; >+ top: 4px; >+ margin-right: 15px; >+ position: relative; >+} >+ >+.exclamation-element { >+ fill: var(--red-color); >+} >+ >+h1 { >+ color: var(--red-color); >+ font-size: 2em; >+ font-weight: 700; >+ line-height: 30px; >+ padding: 0 var(--horizontal-padding); >+ margin-bottom: -6px; >+} >+ >+p { >+ font-size: 14px; >+ line-height: 19px; >+ margin-bottom: 1em; >+ word-wrap: break-word; >+} >+ >+body.ios .alert { >+ box-shadow: none; >+ border-radius: var(--ios-border-radius); >+ max-width: 640px; >+} >+ >+body.ios .alert-body { >+ font: -apple-system-body; >+} >+ >+body.ios #details { >+ font: -apple-system-body; >+ border-bottom-left-radius: var(--ios-border-radius); >+ border-bottom-right-radius: var(--ios-border-radius); >+} >+ >+body.ios h1 { >+ font-size: 26px; >+ font-family: -webkit-system-font; >+} >+ >+body.ios p { >+ font-size: 1.1em; >+ line-height: unset; >+} >+ >+body.ios button { >+ background: none; >+ border: none; >+ color: var(--blue-color); >+ font: -apple-system-short-body; >+} >+ >+body.ios #detailsButton { >+ color: var(--font-color); >+} >+ >+@media screen and (max-width: 666px) { >+ /* iPhone 6 in landscape (667px) and smaller, including all iPhones in portrait */ >+ body { >+ color: var(--compact-font-color); >+ } >+ >+ .alert { >+ box-shadow: none; >+ background-color: var(--red-color); >+ } >+ >+ .alert-body { >+ color: var(--compact-font-color); >+ padding-left: var(--compact-horizontal-padding); >+ padding-right: var(--compact-horizontal-padding); >+ padding-bottom: 30px; >+ } >+ >+ h1 { >+ color: var(--compact-font-color); >+ padding: 0 var(--compact-horizontal-padding); >+ } >+ >+ body.ios button, >+ body.ios #detailsButton { >+ color: white; >+ text-decoration: underline; >+ } >+ >+ #details { >+ color: rgba(255, 255, 255, .85); >+ background-color: var(--red-color); >+ padding: 22px var(--compact-horizontal-padding) 22px var(--compact-horizontal-padding); >+ border-top-width: 1px; >+ border-top-color: rgba(255, 255, 255, .35); >+ } >+ >+ .exclamation-element { >+ fill: var(--compact-font-color); >+ } >+} >+ >+/* RTL support */ >+ >+html[dir="rtl"] .bottom-bar button { >+ float: left; >+} >+ >+html[dir="rtl"] #exclamation { >+ float: right; >+ margin-left: 15px; >+ margin-right: 0; >+} >+@media (prefers-dark-interface) { >+ body { >+ --font-color: rgb(181, 182, 184); >+ --title-color: rgb(224, 225, 225); >+ --red-color: rgb(255, 78, 69); >+ } >+ >+ #title { >+ color: var(--title-color); >+ } >+ >+ .exclamation-element { >+ fill: var(--title-color); >+ } >+ >+ .alert { >+ background-color: rgb(56, 57, 59); >+ box-shadow: 0 6px 12px rgba(0, 0, 0, .24); >+ } >+ >+ #details { >+ background-color: rgb(46, 47, 49); >+ border-top-color: rgb(90, 92, 93); >+ } >+} >+</style> >+<script type="text/javascript"> >+ >+Object.type = function(obj, win) >+{ >+ if (obj === null) >+ return "null"; >+ >+ var type = typeof obj; >+ if (type !== "object" && type !== "function") >+ return type; >+ >+ win = win || window; >+ >+ if (obj instanceof win.Node) >+ return "node"; >+ if (obj instanceof win.String) >+ return "string"; >+ if (obj instanceof win.Array) >+ return "array"; >+ if (obj instanceof win.Boolean) >+ return "boolean"; >+ if (obj instanceof win.Number) >+ return "number"; >+ if (obj instanceof win.Date) >+ return "date"; >+ if (obj instanceof win.RegExp) >+ return "regexp"; >+ if (obj instanceof win.Error) >+ return "error"; >+ return type; >+} >+ >+String.prototype.format = function() >+{ >+ var stringParts = this.split("%@"); >+ for (var i = 0; i < arguments.length; ++i) >+ stringParts.splice(i * 2 + 1, 0, arguments[i].toString()); >+ return stringParts.join(""); >+} >+ >+Array.prototype.remove = function(value, onlyFirst) >+{ >+ if (onlyFirst) { >+ var index = this.indexOf(value); >+ if (index !== -1) >+ this.splice(index, 1); >+ return; >+ } >+ >+ var length = this.length; >+ for (var i = 0; i < length; ++i) { >+ if (this[i] === value) >+ this.splice(i, 1); >+ } >+} >+ >+var HTMLViewController = { >+ trySubmit: function(button) >+ { >+ var computedStyle = window.getComputedStyle(button); >+ // Don't use button.type here, since the default type for button is annoyingly "submit". >+ // Check for an explicit type attribute value of "submit". >+ if (button.getAttribute("type") !== "submit" || computedStyle.visibility === "hidden" || computedStyle.display === "none") >+ return false; >+ button.click(); >+ return true; >+ }, >+ >+ // On Mac, the submit button always has the default button look. >+ keyDown: function(event) >+ { >+ if (event.target.tagName === "TEXTAREA" || event.keyIdentifier !== "Enter") >+ return; >+ >+ var buttons = document.getElementsByTagName("button"); >+ for (var i = 0; i < buttons.length; ++i) { >+ if (HTMLViewController.trySubmit(buttons[i])) { >+ event.preventDefault(); >+ return; >+ } >+ } >+ >+ var inputButtons = document.getElementsByTagName("input"); >+ for (var i = 0; i < inputButtons.length; ++i) { >+ if (HTMLViewController.trySubmit(inputButtons[i])) { >+ event.preventDefault(); >+ return; >+ } >+ } >+ }, >+ >+ addClass: function(itemID, itemClass) >+ { >+ document.getElementById(itemID).classList.add(itemClass); >+ }, >+ >+ removeClass: function(itemID, itemClass) >+ { >+ document.getElementById(itemID).classList.remove(itemClass); >+ }, >+ >+ contextMenu: function(event) >+ { >+ if (event.target.tagName === "TEXTAREA") >+ return; >+ >+ if (event.target.tagName === "INPUT" && (event.target.type === "password" || event.target.type === "text" || event.target.type == "search")) >+ return; >+ >+ event.preventDefault(); >+ }, >+ >+ pageLoaded: function() >+ { >+ document.body.addEventListener("keydown", HTMLViewController.keyDown); >+ document.addEventListener("contextmenu", HTMLViewController.contextMenu); >+ >+ HTMLViewController.localize(); >+ }, >+ >+ UIString: function(string) >+ { >+ if (window.localizedStrings && string in window.localizedStrings) >+ string = window.localizedStrings[string]; >+ else { >+ console.error("Localized string \"" + string + "\" not found."); >+ string = "LOCALIZED STRING NOT FOUND"; >+ } >+ return string; >+ }, >+ >+ localize: function() >+ { >+ var elements = document.getElementsByClassName("l12n"); >+ for (var i = 0; i < elements.length; ++i) >+ elements[i].firstChild.data = HTMLViewController.UIString(elements[i].firstChild.data); >+ } >+} >+ >+ >+var PhishingAlert = { >+ _host: undefined, >+ _source: undefined, >+ _type: undefined, >+ _currentURL: undefined, >+ _extensionDisplayName: undefined, >+ >+ get host() >+ { >+ return this._host >+ }, >+ >+ set host(value) >+ { >+ if (this._host === value) >+ return; >+ this._host = value; >+ >+ this.updateDetailsStrings(); >+ }, >+ >+ get currentURL() >+ { >+ return this._currentURL; >+ }, >+ >+ set currentURL(value) >+ { >+ if (this._currentURL === value) >+ return; >+ this._currentURL = value; >+ >+ document.getElementById("report-an-error").href = "%@&url=%@&hl=%@".format(reportAnErrorURL, escape(this.currentURL), navigator.language); >+ }, >+ >+ get source() >+ { >+ return this._source; >+ }, >+ >+ set source(value) >+ { >+ this._source = value; >+ }, >+ >+ get type() >+ { >+ return this._type; >+ }, >+ >+ set type(value) >+ { >+ this._type = value; >+ }, >+ >+ get extensionDisplayName() >+ { >+ return this._extensionDisplayName; >+ }, >+ >+ set extensionDisplayName(value) >+ { >+ if (this._extensionDisplayName === value) >+ return; >+ >+ this._extensionDisplayName = value; >+ this.updateDetailsStrings(); >+ }, >+ >+ pageLoaded: function() >+ { >+ if (platformMac) >+ document.body.classList.add("mac"); >+ else >+ document.body.classList.add("ios"); >+ >+ HTMLViewController.pageLoaded(); >+ window.addEventListener("resize", layOut, false); >+ layOut(); >+ }, >+ >+ updateUI: function(source, type, host, canGoBack, currentURL, extensionDisplayName) >+ { >+ if (this.source != source || this.type != type) { >+ document.querySelector(".alert ." + type).style.display = "block"; >+ this.source = source; >+ this.type = type; >+ } >+ >+ var title; >+ if (type === "malware") >+ title = HTMLViewController.UIString("Malware Website Warning"); >+ else if (type === "phishing") >+ title = HTMLViewController.UIString("Deceptive Website Warning"); >+ else if (type === "unwantedSoftware") >+ title = HTMLViewController.UIString("Website With Harmful Software Warning"); >+ else if (type === "userinfo") >+ title = HTMLViewController.UIString("Possible Phishing Website"); >+ else >+ console.error("Unknown type (%s) passed to updateUI.", type); >+ >+ document.title = title; >+ document.getElementById("title").innerText = title; >+ >+ if (canGoBack) { >+ HTMLViewController.addClass("bottom-bar", "goBack"); >+ HTMLViewController.removeClass("bottom-bar", "closePage"); >+ } else { >+ HTMLViewController.addClass("bottom-bar", "closePage"); >+ HTMLViewController.removeClass("bottom-bar", "goBack"); >+ } >+ >+ this.extensionDisplayName = extensionDisplayName; >+ this.host = host; >+ this.currentURL = currentURL; >+ }, >+ >+ updateDetailsStrings: function() >+ { >+ var source = this.source; >+ var extensionDisplayName = this.extensionDisplayName; >+ >+ var bypassWarningParagraph = HTMLViewController.UIString("If you understand the risks involved, you can %visit-this-unsafe-site-link%."); >+ var visitThisUnsafeSiteAnchorHTML = "<a role='button' onClick=\"window.loadURLWithoutSafeBrowsingCheck(unsafeURL)\">%@</a>".format(HTMLViewController.UIString("visit this unsafe website")); >+ bypassWarningParagraph = bypassWarningParagraph.replace("%visit-this-unsafe-site-link%", visitThisUnsafeSiteAnchorHTML); >+ >+ switch (this.type) { >+ case "malware": >+ var details = document.getElementById("malware-details"); >+ >+ var firstParagraph; >+ >+ if (extensionDisplayName) >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites where malicious software has been detected."); >+ else { >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites where malicious software has been detected. You can check the %status-link% on the %safeBrowsingProvider% diagnostic page.").replace("%safeBrowsingProvider%", safeBrowsingProvider); >+ var statusLinkHTML = "<a href=\"%@&site=%@&hl=%@\">%@</a>".format(malwareDetailsURL, escape(this.host), navigator.language, HTMLViewController.UIString("malware status of â%site%â").replace("%site%", this.host)); >+ firstParagraph = firstParagraph.replace("%status-link%", statusLinkHTML); >+ } >+ >+ details.innerHTML = "<p>" + firstParagraph + "</p><p>" + bypassWarningParagraph + "</p>"; >+ break; >+ >+ case "phishing": >+ var details = document.getElementById("phishing-details"); >+ >+ var firstParagraph; >+ if (extensionDisplayName) >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust."); >+ else { >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites that have been reported as deceptive. Deceptive websites try to trick you into believing they are legitimate websites you trust. %phishing-learn-more%"); >+ >+ var learnMoreAnchor = document.createElement("a"); >+ learnMoreAnchor.innerText = HTMLViewController.UIString("Learn moreâ¦"); >+ learnMoreAnchor.href = "%@&hl=%@".format(learnMoreAboutPhishingURL, navigator.language); >+ firstParagraph = firstParagraph.replace("%phishing-learn-more%", learnMoreAnchor.outerHTML) >+ } >+ >+ var secondParagraph; >+ if (extensionDisplayName) >+ secondParagraph = bypassWarningParagraph; >+ else { >+ var secondParagraph = HTMLViewController.UIString("If you believe this website is safe, you can %report-an-error%. Or, if you understand the risks involved, you can %bypass-link%."); >+ secondParagraph = secondParagraph.replace("%bypass-link%", visitThisUnsafeSiteAnchorHTML); >+ >+ var reportAnErrorAnchor = document.createElement("a"); >+ reportAnErrorAnchor.id = "report-an-error"; >+ reportAnErrorAnchor.innerText = HTMLViewController.UIString("report an error"); >+ secondParagraph = secondParagraph.replace("%report-an-error%", reportAnErrorAnchor.outerHTML) >+ } >+ >+ details.innerHTML = "<p>" + firstParagraph + "</p><p>" + secondParagraph + "</p>"; >+ break; >+ >+ case "unwantedSoftware": >+ var details = document.getElementById("unwantedSoftware-details"); >+ >+ var firstParagraph; >+ if (extensionDisplayName) >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites where harmful software has been detected."); >+ else { >+ firstParagraph = HTMLViewController.UIString("Warnings are shown for websites where harmful software has been detected. You can check %the-status-of-site% on the %safeBrowsingProvider% diagnostic page.").replace("%safeBrowsingProvider%", safeBrowsingProvider); >+ var statusLinkHTML = "<a href=\"%@&site=%@&hl=%@\">%@</a>".format(malwareDetailsURL, escape(this.host), navigator.language, HTMLViewController.UIString("the status of â%site%â").replace("%site%", this.host)); >+ firstParagraph = firstParagraph.replace("%the-status-of-site%", statusLinkHTML); >+ } >+ >+ details.innerHTML = "<p>" + firstParagraph + "</p><p>" + bypassWarningParagraph + "</p>"; >+ break; >+ >+ case "userinfo": >+ document.getElementById("ignoreWarning").style.display = "block"; >+ break; >+ } >+ >+ if (extensionDisplayName) { >+ document.getElementById("malwareExtensionDetails").innerText = HTMLViewController.UIString("This website was detected as containing malicious software by â%@â.").format(extensionDisplayName); >+ document.getElementById("phishingExtensionDetails").innerText = HTMLViewController.UIString("This website was reported as a deceptive website by â%@â.").format(extensionDisplayName); >+ document.getElementById("unwantedSoftwareExtensionDetails").innerText = HTMLViewController.UIString("This website was detected as containing harmful software by â%@â.").format(extensionDisplayName); >+ } else { >+ document.getElementById("malwareExtensionDetails").innerText = ""; >+ document.getElementById("phishingExtensionDetails").innerText = ""; >+ document.getElementById("unwantedSoftwareExtensionDetails").innerText = ""; >+ } >+ >+ setDetailsVisibility(false); >+ if (this.type === "userinfo") >+ document.getElementById("detailsButton").style.display = "none"; >+ }, >+}; >+ >+function setDetailsVisibility(show) >+{ >+ var detailsDiv = document.getElementById("details"); >+ if (show) { >+ detailsDiv.style.display = "block"; >+ document.getElementById("detailsButton").style.display = "none"; >+ detailsDiv.scrollIntoViewIfNeeded(); >+ } else { >+ detailsDiv.style.display = "none"; >+ document.getElementById("detailsButton").style.display = "block"; >+ } >+ >+ layOut(); >+} >+ >+function layOut() >+{ >+ const minimumMarginTop = 22; >+ const maximumMarginTop = 156; >+ var alertBox = document.getElementById("alert"); >+ var alertHeight = alertBox.getBoundingClientRect().height; >+ var viewportHeight = window.innerHeight; >+ if (viewportHeight > alertHeight + 2 * maximumMarginTop) >+ alertBox.style.top = maximumMarginTop + "px"; >+ else >+ alertBox.style.top = Math.max(minimumMarginTop, (viewportHeight - alertHeight) / 2) + "px"; >+} >+ >+window.addEventListener("load", function() { >+ PhishingAlert.pageLoaded(); >+ PhishingAlert.updateUI(safeBrowsingProvider, typeUIValue, hostUIValue, canGoBack, unsafeURL); >+}, false); >+</script> >+</head> >+ >+<body> >+ <div id="alert" class="alert phishing google"> >+ <h1> >+ <svg id="exclamation" x="0px" y="0px" viewBox="0 0 150 150" style="enable-background:new 0 0 150 150;" xml:space="preserve"> >+ <path class="exclamation-element" d="M75,0C33.6,0,0,33.6,0,75c0,41.4,33.6,75,75,75s75-33.6,75-75C150,33.6,116.4,0,75,0z M66,34c0-5,4-9,9-9 >+ s9,4,9,9v51c0,5-4,9-9,9s-9-4-9-9V34z M75,128c-6.1,0-11-4.9-11-11s4.9-11,11-11s11,4.9,11,11S81.1,128,75,128z"/> >+ </svg> >+ >+ <div id="title"></div> >+ </h1> >+ <div class="alert-body"> >+ <div class="malware"> >+ <p class="l12n">This website may attempt to install dangerous software, which could harm your computer or steal your personal or financial information, like passwords, photos, or credit cards.</p> >+ <p class="google" id="google-malware-details"></p> >+ <p id="malwareExtensionDetails"></p> >+ </div> >+ >+ <div class="phishing"> >+ <p class="l12n">This website may try to trick you into doing something dangerous, like installing software or disclosing personal or financial information, like passwords, phone numbers, or credit cards.</p> >+ <p id="phishingExtensionDetails"></p> >+ </div> >+ >+ <div class="unwantedSoftware"> >+ <p class="l12n">This website may try to trick you into installing software that harms your browsing experience, like changing your settings without your permission or showing you unwanted ads. Once installed, it may be difficult to remove.</p> >+ <p id="unwantedSoftwareExtensionDetails"></p> >+ </div> >+ >+ <div class="userinfo"> >+ <p class="l12n">The address for the website youâre visiting contains a username or password. This may be a âphishingâ website.</p> >+ <p class="l12n">Phishing websites are designed to trick you into disclosing personal or financial information, usually by creating a copy of a legitimate website, such as a bankâs.</p> >+ </div> >+ >+ <div class="bottom-bar goBack closePage" id="bottom-bar"> >+ <button type="button" class="l12n goBack" onClick="window.history.back();">Go Back</button> >+ <button type="button" class="l12n closePage" onClick="window.close();window.location='about:blank'">Close Page</button> >+ <button type="button" id="ignoreWarning" class="l12n" onClick="window.loadURLWithoutSafeBrowsingCheck(unsafeURL)">Ignore Warning</button> >+ <button type="button" id="detailsButton" class="l12n" onClick="setDetailsVisibility(true);">Show Details</button> >+ </div> >+ </div> >+ <div id="details"> >+ <div id="malware-details"></div> >+ <div id="phishing-details"></div> >+ <div id="unwantedSoftware-details"></div> >+ </div> >+ </div> >+</body> >+</html> >Index: Source/WebKit/Shared/WebPreferences.yaml >=================================================================== >--- Source/WebKit/Shared/WebPreferences.yaml (revision 235912) >+++ 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 235912) >+++ Source/WebKit/Shared/API/APIObject.h (working copy) >@@ -150,6 +150,7 @@ public: > RunJavaScriptAlertResultListener, > RunJavaScriptConfirmResultListener, > RunJavaScriptPromptResultListener, >+ SafeBrowsingResult, > TextChecker, > URLSchemeTask, > UserContentController, >Index: Source/WebKit/Shared/Cocoa/APIObject.mm >=================================================================== >--- Source/WebKit/Shared/Cocoa/APIObject.mm (revision 235912) >+++ Source/WebKit/Shared/Cocoa/APIObject.mm (working copy) >@@ -77,6 +77,7 @@ > #import "_WKHitTestResultInternal.h" > #import "_WKInspectorInternal.h" > #import "_WKProcessPoolConfigurationInternal.h" >+#import "_WKUnsafeURLInfoInternal.h" > #import "_WKUserContentWorldInternal.h" > #import "_WKUserInitiatedActionInternal.h" > #import "_WKUserStyleSheetInternal.h" >@@ -264,6 +265,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 235912) >+++ 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,10 @@ 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 235912) >+++ 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 235912) >+++ 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 235912) >+++ 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 235912) >+++ 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 235912) >+++ Source/WebKit/UIProcess/WebPageProxy.cpp (working copy) >@@ -3961,13 +3961,6 @@ void WebPageProxy::frameDidBecomeFrameSe > m_frameSetLargestFrame = value ? m_mainFrame : 0; > } > >-#if !PLATFORM(COCOA) >-void WebPageProxy::beginSafeBrowsingCheck(const URL&, WebFramePolicyListenerProxy& listener) >-{ >- listener.didReceiveSafeBrowsingResults({ }); >-} >-#endif >- > void WebPageProxy::decidePolicyForNavigationActionAsync(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, const FrameInfoData& frameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, WebCore::ShouldSkipSafeBrowsingCheck shouldSkipSafeBrowsingCheck, uint64_t listenerID) > { > decidePolicyForNavigationAction(frameID, frameSecurityOrigin, navigationID, WTFMove(navigationActionData), frameInfoData, originatingPageID, originalRequest, WTFMove(request), WTFMove(redirectResponse), userData, shouldSkipSafeBrowsingCheck, PolicyDecisionSender::create([this, protectedThis = makeRef(*this), frameID, listenerID] (auto... args) { >@@ -4029,29 +4022,64 @@ 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 = sender.copyRef(), navigation] (WebCore::PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, Vector<Ref<SafeBrowsingResult>>&& safeBrowsingResults) mutable { >+ >+ auto completionHandler = [this, protectedThis = protectedThis.copyRef(), frame = WTFMove(frame), navigation = navigation.copyRef(), policies = makeRefPtr(policies), sender = WTFMove(sender), 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()); >- >- RunLoop::main().dispatch([this, protectedThis = WTFMove(protectedThis), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable { >- continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess)); >+ 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()); >+ >+ 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_uiClient && isUnsafe(result)) { >+ m_uiClient->handleSafeBrowsingWarning(*this, result, [this, protectedThis = WTFMove(protectedThis), result = result.copyRef(), navigation = WTFMove(navigation), completionHandler = WTFMove(completionHandler)] (WebKit::SafeBrowsingAction action) mutable { >+ switch (action) { >+ case WebKit::SafeBrowsingAction::ContinueToUnsafePage: >+ completionHandler(PolicyAction::Use); >+ break; >+ case WebKit::SafeBrowsingAction::CancelNavigation: >+ completionHandler(PolicyAction::Ignore); >+ break; >+ case WebKit::SafeBrowsingAction::ShowDefaultWarning: { >+ completionHandler(PolicyAction::Ignore); >+ bool willBeAbleToGoBack = !!backForwardList().currentItem(); >+ auto buffer = safeBrowsingWarningHTML(result, willBeAbleToGoBack); >+ // FIXME: Use SharedBufferDataReference instead of calling data() and don't copy it into the LoadParameters. >+ loadAlternateHTML({ reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size() }, "UTF-8"_s, navigation->currentRequest().url(), navigation->currentRequest().url(), nullptr, true); >+ break; >+ } >+ } > }); >+ return; > } > } >- >- receivedPolicyDecision(policyAction, navigation.get(), WTFMove(data), WTFMove(sender)); >+ completionHandler(policyAction); > }, shouldSkipSafeBrowsingCheck == ShouldSkipSafeBrowsingCheck::Yes ? ShouldExpectSafeBrowsingResult::No : ShouldExpectSafeBrowsingResult::Yes)); > if (shouldSkipSafeBrowsingCheck == ShouldSkipSafeBrowsingCheck::No) > beginSafeBrowsingCheck(request.url(), listener); >@@ -4100,7 +4128,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 +4164,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()); >@@ -7792,6 +7820,18 @@ void WebPageProxy::invalidateAllAttachme > m_attachmentIdentifierToAttachmentMap.clear(); > } > >+#if !HAVE(SAFE_BROWSING) >+void WebPageProxy::beginSafeBrowsingCheck(const URL&, WebFramePolicyListenerProxy& listener) >+{ >+ listener.didReceiveSafeBrowsingResults({ }); >+} >+ >+Ref<SharedBuffer> WebPageProxy::safeBrowsingWarningHTML(const SafeBrowsingResult&, bool) >+{ >+ return SharedBuffer::create(); >+} >+#endif >+ > #if !PLATFORM(COCOA) > > void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&&, const String&, const IPC::DataReference&) >Index: Source/WebKit/UIProcess/WebPageProxy.h >=================================================================== >--- Source/WebKit/UIProcess/WebPageProxy.h (revision 235912) >+++ Source/WebKit/UIProcess/WebPageProxy.h (working copy) >@@ -261,6 +261,7 @@ struct WebPopupItem; > struct URLSchemeTaskParameters; > > enum class ProcessSwapRequestedByClient; >+enum class SafeBrowsingAction : uint8_t; > enum class UndoOrRedo; > > #if USE(QUICK_LOOK) >@@ -1430,6 +1431,7 @@ private: > void decidePolicyForResponse(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, uint64_t listenerID, const UserData&); > void unableToImplementPolicy(uint64_t frameID, const WebCore::ResourceError&, const UserData&); > void beginSafeBrowsingCheck(const WebCore::URL&, WebFramePolicyListenerProxy&); >+ Ref<WebCore::SharedBuffer> safeBrowsingWarningHTML(const SafeBrowsingResult&, bool); > > void willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData&); > >Index: Source/WebKit/UIProcess/API/APIUIClient.h >=================================================================== >--- Source/WebKit/UIProcess/API/APIUIClient.h (revision 235912) >+++ Source/WebKit/UIProcess/API/APIUIClient.h (working copy) >@@ -54,6 +54,7 @@ class WebFrameProxy; > class WebOpenPanelResultListenerProxy; > class WebPageProxy; > struct NavigationActionData; >+enum class SafeBrowsingAction : uint8_t { ContinueToUnsafePage, CancelNavigation, ShowDefaultWarning }; > > #if ENABLE(MEDIA_SESSION) > class WebMediaSessionMetadata; >@@ -113,6 +114,8 @@ public: > > virtual void pageDidScroll(WebKit::WebPageProxy*) { } > >+ virtual void handleSafeBrowsingWarning(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::SafeBrowsingAction)>&& completionHandler) { completionHandler(WebKit::SafeBrowsingAction::ShowDefaultWarning); } >+ > virtual void exceededDatabaseQuota(WebKit::WebPageProxy*, WebKit::WebFrameProxy*, SecurityOrigin*, const WTF::String&, const WTF::String&, unsigned long long currentQuota, unsigned long long, unsigned long long, unsigned long long, Function<void (unsigned long long)>&& completionHandler) > { > completionHandler(currentQuota); >Index: Source/WebKit/UIProcess/API/C/mac/WKContextPrivateMac.mm >=================================================================== >--- Source/WebKit/UIProcess/API/C/mac/WKContextPrivateMac.mm (revision 235912) >+++ 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/WKPreferences.mm >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (revision 235912) >+++ Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (working copy) >@@ -140,6 +140,15 @@ - (void)_setStorageAccessPromptsEnabled: > _preferences->setStorageAccessPromptsEnabled(enabled); > } > >+- (BOOL)_safeBrowsingEnabled >+{ >+ return _preferences->safeBrowsingEnabled(); >+} >+ >+- (void)_setSafeBrowsingEnabled:(BOOL)enabled >+{ >+ _preferences->setSafeBrowsingEnabled(enabled); >+} > #pragma mark OS X-specific methods > > #if PLATFORM(MAC) >Index: Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (revision 235912) >+++ Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (working copy) >@@ -98,6 +98,7 @@ typedef NS_ENUM(NSInteger, _WKEditableLi > @property (nonatomic, setter=_setDefaultFontSize:) NSUInteger _defaultFontSize WK_API_AVAILABLE(macosx(10.12), ios(10.0)); > @property (nonatomic, setter=_setDefaultFixedPitchFontSize:) NSUInteger _defaultFixedPitchFontSize WK_API_AVAILABLE(macosx(10.12), ios(10.0)); > @property (nonatomic, copy, setter=_setFixedPitchFontFamily:) NSString *_fixedPitchFontFamily WK_API_AVAILABLE(macosx(10.12), ios(10.0)); >+@property (nonatomic, setter=_setSafeBrowsingEnabled:) BOOL _safeBrowsingEnabled; > > // FIXME: This should be configured on the WKWebsiteDataStore. > // FIXME: This property should not have the verb "is" in it. >Index: Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h >=================================================================== >--- Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (revision 235912) >+++ Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (working copy) >@@ -40,6 +40,13 @@ > @class _WKActivatedElementInfo; > @class _WKElementAction; > @class _WKFrameHandle; >+@class _WKUnsafeURLInfo; >+ >+typedef NS_ENUM(NSInteger, _WKUnsafeURLAction) { >+ _WKUnsafeURLActionShowDefaultWarning, >+ _WKUnsafeURLActionLoadUnsafeURL, >+ _WKUnsafeURLActionCancelNavigation, >+} WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > > #if TARGET_OS_IOS > @class UIDragItem; >@@ -93,6 +100,7 @@ struct UIEdgeInsets; > > - (void)_webView:(WKWebView *)webView printFrame:(_WKFrameHandle *)frame; > >+- (void)_webView:(WKWebView *)webView attemptedToLoadUnsafeURL:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeURLAction))decisionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > - (void)_webViewClose:(WKWebView *)webView; > - (void)_webViewFullscreenMayReturnToInline:(WKWebView *)webView; > - (void)_webViewDidEnterFullscreen:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.11), ios(8.3)); >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, 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/UIDelegate.h >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/UIDelegate.h (revision 235912) >+++ Source/WebKit/UIProcess/Cocoa/UIDelegate.h (working copy) >@@ -121,6 +121,7 @@ private: > void didExceedBackgroundResourceLimitWhileInForeground(WebPageProxy&, WKResourceLimit) final; > void saveDataToFileInDownloadsFolder(WebPageProxy*, const WTF::String&, const WTF::String&, const WebCore::URL&, API::Data&) final; > #endif >+ void handleSafeBrowsingWarning(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult&, CompletionHandler<void(WebKit::SafeBrowsingAction)>&&) final; > bool decidePolicyForUserMediaPermissionRequest(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin&, API::SecurityOrigin&, UserMediaPermissionRequestProxy&) final; > bool checkUserMediaPermissionForOrigin(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin&, API::SecurityOrigin&, UserMediaPermissionCheckProxy&) final; > void mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags) final; >@@ -189,6 +190,7 @@ private: > bool webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler : 1; > bool webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler : 1; > bool webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded : 1; >+ bool webViewAttemptedToLoadUnsafeURLDecisionHandler : 1; > bool webViewPrintFrame : 1; > bool webViewDidClose : 1; > bool webViewClose : 1; >Index: Source/WebKit/UIProcess/Cocoa/UIDelegate.mm >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (revision 235912) >+++ Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (working copy) >@@ -33,6 +33,7 @@ > #import "CompletionHandlerCallChecker.h" > #import "NativeWebWheelEvent.h" > #import "NavigationActionData.h" >+#import "SafeBrowsingResult.h" > #import "UserMediaPermissionCheckProxy.h" > #import "UserMediaPermissionRequestProxy.h" > #import "WKFrameInfoInternal.h" >@@ -50,6 +51,7 @@ > #import "_WKContextMenuElementInfo.h" > #import "_WKFrameHandleInternal.h" > #import "_WKHitTestResultInternal.h" >+#import "_WKUnsafeURLInfoInternal.h" > #import <WebCore/SecurityOriginData.h> > #import <WebCore/URL.h> > #import <wtf/BlockPtr.h> >@@ -135,6 +137,7 @@ void UIDelegate::setDelegate(id <WKUIDel > m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)]; > m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:databaseName:displayName:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)]; > m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded = [delegate respondsToSelector:@selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:)]; >+ m_delegateMethods.webViewAttemptedToLoadUnsafeURLDecisionHandler = [delegate respondsToSelector:@selector(_webView:attemptedToLoadUnsafeURL:decisionHandler:)]; > m_delegateMethods.webViewPrintFrame = [delegate respondsToSelector:@selector(_webView:printFrame:)]; > m_delegateMethods.webViewDidClose = [delegate respondsToSelector:@selector(webViewDidClose:)]; > m_delegateMethods.webViewClose = [delegate respondsToSelector:@selector(_webViewClose:)]; >@@ -413,6 +416,36 @@ void UIDelegate::UIClient::runBeforeUnlo > }).get()]; > } > >+static WebKit::SafeBrowsingAction toSafeBrowsingAction(_WKUnsafeURLAction action) >+{ >+ switch (action) { >+ case _WKUnsafeURLActionShowDefaultWarning: >+ return WebKit::SafeBrowsingAction::ShowDefaultWarning; >+ case _WKUnsafeURLActionLoadUnsafeURL: >+ return WebKit::SafeBrowsingAction::ContinueToUnsafePage; >+ case _WKUnsafeURLActionCancelNavigation: >+ return WebKit::SafeBrowsingAction::CancelNavigation; >+ } >+} >+ >+void UIDelegate::UIClient::handleSafeBrowsingWarning(WebKit::WebPageProxy&, WebKit::SafeBrowsingResult& info, CompletionHandler<void(WebKit::SafeBrowsingAction)>&& completionHandler) >+{ >+ if (!m_uiDelegate.m_delegateMethods.webViewAttemptedToLoadUnsafeURLDecisionHandler) >+ return completionHandler(WebKit::SafeBrowsingAction::ShowDefaultWarning); >+ >+ auto delegate = m_uiDelegate.m_delegate.get(); >+ if (!delegate) >+ return completionHandler(WebKit::SafeBrowsingAction::ShowDefaultWarning); >+ >+ auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:attemptedToLoadUnsafeURL:decisionHandler:)); >+ [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.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 UIDelegate::UIClient::exceededDatabaseQuota(WebPageProxy*, WebFrameProxy*, API::SecurityOrigin* securityOrigin, const WTF::String& databaseName, const WTF::String& displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentUsage, unsigned long long expectedUsage, Function<void (unsigned long long)>&& completionHandler) > { > if (!m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler && !m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler) { >Index: Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm >=================================================================== >--- Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm (revision 235912) >+++ Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm (working copy) >@@ -71,9 +71,93 @@ void WebPageProxy::loadRecentSearches(co > searchItems = WebCore::loadRecentSearches(name); > } > >+#if HAVE(SAFE_BROWSING) >+// FIXME: These ought to be API calls to the SafariSafeBrowsing framework. >+static const char* detailsURL(const String& provider) >+{ >+ if (provider == String(SSBProviderTencent)) >+ return "https://www.urlsec.qq.com/check.html?tpl=safari"; >+ return "https://google.com/safebrowsing/diagnostic?tpl=safari"; >+} >+ >+static const char* learnMoreURL(const String& provider) >+{ >+ if (provider == String(SSBProviderTencent)) >+ return "https://www.urlsec.qq.com/standard/s1.html?tpl=safari"; >+ return "https://www.google.com/support/bin/answer.py?answer=106318"; >+} >+ >+static const char* reportAnErrorURL(const String& provider) >+{ >+ if (provider == String(SSBProviderTencent)) >+ return "https://www.urlsec.qq.com/complain.html?tpl=safari"; >+ return "https://www.google.com/safebrowsing/report_error/?tpl=safari"; >+} >+ >+static const char* providerName(const String& provider) >+{ >+ if (provider == String(SSBProviderTencent)) >+ return "tencent"; >+ return "google"; >+} >+ >+static const char* alertType(const SafeBrowsingResult& result) >+{ >+ // These correspond to the cases in updateDetailsStrings >+ if (result.isPhishing()) >+ return "phishing"; >+ if (result.isMalware()) >+ return "malware"; >+ if (result.isUnwantedSoftware()) >+ return "unwantedSoftware"; >+ ASSERT(result.isKnownToBeUnsafe()); >+ return "userinfo"; >+} >+ >+static CString variableDeclarations(const SafeBrowsingResult& result, bool canGoBack) >+{ >+ return makeString("var safeBrowsingProvider = '", >+ providerName(result.provider()), >+ "';\n var malwareDetailsURL = '", >+ detailsURL(result.provider()), >+ "';\n var learnMoreAboutPhishingURL = '", >+ learnMoreURL(result.provider()), >+ "';\n var reportAnErrorURL = '", >+ reportAnErrorURL(result.provider()), >+ "';\n var typeUIValue = '", >+ alertType(result), >+ "';\n var hostUIValue = '", >+ result.url().host(), >+ "';\n var canGoBack = ", >+ canGoBack ? "true" : "false", >+ ";\n var unsafeURL = '", >+ result.url().string(), >+ "';\n var platformMac = ", >+#if PLATFORM(MAC) >+ "true", >+#else >+ "false", >+#endif >+ ";\n</script>").utf8(); >+} >+ >+Ref<SharedBuffer> WebPageProxy::safeBrowsingWarningHTML(const SafeBrowsingResult& result, bool canGoBack) >+{ >+ NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit"]; >+ const char* begin = "<!DOCTYPE html><html><head><meta http-equiv='content-type' content='text/html; charset=utf-8'><meta name='viewport' content='width=device-width'><script>"; >+ NSData *localizedStrings = [NSData dataWithContentsOfFile:[bundle pathForResource:@"SafeBrowsingLocalizedStrings" ofType:@"js"] options:NSDataReadingMappedIfSafe error:nil]; >+ auto declarations = variableDeclarations(result, canGoBack); >+ NSData *html = [NSData dataWithContentsOfFile:[bundle pathForResource:@"SafeBrowsingWarning" ofType:@"html"] options:NSDataReadingMappedIfSafe error:nil]; >+ >+ auto buffer = SharedBuffer::create(begin, strlen(begin)); >+ buffer->append(localizedStrings); >+ buffer->append(declarations.data(), declarations.length()); >+ buffer->append(html); >+ return buffer; >+} >+ > void WebPageProxy::beginSafeBrowsingCheck(const URL& url, WebFramePolicyListenerProxy& listener) > { >-#if HAVE(SAFE_BROWSING) > SSBLookupContext *context = [SSBLookupContext sharedLookupContext]; > if (!context) > return listener.didReceiveSafeBrowsingResults({ }); >@@ -85,17 +169,15 @@ 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()]; >-#else >- listener.didReceiveSafeBrowsingResults({ }); >-#endif > } >+#endif > > #if ENABLE(CONTENT_FILTERING) > void WebPageProxy::contentFilterDidBlockLoadForFrame(const WebCore::ContentFilterUnblockHandler& unblockHandler, uint64_t frameID) >Index: Source/WebKit/WebKit.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebKit/WebKit.xcodeproj/project.pbxproj (revision 235912) >+++ Source/WebKit/WebKit.xcodeproj/project.pbxproj (working copy) >@@ -1052,12 +1052,17 @@ > 5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 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, ); }; }; >+ 5CA8595621404F37007A6905 /* SafeBrowsingLocalizedStrings.js in Resources */ = {isa = PBXBuildFile; fileRef = 5CA8595521404F18007A6905 /* SafeBrowsingLocalizedStrings.js */; }; >+ 5CA8595721404F37007A6905 /* SafeBrowsingWarning.html in Resources */ = {isa = PBXBuildFile; fileRef = 5CA8595421404F18007A6905 /* SafeBrowsingWarning.html */; }; > 5CA9854A210BEB640057EB6B /* SafeBrowsingResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CA98549210BEB5A0057EB6B /* SafeBrowsingResult.h */; }; > 5CAFDE452130846300B1F7E1 /* _WKInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE422130843500B1F7E1 /* _WKInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE442130843600B1F7E1 /* _WKInspectorInternal.h */; }; > 5CB2378C1DF0DE6E00117AA3 /* _WKWebsitePolicies.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CB237891DF0DD4300117AA3 /* _WKWebsitePolicies.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 5CB2378E1DF0E0D300117AA3 /* _WKWebsitePoliciesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CB2378D1DF0E0C200117AA3 /* _WKWebsitePoliciesInternal.h */; }; > 5CBC9B8E1C652CA000A8FDCF /* NetworkDataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CBC9B891C6524A500A8FDCF /* NetworkDataTask.h */; }; >+ 5CC5DB7B2146E925006CB8A8 /* _WKUnsafeURLInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CC5DB792146E8FC006CB8A8 /* _WKUnsafeURLInfo.mm */; }; >+ 5CC5DB7C2146E9A7006CB8A8 /* _WKUnsafeURLInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CC5DB7A2146E8FC006CB8A8 /* _WKUnsafeURLInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 5CC5DB7D2146E9AD006CB8A8 /* _WKUnsafeURLInfoInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CC5DB782146E8FC006CB8A8 /* _WKUnsafeURLInfoInternal.h */; }; > 5CD286511E7235990094FDC8 /* WKContentRuleListStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD2864D1E722F440094FDC8 /* WKContentRuleListStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; > 5CD286531E7235AA0094FDC8 /* _WKUserContentFilterPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD286491E722F440094FDC8 /* _WKUserContentFilterPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 5CD286541E7235B10094FDC8 /* WKContentRuleList.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD2864A1E722F440094FDC8 /* WKContentRuleList.h */; settings = {ATTRIBUTES = (Public, ); }; }; >@@ -3428,6 +3433,8 @@ > 5C8DD3811FE455CA00F2A556 /* WebsiteAutoplayQuirk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebsiteAutoplayQuirk.h; sourceTree = "<group>"; }; > 5C9E56801DF7F05500C9EE33 /* WKWebsitePolicies.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKWebsitePolicies.cpp; sourceTree = "<group>"; }; > 5C9E56811DF7F05500C9EE33 /* WKWebsitePolicies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebsitePolicies.h; sourceTree = "<group>"; }; >+ 5CA8595421404F18007A6905 /* SafeBrowsingWarning.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = SafeBrowsingWarning.html; path = Resources/SafeBrowsingWarning.html; sourceTree = "<group>"; }; >+ 5CA8595521404F18007A6905 /* SafeBrowsingLocalizedStrings.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = SafeBrowsingLocalizedStrings.js; path = Resources/SafeBrowsingLocalizedStrings.js; sourceTree = "<group>"; }; > 5CA98549210BEB5A0057EB6B /* SafeBrowsingResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SafeBrowsingResult.h; sourceTree = "<group>"; }; > 5CA9854B210BEB730057EB6B /* SafeBrowsingResultCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SafeBrowsingResultCocoa.mm; sourceTree = "<group>"; }; > 5CAFDE422130843500B1F7E1 /* _WKInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKInspector.h; sourceTree = "<group>"; }; >@@ -3438,6 +3445,9 @@ > 5CB2378D1DF0E0C200117AA3 /* _WKWebsitePoliciesInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKWebsitePoliciesInternal.h; sourceTree = "<group>"; }; > 5CBC9B891C6524A500A8FDCF /* NetworkDataTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkDataTask.h; sourceTree = "<group>"; }; > 5CBC9B8B1C65257300A8FDCF /* NetworkDataTaskCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkDataTaskCocoa.mm; sourceTree = "<group>"; }; >+ 5CC5DB782146E8FC006CB8A8 /* _WKUnsafeURLInfoInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUnsafeURLInfoInternal.h; sourceTree = "<group>"; }; >+ 5CC5DB792146E8FC006CB8A8 /* _WKUnsafeURLInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKUnsafeURLInfo.mm; sourceTree = "<group>"; }; >+ 5CC5DB7A2146E8FC006CB8A8 /* _WKUnsafeURLInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUnsafeURLInfo.h; sourceTree = "<group>"; }; > 5CD286491E722F440094FDC8 /* _WKUserContentFilterPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUserContentFilterPrivate.h; sourceTree = "<group>"; }; > 5CD2864A1E722F440094FDC8 /* WKContentRuleList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentRuleList.h; sourceTree = "<group>"; }; > 5CD2864B1E722F440094FDC8 /* WKContentRuleList.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentRuleList.mm; sourceTree = "<group>"; }; >@@ -4614,6 +4624,8 @@ > 6D8A91A511F0EFD100DD01FE /* com.apple.WebProcess.sb.in */, > 8DC2EF5A0486A6940098B216 /* Info.plist */, > 089C1666FE841158C02AAC07 /* InfoPlist.strings */, >+ 5CA8595521404F18007A6905 /* SafeBrowsingLocalizedStrings.js */, >+ 5CA8595421404F18007A6905 /* SafeBrowsingWarning.html */, > E1D26A4C1759634E0095BFD1 /* WebContentProcess.xib */, > E133FD891423DD7F00FC7BFB /* WebKit.icns */, > ); >@@ -5963,6 +5975,9 @@ > 2D6B371918A967AD0042AE80 /* _WKThumbnailView.h */, > 2D6B371A18A967AD0042AE80 /* _WKThumbnailView.mm */, > 2DACE64D18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h */, >+ 5CC5DB7A2146E8FC006CB8A8 /* _WKUnsafeURLInfo.h */, >+ 5CC5DB792146E8FC006CB8A8 /* _WKUnsafeURLInfo.mm */, >+ 5CC5DB782146E8FC006CB8A8 /* _WKUnsafeURLInfoInternal.h */, > 7C2413011AACFA7500A58C15 /* _WKUserContentExtensionStore.h */, > 7C2413001AACFA7500A58C15 /* _WKUserContentExtensionStore.mm */, > 7C2413041AACFA9C00A58C15 /* _WKUserContentExtensionStoreInternal.h */, >@@ -8744,6 +8759,8 @@ > 1A002D43196B337000B9AD44 /* _WKSessionStateInternal.h in Headers */, > 2D6B371B18A967AD0042AE80 /* _WKThumbnailView.h in Headers */, > 2DACE64E18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h in Headers */, >+ 5CC5DB7C2146E9A7006CB8A8 /* _WKUnsafeURLInfo.h in Headers */, >+ 5CC5DB7D2146E9AD006CB8A8 /* _WKUnsafeURLInfoInternal.h in Headers */, > 7C2413031AACFA7500A58C15 /* _WKUserContentExtensionStore.h in Headers */, > 7C2413051AACFA9C00A58C15 /* _WKUserContentExtensionStoreInternal.h in Headers */, > 7CA3793E1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h in Headers */, >@@ -10082,6 +10099,8 @@ > 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, > 3FB08E431F60B240005E5312 /* iOS.xcassets in Resources */, > 93A2A3461D246125002B59D3 /* mediaIcon.pdf in Resources */, >+ 5CA8595621404F37007A6905 /* SafeBrowsingLocalizedStrings.js in Resources */, >+ 5CA8595721404F37007A6905 /* SafeBrowsingWarning.html in Resources */, > ); > runOnlyForDeploymentPostprocessing = 0; > }; >Index: Source/WebKit/WebProcess/WebPage/WebPage.cpp >=================================================================== >--- Source/WebKit/WebProcess/WebPage/WebPage.cpp (revision 235912) >+++ Source/WebKit/WebProcess/WebPage/WebPage.cpp (working copy) >@@ -1322,6 +1322,7 @@ void WebPage::loadData(LoadParameters&& > void WebPage::loadAlternateHTML(const LoadParameters& loadParameters) > { > platformDidReceiveLoadParameters(loadParameters); >+ m_loadingSafeBrowsingWarning = loadParameters.forSafeBrowsing; > > URL baseURL = loadParameters.baseURLString.isEmpty() ? blankURL() : URL(URL(), loadParameters.baseURLString); > URL unreachableURL = loadParameters.unreachableURLString.isEmpty() ? URL() : URL(URL(), loadParameters.unreachableURLString); >@@ -5337,6 +5338,9 @@ void WebPage::didCommitLoad(WebFrame* fr > > void WebPage::didFinishLoad(WebFrame* frame) > { >+ if (std::exchange(m_loadingSafeBrowsingWarning, false)) >+ m_mainFrame->coreFrame()->document()->injectLoadURLWithoutSafeBrowsingCheck(); >+ > #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) > if (!frame->isMainFrame()) > return; >Index: Source/WebKit/WebProcess/WebPage/WebPage.h >=================================================================== >--- Source/WebKit/WebProcess/WebPage/WebPage.h (revision 235912) >+++ Source/WebKit/WebProcess/WebPage/WebPage.h (working copy) >@@ -1736,6 +1736,7 @@ private: > #endif > > bool m_isSuspended { false }; >+ bool m_loadingSafeBrowsingWarning { false }; > }; > > } // namespace WebKit >Index: Tools/ChangeLog >=================================================================== >--- Tools/ChangeLog (revision 235912) >+++ Tools/ChangeLog (working copy) >@@ -1 +1,38 @@ >+2018-09-11 Alex Christensen <achristensen@webkit.org> >+ >+ Implement safe browsing in WebKit >+ https://bugs.webkit.org/show_bug.cgi?id=188871 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm: >+ (-[SafeBrowsingDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): >+ (-[SafeBrowsingDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): >+ (-[SafeBrowsingDelegate webView:didStartProvisionalNavigation:]): >+ (-[SafeBrowsingDelegate webView:didReceiveServerRedirectForProvisionalNavigation:]): >+ (-[SafeBrowsingDelegate webView:didFailProvisionalNavigation:withError:]): >+ (-[SafeBrowsingDelegate webView:didCommitNavigation:]): >+ (-[SafeBrowsingDelegate webView:didFinishNavigation:]): >+ (-[SafeBrowsingDelegate webView:didFailNavigation:withError:]): >+ (-[SafeBrowsingDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]): >+ (-[SafeBrowsingDelegate webViewDidClose:]): >+ (-[TestLookupContext lookUpURL:completionHandler:]): >+ (initializeTestContext): >+ (resourceURL): >+ (safeResult): >+ (phishingResult): >+ (malwareResult): >+ (unwantedSoftwareResult): >+ (resultKnownToBeUnsafe): >+ (checkBackForwardList): >+ (toString): >+ (checkNavigationCallbacks): >+ (runJavaScript): >+ (emptyWebView): >+ (simpleWebViewWithWarning): >+ (TEST): >+ (-[SafeBrowsingTestDelegate webView:didFinishNavigation:]): >+ (-[SafeBrowsingTestDelegate _webView:attemptedToLoadUnsafeURL:decisionHandler:]): >+ (-[SafeBrowsingNavigationDelegate webView:didFinishNavigation:]): Deleted. >+ > == Rolled over to ChangeLog-2018-09-11 == >Index: Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm >=================================================================== >--- Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm (revision 235912) >+++ Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm (working copy) >@@ -30,20 +30,81 @@ > #import "ClassMethodSwizzler.h" > #import "PlatformUtilities.h" > #import "TestWKWebView.h" >-#import <WebKit/WKNavigationDelegate.h> >+#import <WebKit/WKPreferencesPrivate.h> >+#import <WebKit/WKUIDelegatePrivate.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; >+static bool navigationFinished; >+static bool viewClosed; >+static bool titleChanged; >+ >+enum class Callback { >+ NavigationAction, >+ NavigationResponse, >+ StartProvisionalNavigation, >+ ReceiveServerRedirect, >+ FailProvisionalNavigation, >+ CommitNavigation, >+ FinishNavigation, >+ FailNavigation, >+ AuthenticationChallenge >+}; >+static Vector<Callback> callbacks; > >-@interface SafeBrowsingNavigationDelegate : NSObject <WKNavigationDelegate> >+@interface SafeBrowsingDelegate : NSObject <WKNavigationDelegate, WKUIDelegate> > @end > >-@implementation SafeBrowsingNavigationDelegate >+@implementation SafeBrowsingDelegate > >-- (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); >+} >+- (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); >+} >+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * credential))completionHandler >+{ >+ callbacks.append(Callback::AuthenticationChallenge); >+ completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); >+} >+ >+- (void)webViewDidClose:(WKWebView *)webView >+{ >+ viewClosed = true; > } > > @end >@@ -126,6 +187,8 @@ - (NSArray<TestServiceLookupResult *> *) > > @end > >+static Vector<std::pair<RetainPtr<NSURL>, RetainPtr<TestServiceLookupResult>>> lookupBehavior; >+ > @interface TestLookupContext : NSObject > @end > >@@ -139,25 +202,391 @@ + (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) > { >- TestWebKitAPI::ClassMethodSwizzler swizzler(objc_getClass("SSBLookupContext"), @selector(sharedLookupContext), [TestLookupContext methodForSelector:@selector(sharedLookupContext)]); >+ return [[NSBundle mainBundle] URLForResource:resource withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; >+} > >- auto navigationDelegate = adoptNS([[SafeBrowsingNavigationDelegate 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"]]]; >+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() >+{ >+ return [TestServiceLookupResult resultWithProvider:@"TestProvider" phishing:NO malware:NO unwantedSoftware:YES knownToBeUnsafe:NO]; >+} >+ >+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) { >+ 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); >+} > >- // FIXME: Check that the loading happens as expected once we do something with safe browsing results. >+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"; >+ } >+ return "Unrecognized Callback"; >+} >+ >+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)); >+ } >+} > >+static void runJavaScript(const RetainPtr<WKWebView>& view, String&& script, String&& expectedResult = "(null)") >+{ >+ bool done = false; >+ [view evaluateJavaScript:script completionHandler:BlockPtr<void(id, NSError *)>::fromCallable([expectedResult = WTFMove(expectedResult), done = &done] (id result, NSError *error) { >+ EXPECT_TRUE(error == nil); >+ NSString *resultString = [NSString stringWithFormat:@"%@", result]; >+ EXPECT_STREQ(expectedResult.utf8().data(), resultString.UTF8String); >+ *done = true; >+ }).get()]; > TestWebKitAPI::Util::run(&done); > } > >+static void runJavaScript(const RetainPtr<WKWebView>& view, Vector<std::pair<String, String>>&& scriptResultPairs) >+{ >+ for (auto&& pair : scriptResultPairs) >+ runJavaScript(view, WTFMove(pair.first), WTFMove(pair.second)); >+} >+ >+RetainPtr<WKWebView> emptyWebView() >+{ >+ static auto delegate = adoptNS([[SafeBrowsingDelegate alloc] init]); >+ auto webView = adoptNS([[WKWebView alloc] init]); >+ [webView setNavigationDelegate:delegate.get()]; >+ [webView setUIDelegate:delegate.get()]; >+ checkBackForwardList(webView, { }, "(null)", { }); >+ return webView; >+} >+ >+RetainPtr<WKWebView> simpleWebViewWithWarning(RetainPtr<TestServiceLookupResult>&& result) >+{ >+ auto simpleURL = resourceURL("simple"); >+ initializeTestContext({{simpleURL, result.get()}}); >+ auto webView = emptyWebView(); >+ navigationFinished = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ runJavaScript(webView, "canGoBack", "0"); >+ checkBackForwardList(webView, { }, "simple", { }); >+ return webView; >+} >+ >+const char* buttonDisplayValues = "Array.from(document.querySelectorAll('button')).map(x=>x.style.display).toString()"; >+const char* getTitle = "document.querySelector('#title').innerHTML"; >+ >+TEST(SafeBrowsing, IgnorePhishingWarning) >+{ >+ auto webView = simpleWebViewWithWarning(phishingResult()); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation >+ }); >+ >+ // Clicking "Show Details" should make the button invisible >+ runJavaScript(webView, { >+ {buttonDisplayValues, ",,,block"}, >+ {"typeUIValue", "phishing"}, >+ {"document.querySelector('button#detailsButton').click()", "(null)"}, >+ {buttonDisplayValues, ",,,none"}, >+ {"!!window.loadURLWithoutSafeBrowsingCheck", "1"}, >+ }); >+ >+ // Clicking "visit this unsafe website" should navigate to the site. >+ navigationFinished = false; >+ runJavaScript(webView, "document.querySelector('a[role=\"button\"]').click()"); >+ TestWebKitAPI::Util::run(&navigationFinished); >+ >+ runJavaScript(webView, { >+ {"document.body.innerHTML.trim()", "Simple HTML file."}, >+ {"!!window.loadURLWithoutSafeBrowsingCheck", "0"}, >+ }); >+ checkBackForwardList(webView, { }, "simple", { }); >+ >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+} >+ >+TEST(SafeBrowsing, ClosePage) >+{ >+ auto webView = simpleWebViewWithWarning(phishingResult()); >+ runJavaScript(webView, "document.querySelector('button.closePage').click()"); >+ TestWebKitAPI::Util::run(&viewClosed); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation >+ }); >+} >+ >+TEST(SafeBrowsing, GoBack) >+{ >+ auto simpleURL = resourceURL("simple"); >+ auto simple2URL = resourceURL("simple2"); >+ initializeTestContext({ >+ { simpleURL, safeResult() }, >+ { simple2URL, phishingResult() }, >+ }); >+ auto webView = emptyWebView(); >+ [webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView, { }, "simple", { }); >+ navigationFinished = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:simple2URL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView, {"simple"}, "simple2", { }); >+ runJavaScript(webView, { >+ {buttonDisplayValues, ",,,block"}, >+ {"canGoBack", "1"}, >+ {"document.querySelector('button.goBack').click()", "(null)"}, >+ }); >+ checkBackForwardList(webView, { "simple" }, "simple2", { }); >+ navigationFinished = false; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkBackForwardList(webView, { }, "simple", { "simple2" }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+} >+ >+TEST(SafeBrowsing, ResultTypes) >+{ >+ runJavaScript(simpleWebViewWithWarning(phishingResult()), getTitle, "Deceptive Website Warning"); >+ runJavaScript(simpleWebViewWithWarning(malwareResult()), getTitle, "Malware Website Warning"); >+ runJavaScript(simpleWebViewWithWarning(unwantedSoftwareResult()), getTitle, "Website With Harmful Software Warning"); >+ runJavaScript(simpleWebViewWithWarning(resultKnownToBeUnsafe()), getTitle, "Possible Phishing Website"); >+} >+ >+TEST(SafeBrowsing, Preference) >+{ >+ auto webView = simpleWebViewWithWarning(phishingResult()); >+ runJavaScript(webView, getTitle, "Deceptive Website Warning"); >+ [[[webView configuration] preferences] _setSafeBrowsingEnabled:NO]; >+ navigationFinished = false; >+ [webView reload]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ runJavaScript(webView, "document.body.innerHTML.trim()", "Simple HTML file."); >+ checkBackForwardList(webView, { }, "simple", { }); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+} >+ >+@interface TitleObserver : NSObject >+@end >+ >+@implementation TitleObserver >+ >+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context >+{ >+ if ([[object title] isEqualToString:@"Deceptive Website Warning"]) >+ titleChanged = true; >+} >+ >+@end >+ >+TEST(SafeBrowsing, IFrames) >+{ >+ auto simpleURL = resourceURL("simple"); >+ auto simple2URL = resourceURL("simple2"); >+ initializeTestContext({ >+ { simpleURL, safeResult() }, >+ { simple2URL, phishingResult() }, >+ }); >+ auto webView = emptyWebView(); >+ auto observer = adoptNS([[TitleObserver alloc] init]); >+ [webView addObserver:observer.get() forKeyPath:@"title" options:0 context:nil]; >+ [webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ }); >+ runJavaScript(webView, "var iframe=document.createElement('iframe');iframe.src='simple2.html';document.body.appendChild(iframe);null", "<null>"); >+ TestWebKitAPI::Util::run(&titleChanged); >+ [webView removeObserver:observer.get() forKeyPath:@"title"]; >+ checkNavigationCallbacks({ >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::NavigationResponse, >+ Callback::CommitNavigation, >+ Callback::FinishNavigation, >+ Callback::NavigationAction, >+ Callback::StartProvisionalNavigation, >+ Callback::CommitNavigation, >+ }); >+} >+ >+static _WKUnsafeURLAction action; >+ >+@interface SafeBrowsingTestDelegate : NSObject <WKNavigationDelegate, WKUIDelegate> >+@end >+ >+@implementation SafeBrowsingTestDelegate >+ >+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation >+{ >+ navigationFinished = true; >+} >+ >+- (void)_webView:(WKWebView *)webView attemptedToLoadUnsafeURL:(_WKUnsafeURLInfo *)info decisionHandler:(void (^)(_WKUnsafeURLAction))decisionHandler >+{ >+ EXPECT_STREQ(info.safeBrowsingProvider.UTF8String, "TestProvider"); >+ EXPECT_TRUE([info.URL isEqual:resourceURL("simple").get()]); >+ EXPECT_TRUE(info.isPhishing); >+ EXPECT_FALSE(info.isMalware); >+ EXPECT_FALSE(info.isUnwantedSoftware); >+ EXPECT_FALSE(info.isKnownToBeUnsafe); >+ >+ decisionHandler(action); >+} >+ >+@end >+ >+TEST(SafeBrowsing, UnsafeURLDelegateDecision) >+{ >+ auto simpleURL = resourceURL("simple"); >+ initializeTestContext({{simpleURL, phishingResult()}}); >+ auto delegate = adoptNS([[SafeBrowsingTestDelegate alloc] init]); >+ auto webView = adoptNS([[WKWebView alloc] init]); >+ [webView setNavigationDelegate:delegate.get()]; >+ [webView setUIDelegate:delegate.get()]; >+ >+ action = _WKUnsafeURLActionShowDefaultWarning; >+ navigationFinished = false; >+ [webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ runJavaScript(webView, getTitle, "Deceptive Website Warning"); >+ >+ action = _WKUnsafeURLActionLoadUnsafeURL; >+ navigationFinished = false; >+ [webView reload]; >+ TestWebKitAPI::Util::run(&navigationFinished); >+ runJavaScript(webView, "document.body.innerHTML.trim()", "Simple HTML file."); >+ >+ action = _WKUnsafeURLActionCancelNavigation; >+ navigationFinished = false; >+ [webView reload]; >+ __block bool noFinishNavigation = false; >+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ >+ EXPECT_FALSE(navigationFinished); >+ noFinishNavigation = true; >+ navigationFinished = true; >+ }); >+ TestWebKitAPI::Util::run(&navigationFinished); >+ EXPECT_TRUE(noFinishNavigation); >+ runJavaScript(webView, "document.body.innerHTML.trim()", "Simple HTML file."); >+ checkBackForwardList(webView, { }, "simple", { }); >+} >+ > @interface NullLookupContext : NSObject > @end > @implementation NullLookupContext >@@ -167,7 +596,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