Expose "allowsContentJavaScript" on WKWebpagePreferences
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Feb 2020 01:35:18 +0000 (01:35 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Feb 2020 01:35:18 +0000 (01:35 +0000)
<rdar://problem/51534967> and https://bugs.webkit.org/show_bug.cgi?id=207427

Reviewed by Darin Adler.

Source/WebCore:

Covered by new API tests.

* dom/Document.cpp:
(WebCore::Document::allowsContentJavaScript const):
* dom/Document.h:

* dom/ScriptableDocumentParser.cpp:
(WebCore::ScriptableDocumentParser::ScriptableDocumentParser):

* loader/FrameLoaderClient.h:
* loader/FrameLoaderTypes.h:

* page/Settings.yaml:

* xml/XMLHttpRequest.cpp: Make sure the context document is set BEFORE we parse the document contents.

Source/WebKit:

This utiizes the pre-existing WebCore::Settings::setScriptMarkupEnabled() mechanism.

This also deprecates the global "disable JavaScript" WKPreference as it doesn't make much sense anymore.

* Shared/WebsitePoliciesData.cpp:
(WebKit::WebsitePoliciesData::encode const):
(WebKit::WebsitePoliciesData::decode):
* Shared/WebsitePoliciesData.h:

* UIProcess/API/APIWebsitePolicies.cpp:
(API::WebsitePolicies::data):
* UIProcess/API/APIWebsitePolicies.h:

* UIProcess/API/Cocoa/WKPreferences.h:
* UIProcess/API/Cocoa/WKPreferences.mm:
(-[WKPreferences encodeWithCoder:]):
(-[WKPreferences initWithCoder:]):
(-[WKPreferences javaScriptEnabled]):
(-[WKPreferences setJavaScriptEnabled:]):

* UIProcess/API/Cocoa/WKWebpagePreferences.h:
* UIProcess/API/Cocoa/WKWebpagePreferences.mm:
(-[WKWebpagePreferences setAllowsContentJavaScript:]):
(-[WKWebpagePreferences allowsContentJavaScript]):

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::allowsContentJavaScriptFromMostRecentNavigation const):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:

* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::didReceivePolicyDecision):

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::updateWebsitePolicies):
(WebKit::WebPage::createDocumentLoader):
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::allowsContentJavaScriptFromMostRecentNavigation const):
(WebKit::WebPage::setAllowsContentJavaScriptFromMostRecentNavigation):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm:
(TEST):
* TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
(-[WebsitePoliciesNavigationDelegate webView:decidePolicyForNavigationAction:preferences:decisionHandler:]):
(TEST):
(-[WebsitePoliciesNavigationDelegate _webView:decidePolicyForNavigationAction:preferences:userInfo:decisionHandler:]): Deleted.
* TestWebKitAPI/cocoa/TestNavigationDelegate.h:
* TestWebKitAPI/cocoa/TestNavigationDelegate.mm:
(-[TestNavigationDelegate webView:decidePolicyForNavigationAction:preferences:decisionHandler:]):
(-[TestNavigationDelegate waitForDidFinishNavigationWithPreferences:]):
(-[WKWebView _test_waitForDidFinishNavigationWithPreferences:]):
(-[TestNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): Deleted.
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[WKWebView synchronouslyLoadHTMLString:preferences:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@256715 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/ScriptableDocumentParser.cpp
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/loader/FrameLoaderTypes.h
Source/WebCore/page/Settings.yaml
Source/WebCore/xml/XMLHttpRequest.cpp
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebsitePoliciesData.cpp
Source/WebKit/Shared/WebsitePoliciesData.h
Source/WebKit/UIProcess/API/APIWebsitePolicies.cpp
Source/WebKit/UIProcess/API/APIWebsitePolicies.h
Source/WebKit/UIProcess/API/Cocoa/WKPreferences.h
Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebpagePreferences.h
Source/WebKit/UIProcess/API/Cocoa/WKWebpagePreferences.mm
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm
Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm
Tools/TestWebKitAPI/cocoa/TestNavigationDelegate.h
Tools/TestWebKitAPI/cocoa/TestNavigationDelegate.mm
Tools/TestWebKitAPI/cocoa/TestWKWebView.h
Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

index ca3b93c..802227e 100644 (file)
@@ -1,3 +1,26 @@
+2020-02-16  Brady Eidson  <beidson@apple.com>
+
+        Expose "allowsContentJavaScript" on WKWebpagePreferences
+        <rdar://problem/51534967> and https://bugs.webkit.org/show_bug.cgi?id=207427
+
+        Reviewed by Darin Adler.
+
+        Covered by new API tests.
+
+        * dom/Document.cpp:
+        (WebCore::Document::allowsContentJavaScript const):
+        * dom/Document.h:
+        
+        * dom/ScriptableDocumentParser.cpp:
+        (WebCore::ScriptableDocumentParser::ScriptableDocumentParser):
+        
+        * loader/FrameLoaderClient.h:
+        * loader/FrameLoaderTypes.h:
+        
+        * page/Settings.yaml:
+        
+        * xml/XMLHttpRequest.cpp: Make sure the context document is set BEFORE we parse the document contents.
+
 2020-02-16  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][Float] Simplify BlockFormattingContext::usedAvailableWidthForFloatAvoider
index 5142999..02a6534 100644 (file)
@@ -6812,6 +6812,21 @@ DocumentLoader* Document::loader() const
     return loader;
 }
 
+bool Document::allowsContentJavaScript() const
+{
+    // FIXME: Get all SPI clients off of this potentially dangerous Setting.
+    if (!settings().scriptMarkupEnabled())
+        return false;
+
+    if (!m_frame || m_frame->document() != this) {
+        // If this Document is frameless or in the wrong frame, its context document
+        // must allow for it to run content JavaScript.
+        return m_contextDocument && m_contextDocument->allowsContentJavaScript();
+    }
+
+    return m_frame->loader().client().allowsContentJavaScriptFromMostRecentNavigation() == AllowsContentJavaScript::Yes;
+}
+
 Element* eventTargetElementForDocument(Document* document)
 {
     if (!document)
index 4bee2bb..6f1f145 100644 (file)
@@ -1551,6 +1551,8 @@ public:
     HighlightMap& highlightMap();
     void updateHighlightPositions();
 
+    bool allowsContentJavaScript() const;
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
index 95028bb..06539dd 100644 (file)
@@ -41,7 +41,7 @@ ScriptableDocumentParser::ScriptableDocumentParser(Document& document, ParserCon
     if (!pluginContentIsAllowed(m_parserContentPolicy))
         m_parserContentPolicy = allowPluginContent(m_parserContentPolicy);
 
-    if (scriptingContentIsAllowed(m_parserContentPolicy) && !document.settings().scriptMarkupEnabled())
+    if (scriptingContentIsAllowed(m_parserContentPolicy) && !document.allowsContentJavaScript())
         m_parserContentPolicy = disallowScriptingContent(m_parserContentPolicy);
 }
 
index 98d02cf..5c8abb6 100644 (file)
@@ -377,6 +377,8 @@ public:
     virtual bool hasFrameSpecificStorageAccess() { return false; }
     virtual void addLoadedRegistrableDomain(RegistrableDomain&&) { }
 #endif
+
+    virtual AllowsContentJavaScript allowsContentJavaScriptFromMostRecentNavigation() const { return AllowsContentJavaScript::Yes; }
 };
 
 } // namespace WebCore
index 8d8628a..41e6d33 100644 (file)
@@ -227,6 +227,11 @@ enum class LoadCompletionType : uint8_t {
     Cancel
 };
 
+enum class AllowsContentJavaScript : uint8_t {
+    Yes,
+    No,
+};
+
 } // namespace WebCore
 
 namespace WTF {
@@ -266,4 +271,12 @@ template<> struct EnumTraits<WebCore::ShouldOpenExternalURLsPolicy> {
     >;
 };
 
+template<> struct EnumTraits<WebCore::AllowsContentJavaScript> {
+    using values = EnumValues<
+        WebCore::AllowsContentJavaScript,
+        WebCore::AllowsContentJavaScript::Yes,
+        WebCore::AllowsContentJavaScript::No
+    >;
+};
+
 } // namespace WTF
index 8b9951c..fd90164 100644 (file)
@@ -197,8 +197,6 @@ forceFTPDirectoryListings:
   initial: false
 developerExtrasEnabled:
   initial: false
-scriptMarkupEnabled:
-  initial: true
 needsSiteSpecificQuirks:
   initial: false
   inspectorOverride: true
@@ -947,3 +945,7 @@ mediaCaptureRequiresSecureConnection:
 
 shouldUseServiceWorkerShortTimeout:
   initial: false
+
+# Clients should use per-navigation "allowsContentJavaScript" policies instead
+scriptMarkupEnabled:
+    initial: true
index 39d8ca5..246a4fc 100644 (file)
@@ -188,10 +188,10 @@ ExceptionOr<Document*> XMLHttpRequest::responseXML()
             else
                 m_responseDocument = XMLDocument::create(nullptr, m_response.url());
             m_responseDocument->overrideLastModified(m_response.lastModified());
-            m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity());
             m_responseDocument->setContextDocument(context);
             m_responseDocument->setSecurityOriginPolicy(context.securityOriginPolicy());
             m_responseDocument->overrideMIMEType(mimeType);
+            m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity());
 
             if (!m_responseDocument->wellFormed())
                 m_responseDocument = nullptr;
index 2d3910e..0132bab 100644 (file)
@@ -1,3 +1,49 @@
+2020-02-16  Brady Eidson  <beidson@apple.com>
+
+        Expose "allowsContentJavaScript" on WKWebpagePreferences
+        <rdar://problem/51534967> and https://bugs.webkit.org/show_bug.cgi?id=207427
+
+        Reviewed by Darin Adler.
+
+        This utiizes the pre-existing WebCore::Settings::setScriptMarkupEnabled() mechanism.
+        
+        This also deprecates the global "disable JavaScript" WKPreference as it doesn't make much sense anymore.
+
+        * Shared/WebsitePoliciesData.cpp:
+        (WebKit::WebsitePoliciesData::encode const):
+        (WebKit::WebsitePoliciesData::decode):
+        * Shared/WebsitePoliciesData.h:
+
+        * UIProcess/API/APIWebsitePolicies.cpp:
+        (API::WebsitePolicies::data):
+        * UIProcess/API/APIWebsitePolicies.h:
+
+        * UIProcess/API/Cocoa/WKPreferences.h:
+        * UIProcess/API/Cocoa/WKPreferences.mm:
+        (-[WKPreferences encodeWithCoder:]):
+        (-[WKPreferences initWithCoder:]):
+        (-[WKPreferences javaScriptEnabled]):
+        (-[WKPreferences setJavaScriptEnabled:]):
+
+        * UIProcess/API/Cocoa/WKWebpagePreferences.h:
+        * UIProcess/API/Cocoa/WKWebpagePreferences.mm:
+        (-[WKWebpagePreferences setAllowsContentJavaScript:]):
+        (-[WKWebpagePreferences allowsContentJavaScript]):
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::allowsContentJavaScriptFromMostRecentNavigation const):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::WebFrame::didReceivePolicyDecision):
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::updateWebsitePolicies):
+        (WebKit::WebPage::createDocumentLoader):
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::allowsContentJavaScriptFromMostRecentNavigation const):
+        (WebKit::WebPage::setAllowsContentJavaScriptFromMostRecentNavigation):
+
 2020-02-15  Pavel Feldman  <pavel.feldman@gmail.com>
 
         [Geoclue] Avoid usage of provider in callbacks after it has been destroyed
index 948f2a5..bd64acc 100644 (file)
@@ -54,6 +54,7 @@ void WebsitePoliciesData::encode(IPC::Encoder& encoder) const
     encoder << simulatedMouseEventsDispatchPolicy;
     encoder << legacyOverflowScrollingTouchPolicy;
     encoder << allowContentChangeObserverQuirk;
+    encoder << allowsContentJavaScript;
 }
 
 Optional<WebsitePoliciesData> WebsitePoliciesData::decode(IPC::Decoder& decoder)
@@ -134,7 +135,12 @@ Optional<WebsitePoliciesData> WebsitePoliciesData::decode(IPC::Decoder& decoder)
     decoder >> allowContentChangeObserverQuirk;
     if (!allowContentChangeObserverQuirk)
         return WTF::nullopt;
-    
+
+    Optional<WebCore::AllowsContentJavaScript> allowsContentJavaScript;
+    decoder >> allowsContentJavaScript;
+    if (!allowsContentJavaScript)
+        return WTF::nullopt;
+
     return { {
         WTFMove(*contentBlockersEnabled),
         WTFMove(*allowedAutoplayQuirks),
@@ -153,6 +159,7 @@ Optional<WebsitePoliciesData> WebsitePoliciesData::decode(IPC::Decoder& decoder)
         WTFMove(*simulatedMouseEventsDispatchPolicy),
         WTFMove(*legacyOverflowScrollingTouchPolicy),
         WTFMove(*allowContentChangeObserverQuirk),
+        WTFMove(*allowsContentJavaScript),
     } };
 }
 
index 979573d..0869c84 100644 (file)
@@ -35,6 +35,7 @@
 #include "WebsiteSimulatedMouseEventsDispatchPolicy.h"
 #include <WebCore/CustomHeaderFields.h>
 #include <WebCore/DeviceOrientationOrMotionPermissionState.h>
+#include <WebCore/FrameLoaderTypes.h>
 #include <wtf/OptionSet.h>
 
 namespace IPC {
@@ -68,6 +69,7 @@ struct WebsitePoliciesData {
     WebsiteSimulatedMouseEventsDispatchPolicy simulatedMouseEventsDispatchPolicy { WebsiteSimulatedMouseEventsDispatchPolicy::Default };
     WebsiteLegacyOverflowScrollingTouchPolicy legacyOverflowScrollingTouchPolicy { WebsiteLegacyOverflowScrollingTouchPolicy::Default };
     bool allowContentChangeObserverQuirk { false };
+    WebCore::AllowsContentJavaScript allowsContentJavaScript { WebCore::AllowsContentJavaScript::Yes };
 
     void encode(IPC::Encoder&) const;
     static Optional<WebsitePoliciesData> decode(IPC::Decoder&);
index e71e3b3..7f78aaa 100644 (file)
@@ -117,6 +117,7 @@ WebKit::WebsitePoliciesData WebsitePolicies::data()
         m_simulatedMouseEventsDispatchPolicy,
         m_legacyOverflowScrollingTouchPolicy,
         m_allowContentChangeObserverQuirk,
+        m_allowsContentJavaScript, 
     };
 }
 
index 9463e53..18b2435 100644 (file)
@@ -36,6 +36,7 @@
 #include "WebsiteSimulatedMouseEventsDispatchPolicy.h"
 #include <WebCore/CustomHeaderFields.h>
 #include <WebCore/DeviceOrientationOrMotionPermissionState.h>
+#include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/HTTPHeaderField.h>
 #include <wtf/OptionSet.h>
 #include <wtf/Vector.h>
@@ -116,6 +117,9 @@ public:
     bool allowContentChangeObserverQuirk() const { return m_allowContentChangeObserverQuirk; }
     void setAllowContentChangeObserverQuirk(bool allow) { m_allowContentChangeObserverQuirk = allow; }
 
+    WebCore::AllowsContentJavaScript allowsContentJavaScript() const { return m_allowsContentJavaScript; }
+    void setAllowsContentJavaScript(WebCore::AllowsContentJavaScript allows) { m_allowsContentJavaScript = allows; }
+
 private:
     WebsitePolicies(bool contentBlockersEnabled, OptionSet<WebKit::WebsiteAutoplayQuirk>, WebKit::WebsiteAutoplayPolicy, Vector<WebCore::HTTPHeaderField>&&, Vector<WebCore::CustomHeaderFields>&&, WebKit::WebsitePopUpPolicy, RefPtr<WebKit::WebsiteDataStore>&&);
 
@@ -140,6 +144,7 @@ private:
     bool m_allowSiteSpecificQuirksToOverrideContentMode { false };
     WTF::String m_applicationNameForDesktopUserAgent;
     bool m_allowContentChangeObserverQuirk { false };
+    WebCore::AllowsContentJavaScript m_allowsContentJavaScript { WebCore::AllowsContentJavaScript::Yes };
 };
 
 } // namespace API
index 50a82f7..89686da 100644 (file)
@@ -40,11 +40,6 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
  */
 @property (nonatomic) CGFloat minimumFontSize;
 
-/*! @abstract A Boolean value indicating whether JavaScript is enabled.
- @discussion The default value is YES.
- */
-@property (nonatomic) BOOL javaScriptEnabled;
-
 /*! @abstract A Boolean value indicating whether JavaScript can open
  windows without user interaction.
  @discussion The default value is NO in iOS and YES in OS X.
@@ -71,7 +66,11 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
 
 @interface WKPreferences (WKDeprecated)
 
+#if !TARGET_OS_IPHONE
 @property (nonatomic) BOOL javaEnabled WK_API_DEPRECATED("Java is no longer supported", macos(10.10, 10.15));
 @property (nonatomic) BOOL plugInsEnabled WK_API_DEPRECATED("Plug-ins are no longer supported", macos(10.10, 10.15));
+#endif
+
+@property (nonatomic) BOOL javaScriptEnabled WK_API_DEPRECATED("Use WKWebPagePreferences.allowsJavaScriptMarkup to disable JavaScript markup on a per-navigation basis", macos(10.10, WK_MAC_TBA), ios(8.0, WK_IOS_TBA));
 
 @end
index 54218a4..142011f 100644 (file)
 - (void)encodeWithCoder:(NSCoder *)coder
 {
     [coder encodeDouble:self.minimumFontSize forKey:@"minimumFontSize"];
-    [coder encodeBool:self.javaScriptEnabled forKey:@"javaScriptEnabled"];
     [coder encodeBool:self.javaScriptCanOpenWindowsAutomatically forKey:@"javaScriptCanOpenWindowsAutomatically"];
 
+ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    [coder encodeBool:self.javaScriptEnabled forKey:@"javaScriptEnabled"];
+ALLOW_DEPRECATED_DECLARATIONS_END
+
 #if PLATFORM(MAC)
 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     [coder encodeBool:self.javaEnabled forKey:@"javaEnabled"];
@@ -83,9 +86,12 @@ ALLOW_DEPRECATED_DECLARATIONS_END
         return nil;
 
     self.minimumFontSize = [coder decodeDoubleForKey:@"minimumFontSize"];
-    self.javaScriptEnabled = [coder decodeBoolForKey:@"javaScriptEnabled"];
     self.javaScriptCanOpenWindowsAutomatically = [coder decodeBoolForKey:@"javaScriptCanOpenWindowsAutomatically"];
 
+ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    self.javaScriptEnabled = [coder decodeBoolForKey:@"javaScriptEnabled"];
+ALLOW_DEPRECATED_DECLARATIONS_END
+
 #if PLATFORM(MAC)
 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     self.javaEnabled = [coder decodeBoolForKey:@"javaEnabled"];
@@ -112,16 +118,6 @@ ALLOW_DEPRECATED_DECLARATIONS_END
     _preferences->setMinimumFontSize(minimumFontSize);
 }
 
-- (BOOL)javaScriptEnabled
-{
-    return _preferences->javaScriptEnabled();
-}
-
-- (void)setJavaScriptEnabled:(BOOL)javaScriptEnabled
-{
-    _preferences->setJavaScriptEnabled(javaScriptEnabled);
-}
-
 - (void)setFraudulentWebsiteWarningEnabled:(BOOL)enabled
 {
     _preferences->setSafeBrowsingEnabled(enabled);
@@ -1432,10 +1428,11 @@ static WebCore::EditableLinkBehavior toEditableLinkBehavior(_WKEditableLinkBehav
 
 @end
 
-#if !TARGET_OS_IPHONE
 
 @implementation WKPreferences (WKDeprecated)
 
+#if !TARGET_OS_IPHONE
+
 - (BOOL)javaEnabled
 {
     return _preferences->javaEnabled();
@@ -1456,6 +1453,17 @@ static WebCore::EditableLinkBehavior toEditableLinkBehavior(_WKEditableLinkBehav
     _preferences->setPluginsEnabled(plugInsEnabled);
 }
 
+#endif
+
+- (BOOL)javaScriptEnabled
+{
+    return _preferences->javaScriptEnabled();
+}
+
+- (void)setJavaScriptEnabled:(BOOL)javaScriptEnabled
+{
+    _preferences->setJavaScriptEnabled(javaScriptEnabled);
+}
+
 @end
 
-#endif
index 2747e81..cac1956 100644 (file)
@@ -57,4 +57,19 @@ WK_CLASS_AVAILABLE(macos(10.15), ios(13.0))
  */
 @property (nonatomic) WKContentMode preferredContentMode WK_API_AVAILABLE(ios(13.0));
 
+/* @abstract A Boolean value indicating whether JavaScript from web content is enabled
+ @discussion If this value is set to NO then JavaScript referenced by the web content will not execute.
+ This includes JavaScript found in inline <script> elements, referenced by external JavaScript resources,
+ "javascript:" URLs, and all other forms.
+
+ Even if this value is set to NO your application can still execute JavaScript using:
+ - [WKWebView evaluteJavaScript:completionHandler:]
+ - [WKWebView evaluteJavaScript:inContentWorld:completionHandler:]
+ - [WKWebView callAsyncJavaScript:arguments:inContentWorld:completionHandler:]
+ - WKUserScripts
+
+ The default value is YES.
+*/
+@property (nonatomic) BOOL allowsContentJavaScript WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
index 99f0c0a..03f3671 100644 (file)
@@ -331,6 +331,21 @@ static _WKWebsiteDeviceOrientationAndMotionAccessPolicy toWKWebsiteDeviceOrienta
     return *_websitePolicies;
 }
 
+- (void)setAllowsContentJavaScript:(BOOL)allowsContentJavaScript
+{
+    _websitePolicies->setAllowsContentJavaScript(allowsContentJavaScript ? WebCore::AllowsContentJavaScript::Yes : WebCore::AllowsContentJavaScript::No);
+}
+
+- (BOOL)allowsContentJavaScript
+{
+    switch (_websitePolicies->allowsContentJavaScript()) {
+    case WebCore::AllowsContentJavaScript::Yes:
+        return YES;
+    case WebCore::AllowsContentJavaScript::No:
+        return NO;
+    }
+}
+
 #if PLATFORM(IOS_FAMILY)
 
 - (void)setPreferredContentMode:(WKContentMode)contentMode
index cfb3d43..7788e6e 100644 (file)
@@ -895,6 +895,12 @@ void WebFrameLoaderClient::applyToDocumentLoader(WebsitePoliciesData&& websitePo
     WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader);
 }
 
+WebCore::AllowsContentJavaScript WebFrameLoaderClient::allowsContentJavaScriptFromMostRecentNavigation() const
+{
+    WebPage* webPage = m_frame ? m_frame->page() : nullptr;
+    return webPage ? webPage->allowsContentJavaScriptFromMostRecentNavigation() : WebCore::AllowsContentJavaScript::No;
+}
+
 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, const ResourceResponse& redirectResponse,
     FormState* formState, PolicyDecisionMode policyDecisionMode, WebCore::PolicyCheckIdentifier requestIdentifier, FramePolicyFunction&& function)
 {
index e377b81..db88198 100644 (file)
@@ -63,7 +63,9 @@ public:
     void setHasFrameSpecificStorageAccess(FrameSpecificStorageAccessIdentifier&&);
     void addLoadedRegistrableDomain(WebCore::RegistrableDomain&&) final;
 #endif
-    
+
+    WebCore::AllowsContentJavaScript allowsContentJavaScriptFromMostRecentNavigation() const final;
+
 private:
     void frameLoaderDestroyed() final;
 
index f6c984e..2e0a405 100644 (file)
@@ -265,8 +265,12 @@ void WebFrame::didReceivePolicyDecision(uint64_t listenerID, WebCore::PolicyChec
 
     invalidatePolicyListener();
 
-    if (forNavigationAction && m_frameLoaderClient && websitePolicies)
+    if (forNavigationAction && m_frameLoaderClient && websitePolicies) {
+        ASSERT(page());
+        if (page())
+            page()->setAllowsContentJavaScriptFromMostRecentNavigation(websitePolicies->allowsContentJavaScript);
         m_frameLoaderClient->applyToDocumentLoader(WTFMove(*websitePolicies));
+    }
 
     m_policyDownloadID = downloadID;
     if (navigationID) {
index aa99e9d..8683c10 100644 (file)
@@ -6264,6 +6264,7 @@ void WebPage::updateWebsitePolicies(WebsitePoliciesData&& websitePolicies)
     if (!documentLoader)
         return;
 
+    m_allowsContentJavaScriptFromMostRecentNavigation = websitePolicies.allowsContentJavaScript;
     WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader);
     
 #if ENABLE(VIDEO)
@@ -6319,6 +6320,7 @@ Ref<DocumentLoader> WebPage::createDocumentLoader(Frame& frame, const ResourceRe
         }
 
         if (m_pendingWebsitePolicies) {
+            m_allowsContentJavaScriptFromMostRecentNavigation = m_pendingWebsitePolicies->allowsContentJavaScript;
             WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader);
             m_pendingWebsitePolicies = WTF::nullopt;
         }
index 76d04a0..b33113d 100644 (file)
@@ -1278,7 +1278,10 @@ public:
 
     const String& overriddenMediaType() const { return m_overriddenMediaType; }
     void setOverriddenMediaType(const String&);
-    
+
+    WebCore::AllowsContentJavaScript allowsContentJavaScriptFromMostRecentNavigation() const { return m_allowsContentJavaScriptFromMostRecentNavigation; }
+    void setAllowsContentJavaScriptFromMostRecentNavigation(WebCore::AllowsContentJavaScript allows) { m_allowsContentJavaScriptFromMostRecentNavigation = allows; }
+
 private:
     WebPage(WebCore::PageIdentifier, WebPageCreationParameters&&);
 
@@ -2053,6 +2056,7 @@ private:
 #endif
 
     String m_overriddenMediaType;
+    WebCore::AllowsContentJavaScript m_allowsContentJavaScriptFromMostRecentNavigation { WebCore::AllowsContentJavaScript::Yes };
 
 #if PLATFORM(GTK)
     String m_themeName;
index 3f17345..baac57c 100644 (file)
@@ -1,3 +1,26 @@
+2020-02-16  Brady Eidson  <beidson@apple.com>
+
+        Expose "allowsContentJavaScript" on WKWebpagePreferences
+        <rdar://problem/51534967> and https://bugs.webkit.org/show_bug.cgi?id=207427
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm:
+        (TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
+        (-[WebsitePoliciesNavigationDelegate webView:decidePolicyForNavigationAction:preferences:decisionHandler:]):
+        (TEST):
+        (-[WebsitePoliciesNavigationDelegate _webView:decidePolicyForNavigationAction:preferences:userInfo:decisionHandler:]): Deleted.
+        * TestWebKitAPI/cocoa/TestNavigationDelegate.h:
+        * TestWebKitAPI/cocoa/TestNavigationDelegate.mm:
+        (-[TestNavigationDelegate webView:decidePolicyForNavigationAction:preferences:decisionHandler:]):
+        (-[TestNavigationDelegate waitForDidFinishNavigationWithPreferences:]):
+        (-[WKWebView _test_waitForDidFinishNavigationWithPreferences:]):
+        (-[TestNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): Deleted.
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[WKWebView synchronouslyLoadHTMLString:preferences:]):
+
 2020-02-14  Yusuke Suzuki  <ysuzuki@apple.com>
 
         NetworkLoadMetrics should be shared by multiple ResourceResponse instances
index fc03375..5377bba 100644 (file)
 #import "config.h"
 #import <WebKit/WKFoundation.h>
 
+#import "HTTPServer.h"
 #import "PlatformUtilities.h"
 #import "TCPServer.h"
 #import "Test.h"
 #import "TestNavigationDelegate.h"
 #import "TestWKWebView.h"
+#import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WKContentWorld.h>
 #import <WebKit/WKErrorPrivate.h>
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKPreferencesRef.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 
@@ -254,3 +258,114 @@ TEST(WebKit, EvaluateJavaScriptInAttachments)
     TestWebKitAPI::Util::run(&done);
 }
 
+TEST(WebKit, AllowsContentJavaScript)
+{
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+    [webView synchronouslyLoadHTMLString:@"<script>var foo = 'bar'</script>"];
+
+    __block bool done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
+        EXPECT_TRUE([result isEqualToString:@"bar"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    RetainPtr<WKWebpagePreferences> preferences = adoptNS([[WKWebpagePreferences alloc] init]);
+    EXPECT_TRUE(preferences.get().allowsContentJavaScript);
+    preferences.get().allowsContentJavaScript = NO;
+    [webView synchronouslyLoadHTMLString:@"<script>var foo = 'bar'</script>" preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(result);
+        EXPECT_TRUE([[error description] containsString:@"Can't find variable: foo"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    TestWebKitAPI::HTTPServer server({
+        { "/script", { "var foo = 'bar'" } }
+    });
+    preferences.get().allowsContentJavaScript = YES;
+    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<script src='http://127.0.0.1:%d/script'></script>", server.port()] preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
+        EXPECT_TRUE([result isEqualToString:@"bar"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    preferences.get().allowsContentJavaScript = NO;
+    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<script src='http://127.0.0.1:%d/script'></script>", server.port()] preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(result);
+        EXPECT_TRUE([[error description] containsString:@"Can't find variable: foo"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    preferences.get().allowsContentJavaScript = YES;
+    [webView synchronouslyLoadHTMLString:@"<iframe src='javascript:window.foo = 1'></iframe>" preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"window.frames[0].foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSNumber class]]);
+        EXPECT_TRUE([result isEqualToNumber:@1]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    preferences.get().allowsContentJavaScript = NO;
+    [webView synchronouslyLoadHTMLString:@"<iframe src='javascript:window.foo = 1'></iframe>" preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"window.frames[0].foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(result);
+        EXPECT_NULL(error);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
+TEST(WebKit, SPIJavascriptMarkupVsAPIContentJavaScript)
+{
+    // There's not a dynamically configuration setting for javascript markup,
+    // but it can be configured at WKWebView creation time.
+    WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease];
+    configuration._allowsJavaScriptMarkup = NO;
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
+
+    // Verify that the following JS does not execute.
+    [webView synchronouslyLoadHTMLString:@"<script>var foo = 'bar'</script>"];
+
+    __block bool done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(result);
+        EXPECT_TRUE([[error description] containsString:@"Can't find variable: foo"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    // Try to explicitly enable script markup using WKWebpagePreferences, but verify it should still fail because
+    // of the above configuration setting.
+    RetainPtr<WKWebpagePreferences> preferences = adoptNS([[WKWebpagePreferences alloc] init]);
+    EXPECT_TRUE(preferences.get().allowsContentJavaScript);
+    [webView synchronouslyLoadHTMLString:@"<script>var foo = 'bar'</script>" preferences:preferences.get()];
+
+    done = false;
+    [webView evaluateJavaScript:@"foo" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(result);
+        EXPECT_TRUE([[error description] containsString:@"Can't find variable: foo"]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+}
index dd79c5d..0976b36 100644 (file)
@@ -239,15 +239,15 @@ TEST(WebpagePreferences, WebsitePoliciesContentBlockersEnabled)
 @end
 
 @interface WebsitePoliciesNavigationDelegate : TestNavigationDelegate <WKNavigationDelegatePrivate>
-@property (nonatomic, copy) void (^decidePolicyForNavigationActionWithWebsitePolicies)(WKNavigationAction *, WKWebpagePreferences *, id <NSSecureCoding>, void (^)(WKNavigationActionPolicy, WKWebpagePreferences *));
+@property (nonatomic, copy) void (^decidePolicyForNavigationActionWithWebsitePolicies)(WKNavigationAction *, WKWebpagePreferences *, void (^)(WKNavigationActionPolicy, WKWebpagePreferences *));
 @end
 
 @implementation WebsitePoliciesNavigationDelegate
 
-- (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences userInfo:(id <NSSecureCoding>)userInfo decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler
 {
     if (_decidePolicyForNavigationActionWithWebsitePolicies)
-        _decidePolicyForNavigationActionWithWebsitePolicies(navigationAction, preferences, userInfo, decisionHandler);
+        _decidePolicyForNavigationActionWithWebsitePolicies(navigationAction, preferences, decisionHandler);
     else
         decisionHandler(WKNavigationActionPolicyAllow, nil);
 }
@@ -616,7 +616,7 @@ TEST(WebpagePreferences, WebsitePoliciesWithBridgingCast)
     auto delegate = adoptNS([[WebsitePoliciesNavigationDelegate alloc] init]);
 
     __block bool didInvokeDecisionHandler = false;
-    [delegate setDecidePolicyForNavigationActionWithWebsitePolicies:^(WKNavigationAction *, WKWebpagePreferences *, id <NSSecureCoding>, void (^decisionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
+    [delegate setDecidePolicyForNavigationActionWithWebsitePolicies:^(WKNavigationAction *, WKWebpagePreferences *, void (^decisionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
         auto policies = adoptWK(WKWebsitePoliciesCreate());
         decisionHandler(WKNavigationActionPolicyAllow, (__bridge WKWebpagePreferences *)policies.get());
         didInvokeDecisionHandler = true;
@@ -635,7 +635,7 @@ TEST(WebpagePreferences, WebsitePoliciesWithUnexpectedType)
     auto delegate = adoptNS([[WebsitePoliciesNavigationDelegate alloc] init]);
 
     __block bool didCatchException = false;
-    [delegate setDecidePolicyForNavigationActionWithWebsitePolicies:^(WKNavigationAction *, WKWebpagePreferences *, id <NSSecureCoding>, void (^decisionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
+    [delegate setDecidePolicyForNavigationActionWithWebsitePolicies:^(WKNavigationAction *, WKWebpagePreferences *, void (^decisionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
         @try {
             id fakePolicies = @"Hello";
             decisionHandler(WKNavigationActionPolicyAllow, (WKWebpagePreferences *)fakePolicies);
index 223201b..b647229 100644 (file)
@@ -31,6 +31,7 @@
 @interface TestNavigationDelegate : NSObject <WKNavigationDelegate>
 
 @property (nonatomic, copy) void (^decidePolicyForNavigationAction)(WKNavigationAction *, void (^)(WKNavigationActionPolicy));
+@property (nonatomic, copy) void (^decidePolicyForNavigationActionWithPreferences)(WKNavigationAction *, WKWebpagePreferences *, void (^)(WKNavigationActionPolicy, WKWebpagePreferences *));
 @property (nonatomic, copy) void (^didFailProvisionalNavigation)(WKWebView *, WKNavigation *, NSError *);
 @property (nonatomic, copy) void (^didStartProvisionalNavigation)(WKWebView *, WKNavigation *);
 @property (nonatomic, copy) void (^didCommitNavigation)(WKWebView *, WKNavigation *);
@@ -41,6 +42,7 @@
 
 - (void)waitForDidStartProvisionalNavigation;
 - (void)waitForDidFinishNavigation;
+- (void)waitForDidFinishNavigationWithPreferences:(WKWebpagePreferences *)preferences;
 - (void)waitForDidFailProvisionalNavigation;
 
 @end
@@ -48,5 +50,6 @@
 @interface WKWebView (TestWebKitAPIExtras)
 - (void)_test_waitForDidStartProvisionalNavigation;
 - (void)_test_waitForDidFinishNavigation;
+- (void)_test_waitForDidFinishNavigationWithPreferences:(WKWebpagePreferences *)preferences;
 - (void)_test_waitForDidFinishNavigationWithoutPresentationUpdate;
 @end
index 33e211b..bdc5175 100644 (file)
 
 @implementation TestNavigationDelegate
 
-- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler
 {
-    if (_decidePolicyForNavigationAction)
-        _decidePolicyForNavigationAction(navigationAction, decisionHandler);
-    else
-        decisionHandler(WKNavigationActionPolicyAllow);
+    if (_decidePolicyForNavigationActionWithPreferences)
+        _decidePolicyForNavigationActionWithPreferences(navigationAction, preferences, decisionHandler);
+    else if (_decidePolicyForNavigationAction) {
+        _decidePolicyForNavigationAction(navigationAction, ^(WKNavigationActionPolicy action) {
+            decisionHandler(action, preferences);
+        });
+    } else
+        decisionHandler(WKNavigationActionPolicyAllow, preferences);
 }
 
 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
     self.didFinishNavigation = nil;
 }
 
+- (void)waitForDidFinishNavigationWithPreferences:(WKWebpagePreferences *)preferences
+{
+    EXPECT_FALSE(self.decidePolicyForNavigationActionWithPreferences);
+    EXPECT_TRUE(!!preferences);
+
+    self.decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *, void (^handler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
+        handler(WKNavigationActionPolicyAllow, preferences);
+    };
+
+    [self waitForDidFinishNavigation];
+    self.decidePolicyForNavigationActionWithPreferences = nil;
+}
+
 - (void)waitForDidFailProvisionalNavigation
 {
     EXPECT_FALSE(self.didFailProvisionalNavigation);
     self.navigationDelegate = nil;
 }
 
+- (void)_test_waitForDidFinishNavigationWithPreferences:(WKWebpagePreferences *)preferences
+{
+    EXPECT_FALSE(self.navigationDelegate);
+
+    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
+    self.navigationDelegate = navigationDelegate.get();
+    [navigationDelegate waitForDidFinishNavigationWithPreferences:preferences];
+
+    self.navigationDelegate = nil;
+}
+
 - (void)_test_waitForDidFinishNavigation
 {
     EXPECT_FALSE(self.navigationDelegate);
index d8e75dc..c1620ce 100644 (file)
@@ -54,6 +54,7 @@
 - (void)synchronouslyGoForward;
 - (void)synchronouslyLoadHTMLString:(NSString *)html;
 - (void)synchronouslyLoadHTMLString:(NSString *)html baseURL:(NSURL *)url;
+- (void)synchronouslyLoadHTMLString:(NSString *)html preferences:(WKWebpagePreferences *)preferences;
 - (void)synchronouslyLoadRequest:(NSURLRequest *)request;
 - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName;
 - (BOOL)_synchronouslyExecuteEditCommand:(NSString *)command argument:(NSString *)argument;
index cabb2c3..35600b7 100644 (file)
@@ -122,6 +122,12 @@ static NSString *overrideBundleIdentifier(id, SEL)
     [self synchronouslyLoadHTMLString:html baseURL:[[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"TestWebKitAPI.resources"]];
 }
 
+- (void)synchronouslyLoadHTMLString:(NSString *)html preferences:(WKWebpagePreferences *)preferences
+{
+    [self loadHTMLString:html baseURL:[[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"TestWebKitAPI.resources"]];
+    [self _test_waitForDidFinishNavigationWithPreferences:preferences];
+}
+
 - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName
 {
     [self loadTestPageNamed:pageName];