- Revision
- 258863
- Author
- [email protected]
- Date
- 2020-03-23 11:47:48 -0700 (Mon, 23 Mar 2020)
Log Message
Add checks for app-bound navigations when evaluating user style sheets
https://bugs.webkit.org/show_bug.cgi?id=209368
<rdar://problem/60204230>
Reviewed by Brent Fulgham.
Source/WebCore:
* page/Page.cpp:
(WebCore::Page::injectUserStyleSheet):
If the style sheet is for a specific WebView, it will have a pageID
and we can check for app-bound navigation in the page object.
* style/StyleScopeRuleSets.cpp:
(WebCore::Style::ScopeRuleSets::initializeUserStyle):
If the user style sheet is being applied to all WebViews, we can check for
for a page's existence and navigation state here before the style sheet is
updated.
Tools:
Tested cases based on those in UserContentController.mm.
* TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
(-[InAppBrowserSchemeHandler webView:startURLSchemeTask:]):
(expectScriptEvaluatesToColor):
(TEST):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (258862 => 258863)
--- trunk/Source/WebCore/ChangeLog 2020-03-23 18:40:03 UTC (rev 258862)
+++ trunk/Source/WebCore/ChangeLog 2020-03-23 18:47:48 UTC (rev 258863)
@@ -1,3 +1,22 @@
+2020-03-23 Kate Cheney <[email protected]>
+
+ Add checks for app-bound navigations when evaluating user style sheets
+ https://bugs.webkit.org/show_bug.cgi?id=209368
+ <rdar://problem/60204230>
+
+ Reviewed by Brent Fulgham.
+
+ * page/Page.cpp:
+ (WebCore::Page::injectUserStyleSheet):
+ If the style sheet is for a specific WebView, it will have a pageID
+ and we can check for app-bound navigation in the page object.
+
+ * style/StyleScopeRuleSets.cpp:
+ (WebCore::Style::ScopeRuleSets::initializeUserStyle):
+ If the user style sheet is being applied to all WebViews, we can check for
+ for a page's existence and navigation state here before the style sheet is
+ updated.
+
2020-03-23 Antoine Quint <[email protected]>
DocumentTimeline / CSSTransition objects are leaking on CNN.com
Modified: trunk/Source/WebCore/page/Page.cpp (258862 => 258863)
--- trunk/Source/WebCore/page/Page.cpp 2020-03-23 18:40:03 UTC (rev 258862)
+++ trunk/Source/WebCore/page/Page.cpp 2020-03-23 18:47:48 UTC (rev 258863)
@@ -3075,6 +3075,12 @@
void Page::injectUserStyleSheet(UserStyleSheet& userStyleSheet)
{
+ if (m_mainFrame->loader().client().hasNavigatedAwayFromAppBoundDomain()) {
+ if (auto* document = m_mainFrame->document())
+ document->addConsoleMessage(MessageSource::Security, MessageLevel::Warning, "Ignoring user style sheet for non-app bound domain."_s);
+ return;
+ }
+
// We need to wait until we're no longer displaying the initial empty document before we can inject the stylesheets.
if (m_mainFrame->loader().stateMachine().isDisplayingInitialEmptyDocument()) {
m_userStyleSheetsPendingInjection.append(userStyleSheet);
Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.cpp (258862 => 258863)
--- trunk/Source/WebCore/style/StyleScopeRuleSets.cpp 2020-03-23 18:40:03 UTC (rev 258862)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.cpp 2020-03-23 18:47:48 UTC (rev 258863)
@@ -31,7 +31,11 @@
#include "CSSStyleSheet.h"
#include "ExtensionStyleSheets.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
#include "MediaQueryEvaluator.h"
+#include "Page.h"
#include "StyleResolver.h"
#include "StyleSheetContents.h"
@@ -87,7 +91,11 @@
auto tempUserStyle = RuleSet::create();
if (CSSStyleSheet* pageUserSheet = extensionStyleSheets.pageUserSheet())
tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), nullptr, mediaQueryEvaluator, m_styleResolver);
- collectRulesFromUserStyleSheets(extensionStyleSheets.injectedUserStyleSheets(), tempUserStyle.get(), mediaQueryEvaluator);
+ auto* page = m_styleResolver.document().page();
+ if (page && page->mainFrame().loader().client().hasNavigatedAwayFromAppBoundDomain())
+ m_styleResolver.document().addConsoleMessage(MessageSource::Security, MessageLevel::Warning, "Ignoring user style sheet for non-app bound domain."_s);
+ else
+ collectRulesFromUserStyleSheets(extensionStyleSheets.injectedUserStyleSheets(), tempUserStyle.get(), mediaQueryEvaluator);
collectRulesFromUserStyleSheets(extensionStyleSheets.documentUserStyleSheets(), tempUserStyle.get(), mediaQueryEvaluator);
if (tempUserStyle->ruleCount() > 0 || tempUserStyle->pageRules().size() > 0)
m_userStyle = WTFMove(tempUserStyle);
Modified: trunk/Tools/ChangeLog (258862 => 258863)
--- trunk/Tools/ChangeLog 2020-03-23 18:40:03 UTC (rev 258862)
+++ trunk/Tools/ChangeLog 2020-03-23 18:47:48 UTC (rev 258863)
@@ -1,3 +1,19 @@
+2020-03-23 Kate Cheney <[email protected]>
+
+ Add checks for app-bound navigations when evaluating user style sheets
+ https://bugs.webkit.org/show_bug.cgi?id=209368
+ <rdar://problem/60204230>
+
+ Reviewed by Brent Fulgham.
+
+ Tested cases based on those in UserContentController.mm.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
+ (-[InAppBrowserSchemeHandler webView:startURLSchemeTask:]):
+ (expectScriptEvaluatesToColor):
+ (TEST):
+
+
2020-03-23 Alex Christensen <[email protected]>
Add SPI to move localStorage to a different domain
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm (258862 => 258863)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm 2020-03-23 18:40:03 UTC (rev 258862)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm 2020-03-23 18:47:48 UTC (rev 258863)
@@ -34,6 +34,8 @@
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKUserContentControllerPrivate.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <WebKit/_WKUserContentWorld.h>
+#import <WebKit/_WKUserStyleSheet.h>
#import <wtf/RunLoop.h>
#import <wtf/text/WTFString.h>
@@ -68,6 +70,10 @@
response = @"<script>window.webkit.messageHandlers.testInAppBrowserPrivacy.postMessage(\"done\");</script>";
else if ([task.request.URL.path isEqualToString:@"/in-app-browser-privacy-test-user-agent-script"])
response = @"<script> window.wkUserScriptInjected = true; </script>";
+ else if ([task.request.URL.path isEqualToString:@"/in-app-browser-privacy-test-user-style-sheets"])
+ response = @"<body style='background-color: red;'></body>";
+ else if ([task.request.URL.path isEqualToString:@"/in-app-browser-privacy-test-user-style-sheets-iframe"])
+ response = @"<body style='background-color: red;'><iframe src=''></iframe></body>";
[task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:response.length textEncodingName:nil] autorelease]];
[task didReceiveData:[response dataUsingEncoding:NSUTF8StringEncoding]];
@@ -411,5 +417,92 @@
TestWebKitAPI::Util::run(&isDone);
}
+static NSString *styleSheetSource = @"body { background-color: green !important; }";
+static NSString *backgroundColorScript = @"window.getComputedStyle(document.body, null).getPropertyValue('background-color')";
+static NSString *frameBackgroundColorScript = @"window.getComputedStyle(document.getElementsByTagName('iframe')[0].contentDocument.body, null).getPropertyValue('background-color')";
+static const char* redInRGB = "rgb(255, 0, 0)";
+
+static void expectScriptEvaluatesToColor(WKWebView *webView, NSString *script, const char* color)
+{
+ static bool didCheckBackgroundColor;
+
+ [webView evaluateJavaScript:script completionHandler:^(id value, NSError * error) {
+ EXPECT_TRUE([value isKindOfClass:[NSString class]]);
+ EXPECT_WK_STREQ(color, value);
+ didCheckBackgroundColor = true;
+ }];
+
+ TestWebKitAPI::Util::run(&didCheckBackgroundColor);
+ didCheckBackgroundColor = false;
+}
+
+TEST(InAppBrowserPrivacy, NonAppBoundUserStyleSheetForSpecificWebViewFails)
+{
+ initializeInAppBrowserPrivacyTestSettings();
+
+ RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ auto schemeHandler = adoptNS([[InAppBrowserSchemeHandler alloc] init]);
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"in-app-browser"];
+ [[configuration preferences] _setInAppBrowserPrivacyEnabled:YES];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"in-app-browser:///in-app-browser-privacy-test-user-style-sheets"]];
+ [webView loadRequest:request];
+ [webView _test_waitForDidFinishNavigation];
+
+ RetainPtr<_WKUserContentWorld> world = [_WKUserContentWorld worldWithName:@"TestWorld"];
+ RetainPtr<_WKUserStyleSheet> styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forWKWebView:webView.get() forMainFrameOnly:YES userContentWorld:world.get()]);
+ [[configuration userContentController] _addUserStyleSheet:styleSheet.get()];
+
+ expectScriptEvaluatesToColor(webView.get(), backgroundColorScript, redInRGB);
+}
+
+TEST(InAppBrowserPrivacy, NonAppBoundUserStyleSheetForAllWebViewsFails)
+{
+ initializeInAppBrowserPrivacyTestSettings();
+
+ RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ auto schemeHandler = adoptNS([[InAppBrowserSchemeHandler alloc] init]);
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"in-app-browser"];
+ [[configuration preferences] _setInAppBrowserPrivacyEnabled:YES];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"in-app-browser:///in-app-browser-privacy-test-user-style-sheets"]];
+ [webView loadRequest:request];
+ [webView _test_waitForDidFinishNavigation];
+
+ RetainPtr<_WKUserStyleSheet> styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:YES]);
+ [[configuration userContentController] _addUserStyleSheet:styleSheet.get()];
+
+ expectScriptEvaluatesToColor(webView.get(), backgroundColorScript, redInRGB);
+}
+
+TEST(InAppBrowserPrivacy, NonAppBoundUserStyleSheetAffectingAllFramesFails)
+{
+ initializeInAppBrowserPrivacyTestSettings();
+
+ RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ auto schemeHandler = adoptNS([[InAppBrowserSchemeHandler alloc] init]);
+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"in-app-browser"];
+ [[configuration preferences] _setInAppBrowserPrivacyEnabled:YES];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"in-app-browser:///in-app-browser-privacy-test-user-style-sheets-iframe"]];
+ [webView loadRequest:request];
+ [webView _test_waitForDidFinishNavigation];
+
+ RetainPtr<_WKUserStyleSheet> styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO]);
+ [[configuration userContentController] _addUserStyleSheet:styleSheet.get()];
+
+ // The main frame should be affected.
+ expectScriptEvaluatesToColor(webView.get(), backgroundColorScript, redInRGB);
+
+ // The subframe should also be affected.
+ expectScriptEvaluatesToColor(webView.get(), frameBackgroundColorScript, redInRGB);
+}
+
#endif // USE(APPLE_INTERNAL_SDK)