/* * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "TestInvocation.h" #include "PlatformWebView.h" #include "StringFunctions.h" #include "TestController.h" #include #include #include #include #include #include #include #include #include #if PLATFORM(MAC) #include #endif #if OS(WINDOWS) #include // For _getcwd. #define getcwd _getcwd // MSDN says getcwd is deprecated. #define PATH_MAX _MAX_PATH #else #include // For getcwd. #endif 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; #if OS(WINDOWS) const char separator = '\\'; bool isAbsolutePath = length >= 3 && pathOrURL[1] == ':' && pathOrURL[2] == separator; // FIXME: Remove the "localhost/" suffix once is fixed. const char* filePrefix = "file://localhost/"; #else const char separator = '/'; bool isAbsolutePath = pathOrURL[0] == separator; const char* filePrefix = "file://"; #endif static const size_t prefixLength = strlen(filePrefix); OwnArrayPtr buffer; if (isAbsolutePath) { buffer = adoptArrayPtr(new char[prefixLength + length + 1]); strcpy(buffer.get(), filePrefix); strcpy(buffer.get() + prefixLength, pathOrURL); } else { buffer = adoptArrayPtr(new 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_pathOrURL(pathOrURL) , m_dumpPixels(false) , m_gotInitialResponse(false) , m_gotFinalMessage(false) , m_gotRepaint(false) , m_error(false) { } TestInvocation::~TestInvocation() { } void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash) { m_dumpPixels = true; m_expectedPixelHash = expectedPixelHash; } static const unsigned w3cSVGWidth = 480; static const unsigned w3cSVGHeight = 360; static const unsigned normalWidth = 800; static const unsigned normalHeight = 600; static void sizeWebViewForCurrentTest(const char* pathOrURL) { bool isSVGW3CTest = strstr(pathOrURL, "svg/W3C-SVG-1.1") || strstr(pathOrURL, "svg\\W3C-SVG-1.1"); if (isSVGW3CTest) TestController::shared().mainWebView()->resizeTo(w3cSVGWidth, w3cSVGHeight); else TestController::shared().mainWebView()->resizeTo(normalWidth, normalHeight); } static bool shouldLogFrameLoadDelegates(const char* pathOrURL) { return strstr(pathOrURL, "loading/"); } #if ENABLE(INSPECTOR) static bool shouldOpenWebInspector(const char* pathOrURL) { return strstr(pathOrURL, "inspector/") || strstr(pathOrURL, "inspector\\"); } #endif #if PLATFORM(MAC) static bool shouldUseTiledDrawing(const char* pathOrURL) { return strstr(pathOrURL, "tiled-drawing/") || strstr(pathOrURL, "tiled-drawing\\"); } #endif static void updateTiledDrawingForCurrentTest(const char* pathOrURL) { #if PLATFORM(MAC) WKRetainPtr viewOptions = adoptWK(WKMutableDictionaryCreate()); WKRetainPtr useTiledDrawingKey = adoptWK(WKStringCreateWithUTF8CString("TiledDrawing")); WKRetainPtr useTiledDrawingValue = adoptWK(WKBooleanCreate(shouldUseTiledDrawing(pathOrURL))); WKDictionaryAddItem(viewOptions.get(), useTiledDrawingKey.get(), useTiledDrawingValue.get()); TestController::shared().ensureViewSupportsOptions(viewOptions.get()); #else UNUSED_PARAM(pathOrURL); #endif } void TestInvocation::invoke() { sizeWebViewForCurrentTest(m_pathOrURL.c_str()); updateTiledDrawingForCurrentTest(m_pathOrURL.c_str()); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest")); WKRetainPtr beginTestMessageBody = adoptWK(WKMutableDictionaryCreate()); WKRetainPtr dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates")); WKRetainPtr dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates(m_pathOrURL.c_str()))); WKDictionaryAddItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get()); WKRetainPtr dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels")); WKRetainPtr dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels)); WKDictionaryAddItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get()); WKRetainPtr useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer")); WKRetainPtr useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::shared().useWaitToDumpWatchdogTimer())); WKDictionaryAddItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get()); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), beginTestMessageBody.get()); const char* errorMessage = 0; TestController::shared().runUntil(m_gotInitialResponse, TestController::ShortTimeout); if (!m_gotInitialResponse) { errorMessage = "Timed out waiting for initial response from web process\n"; goto end; } if (m_error) { errorMessage = "FAIL\n"; goto end; } #if ENABLE(INSPECTOR) if (shouldOpenWebInspector(m_pathOrURL.c_str())) WKInspectorShow(WKPageGetInspector(TestController::shared().mainWebView()->page())); #endif // ENABLE(INSPECTOR) WKPageLoadURL(TestController::shared().mainWebView()->page(), m_url.get()); TestController::shared().runUntil(m_gotFinalMessage, TestController::shared().useWaitToDumpWatchdogTimer() ? TestController::LongTimeout : TestController::NoTimeout); if (!m_gotFinalMessage) { errorMessage = "Timed out waiting for final message from web process\n"; goto end; } if (m_error) { errorMessage = "FAIL\n"; goto end; } dumpResults(); end: #if ENABLE(INSPECTOR) if (m_gotInitialResponse) WKInspectorClose(WKPageGetInspector(TestController::shared().mainWebView()->page())); #endif // ENABLE(INSPECTOR) if (errorMessage) dumpWebProcessUnresponsiveness(errorMessage); else if (!TestController::shared().resetStateToConsistentValues()) dumpWebProcessUnresponsiveness("Timed out loading about:blank before the next test"); } void TestInvocation::dumpWebProcessUnresponsiveness(const char* textToStdout) { const char* errorMessageToStderr = 0; #if PLATFORM(MAC) char buffer[64]; pid_t pid = WKPageGetProcessIdentifier(TestController::shared().mainWebView()->page()); sprintf(buffer, "#PROCESS UNRESPONSIVE - WebProcess (pid %ld)\n", static_cast(pid)); errorMessageToStderr = buffer; #else errorMessageToStderr = "#PROCESS UNRESPONSIVE - WebProcess"; #endif dump(textToStdout, 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::dumpResults() { dump(toWTFString(m_textOutput.get()).utf8().data()); if (m_dumpPixels && m_pixelResult) dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get()); fputs("#EOF\n", stdout); fflush(stdout); } 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; TestController::shared().notifyDone(); return; } if (WKStringIsEqualToUTF8CString(messageName, "Ack")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef messageBodyString = static_cast(messageBody); if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) { m_gotInitialResponse = true; TestController::shared().notifyDone(); return; } ASSERT_NOT_REACHED(); } if (WKStringIsEqualToUTF8CString(messageName, "Done")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput")); m_textOutput = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, textOutputKey.get())); WKRetainPtr pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult")); m_pixelResult = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get())); ASSERT(!m_pixelResult || m_dumpPixels); WKRetainPtr repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects")); m_repaintRects = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get())); m_gotFinalMessage = true; TestController::shared().notifyDone(); return; } if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef beforeUnloadReturnValue = static_cast(messageBody); TestController::shared().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue)); return; } if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) { TestController::shared().mainWebView()->addChromeInputField(); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback")); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) { TestController::shared().mainWebView()->removeChromeInputField(); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback")); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) { TestController::shared().mainWebView()->makeWebViewFirstResponder(); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback")); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) { ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID()); double backingScaleFactor = WKDoubleGetValue(static_cast(messageBody)); WKPageSetCustomBackingScaleFactor(TestController::shared().mainWebView()->page(), backingScaleFactor); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback")); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) { ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); uint64_t notificationID = WKUInt64GetValue(static_cast(messageBody)); TestController::shared().simulateWebNotificationClick(notificationID); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef enabledWK = static_cast(messageBody); TestController::shared().setGeolocationPermission(WKBooleanGetValue(enabledWK)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude")); WKDoubleRef latitudeWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, latitudeKeyWK.get())); double latitude = WKDoubleGetValue(latitudeWK); WKRetainPtr longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude")); WKDoubleRef longitudeWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, longitudeKeyWK.get())); double longitude = WKDoubleGetValue(longitudeWK); WKRetainPtr accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy")); WKDoubleRef accuracyWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, accuracyKeyWK.get())); double accuracy = WKDoubleGetValue(accuracyWK); WKRetainPtr providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude")); WKBooleanRef providesAltitudeWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeKeyWK.get())); bool providesAltitude = WKBooleanGetValue(providesAltitudeWK); WKRetainPtr altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude")); WKDoubleRef altitudeWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeKeyWK.get())); double altitude = WKDoubleGetValue(altitudeWK); WKRetainPtr providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy")); WKBooleanRef providesAltitudeAccuracyWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeAccuracyKeyWK.get())); bool providesAltitudeAccuracy = WKBooleanGetValue(providesAltitudeAccuracyWK); WKRetainPtr altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy")); WKDoubleRef altitudeAccuracyWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeAccuracyKeyWK.get())); double altitudeAccuracy = WKDoubleGetValue(altitudeAccuracyWK); WKRetainPtr providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading")); WKBooleanRef providesHeadingWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, providesHeadingKeyWK.get())); bool providesHeading = WKBooleanGetValue(providesHeadingWK); WKRetainPtr headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading")); WKDoubleRef headingWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, headingKeyWK.get())); double heading = WKDoubleGetValue(headingWK); WKRetainPtr providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed")); WKBooleanRef providesSpeedWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, providesSpeedKeyWK.get())); bool providesSpeed = WKBooleanGetValue(providesSpeedWK); WKRetainPtr speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed")); WKDoubleRef speedWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get())); double speed = WKDoubleGetValue(speedWK); TestController::shared().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(messageBody); TestController::shared().setMockGeolocationPositionUnavailableError(errorMessage); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled")); WKBooleanRef enabledWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, enabledKeyWK.get())); bool enabled = WKBooleanGetValue(enabledWK); WKRetainPtr permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive")); WKBooleanRef permissiveWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get())); bool permissive = WKBooleanGetValue(permissiveWK); TestController::shared().setCustomPolicyDelegate(enabled, permissive); return; } if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) { if (TestController::shared().workQueueManager().processWorkQueue()) { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback")); WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); } return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) { ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); uint64_t stepCount = WKUInt64GetValue(static_cast(messageBody)); TestController::shared().workQueueManager().queueBackNavigation(stepCount); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) { ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); uint64_t stepCount = WKUInt64GetValue(static_cast(messageBody)); TestController::shared().workQueueManager().queueForwardNavigation(stepCount); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef loadDataDictionary = static_cast(messageBody); WKRetainPtr urlKey(AdoptWK, WKStringCreateWithUTF8CString("url")); WKStringRef urlWK = static_cast(WKDictionaryGetItemForKey(loadDataDictionary, urlKey.get())); WKRetainPtr targetKey(AdoptWK, WKStringCreateWithUTF8CString("target")); WKStringRef targetWK = static_cast(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get())); TestController::shared().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef loadDataDictionary = static_cast(messageBody); WKRetainPtr contentKey(AdoptWK, WKStringCreateWithUTF8CString("content")); WKStringRef contentWK = static_cast(WKDictionaryGetItemForKey(loadDataDictionary, contentKey.get())); WKRetainPtr baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL")); WKStringRef baseURLWK = static_cast(WKDictionaryGetItemForKey(loadDataDictionary, baseURLKey.get())); WKRetainPtr unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL")); WKStringRef unreachableURLWK = static_cast(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get())); TestController::shared().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String()); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) { TestController::shared().workQueueManager().queueReload(); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef script = static_cast(messageBody); TestController::shared().workQueueManager().queueLoadingScript(toWTFString(script)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef script = static_cast(messageBody); TestController::shared().workQueueManager().queueNonLoadingScript(toWTFString(script)); return; } ASSERT_NOT_REACHED(); } WKRetainPtr TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody) { if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef isKeyValue = static_cast(messageBody); TestController::shared().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue)); return 0; } if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) { bool isEmpty = TestController::shared().workQueueManager().isWorkQueueEmpty(); WKRetainPtr result(AdoptWK, WKBooleanCreate(isEmpty)); return result; } ASSERT_NOT_REACHED(); return 0; } } // namespace WTR