tizen beta release
[profile/ivi/webkit-efl.git] / Tools / WebKitTestRunner / TestController.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "TestController.h"
28
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>
38 #include <cstdio>
39 #include <wtf/PassOwnPtr.h>
40
41 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK)
42 #include "EventSenderProxy.h"
43 #endif
44
45 namespace WTR {
46
47 static const double defaultLongTimeout = 30;
48 static const double defaultShortTimeout = 5;
49
50 static WKURLRef blankURL()
51 {
52     static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
53     return staticBlankURL;
54 }
55
56 static TestController* controller;
57
58 TestController& TestController::shared()
59 {
60     ASSERT(controller);
61     return *controller;
62 }
63
64 TestController::TestController(int argc, const char* argv[])
65     : m_dumpPixels(false)
66     , m_verbose(false)
67     , m_printSeparators(false)
68     , m_usingServerMode(false)
69     , m_gcBetweenTests(false)
70     , m_state(Initial)
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))
79 #endif
80 {
81     initialize(argc, argv);
82     controller = this;
83     run();
84     controller = 0;
85 }
86
87 TestController::~TestController()
88 {
89 }
90
91 static WKRect getWindowFrameMainPage(WKPageRef page, const void* clientInfo)
92 {
93     PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
94     return view->windowFrame();
95 }
96
97 static void setWindowFrameMainPage(WKPageRef page, WKRect frame, const void* clientInfo)
98 {
99     PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView();
100     view->setWindowFrame(frame);
101 }
102
103 static WKRect getWindowFrameOtherPage(WKPageRef page, const void* clientInfo)
104 {
105     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
106     return view->windowFrame();
107 }
108
109 static void setWindowFrameOtherPage(WKPageRef page, WKRect frame, const void* clientInfo)
110 {
111     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
112     view->setWindowFrame(frame);
113 }
114
115 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void *clientInfo)
116 {
117     TestController* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
118     printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
119     return testController->beforeUnloadReturnValue();
120 }
121
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*)
123 {
124     static const unsigned long long defaultQuota = 5 * 1024 * 1024;    
125     return defaultQuota;
126 }
127
128
129 void TestController::runModal(WKPageRef page, const void* clientInfo)
130 {
131     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
132     view->setWindowIsKey(false);
133     runModal(view);
134     view->setWindowIsKey(true);
135 }
136
137 static void closeOtherPage(WKPageRef page, const void* clientInfo)
138 {
139     WKPageClose(page);
140     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
141     delete view;
142 }
143
144 static void focus(WKPageRef page, const void* clientInfo)
145 {
146     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
147     view->setWindowIsKey(true);
148 }
149
150 static void unfocus(WKPageRef page, const void* clientInfo)
151 {
152     PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
153     view->setWindowIsKey(false);
154 }
155
156 WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void*)
157 {
158     PlatformWebView* view = new PlatformWebView(WKPageGetContext(oldPage), WKPageGetPageGroup(oldPage));
159     WKPageRef newPage = view->page();
160
161     view->resizeTo(800, 600);
162
163     WKPageUIClient otherPageUIClient = {
164         kWKPageUIClientCurrentVersion,
165         view,
166         0, // createNewPage_deprecatedForUseWithV0
167         0, // showPage
168         closeOtherPage,
169         0, // takeFocus
170         focus,
171         unfocus,
172         0, // runJavaScriptAlert        
173         0, // runJavaScriptConfirm
174         0, // runJavaScriptPrompt
175         0, // setStatusText
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
186         0, // isResizable
187         0, // setIsResizable
188         getWindowFrameOtherPage,
189         setWindowFrameOtherPage,
190         runBeforeUnloadConfirmPanel,
191         0, // didDraw
192         0, // pageDidScroll
193         exceededDatabaseQuota,
194         0, // runOpenPanel
195         0, // decidePolicyForGeolocationPermissionRequest
196         0, // headerHeight
197         0, // footerHeight
198         0, // drawHeader
199         0, // drawFooter
200         0, // printFrame
201         runModal,
202         0, // didCompleteRubberBandForMainFrame
203         0, // saveDataToFileInDownloadsFolder
204         0, // shouldInterruptJavaScript
205         createOtherPage,
206         0, // mouseDidMoveOverElement
207     };
208     WKPageSetPageUIClient(newPage, &otherPageUIClient);
209
210     WKRetain(newPage);
211     return newPage;
212 }
213
214 const char* TestController::libraryPathForTesting()
215 {
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();
223 }
224
225
226 void TestController::initialize(int argc, const char* argv[])
227 {
228     platformInitialize();
229
230     if (argc < 2) {
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.
234         exit(1);
235     }
236
237     bool printSupportedFeatures = false;
238
239     for (int i = 1; i < argc; ++i) {
240         std::string argument(argv[i]);
241
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;
246             continue;
247         }
248         if (argument == "--pixel-tests") {
249             m_dumpPixels = true;
250             continue;
251         }
252         if (argument == "--verbose") {
253             m_verbose = true;
254             continue;
255         }
256         if (argument == "--gc-between-tests") {
257             m_gcBetweenTests = true;
258             continue;
259         }
260         if (argument == "--print-supported-features") {
261             printSupportedFeatures = true;
262             break;
263         }
264
265         // Skip any other arguments that begin with '--'.
266         if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
267             continue;
268
269         m_paths.push_back(argument);
270     }
271
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.
276         exit(0);
277     }
278
279     m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
280     if (m_usingServerMode)
281         m_printSeparators = true;
282     else
283         m_printSeparators = m_paths.size() > 1;
284
285     initializeInjectedBundlePath();
286     initializeTestPluginDirectory();
287
288     WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup"));
289     m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
290
291     m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
292
293     const char* path = libraryPathForTesting();
294     if (path) {
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());
299     }
300
301     platformInitializeContext();
302
303     WKContextInjectedBundleClient injectedBundleClient = {
304         kWKContextInjectedBundleClientCurrentVersion,
305         this,
306         didReceiveMessageFromInjectedBundle,
307         didReceiveSynchronousMessageFromInjectedBundle
308     };
309     WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
310
311     WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
312
313     m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get()));
314
315     WKPageUIClient pageUIClient = {
316         kWKPageUIClientCurrentVersion,
317         this,
318         0, // createNewPage_deprecatedForUseWithV0
319         0, // showPage
320         0, // close
321         0, // takeFocus
322         0, // focus
323         0, // unfocus
324         0, // runJavaScriptAlert        
325         0, // runJavaScriptConfirm
326         0, // runJavaScriptPrompt
327         0, // setStatusText
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
338         0, // isResizable
339         0, // setIsResizable
340         getWindowFrameMainPage,
341         setWindowFrameMainPage,
342         runBeforeUnloadConfirmPanel,
343         0, // didDraw
344         0, // pageDidScroll
345         exceededDatabaseQuota,
346         0, // runOpenPanel
347         0, // decidePolicyForGeolocationPermissionRequest
348         0, // headerHeight
349         0, // footerHeight
350         0, // drawHeader
351         0, // drawFooter
352         0, // printFrame
353         runModal,
354         0, // didCompleteRubberBandForMainFrame
355         0, // saveDataToFileInDownloadsFolder
356         0, // shouldInterruptJavaScript
357         createOtherPage,
358         0, // mouseDidMoveOverElement
359     };
360     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
361
362     WKPageLoaderClient pageLoaderClient = {
363         kWKPageLoaderClientCurrentVersion,
364         this,
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
386         processDidCrash,
387         0, // didChangeBackForwardList
388         0, // shouldGoToBackForwardListItem
389         0, // didRunInsecureContentForFrame
390         0  // didDetectXSSForFrame
391     };
392     WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
393 }
394
395 bool TestController::resetStateToConsistentValues()
396 {
397     m_state = Resetting;
398     
399     m_beforeUnloadReturnValue = true;
400
401     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
402     WKRetainPtr<WKMutableDictionaryRef> resetMessageBody = adoptWK(WKMutableDictionaryCreate());
403
404     WKRetainPtr<WKStringRef> shouldGCKey = adoptWK(WKStringCreateWithUTF8CString("ShouldGC"));
405     WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
406     WKDictionaryAddItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
407
408     WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), resetMessageBody.get());
409
410     WKContextSetShouldUseFontSmoothing(TestController::shared().context(), false);
411
412     // FIXME: This function should also ensure that there is only one page open.
413
414     // Reset preferences
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);
427 #endif
428
429 #if !PLATFORM(QT)
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");
437
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);
445 #endif
446
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();
450
451     // Re-set to the default backing scale factor by setting the custom scale factor to 0.
452     WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);
453
454     // Reset main page back to about:blank
455     m_doneResetting = false;
456
457     WKPageLoadURL(m_mainWebView->page(), blankURL());
458     runUntil(m_doneResetting, ShortTimeout);
459     return m_doneResetting;
460 }
461
462 bool TestController::runTest(const char* test)
463 {
464     if (!resetStateToConsistentValues()) {
465         fputs("#CRASHED - WebProcess\n", stderr);
466         fflush(stderr);
467         return false;
468     }
469
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);
476     }
477
478     m_state = RunningTest;
479
480     m_currentInvocation = adoptPtr(new TestInvocation(pathOrURL));
481     if (m_dumpPixels)
482         m_currentInvocation->setIsPixelTest(expectedPixelHash);    
483
484     m_currentInvocation->invoke();
485     m_currentInvocation.clear();
486
487     return true;
488 }
489
490 void TestController::runTestingServerLoop()
491 {
492     char filenameBuffer[2048];
493     while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
494         char* newLineCharacter = strchr(filenameBuffer, '\n');
495         if (newLineCharacter)
496             *newLineCharacter = '\0';
497
498         if (strlen(filenameBuffer) == 0)
499             continue;
500
501         if (!runTest(filenameBuffer))
502             break;
503     }
504 }
505
506 void TestController::run()
507 {
508     if (m_usingServerMode)
509         runTestingServerLoop();
510     else {
511         for (size_t i = 0; i < m_paths.size(); ++i) {
512             if (!runTest(m_paths[i].c_str()))
513                 break;
514         }
515     }
516 }
517
518 void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
519 {
520     platformRunUntil(done, timeoutDuration == ShortTimeout ? m_shortTimeout : m_longTimeout);
521 }
522
523 // WKContextInjectedBundleClient
524
525 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
526 {
527     static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
528 }
529
530 void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
531 {
532     *returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
533 }
534
535 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
536 {
537     if (!m_currentInvocation)
538         return;
539     m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
540 }
541
542 WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
543 {
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);
548
549         WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
550         WKStringRef subMessageName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subMessageKey.get()));
551
552         if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
553             WKRetainPtr<WKStringRef> keyKey = adoptWK(WKStringCreateWithUTF8CString("Key"));
554             WKStringRef key = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, keyKey.get()));
555
556             WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
557             WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
558
559             WKRetainPtr<WKStringRef> locationKey = adoptWK(WKStringCreateWithUTF8CString("Location"));
560             unsigned location = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, locationKey.get()))));
561
562             // Forward to WebProcess
563             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
564             m_eventSenderProxy->keyDown(key, modifiers, location);
565             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
566             return 0;
567         }
568
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()))));
573
574             WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
575             WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
576
577             // Forward to WebProcess
578             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
579             if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
580                 m_eventSenderProxy->mouseDown(button, modifiers);
581             else
582                 m_eventSenderProxy->mouseUp(button, modifiers);
583             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
584             return 0;
585         }
586
587         if (WKStringIsEqualToUTF8CString(subMessageName, "MouseMoveTo")) {
588             WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
589             double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
590
591             WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
592             double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
593
594             // Forward to WebProcess
595             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
596             m_eventSenderProxy->mouseMoveTo(x, y);
597             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
598             return 0;
599         }
600
601         if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
602             WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
603             double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
604
605             WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
606             double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
607
608             // Forward to WebProcess
609             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
610             m_eventSenderProxy->mouseScrollBy(x, y);
611             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
612             return 0;
613         }
614
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()))));
618
619             m_eventSenderProxy->leapForward(time);
620             return 0;
621         }
622 #endif
623
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()))));
628
629             WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
630             int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
631
632             m_eventSenderProxy->addTouchPoint(x, y);
633             return 0;
634         }
635
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()))));
639
640             WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
641             int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
642
643             WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
644             int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
645
646             m_eventSenderProxy->updateTouchPoint(index, x, y);
647             return 0;
648         }
649
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()))));
653
654             WKRetainPtr<WKStringRef> enableKey = adoptWK(WKStringCreateWithUTF8CString("Enable"));
655             bool enable = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, enableKey.get()))));
656
657             m_eventSenderProxy->setTouchModifier(modifier, enable);
658             return 0;
659         }
660
661         if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
662             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
663             m_eventSenderProxy->touchStart();
664             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
665             return 0;
666         }
667
668         if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
669             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
670             m_eventSenderProxy->touchMove();
671             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
672             return 0;
673         }
674
675         if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
676             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
677             m_eventSenderProxy->touchEnd();
678             WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
679             return 0;
680         }
681
682         if (WKStringIsEqualToUTF8CString(subMessageName, "ClearTouchPoints")) {
683             m_eventSenderProxy->clearTouchPoints();
684             return 0;
685         }
686
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);
691             return 0;
692         }
693 #endif
694         ASSERT_NOT_REACHED();
695     }
696 #endif
697     return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody);
698 }
699
700 // WKPageLoaderClient
701
702 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
703 {
704     static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(page, frame);
705 }
706
707 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
708 {
709     static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
710 }
711
712 void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
713 {
714     static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
715 }
716
717 void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame)
718 {
719     if (!WKFrameIsMainFrame(frame))
720         return;
721
722     mainWebView()->focus();
723 }
724
725 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
726 {
727     if (m_state != Resetting)
728         return;
729
730     if (!WKFrameIsMainFrame(frame))
731         return;
732
733     WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
734     if (!WKURLIsEqual(wkURL.get(), blankURL()))
735         return;
736
737     m_doneResetting = true;
738     shared().notifyDone();
739 }
740
741 void TestController::processDidCrash()
742 {
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);
747         fflush(stderr);
748         m_didPrintWebProcessCrashedMessage = true;
749     }
750
751     if (m_shouldExitWhenWebProcessCrashes)
752         exit(1);
753 }
754
755 } // namespace WTR