diff options
Diffstat (limited to 'Tools/WebKitTestRunner/TestInvocation.cpp')
-rw-r--r-- | Tools/WebKitTestRunner/TestInvocation.cpp | 683 |
1 files changed, 683 insertions, 0 deletions
diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp new file mode 100644 index 000000000..7a36d49e6 --- /dev/null +++ b/Tools/WebKitTestRunner/TestInvocation.cpp @@ -0,0 +1,683 @@ +/* + * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012 Intel Corporation. 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. + */ + +#include "config.h" +#include "TestInvocation.h" + +#include "PlatformWebView.h" +#include "StringFunctions.h" +#include "TestController.h" +#include <WebKit/WKContextPrivate.h> +#include <WebKit/WKCookieManager.h> +#include <WebKit/WKData.h> +#include <WebKit/WKDictionary.h> +#include <WebKit/WKInspector.h> +#include <WebKit/WKPagePrivate.h> +#include <WebKit/WKRetainPtr.h> +#include <climits> +#include <cstdio> +#include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> + +#if PLATFORM(MAC) && !PLATFORM(IOS) +#include <Carbon/Carbon.h> +#endif + +#if PLATFORM(COCOA) +#include <WebKit/WKPagePrivateMac.h> +#endif + +#include <unistd.h> // For getcwd. + +using namespace WebKit; +using namespace std; + +namespace WTR { + +static WKURLRef createWKURL(const char* pathOrURL) +{ + if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://")) + return WKURLCreateWithUTF8CString(pathOrURL); + + // Creating from filesytem path. + size_t length = strlen(pathOrURL); + if (!length) + return 0; + + const char separator = '/'; + bool isAbsolutePath = pathOrURL[0] == separator; + const char* filePrefix = "file://"; + static const size_t prefixLength = strlen(filePrefix); + + std::unique_ptr<char[]> buffer; + if (isAbsolutePath) { + buffer = std::make_unique<char[]>(prefixLength + length + 1); + strcpy(buffer.get(), filePrefix); + strcpy(buffer.get() + prefixLength, pathOrURL); + } else { + buffer = std::make_unique<char[]>(prefixLength + PATH_MAX + length + 2); // 1 for the separator + strcpy(buffer.get(), filePrefix); + if (!getcwd(buffer.get() + prefixLength, PATH_MAX)) + return 0; + size_t numCharacters = strlen(buffer.get()); + buffer[numCharacters] = separator; + strcpy(buffer.get() + numCharacters + 1, pathOrURL); + } + + return WKURLCreateWithUTF8CString(buffer.get()); +} + +TestInvocation::TestInvocation(const std::string& pathOrURL) + : m_url(AdoptWK, createWKURL(pathOrURL.c_str())) + , m_dumpPixels(false) + , m_timeout(0) + , m_gotInitialResponse(false) + , m_gotFinalMessage(false) + , m_gotRepaint(false) + , m_error(false) + , m_webProcessIsUnresponsive(false) +{ + WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(m_url.get())); + + size_t stringLength = WKStringGetLength(urlString.get()); + + Vector<char> urlVector; + urlVector.resize(stringLength + 1); + + WKStringGetUTF8CString(urlString.get(), urlVector.data(), stringLength + 1); + + m_urlString = String(urlVector.data(), stringLength); +} + +TestInvocation::~TestInvocation() +{ +} + +WKURLRef TestInvocation::url() const +{ + return m_url.get(); +} + +bool TestInvocation::urlContains(const char* searchString) const +{ + return m_urlString.contains(searchString, false); +} + +void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash) +{ + m_dumpPixels = true; + m_expectedPixelHash = expectedPixelHash; +} + +bool TestInvocation::shouldLogFrameLoadDelegates() +{ + return urlContains("loading/"); +} + +bool TestInvocation::shouldLogHistoryClientCallbacks() +{ + return urlContains("globalhistory/"); +} + +void TestInvocation::invoke() +{ + TestController::singleton().configureViewForTest(*this); + + WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), false); + + m_textOutput.clear(); + + TestController::singleton().setShouldLogHistoryClientCallbacks(shouldLogHistoryClientCallbacks()); + + WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain); + + // FIXME: We should clear out visited links here. + + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest")); + WKRetainPtr<WKMutableDictionaryRef> beginTestMessageBody = adoptWK(WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates")); + WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates())); + WKDictionarySetItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get()); + + WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels")); + WKRetainPtr<WKBooleanRef> dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels)); + WKDictionarySetItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get()); + + WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer")); + WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::singleton().useWaitToDumpWatchdogTimer())); + WKDictionarySetItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get()); + + WKRetainPtr<WKStringRef> timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout")); + WKRetainPtr<WKUInt64Ref> timeoutValue = adoptWK(WKUInt64Create(m_timeout)); + WKDictionarySetItem(beginTestMessageBody.get(), timeoutKey.get(), timeoutValue.get()); + + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), beginTestMessageBody.get()); + + bool shouldOpenExternalURLs = false; + + TestController::singleton().runUntil(m_gotInitialResponse, TestController::shortTimeout); + if (!m_gotInitialResponse) { + m_errorMessage = "Timed out waiting for initial response from web process\n"; + m_webProcessIsUnresponsive = true; + goto end; + } + if (m_error) + goto end; + + WKPageLoadURLWithShouldOpenExternalURLsPolicy(TestController::singleton().mainWebView()->page(), m_url.get(), shouldOpenExternalURLs); + + TestController::singleton().runUntil(m_gotFinalMessage, TestController::noTimeout); + if (m_error) + goto end; + + dumpResults(); + +end: +#if !PLATFORM(IOS) + if (m_gotInitialResponse) + WKInspectorClose(WKPageGetInspector(TestController::singleton().mainWebView()->page())); +#endif // !PLATFORM(IOS) + + if (m_webProcessIsUnresponsive) + dumpWebProcessUnresponsiveness(); + else if (!TestController::singleton().resetStateToConsistentValues()) { + // The process froze while loading about:blank, let's start a fresh one. + // It would be nice to report that the previous test froze after dumping results, but we have no way to do that. + TestController::singleton().terminateWebContentProcess(); + // Make sure that we have a process, as invoke() will need one to send bundle messages for the next test. + TestController::singleton().reattachPageToWebProcess(); + } +} + +void TestInvocation::dumpWebProcessUnresponsiveness() +{ + dumpWebProcessUnresponsiveness(m_errorMessage.c_str()); +} + +void TestInvocation::dumpWebProcessUnresponsiveness(const char* errorMessage) +{ + char errorMessageToStderr[1024]; +#if PLATFORM(COCOA) + pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page()); + sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast<long>(pid)); +#else + sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s", TestController::webProcessName()); +#endif + + dump(errorMessage, errorMessageToStderr, true); +} + +void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError) +{ + printf("Content-Type: text/plain\n"); + if (textToStdout) + fputs(textToStdout, stdout); + if (textToStderr) + fputs(textToStderr, stderr); + + fputs("#EOF\n", stdout); + fputs("#EOF\n", stderr); + if (seenError) + fputs("#EOF\n", stdout); + fflush(stdout); + fflush(stderr); +} + +void TestInvocation::forceRepaintDoneCallback(WKErrorRef error, void* context) +{ + // The context may not be valid any more, e.g. if WebKit is invalidating callbacks at process exit. + if (error) + return; + + TestInvocation* testInvocation = static_cast<TestInvocation*>(context); + RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(testInvocation)); + + testInvocation->m_gotRepaint = true; + TestController::singleton().notifyDone(); +} + +void TestInvocation::dumpResults() +{ + if (m_textOutput.length() || !m_audioResult) + dump(m_textOutput.toString().utf8().data()); + else + dumpAudio(m_audioResult.get()); + + if (m_dumpPixels && m_pixelResult) { + if (PlatformWebView::windowSnapshotEnabled()) { + m_gotRepaint = false; + WKPageForceRepaint(TestController::singleton().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback); + TestController::singleton().runUntil(m_gotRepaint, TestController::shortTimeout); + if (!m_gotRepaint) { + m_errorMessage = "Timed out waiting for pre-pixel dump repaint\n"; + m_webProcessIsUnresponsive = true; + return; + } + } + dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get()); + } + + fputs("#EOF\n", stdout); + fflush(stdout); + fflush(stderr); +} + +void TestInvocation::dumpAudio(WKDataRef audioData) +{ + size_t length = WKDataGetSize(audioData); + if (!length) + return; + + const unsigned char* data = WKDataGetBytes(audioData); + + printf("Content-Type: audio/wav\n"); + printf("Content-Length: %lu\n", static_cast<unsigned long>(length)); + + fwrite(data, 1, length, stdout); + printf("#EOF\n"); + fprintf(stderr, "#EOF\n"); +} + +bool TestInvocation::compareActualHashToExpectedAndDumpResults(const char actualHash[33]) +{ + // Compute the hash of the bitmap context pixels + fprintf(stdout, "\nActualHash: %s\n", actualHash); + + if (!m_expectedPixelHash.length()) + return false; + + ASSERT(m_expectedPixelHash.length() == 32); + fprintf(stdout, "\nExpectedHash: %s\n", m_expectedPixelHash.c_str()); + + // FIXME: Do case insensitive compare. + return m_expectedPixelHash == actualHash; +} + +void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody) +{ + if (WKStringIsEqualToUTF8CString(messageName, "Error")) { + // Set all states to true to stop spinning the runloop. + m_gotInitialResponse = true; + m_gotFinalMessage = true; + m_error = true; + m_errorMessage = "FAIL\n"; + TestController::singleton().notifyDone(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "Ack")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody); + if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) { + m_gotInitialResponse = true; + TestController::singleton().notifyDone(); + return; + } + + ASSERT_NOT_REACHED(); + } + + if (WKStringIsEqualToUTF8CString(messageName, "Done")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult")); + m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get())); + ASSERT(!m_pixelResult || m_dumpPixels); + + WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects")); + m_repaintRects = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get())); + + WKRetainPtr<WKStringRef> audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult")); + m_audioResult = static_cast<WKDataRef>(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get())); + + m_gotFinalMessage = true; + TestController::singleton().notifyDone(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef textOutput = static_cast<WKStringRef>(messageBody); + m_textOutput.append(toWTFString(textOutput)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) { + TestController::singleton().mainWebView()->addChromeInputField(); + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) { + TestController::singleton().mainWebView()->removeChromeInputField(); + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) { + TestController::singleton().mainWebView()->makeWebViewFirstResponder(); + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) { + ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID()); + double backingScaleFactor = WKDoubleGetValue(static_cast<WKDoubleRef>(messageBody)); + WKPageSetCustomBackingScaleFactor(TestController::singleton().mainWebView()->page(), backingScaleFactor); + + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + uint64_t notificationID = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody)); + TestController::singleton().simulateWebNotificationClick(notificationID); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetAddsVisitedLinks")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody); + WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), WKBooleanGetValue(enabledWK)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().setGeolocationPermission(WKBooleanGetValue(enabledWK)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude")); + WKDoubleRef latitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, latitudeKeyWK.get())); + double latitude = WKDoubleGetValue(latitudeWK); + + WKRetainPtr<WKStringRef> longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude")); + WKDoubleRef longitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, longitudeKeyWK.get())); + double longitude = WKDoubleGetValue(longitudeWK); + + WKRetainPtr<WKStringRef> accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy")); + WKDoubleRef accuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, accuracyKeyWK.get())); + double accuracy = WKDoubleGetValue(accuracyWK); + + WKRetainPtr<WKStringRef> providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude")); + WKBooleanRef providesAltitudeWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeKeyWK.get())); + bool providesAltitude = WKBooleanGetValue(providesAltitudeWK); + + WKRetainPtr<WKStringRef> altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude")); + WKDoubleRef altitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeKeyWK.get())); + double altitude = WKDoubleGetValue(altitudeWK); + + WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy")); + WKBooleanRef providesAltitudeAccuracyWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeAccuracyKeyWK.get())); + bool providesAltitudeAccuracy = WKBooleanGetValue(providesAltitudeAccuracyWK); + + WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy")); + WKDoubleRef altitudeAccuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeAccuracyKeyWK.get())); + double altitudeAccuracy = WKDoubleGetValue(altitudeAccuracyWK); + + WKRetainPtr<WKStringRef> providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading")); + WKBooleanRef providesHeadingWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesHeadingKeyWK.get())); + bool providesHeading = WKBooleanGetValue(providesHeadingWK); + + WKRetainPtr<WKStringRef> headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading")); + WKDoubleRef headingWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, headingKeyWK.get())); + double heading = WKDoubleGetValue(headingWK); + + WKRetainPtr<WKStringRef> providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed")); + WKBooleanRef providesSpeedWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesSpeedKeyWK.get())); + bool providesSpeed = WKBooleanGetValue(providesSpeedWK); + + WKRetainPtr<WKStringRef> speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed")); + WKDoubleRef speedWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get())); + double speed = WKDoubleGetValue(speedWK); + + TestController::singleton().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef errorMessage = static_cast<WKStringRef>(messageBody); + TestController::singleton().setMockGeolocationPositionUnavailableError(errorMessage); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermission")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().setUserMediaPermission(WKBooleanGetValue(enabledWK)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + uint64_t model = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody)); + WKContextSetCacheModel(TestController::singleton().context(), model); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled")); + WKBooleanRef enabledWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, enabledKeyWK.get())); + bool enabled = WKBooleanGetValue(enabledWK); + + WKRetainPtr<WKStringRef> permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive")); + WKBooleanRef permissiveWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get())); + bool permissive = WKBooleanGetValue(permissiveWK); + + TestController::singleton().setCustomPolicyDelegate(enabled, permissive); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetHidden")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden")); + WKBooleanRef hiddenWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get())); + bool hidden = WKBooleanGetValue(hiddenWK); + + TestController::singleton().setHidden(hidden); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) { + if (TestController::singleton().workQueueManager().processWorkQueue()) { + WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); + } + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody)); + TestController::singleton().workQueueManager().queueBackNavigation(stepCount); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody)); + TestController::singleton().workQueueManager().queueForwardNavigation(stepCount); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url")); + WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, urlKey.get())); + + WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target")); + WKStringRef targetWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get())); + + WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs")); + WKBooleanRef shouldOpenExternalURLsValueWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(loadDataDictionary, shouldOpenExternalURLsKey.get())); + + TestController::singleton().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK), WKBooleanGetValue(shouldOpenExternalURLsValueWK)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> contentKey(AdoptWK, WKStringCreateWithUTF8CString("content")); + WKStringRef contentWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, contentKey.get())); + + WKRetainPtr<WKStringRef> baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL")); + WKStringRef baseURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, baseURLKey.get())); + + WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL")); + WKStringRef unreachableURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get())); + + TestController::singleton().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String()); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) { + TestController::singleton().workQueueManager().queueReload(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef script = static_cast<WKStringRef>(messageBody); + TestController::singleton().workQueueManager().queueLoadingScript(toWTFString(script)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef script = static_cast<WKStringRef>(messageBody); + TestController::singleton().workQueueManager().queueNonLoadingScript(toWTFString(script)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef value = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().setHandlesAuthenticationChallenges(WKBooleanGetValue(value)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef username = static_cast<WKStringRef>(messageBody); + TestController::singleton().setAuthenticationUsername(toWTFString(username)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) { + ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef password = static_cast<WKStringRef>(messageBody); + TestController::singleton().setAuthenticationPassword(toWTFString(password)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetBlockAllPlugins")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef shouldBlock = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().setBlockAllPlugins(WKBooleanGetValue(shouldBlock)); + return; + } + + ASSERT_NOT_REACHED(); +} + +WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody) +{ + if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef isKeyValue = static_cast<WKBooleanRef>(messageBody); + TestController::singleton().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue)); + return 0; + } + + if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) { + bool isActive = TestController::singleton().isGeolocationProviderActive(); + WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isActive)); + return result; + } + + if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) { + bool isEmpty = TestController::singleton().workQueueManager().isWorkQueueEmpty(); + WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isEmpty)); + return result; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SecureEventInputIsEnabled")) { +#if PLATFORM(MAC) && !PLATFORM(IOS) + WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(IsSecureEventInputEnabled())); +#else + WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(false)); +#endif + return result; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetAlwaysAcceptCookies")) { + WKBooleanRef accept = static_cast<WKBooleanRef>(messageBody); + WKHTTPCookieAcceptPolicy policy = WKBooleanGetValue(accept) ? kWKHTTPCookieAcceptPolicyAlways : kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain; + // FIXME: This updates the policy in WebProcess and in NetworkProcess asynchronously, which might break some tests' expectations. + WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), policy); + return 0; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +void TestInvocation::outputText(const WTF::String& text) +{ + m_textOutput.append(text); +} + +} // namespace WTR |