2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "TestController.h"
29 #include "PlatformWebView.h"
30 #include "StringFunctions.h"
31 #include "TestInvocation.h"
32 #include <WebKit2/WKContextPrivate.h>
33 #include <WebKit2/WKNumber.h>
34 #include <WebKit2/WKPageGroup.h>
35 #include <WebKit2/WKPagePrivate.h>
36 #include <WebKit2/WKPreferencesPrivate.h>
37 #include <WebKit2/WKRetainPtr.h>
39 #include <wtf/PassOwnPtr.h>
42 #include <WebKit2/WKPagePrivateMac.h>
45 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
46 #include "EventSenderProxy.h"
51 static const double defaultLongTimeout = 30;
52 static const double defaultShortTimeout = 5;
53 static const double defaultNoTimeout = -1;
55 static WKURLRef blankURL()
57 static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
58 return staticBlankURL;
61 static TestController* controller;
63 TestController& TestController::shared()
69 TestController::TestController(int argc, const char* argv[])
72 , m_printSeparators(false)
73 , m_usingServerMode(false)
74 , m_gcBetweenTests(false)
76 , m_doneResetting(false)
77 , m_longTimeout(defaultLongTimeout)
78 , m_shortTimeout(defaultShortTimeout)
79 , m_noTimeout(defaultNoTimeout)
80 , m_useWaitToDumpWatchdogTimer(true)
81 , m_didPrintWebProcessCrashedMessage(false)
82 , m_shouldExitWhenWebProcessCrashes(true)
83 , m_beforeUnloadReturnValue(true)
84 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
85 , m_eventSenderProxy(new EventSenderProxy(this))
88 initialize(argc, argv);
94 TestController::~TestController()
98 static WKRect getWindowFrameMainPage(WKPageRef page, const void* clientInfo)
100 PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
101 return view->windowFrame();
104 static void setWindowFrameMainPage(WKPageRef page, WKRect frame, const void* clientInfo)
106 PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
107 view->setWindowFrame(frame);
110 static WKRect getWindowFrameOtherPage(WKPageRef page, const void* clientInfo)
112 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
113 return view->windowFrame();
116 static void setWindowFrameOtherPage(WKPageRef page, WKRect frame, const void* clientInfo)
118 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
119 view->setWindowFrame(frame);
122 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void *clientInfo)
124 TestController* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
125 printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
126 return testController->beforeUnloadReturnValue();
129 static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long, unsigned long long, unsigned long long, unsigned long long, const void*)
131 static const unsigned long long defaultQuota = 5 * 1024 * 1024;
136 void TestController::runModal(WKPageRef page, const void* clientInfo)
138 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
139 view->setWindowIsKey(false);
141 view->setWindowIsKey(true);
144 static void closeOtherPage(WKPageRef page, const void* clientInfo)
147 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
151 static void focus(WKPageRef page, const void* clientInfo)
153 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
154 view->setWindowIsKey(true);
157 static void unfocus(WKPageRef page, const void* clientInfo)
159 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
160 view->setWindowIsKey(false);
163 WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void*)
165 PlatformWebView* view = new PlatformWebView(WKPageGetContext(oldPage), WKPageGetPageGroup(oldPage));
166 WKPageRef newPage = view->page();
168 view->resizeTo(800, 600);
170 WKPageUIClient otherPageUIClient = {
171 kWKPageUIClientCurrentVersion,
173 0, // createNewPage_deprecatedForUseWithV0
179 0, // runJavaScriptAlert
180 0, // runJavaScriptConfirm
181 0, // runJavaScriptPrompt
183 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
184 0, // missingPluginButtonClicked
185 0, // didNotHandleKeyEvent
186 0, // didNotHandleWheelEvent
187 0, // toolbarsAreVisible
188 0, // setToolbarsAreVisible
189 0, // menuBarIsVisible
190 0, // setMenuBarIsVisible
191 0, // statusBarIsVisible
192 0, // setStatusBarIsVisible
195 getWindowFrameOtherPage,
196 setWindowFrameOtherPage,
197 runBeforeUnloadConfirmPanel,
200 exceededDatabaseQuota,
202 0, // decidePolicyForGeolocationPermissionRequest
209 0, // didCompleteRubberBandForMainFrame
210 0, // saveDataToFileInDownloadsFolder
211 0, // shouldInterruptJavaScript
213 0, // mouseDidMoveOverElement
214 0, // decidePolicyForNotificationPermissionRequest
216 WKPageSetPageUIClient(newPage, &otherPageUIClient);
222 const char* TestController::libraryPathForTesting()
224 // FIXME: This may not be sufficient to prevent interactions/crashes
225 // when running more than one copy of DumpRenderTree.
226 // See https://bugs.webkit.org/show_bug.cgi?id=10906
227 char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP");
228 if (dumpRenderTreeTemp)
229 return dumpRenderTreeTemp;
230 return platformLibraryPathForTesting();
234 void TestController::initialize(int argc, const char* argv[])
236 platformInitialize();
239 fputs("Usage: WebKitTestRunner [options] filename [filename2..n]\n", stderr);
240 // FIXME: Refactor option parsing to allow us to print
241 // an auto-generated list of options.
245 bool printSupportedFeatures = false;
247 for (int i = 1; i < argc; ++i) {
248 std::string argument(argv[i]);
250 if (argument == "--timeout" && i + 1 < argc) {
251 m_longTimeout = atoi(argv[++i]);
252 // Scale up the short timeout to match.
253 m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout;
257 if (argument == "--no-timeout") {
258 m_useWaitToDumpWatchdogTimer = false;
262 if (argument == "--pixel-tests") {
266 if (argument == "--verbose") {
270 if (argument == "--gc-between-tests") {
271 m_gcBetweenTests = true;
274 if (argument == "--print-supported-features") {
275 printSupportedFeatures = true;
279 // Skip any other arguments that begin with '--'.
280 if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
283 m_paths.push_back(argument);
286 if (printSupportedFeatures) {
287 // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
288 // transforms and accelerated compositing. When we support those features, we
289 // should match DRT's behavior.
293 m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
294 if (m_usingServerMode)
295 m_printSeparators = true;
297 m_printSeparators = m_paths.size() > 1;
299 initializeInjectedBundlePath();
300 initializeTestPluginDirectory();
302 WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup"));
303 m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
305 m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
307 const char* path = libraryPathForTesting();
309 Vector<char> databaseDirectory(strlen(path) + strlen("/Databases") + 1);
310 sprintf(databaseDirectory.data(), "%s%s", path, "/Databases");
311 WKRetainPtr<WKStringRef> databaseDirectoryWK(AdoptWK, WKStringCreateWithUTF8CString(databaseDirectory.data()));
312 WKContextSetDatabaseDirectory(m_context.get(), databaseDirectoryWK.get());
315 platformInitializeContext();
317 WKContextInjectedBundleClient injectedBundleClient = {
318 kWKContextInjectedBundleClientCurrentVersion,
320 didReceiveMessageFromInjectedBundle,
321 didReceiveSynchronousMessageFromInjectedBundle
323 WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
325 WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
327 m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get()));
329 WKPageUIClient pageUIClient = {
330 kWKPageUIClientCurrentVersion,
332 0, // createNewPage_deprecatedForUseWithV0
338 0, // runJavaScriptAlert
339 0, // runJavaScriptConfirm
340 0, // runJavaScriptPrompt
342 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
343 0, // missingPluginButtonClicked
344 0, // didNotHandleKeyEvent
345 0, // didNotHandleWheelEvent
346 0, // toolbarsAreVisible
347 0, // setToolbarsAreVisible
348 0, // menuBarIsVisible
349 0, // setMenuBarIsVisible
350 0, // statusBarIsVisible
351 0, // setStatusBarIsVisible
354 getWindowFrameMainPage,
355 setWindowFrameMainPage,
356 runBeforeUnloadConfirmPanel,
359 exceededDatabaseQuota,
361 0, // decidePolicyForGeolocationPermissionRequest
368 0, // didCompleteRubberBandForMainFrame
369 0, // saveDataToFileInDownloadsFolder
370 0, // shouldInterruptJavaScript
372 0, // mouseDidMoveOverElement
373 0, // decidePolicyForNotificationPermissionRequest
375 WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
377 WKPageLoaderClient pageLoaderClient = {
378 kWKPageLoaderClientCurrentVersion,
380 0, // didStartProvisionalLoadForFrame
381 0, // didReceiveServerRedirectForProvisionalLoadForFrame
382 0, // didFailProvisionalLoadWithErrorForFrame
383 didCommitLoadForFrame,
384 0, // didFinishDocumentLoadForFrame
385 didFinishLoadForFrame,
386 0, // didFailLoadWithErrorForFrame
387 0, // didSameDocumentNavigationForFrame
388 0, // didReceiveTitleForFrame
389 0, // didFirstLayoutForFrame
390 0, // didFirstVisuallyNonEmptyLayoutForFrame
391 0, // didRemoveFrameFromHierarchy
392 0, // didFailToInitializePlugin
393 0, // didDisplayInsecureContentForFrame
394 0, // canAuthenticateAgainstProtectionSpaceInFrame
395 0, // didReceiveAuthenticationChallengeInFrame
396 0, // didStartProgress
397 0, // didChangeProgress
398 0, // didFinishProgress
399 0, // didBecomeUnresponsive
400 0, // didBecomeResponsive
402 0, // didChangeBackForwardList
403 0, // shouldGoToBackForwardListItem
404 0, // didRunInsecureContentForFrame
405 0, // didDetectXSSForFrame
406 0, // didNewFirstVisuallyNonEmptyLayout
407 0, // willGoToBackForwardListItem
408 0, // interactionOccurredWhileProcessUnresponsive
410 WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
413 bool TestController::resetStateToConsistentValues()
417 m_beforeUnloadReturnValue = true;
419 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
420 WKRetainPtr<WKMutableDictionaryRef> resetMessageBody = adoptWK(WKMutableDictionaryCreate());
422 WKRetainPtr<WKStringRef> shouldGCKey = adoptWK(WKStringCreateWithUTF8CString("ShouldGC"));
423 WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
424 WKDictionaryAddItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
426 WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), resetMessageBody.get());
428 WKContextSetShouldUseFontSmoothing(TestController::shared().context(), false);
430 WKContextSetCacheModel(TestController::shared().context(), kWKCacheModelDocumentBrowser);
432 // FIXME: This function should also ensure that there is only one page open.
435 WKPreferencesRef preferences = WKPageGroupGetPreferences(m_pageGroup.get());
436 WKPreferencesResetTestRunnerOverrides(preferences);
437 WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
438 WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
439 WKPreferencesSetXSSAuditorEnabled(preferences, false);
440 WKPreferencesSetWebAudioEnabled(preferences, true);
441 WKPreferencesSetDeveloperExtrasEnabled(preferences, true);
442 WKPreferencesSetJavaScriptCanOpenWindowsAutomatically(preferences, true);
443 WKPreferencesSetJavaScriptCanAccessClipboard(preferences, true);
444 WKPreferencesSetDOMPasteAllowed(preferences, true);
445 WKPreferencesSetUniversalAccessFromFileURLsAllowed(preferences, true);
446 WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
447 #if ENABLE(FULLSCREEN_API)
448 WKPreferencesSetFullScreenEnabled(preferences, true);
450 WKPreferencesSetPageCacheEnabled(preferences, false);
452 // [Qt][WK2]REGRESSION(r104881):It broke hundreds of tests
453 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=76247
455 WKPreferencesSetMockScrollbarsEnabled(preferences, true);
459 static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
460 static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
461 static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
462 static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier");
463 static WKStringRef pictographFontFamily = WKStringCreateWithUTF8CString("Apple Color Emoji");
464 static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica");
465 static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times");
467 WKPreferencesSetStandardFontFamily(preferences, standardFontFamily);
468 WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily);
469 WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily);
470 WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily);
471 WKPreferencesSetPictographFontFamily(preferences, pictographFontFamily);
472 WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
473 WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
475 WKPreferencesSetInspectorUsesWebKitUserInterface(preferences, true);
477 // in the case that a test using the chrome input field failed, be sure to clean up for the next test
478 m_mainWebView->removeChromeInputField();
479 m_mainWebView->focus();
481 // Re-set to the default backing scale factor by setting the custom scale factor to 0.
482 WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);
484 // Reset main page back to about:blank
485 m_doneResetting = false;
487 WKPageLoadURL(m_mainWebView->page(), blankURL());
488 runUntil(m_doneResetting, ShortTimeout);
489 return m_doneResetting;
492 bool TestController::runTest(const char* test)
494 if (!resetStateToConsistentValues()) {
496 pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page());
497 fprintf(stderr, "#CRASHED - WebProcess (pid %ld)\n", static_cast<long>(pid));
499 fputs("#CRASHED - WebProcess\n", stderr);
505 std::string pathOrURL(test);
506 std::string expectedPixelHash;
507 size_t separatorPos = pathOrURL.find("'");
508 if (separatorPos != std::string::npos) {
509 pathOrURL = std::string(std::string(test), 0, separatorPos);
510 expectedPixelHash = std::string(std::string(test), separatorPos + 1);
513 m_state = RunningTest;
515 m_currentInvocation = adoptPtr(new TestInvocation(pathOrURL));
517 m_currentInvocation->setIsPixelTest(expectedPixelHash);
519 m_currentInvocation->invoke();
520 m_currentInvocation.clear();
525 void TestController::runTestingServerLoop()
527 char filenameBuffer[2048];
528 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
529 char* newLineCharacter = strchr(filenameBuffer, '\n');
530 if (newLineCharacter)
531 *newLineCharacter = '\0';
533 if (strlen(filenameBuffer) == 0)
536 if (!runTest(filenameBuffer))
541 void TestController::run()
543 if (m_usingServerMode)
544 runTestingServerLoop();
546 for (size_t i = 0; i < m_paths.size(); ++i) {
547 if (!runTest(m_paths[i].c_str()))
553 void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
556 switch (timeoutDuration) {
558 timeout = m_shortTimeout;
561 timeout = m_longTimeout;
565 timeout = m_noTimeout;
569 platformRunUntil(done, timeout);
572 // WKContextInjectedBundleClient
574 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
576 static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
579 void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
581 *returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
584 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
586 if (!m_currentInvocation)
588 m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
591 WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
593 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
594 if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
595 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
596 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
598 WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
599 WKStringRef subMessageName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subMessageKey.get()));
601 if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
602 WKRetainPtr<WKStringRef> keyKey = adoptWK(WKStringCreateWithUTF8CString("Key"));
603 WKStringRef key = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, keyKey.get()));
605 WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
606 WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
608 WKRetainPtr<WKStringRef> locationKey = adoptWK(WKStringCreateWithUTF8CString("Location"));
609 unsigned location = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, locationKey.get()))));
611 // Forward to WebProcess
612 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
613 m_eventSenderProxy->keyDown(key, modifiers, location);
614 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
618 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
619 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown") || WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
620 WKRetainPtr<WKStringRef> buttonKey = adoptWK(WKStringCreateWithUTF8CString("Button"));
621 unsigned button = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonKey.get()))));
623 WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
624 WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
626 // Forward to WebProcess
627 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
628 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
629 m_eventSenderProxy->mouseDown(button, modifiers);
631 m_eventSenderProxy->mouseUp(button, modifiers);
632 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
636 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseMoveTo")) {
637 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
638 double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
640 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
641 double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
643 // Forward to WebProcess
644 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
645 m_eventSenderProxy->mouseMoveTo(x, y);
646 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
650 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
651 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
652 double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
654 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
655 double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
657 // Forward to WebProcess
658 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
659 m_eventSenderProxy->mouseScrollBy(x, y);
660 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
664 if (WKStringIsEqualToUTF8CString(subMessageName, "LeapForward")) {
665 WKRetainPtr<WKStringRef> timeKey = adoptWK(WKStringCreateWithUTF8CString("TimeInMilliseconds"));
666 unsigned time = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeKey.get()))));
668 m_eventSenderProxy->leapForward(time);
673 #if ENABLE(TOUCH_EVENTS)
674 if (WKStringIsEqualToUTF8CString(subMessageName, "AddTouchPoint")) {
675 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
676 int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
678 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
679 int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
681 m_eventSenderProxy->addTouchPoint(x, y);
685 if (WKStringIsEqualToUTF8CString(subMessageName, "UpdateTouchPoint")) {
686 WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
687 int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
689 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
690 int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
692 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
693 int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
695 m_eventSenderProxy->updateTouchPoint(index, x, y);
699 if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchModifier")) {
700 WKRetainPtr<WKStringRef> modifierKey = adoptWK(WKStringCreateWithUTF8CString("Modifier"));
701 WKEventModifiers modifier = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifierKey.get()))));
703 WKRetainPtr<WKStringRef> enableKey = adoptWK(WKStringCreateWithUTF8CString("Enable"));
704 bool enable = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, enableKey.get()))));
706 m_eventSenderProxy->setTouchModifier(modifier, enable);
710 if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchPointRadius")) {
711 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("RadiusX"));
712 int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
714 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("RadiusY"));
715 int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
717 m_eventSenderProxy->setTouchPointRadius(x, y);
721 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
722 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
723 m_eventSenderProxy->touchStart();
724 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
728 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
729 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
730 m_eventSenderProxy->touchMove();
731 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
735 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
736 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
737 m_eventSenderProxy->touchEnd();
738 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
742 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchCancel")) {
743 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
744 m_eventSenderProxy->touchCancel();
745 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
749 if (WKStringIsEqualToUTF8CString(subMessageName, "ClearTouchPoints")) {
750 m_eventSenderProxy->clearTouchPoints();
754 if (WKStringIsEqualToUTF8CString(subMessageName, "ReleaseTouchPoint")) {
755 WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
756 int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
757 m_eventSenderProxy->releaseTouchPoint(index);
761 if (WKStringIsEqualToUTF8CString(subMessageName, "CancelTouchPoint")) {
762 WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
763 int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
764 m_eventSenderProxy->cancelTouchPoint(index);
768 ASSERT_NOT_REACHED();
771 return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody);
774 // WKPageLoaderClient
776 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
778 static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(page, frame);
781 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
783 static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
786 void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
788 static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
791 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame)
793 if (!WKFrameIsMainFrame(frame))
796 mainWebView()->focus();
799 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
801 if (m_state != Resetting)
804 if (!WKFrameIsMainFrame(frame))
807 WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
808 if (!WKURLIsEqual(wkURL.get(), blankURL()))
811 m_doneResetting = true;
812 shared().notifyDone();
815 void TestController::processDidCrash()
817 // This function can be called multiple times when crash logs are being saved on Windows, so
818 // ensure we only print the crashed message once.
819 if (!m_didPrintWebProcessCrashedMessage) {
821 pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page());
822 fprintf(stderr, "#CRASHED - WebProcess (pid %ld)\n", static_cast<long>(pid));
824 fputs("#CRASHED - WebProcess\n", stderr);
827 m_didPrintWebProcessCrashedMessage = true;
830 if (m_shouldExitWhenWebProcessCrashes)