/* * Copyright (C) 2010-2017 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 "DictionaryFunctions.h" #include "PlatformWebView.h" #include "TestController.h" #include "UIScriptController.h" #include "WebCoreTestSupport.h" #include #include #include #include #include #include #include #include #include #include #include #include #if PLATFORM(MAC) && !PLATFORM(IOS_FAMILY) #include #endif #if PLATFORM(COCOA) #include #endif #if PLATFORM(WIN) #include #define isatty _isatty #else #include #endif using namespace JSC; using namespace WebKit; using namespace std; namespace WTR { static void postPageMessage(const char* name, const WKRetainPtr& body) { WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), toWK(name).get(), body.get()); } static void postPageMessage(const char* name) { postPageMessage(name, WKRetainPtr { }); } TestInvocation::TestInvocation(WKURLRef url, const TestOptions& options) : m_options(options) , m_url(url) , m_waitToDumpWatchdogTimer(RunLoop::main(), this, &TestInvocation::waitToDumpWatchdogTimerFired) , m_waitForPostDumpWatchdogTimer(RunLoop::main(), this, &TestInvocation::waitForPostDumpWatchdogTimerFired) { m_urlString = toWTFString(adoptWK(WKURLCopyString(m_url.get())).get()); // FIXME: Avoid mutating the setting via a test directory like this. m_dumpFrameLoadCallbacks = urlContains("loading/") && !urlContains("://localhost"); } 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.containsIgnoringASCIICase(searchString); } void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash) { m_dumpPixels = true; m_expectedPixelHash = expectedPixelHash; } WTF::Seconds TestInvocation::shortTimeout() const { if (!m_timeout) { // Running WKTR directly, without webkitpy. return TestController::defaultShortTimeout; } // This is not exactly correct for the way short timeout is used - it should not depend on whether a test is "slow", // but it currently does. There is no way to know what a normal test's timeout is, as webkitpy only passes timeouts // for each test individually. // But there shouldn't be any observable negative consequences from this. return m_timeout / 4; } bool TestInvocation::shouldLogHistoryClientCallbacks() const { return urlContains("globalhistory/"); } WKRetainPtr TestInvocation::createTestSettingsDictionary() { auto beginTestMessageBody = adoptWK(WKMutableDictionaryCreate()); setValue(beginTestMessageBody, "UseFlexibleViewport", options().useFlexibleViewport()); setValue(beginTestMessageBody, "DumpPixels", m_dumpPixels); setValue(beginTestMessageBody, "Timeout", static_cast(m_timeout.milliseconds())); setValue(beginTestMessageBody, "DumpJSConsoleLogInStdErr", m_dumpJSConsoleLogInStdErr); setValue(beginTestMessageBody, "additionalSupportedImageTypes", options().additionalSupportedImageTypes().c_str()); return beginTestMessageBody; } void TestInvocation::invoke() { TestController::singleton().configureViewForTest(*this); WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), false); m_textOutput.clear(); TestController::singleton().setShouldLogHistoryClientCallbacks(shouldLogHistoryClientCallbacks()); WKHTTPCookieStoreSetHTTPCookieAcceptPolicy(WKWebsiteDataStoreGetHTTPCookieStore(TestController::singleton().websiteDataStore()), kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain, nullptr, nullptr); // FIXME: We should clear out visited links here. postPageMessage("BeginTest", createTestSettingsDictionary()); m_startedTesting = true; bool shouldOpenExternalURLs = false; TestController::singleton().runUntil(m_gotInitialResponse, TestController::noTimeout); 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_FAMILY) if (m_gotInitialResponse) WKInspectorClose(WKPageGetInspector(TestController::singleton().mainWebView()->page())); #endif // !PLATFORM(IOS_FAMILY) if (TestController::singleton().resetStateToConsistentValues(m_options, TestController::ResetStage::AfterTest)) return; // The process is unresponsive, so let's start a new one. 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(const char* errorMessage) { fprintf(stderr, "%s", errorMessage); char buffer[1024] = { }; #if PLATFORM(COCOA) pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page()); snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast(pid)); #else snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s\n", TestController::webProcessName()); #endif dump(errorMessage, buffer, true); if (!TestController::singleton().usingServerMode()) return; if (isatty(fileno(stdin)) || isatty(fileno(stderr))) fputs("Grab an image of the stack, then hit enter...\n", stderr); if (!fgets(buffer, sizeof(buffer), stdin) || strcmp(buffer, "#SAMPLE FINISHED\n")) fprintf(stderr, "Failed receive expected sample response, got:\n\t\"%s\"\nContinuing...\n", buffer); } 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_shouldDumpResourceLoadStatistics) m_textOutput.append(m_savedResourceLoadStatistics.isNull() ? TestController::singleton().dumpResourceLoadStatistics() : m_savedResourceLoadStatistics); if (m_shouldDumpPrivateClickMeasurement) m_textOutput.append(TestController::singleton().dumpPrivateClickMeasurement()); if (m_textOutput.length() || !m_audioResult) dump(m_textOutput.toString().utf8().data()); else dumpAudio(m_audioResult.get()); if (m_dumpPixels) { if (m_pixelResult) dumpPixelsAndCompareWithExpected(SnapshotResultType::WebContents, m_repaintRects.get(), m_pixelResult.get()); else if (m_pixelResultIsPending) { m_gotRepaint = false; WKPageForceRepaint(TestController::singleton().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback); TestController::singleton().runUntil(m_gotRepaint, TestController::noTimeout); dumpPixelsAndCompareWithExpected(SnapshotResultType::WebView, 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(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; TestController::singleton().notifyDone(); return; } if (WKStringIsEqualToUTF8CString(messageName, "Ack")) { if (WKStringIsEqualToUTF8CString(stringValue(messageBody), "BeginTest")) { m_gotInitialResponse = true; TestController::singleton().notifyDone(); return; } ASSERT_NOT_REACHED(); } if (WKStringIsEqualToUTF8CString(messageName, "Done")) { auto messageBodyDictionary = dictionaryValue(messageBody); m_pixelResultIsPending = booleanValue(messageBodyDictionary, "PixelResultIsPending"); if (!m_pixelResultIsPending) { m_pixelResult = static_cast(value(messageBodyDictionary, "PixelResult")); ASSERT(!m_pixelResult || m_dumpPixels); } m_repaintRects = static_cast(value(messageBodyDictionary, "RepaintRects")); m_audioResult = static_cast(value(messageBodyDictionary, "AudioResult")); done(); return; } if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) { m_textOutput.append(toWTFString(stringValue(messageBody))); return; } if (WKStringIsEqualToUTF8CString(messageName, "DumpToStdErr")) { fprintf(stderr, "%s", toWTFString(stringValue(messageBody)).utf8().data()); return; } if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) { TestController::singleton().setBeforeUnloadReturnValue(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) { TestController::singleton().mainWebView()->addChromeInputField(); postPageMessage("CallAddChromeInputFieldCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) { TestController::singleton().mainWebView()->removeChromeInputField(); postPageMessage("CallRemoveChromeInputFieldCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetTextInChromeInputField")) { TestController::singleton().mainWebView()->setTextInChromeInputField(toWTFString(stringValue(messageBody))); postPageMessage("CallSetTextInChromeInputFieldCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "SelectChromeInputField")) { TestController::singleton().mainWebView()->selectChromeInputField(); postPageMessage("CallSelectChromeInputFieldCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "GetSelectedTextInChromeInputField")) { auto selectedText = TestController::singleton().mainWebView()->getSelectedTextInChromeInputField(); postPageMessage("CallGetSelectedTextInChromeInputFieldCallback", toWK(selectedText)); return; } if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) { TestController::singleton().mainWebView()->makeWebViewFirstResponder(); postPageMessage("CallFocusWebViewCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) { WKPageSetCustomBackingScaleFactor(TestController::singleton().mainWebView()->page(), doubleValue(messageBody)); postPageMessage("CallSetBackingScaleFactorCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) { uint64_t notificationID = uint64Value(messageBody); TestController::singleton().simulateWebNotificationClick(notificationID); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAddsVisitedLinks")) { WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) { TestController::singleton().setGeolocationPermission(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto latitude = doubleValue(messageBodyDictionary, "latitude"); auto longitude = doubleValue(messageBodyDictionary, "longitude"); auto accuracy = doubleValue(messageBodyDictionary, "accuracy"); auto altitude = optionalDoubleValue(messageBodyDictionary, "altitude"); auto altitudeAccuracy = optionalDoubleValue(messageBodyDictionary, "altitudeAccuracy"); auto heading = optionalDoubleValue(messageBodyDictionary, "heading"); auto speed = optionalDoubleValue(messageBodyDictionary, "speed"); auto floorLevel = optionalDoubleValue(messageBodyDictionary, "floorLevel"); TestController::singleton().setMockGeolocationPosition(latitude, longitude, accuracy, altitude, altitudeAccuracy, heading, speed, floorLevel); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) { WKStringRef errorMessage = stringValue(messageBody); TestController::singleton().setMockGeolocationPositionUnavailableError(errorMessage); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermission")) { TestController::singleton().setUserMediaPermission(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "ResetUserMediaPermission")) { TestController::singleton().resetUserMediaPermission(); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPersistentPermissionForOrigin")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto permission = booleanValue(messageBodyDictionary, "permission"); auto originWK = stringValue(messageBodyDictionary, "origin"); auto parentOriginWK = stringValue(messageBodyDictionary, "parentOrigin"); TestController::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK, parentOriginWK); return; } if (WKStringIsEqualToUTF8CString(messageName, "ResetUserMediaPermissionRequestCountForOrigin")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto originWK = stringValue(messageBodyDictionary, "origin"); auto parentOriginWK = stringValue(messageBodyDictionary, "parentOrigin"); TestController::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK, parentOriginWK); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto enabled = booleanValue(messageBodyDictionary, "enabled"); auto permissive = booleanValue(messageBodyDictionary, "permissive"); TestController::singleton().setCustomPolicyDelegate(enabled, permissive); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetHidden")) { auto messageBodyDictionary = dictionaryValue(messageBody); TestController::singleton().setHidden(booleanValue(messageBodyDictionary, "hidden")); return; } if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) { if (TestController::singleton().workQueueManager().processWorkQueue()) postPageMessage("WorkQueueProcessedCallback"); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) { TestController::singleton().workQueueManager().queueBackNavigation(uint64Value(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) { TestController::singleton().workQueueManager().queueForwardNavigation(uint64Value(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) { auto loadDataDictionary = dictionaryValue(messageBody); auto url = toWTFString(stringValue(loadDataDictionary, "url")); auto target = toWTFString(stringValue(loadDataDictionary, "target")); auto shouldOpenExternalURLs = booleanValue(loadDataDictionary, "shouldOpenExternalURLs"); TestController::singleton().workQueueManager().queueLoad(url, target, shouldOpenExternalURLs); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) { auto loadDataDictionary = dictionaryValue(messageBody); auto contentWK = stringValue(loadDataDictionary, "content"); auto baseURLWK = stringValue(loadDataDictionary, "baseURL"); auto unreachableURLWK = stringValue(loadDataDictionary, "unreachableURL"); 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")) { WKStringRef script = stringValue(messageBody); TestController::singleton().workQueueManager().queueLoadingScript(toWTFString(script)); return; } if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) { WKStringRef script = stringValue(messageBody); TestController::singleton().workQueueManager().queueNonLoadingScript(toWTFString(script)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")) { TestController::singleton().setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenges")) { TestController::singleton().setHandlesAuthenticationChallenges(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldLogCanAuthenticateAgainstProtectionSpace")) { TestController::singleton().setShouldLogCanAuthenticateAgainstProtectionSpace(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldLogDownloadCallbacks")) { TestController::singleton().setShouldLogDownloadCallbacks(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) { WKStringRef username = stringValue(messageBody); TestController::singleton().setAuthenticationUsername(toWTFString(username)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) { WKStringRef password = stringValue(messageBody); TestController::singleton().setAuthenticationPassword(toWTFString(password)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetBlockAllPlugins")) { TestController::singleton().setBlockAllPlugins(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetPluginSupportedMode")) { WKStringRef mode = stringValue(messageBody); TestController::singleton().setPluginSupportedMode(toWTFString(mode)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDecideNavigationPolicyAfterDelay")) { TestController::singleton().setShouldDecideNavigationPolicyAfterDelay(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDecideResponsePolicyAfterDelay")) { TestController::singleton().setShouldDecideResponsePolicyAfterDelay(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetNavigationGesturesEnabled")) { TestController::singleton().setNavigationGesturesEnabled(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetIgnoresViewportScaleLimits")) { TestController::singleton().setIgnoresViewportScaleLimits(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDownloadUndisplayableMIMETypes")) { TestController::singleton().setShouldDownloadUndisplayableMIMETypes(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldAllowDeviceOrientationAndMotionAccess")) { TestController::singleton().setShouldAllowDeviceOrientationAndMotionAccess(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsShouldBlockThirdPartyCookiesOnSitesWithoutUserInteraction")) { TestController::singleton().setStatisticsShouldBlockThirdPartyCookies(booleanValue(messageBody), true); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsShouldBlockThirdPartyCookies")) { TestController::singleton().setStatisticsShouldBlockThirdPartyCookies(booleanValue(messageBody), false); return; } if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScript")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto invocationData = new UIScriptInvocationData; invocationData->testInvocation = this; invocationData->callbackID = uint64Value(messageBodyDictionary, "CallbackID"); invocationData->scriptString = stringValue(messageBodyDictionary, "Script"); m_pendingUIScriptInvocationData = invocationData; WKPageCallAfterNextPresentationUpdate(TestController::singleton().mainWebView()->page(), invocationData, runUISideScriptAfterUpdateCallback); return; } if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScriptImmediately")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto invocationData = new UIScriptInvocationData; invocationData->testInvocation = this; invocationData->callbackID = uint64Value(messageBodyDictionary, "CallbackID"); invocationData->scriptString = stringValue(messageBodyDictionary, "Script"); m_pendingUIScriptInvocationData = invocationData; runUISideScriptImmediately(nullptr, invocationData); return; } if (WKStringIsEqualToUTF8CString(messageName, "InstallCustomMenuAction")) { auto messageBodyDictionary = static_cast(messageBody); auto name = stringValue(messageBodyDictionary, "name"); auto dismissesAutomatically = booleanValue(messageBodyDictionary, "dismissesAutomatically"); TestController::singleton().installCustomMenuAction(toWTFString(name), dismissesAutomatically); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAllowedMenuActions")) { auto messageBodyArray = static_cast(messageBody); auto size = WKArrayGetSize(messageBodyArray); Vector actions; actions.reserveInitialCapacity(size); for (size_t index = 0; index < size; ++index) actions.append(toWTFString(stringValue(WKArrayGetItemAtIndex(messageBodyArray, index)))); TestController::singleton().setAllowedMenuActions(actions); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetOpenPanelFileURLs")) { TestController::singleton().setOpenPanelFileURLs(static_cast(messageBody)); return; } #if PLATFORM(IOS_FAMILY) if (WKStringIsEqualToUTF8CString(messageName, "SetOpenPanelFileURLsMediaIcon")) { TestController::singleton().setOpenPanelFileURLsMediaIcon(static_cast(messageBody)); return; } #endif if (WKStringIsEqualToUTF8CString(messageName, "LoadedSubresourceDomains")) { TestController::singleton().loadedSubresourceDomains(); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsDebugMode")) { TestController::singleton().setStatisticsDebugMode(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsPrevalentResourceForDebugMode")) { WKStringRef hostName = stringValue(messageBody); TestController::singleton().setStatisticsPrevalentResourceForDebugMode(hostName); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsLastSeen")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto value = doubleValue(messageBodyDictionary, "Value"); TestController::singleton().setStatisticsLastSeen(hostName, value); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsMergeStatistic")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto topFrameDomain1 = stringValue(messageBodyDictionary, "TopFrameDomain1"); auto topFrameDomain2 = stringValue(messageBodyDictionary, "TopFrameDomain2"); auto lastSeen = doubleValue(messageBodyDictionary, "LastSeen"); auto hadUserInteraction = booleanValue(messageBodyDictionary, "HadUserInteraction"); auto mostRecentUserInteraction = doubleValue(messageBodyDictionary, "MostRecentUserInteraction"); auto isGrandfathered = booleanValue(messageBodyDictionary, "IsGrandfathered"); auto isPrevalent = booleanValue(messageBodyDictionary, "IsPrevalent"); auto isVeryPrevalent = booleanValue(messageBodyDictionary, "IsVeryPrevalent"); auto dataRecordsRemoved = uint64Value(messageBodyDictionary, "DataRecordsRemoved"); TestController::singleton().setStatisticsMergeStatistic(hostName, topFrameDomain1, topFrameDomain2, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsExpiredStatistic")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto numberOfOperatingDaysPassed = uint64Value(messageBodyDictionary, "NumberOfOperatingDaysPassed"); auto hadUserInteraction = booleanValue(messageBodyDictionary, "HadUserInteraction"); auto isScheduledForAllButCookieDataRemoval = booleanValue(messageBodyDictionary, "IsScheduledForAllButCookieDataRemoval"); auto isPrevalent = booleanValue(messageBodyDictionary, "IsPrevalent"); TestController::singleton().setStatisticsExpiredStatistic(hostName, numberOfOperatingDaysPassed, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsPrevalentResource")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto value = booleanValue(messageBodyDictionary, "Value"); TestController::singleton().setStatisticsPrevalentResource(hostName, value); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsVeryPrevalentResource")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto value = booleanValue(messageBodyDictionary, "Value"); TestController::singleton().setStatisticsVeryPrevalentResource(hostName, value); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsClearInMemoryAndPersistentStore")) { TestController::singleton().statisticsClearInMemoryAndPersistentStore(); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsClearThroughWebsiteDataRemoval")) { TestController::singleton().statisticsClearThroughWebsiteDataRemoval(); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours")) { TestController::singleton().statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(uint64Value(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsShouldDowngradeReferrer")) { TestController::singleton().setStatisticsShouldDowngradeReferrer(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsFirstPartyWebsiteDataRemovalMode")) { TestController::singleton().setStatisticsFirstPartyWebsiteDataRemovalMode(booleanValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsSetToSameSiteStrictCookies")) { TestController::singleton().setStatisticsToSameSiteStrictCookies(stringValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsSetFirstPartyHostCNAMEDomain")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto firstPartyURLString = stringValue(messageBodyDictionary, "FirstPartyURL"); auto cnameURLString = stringValue(messageBodyDictionary, "CNAME"); TestController::singleton().setStatisticsFirstPartyHostCNAMEDomain(firstPartyURLString, cnameURLString); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsSetThirdPartyCNAMEDomain")) { TestController::singleton().setStatisticsThirdPartyCNAMEDomain(stringValue(messageBody)); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsResetToConsistentState")) { if (m_shouldDumpResourceLoadStatistics) m_savedResourceLoadStatistics = TestController::singleton().dumpResourceLoadStatistics(); TestController::singleton().statisticsResetToConsistentState(); return; } if (WKStringIsEqualToUTF8CString(messageName, "GetAllStorageAccessEntries")) { TestController::singleton().getAllStorageAccessEntries(); return; } if (WKStringIsEqualToUTF8CString(messageName, "RemoveAllSessionCredentials")) { TestController::singleton().removeAllSessionCredentials(); return; } if (WKStringIsEqualToUTF8CString(messageName, "GetApplicationManifest")) { #ifdef __BLOCKS__ WKPageGetApplicationManifest_b(TestController::singleton().mainWebView()->page(), ^{ postPageMessage("DidGetApplicationManifest"); }); #else // FIXME: Add API for loading the manifest on non-__BLOCKS__ ports. ASSERT_NOT_REACHED(); #endif return; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsHasHadUserInteraction")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto value = booleanValue(messageBodyDictionary, "Value"); TestController::singleton().setStatisticsHasHadUserInteraction(hostName, value); return; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsUpdateCookieBlocking")) { TestController::singleton().statisticsUpdateCookieBlocking(); return; } if (WKStringIsEqualToUTF8CString(messageName, "SetAppBoundDomains")) { ASSERT(WKGetTypeID(messageBody) == WKArrayGetTypeID()); TestController::singleton().setAppBoundDomains(static_cast(messageBody)); return; } ASSERT_NOT_REACHED(); } WKRetainPtr TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody) { if (WKStringIsEqualToUTF8CString(messageName, "Initialization")) { auto settings = createTestSettingsDictionary(); setValue(settings, "ResumeTesting", m_startedTesting); return settings; } if (WKStringIsEqualToUTF8CString(messageName, "SetDumpPixels")) { m_dumpPixels = booleanValue(messageBody); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "GetDumpPixels")) return adoptWK(WKBooleanCreate(m_dumpPixels)); if (WKStringIsEqualToUTF8CString(messageName, "SetWhatToDump")) { m_whatToDump = static_cast(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "GetWhatToDump")) return adoptWK(WKUInt64Create(static_cast(m_whatToDump))); if (WKStringIsEqualToUTF8CString(messageName, "SetWaitUntilDone")) { setWaitUntilDone(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "GetWaitUntilDone")) return adoptWK(WKBooleanCreate(m_waitUntilDone)); if (WKStringIsEqualToUTF8CString(messageName, "SetDumpFrameLoadCallbacks")) { m_dumpFrameLoadCallbacks = booleanValue(messageBody); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "GetDumpFrameLoadCallbacks")) return adoptWK(WKBooleanCreate(m_dumpFrameLoadCallbacks)); if (WKStringIsEqualToUTF8CString(messageName, "SetCanOpenWindows")) { m_canOpenWindows = booleanValue(messageBody); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) { TestController::singleton().mainWebView()->setWindowIsKey(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetViewSize")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto width = doubleValue(messageBodyDictionary, "width"); auto height = doubleValue(messageBodyDictionary, "height"); TestController::singleton().mainWebView()->resizeTo(width, height); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) return adoptWK(WKBooleanCreate(TestController::singleton().isGeolocationProviderActive())); if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) { uint64_t model = uint64Value(messageBody); WKWebsiteDataStoreSetCacheModelSynchronouslyForTesting(TestController::singleton().websiteDataStore(), model); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) return adoptWK(WKBooleanCreate(TestController::singleton().workQueueManager().isWorkQueueEmpty())); if (WKStringIsEqualToUTF8CString(messageName, "DidReceiveServerRedirectForProvisionalNavigation")) return adoptWK(WKBooleanCreate(TestController::singleton().didReceiveServerRedirectForProvisionalNavigation())); if (WKStringIsEqualToUTF8CString(messageName, "ClearDidReceiveServerRedirectForProvisionalNavigation")) { TestController::singleton().clearDidReceiveServerRedirectForProvisionalNavigation(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SecureEventInputIsEnabled")) { #if PLATFORM(MAC) return adoptWK(WKBooleanCreate(IsSecureEventInputEnabled())); #else return adoptWK(WKBooleanCreate(false)); #endif } if (WKStringIsEqualToUTF8CString(messageName, "SetCustomUserAgent")) { WKPageSetCustomUserAgent(TestController::singleton().mainWebView()->page(), stringValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetAllowsAnySSLCertificate")) { TestController::singleton().setAllowsAnySSLCertificate(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldSwapToEphemeralSessionOnNextNavigation")) { TestController::singleton().setShouldSwapToEphemeralSessionOnNextNavigation(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetShouldSwapToDefaultSessionOnNextNavigation")) { TestController::singleton().setShouldSwapToDefaultSessionOnNextNavigation(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ImageCountInGeneralPasteboard")) return adoptWK(WKUInt64Create(TestController::singleton().imageCountInGeneralPasteboard())); if (WKStringIsEqualToUTF8CString(messageName, "DeleteAllIndexedDatabases")) { WKWebsiteDataStoreRemoveAllIndexedDatabases(TestController::singleton().websiteDataStore(), nullptr, { }); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "AddMockMediaDevice")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto persistentID = stringValue(messageBodyDictionary, "PersistentID"); auto label = stringValue(messageBodyDictionary, "Label"); auto type = stringValue(messageBodyDictionary, "Type"); TestController::singleton().addMockMediaDevice(persistentID, label, type); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ClearMockMediaDevices")) { TestController::singleton().clearMockMediaDevices(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "RemoveMockMediaDevice")) { TestController::singleton().removeMockMediaDevice(stringValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ResetMockMediaDevices")) { TestController::singleton().resetMockMediaDevices(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockCameraOrientation")) { TestController::singleton().setMockCameraOrientation(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsMockRealtimeMediaSourceCenterEnabled")) return adoptWK(WKBooleanCreate(TestController::singleton().isMockRealtimeMediaSourceCenterEnabled())); if (WKStringIsEqualToUTF8CString(messageName, "HasAppBoundSession")) return adoptWK(WKBooleanCreate(TestController::singleton().hasAppBoundSession())); #if ENABLE(GAMEPAD) if (WKStringIsEqualToUTF8CString(messageName, "ConnectMockGamepad")) { WebCoreTestSupport::connectMockGamepad(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "DisconnectMockGamepad")) { WebCoreTestSupport::disconnectMockGamepad(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadDetails")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto gamepadIndex = uint64Value(messageBodyDictionary, "GamepadIndex"); auto gamepadID = stringValue(messageBodyDictionary, "GamepadID"); auto mapping = stringValue(messageBodyDictionary, "Mapping"); auto axisCount = uint64Value(messageBodyDictionary, "AxisCount"); auto buttonCount = uint64Value(messageBodyDictionary, "ButtonCount"); WebCoreTestSupport::setMockGamepadDetails(gamepadIndex, toWTFString(gamepadID), toWTFString(mapping), axisCount, buttonCount); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadAxisValue")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto gamepadIndex = uint64Value(messageBodyDictionary, "GamepadIndex"); auto axisIndex = uint64Value(messageBodyDictionary, "AxisIndex"); auto value = doubleValue(messageBodyDictionary, "Value"); WebCoreTestSupport::setMockGamepadAxisValue(gamepadIndex, axisIndex, value); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadButtonValue")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto gamepadIndex = uint64Value(messageBodyDictionary, "GamepadIndex"); auto buttonIndex = uint64Value(messageBodyDictionary, "ButtonIndex"); auto value = doubleValue(messageBodyDictionary, "Value"); WebCoreTestSupport::setMockGamepadButtonValue(gamepadIndex, buttonIndex, value); return nullptr; } #endif // ENABLE(GAMEPAD) if (WKStringIsEqualToUTF8CString(messageName, "UserMediaPermissionRequestCountForOrigin")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto originWK = stringValue(messageBodyDictionary, "origin"); auto parentOriginWK = stringValue(messageBodyDictionary, "parentOrigin"); unsigned count = TestController::singleton().userMediaPermissionRequestCountForOrigin(originWK, parentOriginWK); return adoptWK(WKUInt64Create(count)); } if (WKStringIsEqualToUTF8CString(messageName, "IsDoingMediaCapture")) return adoptWK(WKBooleanCreate(TestController::singleton().isDoingMediaCapture())); if (WKStringIsEqualToUTF8CString(messageName, "ClearStatisticsDataForDomain")) { TestController::singleton().clearStatisticsDataForDomain(stringValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "DoesStatisticsDomainIDExistInDatabase")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto domainID = uint64Value(messageBodyDictionary, "DomainID"); bool domainIDExists = TestController::singleton().doesStatisticsDomainIDExistInDatabase(domainID); return adoptWK(WKBooleanCreate(domainIDExists)); } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsEnabled")) { TestController::singleton().setStatisticsEnabled(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsEphemeral")) { return adoptWK(WKBooleanCreate(TestController::singleton().isStatisticsEphemeral())); } if (WKStringIsEqualToUTF8CString(messageName, "dumpResourceLoadStatistics")) { dumpResourceLoadStatistics(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsPrevalentResource")) { bool isPrevalent = TestController::singleton().isStatisticsPrevalentResource(stringValue(messageBody)); return adoptWK(WKBooleanCreate(isPrevalent)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsVeryPrevalentResource")) { bool isPrevalent = TestController::singleton().isStatisticsVeryPrevalentResource(stringValue(messageBody)); return adoptWK(WKBooleanCreate(isPrevalent)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsRegisteredAsSubresourceUnder")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto subresourceHost = stringValue(messageBodyDictionary, "SubresourceHost"); auto topFrameHost = stringValue(messageBodyDictionary, "TopFrameHost"); bool isRegisteredAsSubresourceUnder = TestController::singleton().isStatisticsRegisteredAsSubresourceUnder(subresourceHost, topFrameHost); return adoptWK(WKBooleanCreate(isRegisteredAsSubresourceUnder)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsRegisteredAsSubFrameUnder")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto subFrameHost = stringValue(messageBodyDictionary, "SubFrameHost"); auto topFrameHost = stringValue(messageBodyDictionary, "TopFrameHost"); bool isRegisteredAsSubFrameUnder = TestController::singleton().isStatisticsRegisteredAsSubFrameUnder(subFrameHost, topFrameHost); return adoptWK(WKBooleanCreate(isRegisteredAsSubFrameUnder)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsRegisteredAsRedirectingTo")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostRedirectedFrom = stringValue(messageBodyDictionary, "HostRedirectedFrom"); auto hostRedirectedTo = stringValue(messageBodyDictionary, "HostRedirectedTo"); bool isRegisteredAsRedirectingTo = TestController::singleton().isStatisticsRegisteredAsRedirectingTo(hostRedirectedFrom, hostRedirectedTo); return adoptWK(WKBooleanCreate(isRegisteredAsRedirectingTo)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsHasHadUserInteraction")) { bool hasHadUserInteraction = TestController::singleton().isStatisticsHasHadUserInteraction(stringValue(messageBody)); return adoptWK(WKBooleanCreate(hasHadUserInteraction)); } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsOnlyInDatabaseOnce")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto subHost = stringValue(messageBodyDictionary, "SubHost"); auto topHost = stringValue(messageBodyDictionary, "TopHost"); bool statisticInDatabaseOnce = TestController::singleton().isStatisticsOnlyInDatabaseOnce(subHost, topHost); return adoptWK(WKBooleanCreate(statisticInDatabaseOnce)); } if (WKStringIsEqualToUTF8CString(messageName, "DidLoadAppInitiatedRequest")) return adoptWK(WKBooleanCreate(TestController::singleton().didLoadAppInitiatedRequest())); if (WKStringIsEqualToUTF8CString(messageName, "DidLoadNonAppInitiatedRequest")) return adoptWK(WKBooleanCreate(TestController::singleton().didLoadNonAppInitiatedRequest())); if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsGrandfathered")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto value = booleanValue(messageBodyDictionary, "Value"); TestController::singleton().setStatisticsGrandfathered(hostName, value); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsGrandfathered")) { bool isGrandfathered = TestController::singleton().isStatisticsGrandfathered(stringValue(messageBody)); return adoptWK(WKBooleanCreate(isGrandfathered)); } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubframeUnderTopFrameOrigin")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto topFrameHostName = stringValue(messageBodyDictionary, "TopFrameHostName"); TestController::singleton().setStatisticsSubframeUnderTopFrameOrigin(hostName, topFrameHostName); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUnderTopFrameOrigin")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto topFrameHostName = stringValue(messageBodyDictionary, "TopFrameHostName"); TestController::singleton().setStatisticsSubresourceUnderTopFrameOrigin(hostName, topFrameHostName); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUniqueRedirectTo")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto hostNameRedirectedTo = stringValue(messageBodyDictionary, "HostNameRedirectedTo"); TestController::singleton().setStatisticsSubresourceUniqueRedirectTo(hostName, hostNameRedirectedTo); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUniqueRedirectFrom")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto hostNameRedirectedFrom = stringValue(messageBodyDictionary, "HostNameRedirectedFrom"); TestController::singleton().setStatisticsSubresourceUniqueRedirectFrom(hostName, hostNameRedirectedFrom); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTopFrameUniqueRedirectTo")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto hostNameRedirectedTo = stringValue(messageBodyDictionary, "HostNameRedirectedTo"); TestController::singleton().setStatisticsTopFrameUniqueRedirectTo(hostName, hostNameRedirectedTo); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTopFrameUniqueRedirectFrom")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto hostNameRedirectedFrom = stringValue(messageBodyDictionary, "HostNameRedirectedFrom"); TestController::singleton().setStatisticsTopFrameUniqueRedirectFrom(hostName, hostNameRedirectedFrom); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCrossSiteLoadWithLinkDecoration")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto fromHost = stringValue(messageBodyDictionary, "FromHost"); auto toHost = stringValue(messageBodyDictionary, "ToHost"); TestController::singleton().setStatisticsCrossSiteLoadWithLinkDecoration(fromHost, toHost); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTimeToLiveUserInteraction")) { TestController::singleton().setStatisticsTimeToLiveUserInteraction(doubleValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsProcessStatisticsAndDataRecords")) { TestController::singleton().statisticsProcessStatisticsAndDataRecords(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsNotifyPagesWhenDataRecordsWereScanned")) { TestController::singleton().setStatisticsNotifyPagesWhenDataRecordsWereScanned(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsSetIsRunningTest")) { TestController::singleton().setStatisticsIsRunningTest(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval")) { TestController::singleton().setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsMinimumTimeBetweenDataRecordsRemoval")) { TestController::singleton().setStatisticsMinimumTimeBetweenDataRecordsRemoval(doubleValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsGrandfatheringTime")) { TestController::singleton().setStatisticsGrandfatheringTime(doubleValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetMaxStatisticsEntries")) { TestController::singleton().setStatisticsMaxStatisticsEntries(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPruneEntriesDownTo")) { TestController::singleton().setStatisticsPruneEntriesDownTo(uint64Value(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "StatisticsDeleteCookiesForHost")) { auto messageBodyDictionary = dictionaryValue(messageBody); auto hostName = stringValue(messageBodyDictionary, "HostName"); auto includeHttpOnlyCookies = booleanValue(messageBodyDictionary, "IncludeHttpOnlyCookies"); TestController::singleton().statisticsDeleteCookiesForHost(hostName, includeHttpOnlyCookies); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsHasLocalStorage")) { auto hostName = stringValue(messageBody); bool hasLocalStorage = TestController::singleton().isStatisticsHasLocalStorage(hostName); auto result = adoptWK(WKBooleanCreate(hasLocalStorage)); return result; } if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCacheMaxAgeCap")) { TestController::singleton().setStatisticsCacheMaxAgeCap(doubleValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "HasStatisticsIsolatedSession")) { auto hostName = stringValue(messageBody); bool hasIsolatedSession = TestController::singleton().hasStatisticsIsolatedSession(hostName); auto result = adoptWK(WKBooleanCreate(hasIsolatedSession)); return result; } if (WKStringIsEqualToUTF8CString(messageName, "ClearDOMCache")) { auto origin = stringValue(messageBody); TestController::singleton().clearDOMCache(origin); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ClearDOMCaches")) { TestController::singleton().clearDOMCaches(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "HasDOMCache")) { auto origin = stringValue(messageBody); bool hasDOMCache = TestController::singleton().hasDOMCache(origin); return adoptWK(WKBooleanCreate(hasDOMCache)); } if (WKStringIsEqualToUTF8CString(messageName, "DOMCacheSize")) { auto origin = stringValue(messageBody); auto domCacheSize = TestController::singleton().domCacheSize(origin); return adoptWK(WKUInt64Create(domCacheSize)); } if (WKStringIsEqualToUTF8CString(messageName, "SetAllowStorageQuotaIncrease")) { TestController::singleton().setAllowStorageQuotaIncrease(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "InjectUserScript")) { TestController::singleton().injectUserScript(stringValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SendDisplayConfigurationChangedMessageForTesting")) { TestController::singleton().sendDisplayConfigurationChangedMessageForTesting(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetServiceWorkerFetchTimeout")) { TestController::singleton().setServiceWorkerFetchTimeoutForTesting(doubleValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetUseSeparateServiceWorkerProcess")) { auto useSeparateServiceWorkerProcess = booleanValue(messageBody); WKContextSetUseSeparateServiceWorkerProcess(TestController::singleton().context(), useSeparateServiceWorkerProcess); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "TerminateNetworkProcess")) { ASSERT(!messageBody); TestController::singleton().terminateNetworkProcess(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "TerminateServiceWorkers")) { ASSERT(!messageBody); TestController::singleton().terminateServiceWorkers(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "AddTestKeyToKeychain")) { auto testKeyDictionary = dictionaryValue(messageBody); auto privateKeyWK = stringValue(testKeyDictionary, "PrivateKey"); auto attrLabelWK = stringValue(testKeyDictionary, "AttrLabel"); auto applicationTagWK = stringValue(testKeyDictionary, "ApplicationTag"); TestController::singleton().addTestKeyToKeychain(toWTFString(privateKeyWK), toWTFString(attrLabelWK), toWTFString(applicationTagWK)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "CleanUpKeychain")) { auto testDictionary = dictionaryValue(messageBody); auto attrLabelWK = stringValue(testDictionary, "AttrLabel"); auto applicationLabelWK = stringValue(testDictionary, "ApplicationLabel"); TestController::singleton().cleanUpKeychain(toWTFString(attrLabelWK), applicationLabelWK ? toWTFString(applicationLabelWK) : String()); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "KeyExistsInKeychain")) { auto testDictionary = dictionaryValue(messageBody); auto attrLabelWK = stringValue(testDictionary, "AttrLabel"); auto applicationLabelWK = stringValue(testDictionary, "ApplicationLabel"); bool keyExistsInKeychain = TestController::singleton().keyExistsInKeychain(toWTFString(attrLabelWK), toWTFString(applicationLabelWK)); return adoptWK(WKBooleanCreate(keyExistsInKeychain)); } if (WKStringIsEqualToUTF8CString(messageName, "ServerTrustEvaluationCallbackCallsCount")) return adoptWK(WKUInt64Create(TestController::singleton().serverTrustEvaluationCallbackCallsCount())); if (WKStringIsEqualToUTF8CString(messageName, "ShouldDismissJavaScriptAlertsAsynchronously")) { TestController::singleton().setShouldDismissJavaScriptAlertsAsynchronously(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "AbortModal")) { TestController::singleton().abortModal(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "DumpPrivateClickMeasurement")) { dumpPrivateClickMeasurement(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ClearPrivateClickMeasurement")) { TestController::singleton().clearPrivateClickMeasurement(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ClearPrivateClickMeasurementsThroughWebsiteDataRemoval")) { TestController::singleton().clearPrivateClickMeasurementsThroughWebsiteDataRemoval(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "ClearAppBoundSession")) { TestController::singleton().clearAppBoundSession(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPrivateClickMeasurementOverrideTimerForTesting")) { TestController::singleton().setPrivateClickMeasurementOverrideTimerForTesting(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "MarkAttributedPrivateClickMeasurementsAsExpiredForTesting")) { TestController::singleton().markAttributedPrivateClickMeasurementsAsExpiredForTesting(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SimulateResourceLoadStatisticsSessionRestart")) { TestController::singleton().simulateResourceLoadStatisticsSessionRestart(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPrivateClickMeasurementTokenPublicKeyURLForTesting")) { ASSERT(WKGetTypeID(messageBody) == WKURLGetTypeID()); TestController::singleton().setPrivateClickMeasurementTokenPublicKeyURLForTesting(static_cast(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPrivateClickMeasurementTokenSignatureURLForTesting")) { ASSERT(WKGetTypeID(messageBody) == WKURLGetTypeID()); TestController::singleton().setPrivateClickMeasurementTokenSignatureURLForTesting(static_cast(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPrivateClickMeasurementAttributionReportURLsForTesting")) { auto testDictionary = dictionaryValue(messageBody); auto sourceURL = adoptWK(WKURLCreateWithUTF8CString(toWTFString(stringValue(testDictionary, "SourceURLString")).utf8().data())); auto destinationURL = adoptWK(WKURLCreateWithUTF8CString(toWTFString(stringValue(testDictionary, "AttributeOnURLString")).utf8().data())); TestController::singleton().setPrivateClickMeasurementAttributionReportURLsForTesting(sourceURL.get(), destinationURL.get()); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "MarkPrivateClickMeasurementsAsExpiredForTesting")) { TestController::singleton().markPrivateClickMeasurementsAsExpiredForTesting(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetPCMFraudPreventionValuesForTesting")) { auto testDictionary = dictionaryValue(messageBody); auto unlinkableToken = stringValue(testDictionary, "UnlinkableToken"); auto secretToken = stringValue(testDictionary, "SecretToken"); auto signature = stringValue(testDictionary, "Signature"); auto keyID = stringValue(testDictionary, "KeyID"); TestController::singleton().setPCMFraudPreventionValuesForTesting(unlinkableToken, secretToken, signature, keyID); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SyncLocalStorage")) { TestController::singleton().syncLocalStorage(); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetIsSpeechRecognitionPermissionGranted")) { TestController::singleton().setIsSpeechRecognitionPermissionGranted(booleanValue(messageBody)); return nullptr; } if (WKStringIsEqualToUTF8CString(messageName, "SetIsMediaKeySystemPermissionGranted")) { TestController::singleton().setIsMediaKeySystemPermissionGranted(booleanValue(messageBody)); return nullptr; } ASSERT_NOT_REACHED(); return nullptr; } void TestInvocation::runUISideScriptImmediately(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::runUISideScriptAfterUpdateCallback(WKErrorRef error, void* context) { runUISideScriptImmediately(error, context); } void TestInvocation::runUISideScript(WKStringRef script, unsigned scriptCallbackID) { m_pendingUIScriptInvocationData = nullptr; if (!m_UIScriptContext) m_UIScriptContext = makeUnique(*this, UIScriptController::create); m_UIScriptContext->runUIScript(toWTFString(script), scriptCallbackID); } void TestInvocation::uiScriptDidComplete(const String& result, unsigned scriptCallbackID) { auto messageBody = adoptWK(WKMutableDictionaryCreate()); setValue(messageBody, "Result", result); setValue(messageBody, "CallbackID", static_cast(scriptCallbackID)); postPageMessage("CallUISideScriptCallback", messageBody); } void TestInvocation::outputText(const WTF::String& text) { m_textOutput.append(text); } void TestInvocation::didBeginSwipe() { postPageMessage("CallDidBeginSwipeCallback"); } void TestInvocation::willEndSwipe() { postPageMessage("CallWillEndSwipeCallback"); } void TestInvocation::didEndSwipe() { postPageMessage("CallDidEndSwipeCallback"); } void TestInvocation::didRemoveSwipeSnapshot() { postPageMessage("CallDidRemoveSwipeSnapshotCallback"); } void TestInvocation::notifyDownloadDone() { postPageMessage("NotifyDownloadDone"); } void TestInvocation::didClearStatisticsInMemoryAndPersistentStore() { postPageMessage("CallDidClearStatisticsInMemoryAndPersistentStore"); } void TestInvocation::didClearStatisticsThroughWebsiteDataRemoval() { postPageMessage("CallDidClearStatisticsThroughWebsiteDataRemoval"); } void TestInvocation::didSetShouldDowngradeReferrer() { postPageMessage("CallDidSetShouldDowngradeReferrer"); } void TestInvocation::didSetShouldBlockThirdPartyCookies() { postPageMessage("CallDidSetShouldBlockThirdPartyCookies"); } void TestInvocation::didSetFirstPartyWebsiteDataRemovalMode() { postPageMessage("CallDidSetFirstPartyWebsiteDataRemovalMode"); } void TestInvocation::didSetToSameSiteStrictCookies() { postPageMessage("CallDidSetToSameSiteStrictCookies"); } void TestInvocation::didSetFirstPartyHostCNAMEDomain() { postPageMessage("CallDidSetFirstPartyHostCNAMEDomain"); } void TestInvocation::didSetThirdPartyCNAMEDomain() { postPageMessage("CallDidSetThirdPartyCNAMEDomain"); } void TestInvocation::didResetStatisticsToConsistentState() { postPageMessage("CallDidResetStatisticsToConsistentState"); } void TestInvocation::didSetBlockCookiesForHost() { postPageMessage("CallDidSetBlockCookiesForHost"); } void TestInvocation::didSetStatisticsDebugMode() { postPageMessage("CallDidSetStatisticsDebugMode"); } void TestInvocation::didSetPrevalentResourceForDebugMode() { postPageMessage("CallDidSetPrevalentResourceForDebugMode"); } void TestInvocation::didSetLastSeen() { postPageMessage("CallDidSetLastSeen"); } void TestInvocation::didMergeStatistic() { postPageMessage("CallDidMergeStatistic"); } void TestInvocation::didSetExpiredStatistic() { postPageMessage("CallDidSetExpiredStatistic"); } void TestInvocation::didSetPrevalentResource() { postPageMessage("CallDidSetPrevalentResource"); } void TestInvocation::didSetVeryPrevalentResource() { postPageMessage("CallDidSetVeryPrevalentResource"); } void TestInvocation::didSetHasHadUserInteraction() { postPageMessage("CallDidSetHasHadUserInteraction"); } void TestInvocation::didReceiveAllStorageAccessEntries(Vector&& domains) { auto messageBody = adoptWK(WKMutableArrayCreate()); for (auto& domain : domains) WKArrayAppendItem(messageBody.get(), toWK(domain).get()); postPageMessage("CallDidReceiveAllStorageAccessEntries", messageBody); } void TestInvocation::didReceiveLoadedSubresourceDomains(Vector&& domains) { auto messageBody = adoptWK(WKMutableArrayCreate()); for (auto& domain : domains) WKArrayAppendItem(messageBody.get(), toWK(domain).get()); postPageMessage("CallDidReceiveLoadedSubresourceDomains", messageBody); } void TestInvocation::didRemoveAllSessionCredentials() { postPageMessage("CallDidRemoveAllSessionCredentialsCallback"); } void TestInvocation::didSetAppBoundDomains() { postPageMessage("CallDidSetAppBoundDomains"); } void TestInvocation::dumpResourceLoadStatistics() { m_shouldDumpResourceLoadStatistics = true; } void TestInvocation::dumpPrivateClickMeasurement() { m_shouldDumpPrivateClickMeasurement = true; } void TestInvocation::performCustomMenuAction() { postPageMessage("PerformCustomMenuAction"); } void TestInvocation::initializeWaitToDumpWatchdogTimerIfNeeded() { if (m_waitToDumpWatchdogTimer.isActive()) return; m_waitToDumpWatchdogTimer.startOneShot(m_timeout); } void TestInvocation::invalidateWaitToDumpWatchdogTimer() { m_waitToDumpWatchdogTimer.stop(); } void TestInvocation::waitToDumpWatchdogTimerFired() { invalidateWaitToDumpWatchdogTimer(); outputText("FAIL: Timed out waiting for notifyDone to be called\n\n"); postPageMessage("ForceImmediateCompletion"); initializeWaitForPostDumpWatchdogTimerIfNeeded(); } void TestInvocation::initializeWaitForPostDumpWatchdogTimerIfNeeded() { if (m_waitForPostDumpWatchdogTimer.isActive()) return; m_waitForPostDumpWatchdogTimer.startOneShot(shortTimeout()); } void TestInvocation::invalidateWaitForPostDumpWatchdogTimer() { m_waitForPostDumpWatchdogTimer.stop(); } void TestInvocation::waitForPostDumpWatchdogTimerFired() { invalidateWaitForPostDumpWatchdogTimer(); #if PLATFORM(COCOA) char buffer[1024]; snprintf(buffer, sizeof(buffer), "#PID UNRESPONSIVE - %s (pid %d)\n", getprogname(), getpid()); outputText(buffer); #endif done(); } void TestInvocation::setWaitUntilDone(bool waitUntilDone) { m_waitUntilDone = waitUntilDone; if (waitUntilDone && TestController::singleton().useWaitToDumpWatchdogTimer()) initializeWaitToDumpWatchdogTimerIfNeeded(); } void TestInvocation::done() { m_gotFinalMessage = true; invalidateWaitToDumpWatchdogTimer(); invalidateWaitForPostDumpWatchdogTimer(); RunLoop::main().dispatch([] { TestController::singleton().notifyDone(); }); } void TestInvocation::willCreateNewPage() { if (m_UIScriptContext && m_UIScriptContext->callbackWithID(CallbackTypeWillCreateNewPage)) m_UIScriptContext->fireCallback(CallbackTypeWillCreateNewPage); } } // namespace WTR