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>
41 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
42 #include "EventSenderProxy.h"
47 static const double defaultLongTimeout = 30;
48 static const double defaultShortTimeout = 5;
50 static WKURLRef blankURL()
52 static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
53 return staticBlankURL;
56 static TestController* controller;
58 TestController& TestController::shared()
64 TestController::TestController(int argc, const char* argv[])
67 , m_printSeparators(false)
68 , m_usingServerMode(false)
69 , m_gcBetweenTests(false)
71 , m_doneResetting(false)
72 , m_longTimeout(defaultLongTimeout)
73 , m_shortTimeout(defaultShortTimeout)
74 , m_didPrintWebProcessCrashedMessage(false)
75 , m_shouldExitWhenWebProcessCrashes(true)
76 , m_beforeUnloadReturnValue(true)
77 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
78 , m_eventSenderProxy(new EventSenderProxy(this))
81 initialize(argc, argv);
87 TestController::~TestController()
91 static WKRect getWindowFrameMainPage(WKPageRef page, const void* clientInfo)
93 PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
94 return view->windowFrame();
97 static void setWindowFrameMainPage(WKPageRef page, WKRect frame, const void* clientInfo)
99 PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
100 view->setWindowFrame(frame);
103 static WKRect getWindowFrameOtherPage(WKPageRef page, const void* clientInfo)
105 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
106 return view->windowFrame();
109 static void setWindowFrameOtherPage(WKPageRef page, WKRect frame, const void* clientInfo)
111 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
112 view->setWindowFrame(frame);
115 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void *clientInfo)
117 TestController* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
118 printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
119 return testController->beforeUnloadReturnValue();
122 static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long, unsigned long long, unsigned long long, unsigned long long, const void*)
124 static const unsigned long long defaultQuota = 5 * 1024 * 1024;
129 void TestController::runModal(WKPageRef page, const void* clientInfo)
131 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
132 view->setWindowIsKey(false);
134 view->setWindowIsKey(true);
137 static void closeOtherPage(WKPageRef page, const void* clientInfo)
140 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
144 static void focus(WKPageRef page, const void* clientInfo)
146 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
147 view->setWindowIsKey(true);
150 static void unfocus(WKPageRef page, const void* clientInfo)
152 PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
153 view->setWindowIsKey(false);
156 WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void*)
158 PlatformWebView* view = new PlatformWebView(WKPageGetContext(oldPage), WKPageGetPageGroup(oldPage));
159 WKPageRef newPage = view->page();
161 view->resizeTo(800, 600);
163 WKPageUIClient otherPageUIClient = {
164 kWKPageUIClientCurrentVersion,
166 0, // createNewPage_deprecatedForUseWithV0
172 0, // runJavaScriptAlert
173 0, // runJavaScriptConfirm
174 0, // runJavaScriptPrompt
176 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
177 0, // missingPluginButtonClicked
178 0, // didNotHandleKeyEvent
179 0, // didNotHandleWheelEvent
180 0, // toolbarsAreVisible
181 0, // setToolbarsAreVisible
182 0, // menuBarIsVisible
183 0, // setMenuBarIsVisible
184 0, // statusBarIsVisible
185 0, // setStatusBarIsVisible
188 getWindowFrameOtherPage,
189 setWindowFrameOtherPage,
190 runBeforeUnloadConfirmPanel,
193 exceededDatabaseQuota,
195 0, // decidePolicyForGeolocationPermissionRequest
202 0, // didCompleteRubberBandForMainFrame
203 0, // saveDataToFileInDownloadsFolder
204 0, // shouldInterruptJavaScript
206 0, // mouseDidMoveOverElement
208 WKPageSetPageUIClient(newPage, &otherPageUIClient);
214 const char* TestController::libraryPathForTesting()
216 // FIXME: This may not be sufficient to prevent interactions/crashes
217 // when running more than one copy of DumpRenderTree.
218 // See https://bugs.webkit.org/show_bug.cgi?id=10906
219 char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP");
220 if (dumpRenderTreeTemp)
221 return dumpRenderTreeTemp;
222 return platformLibraryPathForTesting();
226 void TestController::initialize(int argc, const char* argv[])
228 platformInitialize();
231 fputs("Usage: WebKitTestRunner [options] filename [filename2..n]\n", stderr);
232 // FIXME: Refactor option parsing to allow us to print
233 // an auto-generated list of options.
237 bool printSupportedFeatures = false;
239 for (int i = 1; i < argc; ++i) {
240 std::string argument(argv[i]);
242 if (argument == "--timeout" && i + 1 < argc) {
243 m_longTimeout = atoi(argv[++i]);
244 // Scale up the short timeout to match.
245 m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout;
248 if (argument == "--pixel-tests") {
252 if (argument == "--verbose") {
256 if (argument == "--gc-between-tests") {
257 m_gcBetweenTests = true;
260 if (argument == "--print-supported-features") {
261 printSupportedFeatures = true;
265 // Skip any other arguments that begin with '--'.
266 if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
269 m_paths.push_back(argument);
272 if (printSupportedFeatures) {
273 // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
274 // transforms and accelerated compositing. When we support those features, we
275 // should match DRT's behavior.
279 m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
280 if (m_usingServerMode)
281 m_printSeparators = true;
283 m_printSeparators = m_paths.size() > 1;
285 initializeInjectedBundlePath();
286 initializeTestPluginDirectory();
288 WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup"));
289 m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
291 m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
293 const char* path = libraryPathForTesting();
295 Vector<char> databaseDirectory(strlen(path) + strlen("/Databases") + 1);
296 sprintf(databaseDirectory.data(), "%s%s", path, "/Databases");
297 WKRetainPtr<WKStringRef> databaseDirectoryWK(AdoptWK, WKStringCreateWithUTF8CString(databaseDirectory.data()));
298 WKContextSetDatabaseDirectory(m_context.get(), databaseDirectoryWK.get());
301 platformInitializeContext();
303 WKContextInjectedBundleClient injectedBundleClient = {
304 kWKContextInjectedBundleClientCurrentVersion,
306 didReceiveMessageFromInjectedBundle,
307 didReceiveSynchronousMessageFromInjectedBundle
309 WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
311 WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
313 m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get()));
315 WKPageUIClient pageUIClient = {
316 kWKPageUIClientCurrentVersion,
318 0, // createNewPage_deprecatedForUseWithV0
324 0, // runJavaScriptAlert
325 0, // runJavaScriptConfirm
326 0, // runJavaScriptPrompt
328 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
329 0, // missingPluginButtonClicked
330 0, // didNotHandleKeyEvent
331 0, // didNotHandleWheelEvent
332 0, // toolbarsAreVisible
333 0, // setToolbarsAreVisible
334 0, // menuBarIsVisible
335 0, // setMenuBarIsVisible
336 0, // statusBarIsVisible
337 0, // setStatusBarIsVisible
340 getWindowFrameMainPage,
341 setWindowFrameMainPage,
342 runBeforeUnloadConfirmPanel,
345 exceededDatabaseQuota,
347 0, // decidePolicyForGeolocationPermissionRequest
354 0, // didCompleteRubberBandForMainFrame
355 0, // saveDataToFileInDownloadsFolder
356 0, // shouldInterruptJavaScript
358 0, // mouseDidMoveOverElement
360 WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
362 WKPageLoaderClient pageLoaderClient = {
363 kWKPageLoaderClientCurrentVersion,
365 0, // didStartProvisionalLoadForFrame
366 0, // didReceiveServerRedirectForProvisionalLoadForFrame
367 0, // didFailProvisionalLoadWithErrorForFrame
368 didCommitLoadForFrame,
369 0, // didFinishDocumentLoadForFrame
370 didFinishLoadForFrame,
371 0, // didFailLoadWithErrorForFrame
372 0, // didSameDocumentNavigationForFrame
373 0, // didReceiveTitleForFrame
374 0, // didFirstLayoutForFrame
375 0, // didFirstVisuallyNonEmptyLayoutForFrame
376 0, // didRemoveFrameFromHierarchy
377 0, // didFailToInitializePlugin
378 0, // didDisplayInsecureContentForFrame
379 0, // canAuthenticateAgainstProtectionSpaceInFrame
380 0, // didReceiveAuthenticationChallengeInFrame
381 0, // didStartProgress
382 0, // didChangeProgress
383 0, // didFinishProgress
384 0, // didBecomeUnresponsive
385 0, // didBecomeResponsive
387 0, // didChangeBackForwardList
388 0, // shouldGoToBackForwardListItem
389 0, // didRunInsecureContentForFrame
390 0 // didDetectXSSForFrame
392 WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
395 bool TestController::resetStateToConsistentValues()
399 m_beforeUnloadReturnValue = true;
401 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
402 WKRetainPtr<WKMutableDictionaryRef> resetMessageBody = adoptWK(WKMutableDictionaryCreate());
404 WKRetainPtr<WKStringRef> shouldGCKey = adoptWK(WKStringCreateWithUTF8CString("ShouldGC"));
405 WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
406 WKDictionaryAddItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
408 WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), resetMessageBody.get());
410 WKContextSetShouldUseFontSmoothing(TestController::shared().context(), false);
412 // FIXME: This function should also ensure that there is only one page open.
415 WKPreferencesRef preferences = WKPageGroupGetPreferences(m_pageGroup.get());
416 WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
417 WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
418 WKPreferencesSetXSSAuditorEnabled(preferences, false);
419 WKPreferencesSetDeveloperExtrasEnabled(preferences, true);
420 WKPreferencesSetJavaScriptCanOpenWindowsAutomatically(preferences, true);
421 WKPreferencesSetJavaScriptCanAccessClipboard(preferences, true);
422 WKPreferencesSetDOMPasteAllowed(preferences, true);
423 WKPreferencesSetUniversalAccessFromFileURLsAllowed(preferences, true);
424 WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
425 #if ENABLE(FULLSCREEN_API)
426 WKPreferencesSetFullScreenEnabled(preferences, true);
430 static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
431 static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
432 static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
433 static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier");
434 static WKStringRef pictographFontFamily = WKStringCreateWithUTF8CString("Apple Color Emoji");
435 static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica");
436 static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times");
438 WKPreferencesSetStandardFontFamily(preferences, standardFontFamily);
439 WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily);
440 WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily);
441 WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily);
442 WKPreferencesSetPictographFontFamily(preferences, pictographFontFamily);
443 WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
444 WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
447 // in the case that a test using the chrome input field failed, be sure to clean up for the next test
448 m_mainWebView->removeChromeInputField();
449 m_mainWebView->focus();
451 // Re-set to the default backing scale factor by setting the custom scale factor to 0.
452 WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);
454 // Reset main page back to about:blank
455 m_doneResetting = false;
457 WKPageLoadURL(m_mainWebView->page(), blankURL());
458 runUntil(m_doneResetting, ShortTimeout);
459 return m_doneResetting;
462 bool TestController::runTest(const char* test)
464 if (!resetStateToConsistentValues()) {
465 fputs("#CRASHED - WebProcess\n", stderr);
470 std::string pathOrURL(test);
471 std::string expectedPixelHash;
472 size_t separatorPos = pathOrURL.find("'");
473 if (separatorPos != std::string::npos) {
474 pathOrURL = std::string(std::string(test), 0, separatorPos);
475 expectedPixelHash = std::string(std::string(test), separatorPos + 1);
478 m_state = RunningTest;
480 m_currentInvocation = adoptPtr(new TestInvocation(pathOrURL));
482 m_currentInvocation->setIsPixelTest(expectedPixelHash);
484 m_currentInvocation->invoke();
485 m_currentInvocation.clear();
490 void TestController::runTestingServerLoop()
492 char filenameBuffer[2048];
493 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
494 char* newLineCharacter = strchr(filenameBuffer, '\n');
495 if (newLineCharacter)
496 *newLineCharacter = '\0';
498 if (strlen(filenameBuffer) == 0)
501 if (!runTest(filenameBuffer))
506 void TestController::run()
508 if (m_usingServerMode)
509 runTestingServerLoop();
511 for (size_t i = 0; i < m_paths.size(); ++i) {
512 if (!runTest(m_paths[i].c_str()))
518 void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
520 platformRunUntil(done, timeoutDuration == ShortTimeout ? m_shortTimeout : m_longTimeout);
523 // WKContextInjectedBundleClient
525 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
527 static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
530 void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
532 *returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
535 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
537 if (!m_currentInvocation)
539 m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
542 WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
544 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
545 if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
546 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
547 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
549 WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
550 WKStringRef subMessageName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subMessageKey.get()));
552 if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
553 WKRetainPtr<WKStringRef> keyKey = adoptWK(WKStringCreateWithUTF8CString("Key"));
554 WKStringRef key = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, keyKey.get()));
556 WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
557 WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
559 WKRetainPtr<WKStringRef> locationKey = adoptWK(WKStringCreateWithUTF8CString("Location"));
560 unsigned location = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, locationKey.get()))));
562 // Forward to WebProcess
563 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
564 m_eventSenderProxy->keyDown(key, modifiers, location);
565 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
569 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
570 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown") || WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
571 WKRetainPtr<WKStringRef> buttonKey = adoptWK(WKStringCreateWithUTF8CString("Button"));
572 unsigned button = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonKey.get()))));
574 WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
575 WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
577 // Forward to WebProcess
578 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
579 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
580 m_eventSenderProxy->mouseDown(button, modifiers);
582 m_eventSenderProxy->mouseUp(button, modifiers);
583 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
587 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseMoveTo")) {
588 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
589 double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
591 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
592 double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
594 // Forward to WebProcess
595 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
596 m_eventSenderProxy->mouseMoveTo(x, y);
597 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
601 if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
602 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
603 double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
605 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
606 double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
608 // Forward to WebProcess
609 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
610 m_eventSenderProxy->mouseScrollBy(x, y);
611 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
615 if (WKStringIsEqualToUTF8CString(subMessageName, "LeapForward")) {
616 WKRetainPtr<WKStringRef> timeKey = adoptWK(WKStringCreateWithUTF8CString("TimeInMilliseconds"));
617 unsigned time = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeKey.get()))));
619 m_eventSenderProxy->leapForward(time);
624 #if ENABLE(TOUCH_EVENTS)
625 if (WKStringIsEqualToUTF8CString(subMessageName, "AddTouchPoint")) {
626 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
627 int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
629 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
630 int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
632 m_eventSenderProxy->addTouchPoint(x, y);
636 if (WKStringIsEqualToUTF8CString(subMessageName, "UpdateTouchPoint")) {
637 WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
638 int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
640 WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
641 int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
643 WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
644 int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
646 m_eventSenderProxy->updateTouchPoint(index, x, y);
650 if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchModifier")) {
651 WKRetainPtr<WKStringRef> modifierKey = adoptWK(WKStringCreateWithUTF8CString("Modifier"));
652 WKEventModifiers modifier = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifierKey.get()))));
654 WKRetainPtr<WKStringRef> enableKey = adoptWK(WKStringCreateWithUTF8CString("Enable"));
655 bool enable = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, enableKey.get()))));
657 m_eventSenderProxy->setTouchModifier(modifier, enable);
661 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
662 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
663 m_eventSenderProxy->touchStart();
664 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
668 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
669 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
670 m_eventSenderProxy->touchMove();
671 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
675 if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
676 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
677 m_eventSenderProxy->touchEnd();
678 WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
682 if (WKStringIsEqualToUTF8CString(subMessageName, "ClearTouchPoints")) {
683 m_eventSenderProxy->clearTouchPoints();
687 if (WKStringIsEqualToUTF8CString(subMessageName, "ReleaseTouchPoint")) {
688 WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
689 int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
690 m_eventSenderProxy->releaseTouchPoint(index);
694 ASSERT_NOT_REACHED();
697 return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody);
700 // WKPageLoaderClient
702 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
704 static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(page, frame);
707 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
709 static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
712 void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
714 static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
717 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame)
719 if (!WKFrameIsMainFrame(frame))
722 mainWebView()->focus();
725 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
727 if (m_state != Resetting)
730 if (!WKFrameIsMainFrame(frame))
733 WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
734 if (!WKURLIsEqual(wkURL.get(), blankURL()))
737 m_doneResetting = true;
738 shared().notifyDone();
741 void TestController::processDidCrash()
743 // This function can be called multiple times when crash logs are being saved on Windows, so
744 // ensure we only print the crashed message once.
745 if (!m_didPrintWebProcessCrashedMessage) {
746 fputs("#CRASHED - WebProcess\n", stderr);
748 m_didPrintWebProcessCrashedMessage = true;
751 if (m_shouldExitWhenWebProcessCrashes)