/* * 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 "UIScriptController.h" #include #include #include #include #include #include #include #include #include #include #include #if PLATFORM(MAC) && !PLATFORM(IOS) #include #endif #if PLATFORM(COCOA) #include #endif using namespace JSC; using namespace WebKit; using namespace std; namespace WTR { TestInvocation::TestInvocation(WKURLRef url, const TestOptions& options) : m_options(options) , m_url(url) { WKRetainPtr urlString = adoptWK(WKURLCopyString(m_url.get())); size_t stringLength = WKStringGetLength(urlString.get()); Vector urlVector; urlVector.resize(stringLength + 1); WKStringGetUTF8CString(urlString.get(), urlVector.data(), stringLength + 1); m_urlString = String(urlVector.data(), stringLength); } TestInvocation::~TestInvocation() { if (m_pendingUIScriptInvocationData) m_pendingUIScriptInvocationData->testInvocation = nullptr; } 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() const { return urlContains("loading/"); } bool TestInvocation::shouldLogHistoryClientCallbacks() const { 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 messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest")); WKRetainPtr beginTestMessageBody = adoptWK(WKMutableDictionaryCreate()); WKRetainPtr dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates")); WKRetainPtr dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates())); WKDictionarySetItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get()); WKRetainPtr useFlexibleViewportKey = adoptWK(WKStringCreateWithUTF8CString("UseFlexibleViewport")); WKRetainPtr useFlexibleViewportValue = adoptWK(WKBooleanCreate(options().useFlexibleViewport)); WKDictionarySetItem(beginTestMessageBody.get(), useFlexibleViewportKey.get(), useFlexibleViewportValue.get()); WKRetainPtr dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels")); WKRetainPtr dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels)); WKDictionarySetItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get()); WKRetainPtr useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer")); WKRetainPtr useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::singleton().useWaitToDumpWatchdogTimer())); WKDictionarySetItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get()); WKRetainPtr timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout")); WKRetainPtr 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(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(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) { if (m_pixelResult) dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebContents); else if (m_pixelResultIsPending) { 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; } WKRetainPtr windowSnapshot = TestController::singleton().mainWebView()->windowSnapshotImage(); ASSERT(windowSnapshot); dumpPixelsAndCompareWithExpected(windowSnapshot.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebView); } } 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(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(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(messageBody); WKRetainPtr pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending")); WKBooleanRef pixelResultIsPending = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultIsPendingKey.get())); m_pixelResultIsPending = WKBooleanGetValue(pixelResultIsPending); if (!m_pixelResultIsPending) { 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())); WKRetainPtr audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult")); m_audioResult = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get())); m_gotFinalMessage = true; TestController::singleton().notifyDone(); return; } if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef textOutput = static_cast(messageBody); m_textOutput.append(toWTFString(textOutput)); return; } if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef beforeUnloadReturnValue = static_cast(messageBody); TestController::singleton().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue)); return; } if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) { TestController::singleton().mainWebView()->addChromeInputField(); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) { TestController::singleton().mainWebView()->removeChromeInputField(); WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); return; } if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) { TestController::singleton().mainWebView()->makeWebViewFirstResponder(); WKRetainPtr 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(messageBody)); WKPageSetCustomBackingScaleFactor(TestController::singleton().mainWebView()->page(), backingScaleFactor); WKRetainPtr 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(messageBody)); TestController::singleton().simulateWebNotificationClick(notificationID); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAddsVisitedLinks")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef enabledWK = static_cast(messageBody); WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), WKBooleanGetValue(enabledWK)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef enabledWK = static_cast(messageBody); TestController::singleton().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::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(messageBody); TestController::singleton().setMockGeolocationPositionUnavailableError(errorMessage); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermission")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef enabledWK = static_cast(messageBody); TestController::singleton().setUserMediaPermission(WKBooleanGetValue(enabledWK)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermissionForOrigin")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission")); WKBooleanRef permissionWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, permissionKeyWK.get())); bool permission = WKBooleanGetValue(permissionWK); WKRetainPtr urlKey(AdoptWK, WKStringCreateWithUTF8CString("url")); WKStringRef urlWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, urlKey.get())); TestController::singleton().setUserMediaPermissionForOrigin(permission, urlWK); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) { ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); uint64_t model = WKUInt64GetValue(static_cast(messageBody)); WKContextSetCacheModel(TestController::singleton().context(), model); 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::singleton().setCustomPolicyDelegate(enabled, permissive); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetHidden")) { ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden")); WKBooleanRef hiddenWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get())); bool hidden = WKBooleanGetValue(hiddenWK); TestController::singleton().setHidden(hidden); return; } if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) { if (TestController::singleton().workQueueManager().processWorkQueue()) { WKRetainPtr 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(messageBody)); TestController::singleton().workQueueManager().queueBackNavigation(stepCount); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) { ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); uint64_t stepCount = WKUInt64GetValue(static_cast(messageBody)); TestController::singleton().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())); WKRetainPtr shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs")); WKBooleanRef shouldOpenExternalURLsValueWK = static_cast(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(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::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(messageBody); TestController::singleton().workQueueManager().queueLoadingScript(toWTFString(script)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef script = static_cast(messageBody); TestController::singleton().workQueueManager().queueNonLoadingScript(toWTFString(script)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef value = static_cast(messageBody); TestController::singleton().setHandlesAuthenticationChallenges(WKBooleanGetValue(value)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef username = static_cast(messageBody); TestController::singleton().setAuthenticationUsername(toWTFString(username)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef password = static_cast(messageBody); TestController::singleton().setAuthenticationPassword(toWTFString(password)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetBlockAllPlugins")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef shouldBlock = static_cast(messageBody); TestController::singleton().setBlockAllPlugins(WKBooleanGetValue(shouldBlock)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDecideNavigationPolicyAfterDelay")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef value = static_cast(messageBody); TestController::singleton().setShouldDecideNavigationPolicyAfterDelay(WKBooleanGetValue(value)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetNavigationGesturesEnabled")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef value = static_cast(messageBody); TestController::singleton().setNavigationGesturesEnabled(WKBooleanGetValue(value)); return; } if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScript")) { WKDictionaryRef messageBodyDictionary = static_cast(messageBody); WKRetainPtr scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script")); WKRetainPtr callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID")); UIScriptInvocationData* invocationData = new UIScriptInvocationData(); invocationData->testInvocation = this; invocationData->callbackID = (unsigned)WKUInt64GetValue(static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get()))); invocationData->scriptString = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, scriptKey.get())); m_pendingUIScriptInvocationData = invocationData; WKPageCallAfterNextPresentationUpdate(TestController::singleton().mainWebView()->page(), invocationData, runUISideScriptAfterUpdateCallback); 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::singleton().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) { bool isActive = TestController::singleton().isGeolocationProviderActive(); WKRetainPtr result(AdoptWK, WKBooleanCreate(isActive)); return result; } if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) { bool isEmpty = TestController::singleton().workQueueManager().isWorkQueueEmpty(); WKRetainPtr result(AdoptWK, WKBooleanCreate(isEmpty)); return result; } if (WKStringIsEqualToUTF8CString(messageName, "SecureEventInputIsEnabled")) { #if PLATFORM(MAC) && !PLATFORM(IOS) WKRetainPtr result(AdoptWK, WKBooleanCreate(IsSecureEventInputEnabled())); #else WKRetainPtr result(AdoptWK, WKBooleanCreate(false)); #endif return result; } if (WKStringIsEqualToUTF8CString(messageName, "SetAlwaysAcceptCookies")) { WKBooleanRef accept = static_cast(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 nullptr; } ASSERT_NOT_REACHED(); return nullptr; } void TestInvocation::runUISideScriptAfterUpdateCallback(WKErrorRef, void* context) { UIScriptInvocationData* data = static_cast(context); if (TestInvocation* invocation = data->testInvocation) { RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(invocation)); invocation->runUISideScript(data->scriptString.get(), data->callbackID); } delete data; } void TestInvocation::runUISideScript(WKStringRef script, unsigned scriptCallbackID) { m_pendingUIScriptInvocationData = nullptr; if (!m_UIScriptContext) m_UIScriptContext = std::make_unique(*this); m_UIScriptContext->runUIScript(script, scriptCallbackID); } void TestInvocation::uiScriptDidComplete(WKStringRef result, unsigned scriptCallbackID) { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallUISideScriptCallback")); WKRetainPtr messageBody(AdoptWK, WKMutableDictionaryCreate()); WKRetainPtr resultKey(AdoptWK, WKStringCreateWithUTF8CString("Result")); WKRetainPtr callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID")); WKRetainPtr callbackIDValue = adoptWK(WKUInt64Create(scriptCallbackID)); WKDictionarySetItem(messageBody.get(), resultKey.get(), result); WKDictionarySetItem(messageBody.get(), callbackIDKey.get(), callbackIDValue.get()); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), messageBody.get()); } void TestInvocation::outputText(const WTF::String& text) { m_textOutput.append(text); } void TestInvocation::didBeginSwipe() { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidBeginSwipeCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); } void TestInvocation::willEndSwipe() { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallWillEndSwipeCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); } void TestInvocation::didEndSwipe() { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidEndSwipeCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); } void TestInvocation::didRemoveSwipeSnapshot() { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidRemoveSwipeSnapshotCallback")); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); } } // namespace WTR