- Revision
- 182017
- Author
- [email protected]
- Date
- 2015-03-26 11:12:56 -0700 (Thu, 26 Mar 2015)
Log Message
[Mac] Add an --allowed-host argument to DRT and WKTR to allow tests to connect to non-localhost servers
https://bugs.webkit.org/show_bug.cgi?id=142931
Reviewed by Brent Fulgham.
Currently, both DRT and WKTR will refuse to allow network connections to non-localhost servers
over HTTP/HTTPS. For certain testing scenarios, however, it would be useful if both DRT and
WKTR could be allowed to make HTTP/HTTPS connections to certain, specific servers defined at
runtime.
To allow this, add an optional argument to DRT and WKTR, --allowed-host, which will add the specified
hostname to a whitelist; requests to these hosts will allowed to proceed normally.
Drive-by fix: in InjectedBundlePage::willSendRequestForFrame, we get the top loading frame from the
injected bundle. But after the main resource load completes, the bundle nulls out it's pointer to the
top loading frame, which causes a subsequent crash when further resources are requested. Instead, get
the top loading frame from the page, as we do elsewhere in this class.
* DumpRenderTree/TestRunner.h:
(TestRunner::allowedHosts):
(TestRunner::setAllowedHosts):
* DumpRenderTree/mac/DumpRenderTree.mm:
(initializeGlobalsFromCommandLineOptions):
(runTest):
* DumpRenderTree/mac/ResourceLoadDelegate.mm:
(isAllowedHost):
(-[ResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessage):
(WTR::InjectedBundle::isAllowedHost):
* WebKitTestRunner/InjectedBundle/InjectedBundle.h:
* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::isAllowedHost):
(WTR::InjectedBundlePage::willSendRequestForFrame):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/Options.cpp:
(WTR::handleOptionAllowedHost):
(WTR::OptionsHandler::OptionsHandler):
* WebKitTestRunner/Options.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::initialize):
(WTR::TestController::resetStateToConsistentValues):
* WebKitTestRunner/TestController.h:
Modified Paths
Diff
Modified: trunk/Tools/ChangeLog (182016 => 182017)
--- trunk/Tools/ChangeLog 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/ChangeLog 2015-03-26 18:12:56 UTC (rev 182017)
@@ -1,3 +1,49 @@
+2015-03-26 Jer Noble <[email protected]>
+
+ [Mac] Add an --allowed-host argument to DRT and WKTR to allow tests to connect to non-localhost servers
+ https://bugs.webkit.org/show_bug.cgi?id=142931
+
+ Reviewed by Brent Fulgham.
+
+ Currently, both DRT and WKTR will refuse to allow network connections to non-localhost servers
+ over HTTP/HTTPS. For certain testing scenarios, however, it would be useful if both DRT and
+ WKTR could be allowed to make HTTP/HTTPS connections to certain, specific servers defined at
+ runtime.
+
+ To allow this, add an optional argument to DRT and WKTR, --allowed-host, which will add the specified
+ hostname to a whitelist; requests to these hosts will allowed to proceed normally.
+
+ Drive-by fix: in InjectedBundlePage::willSendRequestForFrame, we get the top loading frame from the
+ injected bundle. But after the main resource load completes, the bundle nulls out it's pointer to the
+ top loading frame, which causes a subsequent crash when further resources are requested. Instead, get
+ the top loading frame from the page, as we do elsewhere in this class.
+
+ * DumpRenderTree/TestRunner.h:
+ (TestRunner::allowedHosts):
+ (TestRunner::setAllowedHosts):
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (initializeGlobalsFromCommandLineOptions):
+ (runTest):
+ * DumpRenderTree/mac/ResourceLoadDelegate.mm:
+ (isAllowedHost):
+ (-[ResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessage):
+ (WTR::InjectedBundle::isAllowedHost):
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
+ * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+ (WTR::isAllowedHost):
+ (WTR::InjectedBundlePage::willSendRequestForFrame):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/Options.cpp:
+ (WTR::handleOptionAllowedHost):
+ (WTR::OptionsHandler::OptionsHandler):
+ * WebKitTestRunner/Options.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::initialize):
+ (WTR::TestController::resetStateToConsistentValues):
+ * WebKitTestRunner/TestController.h:
+
2015-03-26 Brady Eidson <[email protected]>
Apply ContentExtension actions after redirects.
Modified: trunk/Tools/DumpRenderTree/TestRunner.h (182016 => 182017)
--- trunk/Tools/DumpRenderTree/TestRunner.h 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/DumpRenderTree/TestRunner.h 2015-03-26 18:12:56 UTC (rev 182017)
@@ -52,6 +52,8 @@
void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception);
void addDisallowedURL(JSStringRef url);
+ const std::set<std::string>& allowedHosts() const { return m_allowedHosts; }
+ void setAllowedHosts(std::set<std::string> hosts) { m_allowedHosts = WTF::move(hosts); }
void addURLToRedirect(std::string origin, std::string destination);
const std::string& redirectionDestinationForURL(std::string);
void clearAllApplicationCaches();
@@ -418,11 +420,12 @@
std::string m_titleTextDirection;
std::set<std::string> m_willSendRequestClearHeaders;
+ std::set<std::string> m_allowedHosts;
std::vector<char> m_audioResult;
std::map<std::string, std::string> m_URLsToRedirect;
-
+
static JSClassRef getJSClass();
static JSStaticValue* staticValues();
static JSStaticFunction* staticFunctions();
Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (182016 => 182017)
--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2015-03-26 18:12:56 UTC (rev 182017)
@@ -202,6 +202,7 @@
static int gcBetweenTests;
static BOOL printSeparators;
static RetainPtr<CFStringRef> persistentUserStyleSheetLocation;
+static std::set<std::string> allowedHosts;
static WebHistoryItem *prevTestBFItem = nil; // current b/f item at the end of the previous test
@@ -1080,6 +1081,7 @@
{"accelerated-drawing", no_argument, &useAcceleratedDrawing, YES},
{"gc-between-tests", no_argument, &gcBetweenTests, YES},
{"no-timeout", no_argument, &useTimeoutWatchdog, NO},
+ {"allowed-host", required_argument, nullptr, 'a'},
{nullptr, 0, nullptr, 0}
};
@@ -1090,6 +1092,9 @@
case ':': // missing argument
exit(1);
break;
+ case 'a': // "allowed-host"
+ allowedHosts.insert(optarg);
+ break;
}
}
}
@@ -1880,6 +1885,7 @@
#endif
gTestRunner = TestRunner::create(testURL, command.expectedPixelHash);
+ gTestRunner->setAllowedHosts(allowedHosts);
gTestRunner->setCustomTimeout(command.timeout);
topLoadingFrame = nil;
#if !PLATFORM(IOS)
Modified: trunk/Tools/DumpRenderTree/mac/ResourceLoadDelegate.mm (182016 => 182017)
--- trunk/Tools/DumpRenderTree/mac/ResourceLoadDelegate.mm 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/DumpRenderTree/mac/ResourceLoadDelegate.mm 2015-03-26 18:12:56 UTC (rev 182017)
@@ -137,6 +137,11 @@
return NSOrderedSame == [host compare:@"255.255.255.255"];
}
+BOOL isAllowedHost(NSString *host)
+{
+ return gTestRunner->allowedHosts().count(host.UTF8String);
+}
+
-(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
{
if (!done && gTestRunner->dumpResourceLoadCallbacks()) {
@@ -165,7 +170,7 @@
NSString *testHost = 0;
if ([lowercaseTestURL hasPrefix:@"http:"] || [lowercaseTestURL hasPrefix:@"https:"])
testHost = [[NSURL URLWithString:testURL] host];
- if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host) && (!testHost || isLocalhost(testHost))) {
+ if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host) && !isAllowedHost(host) && (!testHost || isLocalhost(testHost))) {
printf("Blocked access to external URL %s\n", [[url absoluteString] cStringUsingEncoding:NSUTF8StringEncoding]);
return nil;
}
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2015-03-26 18:12:56 UTC (rev 182017)
@@ -166,6 +166,17 @@
if (shouldGC)
WKBundleGarbageCollectJavaScriptObjects(m_bundle);
+ WKRetainPtr<WKStringRef> allowedHostsKey(AdoptWK, WKStringCreateWithUTF8CString("AllowedHosts"));
+ WKTypeRef allowedHostsValue = WKDictionaryGetItemForKey(messageBodyDictionary, allowedHostsKey.get());
+ if (allowedHostsValue && WKGetTypeID(allowedHostsValue) == WKArrayGetTypeID()) {
+ WKArrayRef allowedHostsArray = static_cast<WKArrayRef>(allowedHostsValue);
+ for (size_t i = 0, size = WKArrayGetSize(allowedHostsArray); i < size; ++i) {
+ WKTypeRef item = WKArrayGetItemAtIndex(allowedHostsArray, i);
+ if (item && WKGetTypeID(item) == WKStringGetTypeID())
+ m_allowedHosts.append(toWTFString(static_cast<WKStringRef>(item)));
+ }
+ }
+
m_state = Idle;
m_dumpPixels = false;
@@ -599,4 +610,11 @@
WKBundlePostMessage(m_bundle, messageName.get(), script);
}
+bool InjectedBundle::isAllowedHost(WKStringRef host)
+{
+ if (m_allowedHosts.isEmpty())
+ return false;
+ return m_allowedHosts.contains(toWTFString(host));
+}
+
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h 2015-03-26 18:12:56 UTC (rev 182017)
@@ -115,6 +115,8 @@
void queueLoadingScript(WKStringRef script);
void queueNonLoadingScript(WKStringRef script);
+ bool isAllowedHost(WKStringRef);
+
private:
InjectedBundle();
~InjectedBundle();
@@ -165,6 +167,8 @@
WKRetainPtr<WKDataRef> m_audioResult;
WKRetainPtr<WKImageRef> m_pixelResult;
WKRetainPtr<WKArrayRef> m_repaintRects;
+
+ Vector<String> m_allowedHosts;
};
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2015-03-26 18:12:56 UTC (rev 182017)
@@ -1077,6 +1077,11 @@
return WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "https");
}
+static inline bool isAllowedHost(WKStringRef host)
+{
+ return InjectedBundle::singleton().isAllowedHost(host);
+}
+
WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef response)
{
auto& injectedBundle = InjectedBundle::singleton();
@@ -1111,7 +1116,7 @@
&& !isLocalHost(host.get())) {
bool mainFrameIsExternal = false;
if (injectedBundle.isTestRunning()) {
- WKBundleFrameRef mainFrame = injectedBundle.topLoadingFrame();
+ WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(m_page);
WKRetainPtr<WKURLRef> mainFrameURL = adoptWK(WKBundleFrameCopyURL(mainFrame));
if (!mainFrameURL || WKStringIsEqualToUTF8CString(adoptWK(WKURLCopyString(mainFrameURL.get())).get(), "about:blank"))
mainFrameURL = adoptWK(WKBundleFrameCopyProvisionalURL(mainFrame));
@@ -1120,7 +1125,7 @@
WKRetainPtr<WKStringRef> mainFrameScheme = adoptWK(WKURLCopyScheme(mainFrameURL.get()));
mainFrameIsExternal = isHTTPOrHTTPSScheme(mainFrameScheme.get()) && !isLocalHost(mainFrameHost.get());
}
- if (!mainFrameIsExternal) {
+ if (!mainFrameIsExternal && !isAllowedHost(host.get())) {
StringBuilder stringBuilder;
stringBuilder.appendLiteral("Blocked access to external URL ");
stringBuilder.append(toWTFString(urlString));
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2015-03-26 18:12:56 UTC (rev 182017)
@@ -331,6 +331,8 @@
bool m_userStyleSheetEnabled;
WKRetainPtr<WKStringRef> m_userStyleSheetLocation;
+ WKRetainPtr<WKArrayRef> m_allowedHosts;
+
PlatformTimerRef m_waitToDumpWatchdogTimer;
};
Modified: trunk/Tools/WebKitTestRunner/Options.cpp (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/Options.cpp 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/Options.cpp 2015-03-26 18:12:56 UTC (rev 182017)
@@ -99,6 +99,12 @@
return true;
}
+bool handleOptionAllowedHost(Options& options, const char*, const char* host)
+{
+ options.allowedHosts.push_back(host);
+ return true;
+}
+
bool handleOptionUnmatched(Options& options, const char* option, const char*)
{
if (option[0] && option[1] && option[0] == '-' && option[1] == '-')
@@ -120,6 +126,8 @@
optionList.append(Option("--complex-text", "Force complex tests.", handleOptionComplexText));
optionList.append(Option("--accelerated-drawing", "Use accelerated drawing.", handleOptionAcceleratedDrawing));
optionList.append(Option("--remote-layer-tree", "Use remote layer tree.", handleOptionRemoteLayerTree));
+ optionList.append(Option("--allowed-host", "Allows access to the specified host from tests.", handleOptionAllowedHost, true));
+
optionList.append(Option(0, 0, handleOptionUnmatched));
}
Modified: trunk/Tools/WebKitTestRunner/Options.h (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/Options.h 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/Options.h 2015-03-26 18:12:56 UTC (rev 182017)
@@ -47,6 +47,7 @@
bool shouldUseAcceleratedDrawing;
bool shouldUseRemoteLayerTree;
std::vector<std::string> paths;
+ std::vector<std::string> allowedHosts;
};
class Option {
Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/TestController.cpp 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp 2015-03-26 18:12:56 UTC (rev 182017)
@@ -325,6 +325,7 @@
m_shouldUseAcceleratedDrawing = options.shouldUseAcceleratedDrawing;
m_shouldUseRemoteLayerTree = options.shouldUseRemoteLayerTree;
m_paths = options.paths;
+ m_allowedHosts = options.allowedHosts;
if (options.printSupportedFeatures) {
// FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
@@ -612,6 +613,14 @@
WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
WKDictionarySetItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
+ WKRetainPtr<WKStringRef> allowedHostsKey = adoptWK(WKStringCreateWithUTF8CString("AllowedHosts"));
+ WKRetainPtr<WKMutableArrayRef> allowedHostsValue = adoptWK(WKMutableArrayCreate());
+ for (auto& host : m_allowedHosts) {
+ WKRetainPtr<WKStringRef> wkHost = adoptWK(WKStringCreateWithUTF8CString(host.c_str()));
+ WKArrayAppendItem(allowedHostsValue.get(), wkHost.get());
+ }
+ WKDictionarySetItem(resetMessageBody.get(), allowedHostsKey.get(), allowedHostsValue.get());
+
WKContextPostMessageToInjectedBundle(TestController::singleton().context(), messageName.get(), resetMessageBody.get());
WKContextSetShouldUseFontSmoothing(TestController::singleton().context(), false);
Modified: trunk/Tools/WebKitTestRunner/TestController.h (182016 => 182017)
--- trunk/Tools/WebKitTestRunner/TestController.h 2015-03-26 17:45:12 UTC (rev 182016)
+++ trunk/Tools/WebKitTestRunner/TestController.h 2015-03-26 18:12:56 UTC (rev 182017)
@@ -214,6 +214,7 @@
bool m_gcBetweenTests;
bool m_shouldDumpPixelsForAllTests;
std::vector<std::string> m_paths;
+ std::vector<std::string> m_allowedHosts;
WKRetainPtr<WKStringRef> m_injectedBundlePath;
WKRetainPtr<WKStringRef> m_testPluginDirectory;