a774692a8b53729bea98b548c01b79a45cc1be60
[WebKit-https.git] / Tools / WebKitTestRunner / TestInvocation.cpp
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "TestInvocation.h"
29
30 #include "PlatformWebView.h"
31 #include "StringFunctions.h"
32 #include "TestController.h"
33 #include "UIScriptController.h"
34 #include "WebCoreTestSupport.h"
35 #include <WebKit/WKContextPrivate.h>
36 #include <WebKit/WKCookieManager.h>
37 #include <WebKit/WKData.h>
38 #include <WebKit/WKDictionary.h>
39 #include <WebKit/WKInspector.h>
40 #include <WebKit/WKPagePrivate.h>
41 #include <WebKit/WKRetainPtr.h>
42 #include <WebKit/WKWebsiteDataStoreRef.h>
43 #include <climits>
44 #include <cstdio>
45 #include <unistd.h>
46 #include <wtf/StdLibExtras.h>
47 #include <wtf/text/CString.h>
48
49 #if PLATFORM(MAC) && !PLATFORM(IOS)
50 #include <Carbon/Carbon.h>
51 #endif
52
53 #if PLATFORM(COCOA)
54 #include <WebKit/WKPagePrivateMac.h>
55 #endif
56
57 using namespace JSC;
58 using namespace WebKit;
59 using namespace std;
60
61 namespace WTR {
62
63 TestInvocation::TestInvocation(WKURLRef url, const TestOptions& options)
64     : m_options(options)
65     , m_url(url)
66 {
67     WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(m_url.get()));
68
69     size_t stringLength = WKStringGetLength(urlString.get());
70
71     Vector<char> urlVector;
72     urlVector.resize(stringLength + 1);
73
74     WKStringGetUTF8CString(urlString.get(), urlVector.data(), stringLength + 1);
75
76     m_urlString = String(urlVector.data(), stringLength);
77 }
78
79 TestInvocation::~TestInvocation()
80 {
81     if (m_pendingUIScriptInvocationData)
82         m_pendingUIScriptInvocationData->testInvocation = nullptr;
83 }
84
85 WKURLRef TestInvocation::url() const
86 {
87     return m_url.get();
88 }
89
90 bool TestInvocation::urlContains(const char* searchString) const
91 {
92     return m_urlString.contains(searchString, false);
93 }
94
95 void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
96 {
97     m_dumpPixels = true;
98     m_expectedPixelHash = expectedPixelHash;
99 }
100
101 double TestInvocation::shortTimeout() const
102 {
103     if (!m_timeout) {
104         // Running WKTR directly, without webkitpy.
105         return TestController::defaultShortTimeout;
106     }
107
108     // This is not exactly correct for the way short timeout is used - it should not depend on whether a test is "slow",
109     // but it currently does. There is no way to know what a normal test's timeout is, as webkitpy only passes timeouts
110     // for each test individually.
111     // But there shouldn't be any observable negative consequences from this.
112     return m_timeout / 1000. / 2;
113 }
114
115 bool TestInvocation::shouldLogFrameLoadDelegates() const
116 {
117     return urlContains("loading/");
118 }
119
120 bool TestInvocation::shouldLogHistoryClientCallbacks() const
121 {
122     return urlContains("globalhistory/");
123 }
124
125 void TestInvocation::invoke()
126 {
127     TestController::singleton().configureViewForTest(*this);
128
129     WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), false);
130
131     m_textOutput.clear();
132
133     TestController::singleton().setShouldLogHistoryClientCallbacks(shouldLogHistoryClientCallbacks());
134
135     WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain);
136
137     // FIXME: We should clear out visited links here.
138
139     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest"));
140     WKRetainPtr<WKMutableDictionaryRef> beginTestMessageBody = adoptWK(WKMutableDictionaryCreate());
141
142     WKRetainPtr<WKStringRef> dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates"));
143     WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates()));
144     WKDictionarySetItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get());
145
146     WKRetainPtr<WKStringRef> useFlexibleViewportKey = adoptWK(WKStringCreateWithUTF8CString("UseFlexibleViewport"));
147     WKRetainPtr<WKBooleanRef> useFlexibleViewportValue = adoptWK(WKBooleanCreate(options().useFlexibleViewport));
148     WKDictionarySetItem(beginTestMessageBody.get(), useFlexibleViewportKey.get(), useFlexibleViewportValue.get());
149
150     WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels"));
151     WKRetainPtr<WKBooleanRef> dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels));
152     WKDictionarySetItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get());
153
154     WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer"));
155     WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::singleton().useWaitToDumpWatchdogTimer()));
156     WKDictionarySetItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get());
157
158     WKRetainPtr<WKStringRef> timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout"));
159     WKRetainPtr<WKUInt64Ref> timeoutValue = adoptWK(WKUInt64Create(m_timeout));
160     WKDictionarySetItem(beginTestMessageBody.get(), timeoutKey.get(), timeoutValue.get());
161
162     WKRetainPtr<WKStringRef> dumpJSConsoleLogInStdErrKey = adoptWK(WKStringCreateWithUTF8CString("DumpJSConsoleLogInStdErr"));
163     WKRetainPtr<WKBooleanRef> dumpJSConsoleLogInStdErrValue = adoptWK(WKBooleanCreate(m_dumpJSConsoleLogInStdErr));
164     WKDictionarySetItem(beginTestMessageBody.get(), dumpJSConsoleLogInStdErrKey.get(), dumpJSConsoleLogInStdErrValue.get());
165
166     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), beginTestMessageBody.get());
167
168     bool shouldOpenExternalURLs = false;
169
170     TestController::singleton().runUntil(m_gotInitialResponse, shortTimeout());
171     if (!m_gotInitialResponse) {
172         m_errorMessage = "Timed out waiting for initial response from web process\n";
173         m_webProcessIsUnresponsive = true;
174         goto end;
175     }
176     if (m_error)
177         goto end;
178
179     WKPageLoadURLWithShouldOpenExternalURLsPolicy(TestController::singleton().mainWebView()->page(), m_url.get(), shouldOpenExternalURLs);
180
181     TestController::singleton().runUntil(m_gotFinalMessage, TestController::noTimeout);
182     if (m_error)
183         goto end;
184
185     dumpResults();
186
187 end:
188 #if !PLATFORM(IOS)
189     if (m_gotInitialResponse)
190         WKInspectorClose(WKPageGetInspector(TestController::singleton().mainWebView()->page()));
191 #endif // !PLATFORM(IOS)
192
193     if (m_webProcessIsUnresponsive)
194         dumpWebProcessUnresponsiveness();
195     else if (TestController::singleton().resetStateToConsistentValues(m_options))
196         return;
197
198     // The process is unresponsive, so let's start a new one.
199     TestController::singleton().terminateWebContentProcess();
200     // Make sure that we have a process, as invoke() will need one to send bundle messages for the next test.
201     TestController::singleton().reattachPageToWebProcess();
202 }
203
204 void TestInvocation::dumpWebProcessUnresponsiveness()
205 {
206     dumpWebProcessUnresponsiveness(m_errorMessage.c_str());
207 }
208
209 void TestInvocation::dumpWebProcessUnresponsiveness(const char* errorMessage)
210 {
211     fprintf(stderr, "%s", errorMessage);
212     char buffer[1024] = { };
213 #if PLATFORM(COCOA)
214     pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page());
215     snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast<long>(pid));
216 #else
217     snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s\n", TestController::webProcessName());
218 #endif
219
220     dump(errorMessage, buffer, true);
221     
222     if (!TestController::singleton().usingServerMode())
223         return;
224     
225     if (isatty(fileno(stdin)) || isatty(fileno(stderr)))
226         fputs("Grab an image of the stack, then hit enter...\n", stderr);
227     
228     if (!fgets(buffer, sizeof(buffer), stdin) || strcmp(buffer, "#SAMPLE FINISHED\n"))
229         fprintf(stderr, "Failed receive expected sample response, got:\n\t\"%s\"\nContinuing...\n", buffer);
230 }
231
232 void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError)
233 {
234     printf("Content-Type: text/plain\n");
235     if (textToStdout)
236         fputs(textToStdout, stdout);
237     if (textToStderr)
238         fputs(textToStderr, stderr);
239
240     fputs("#EOF\n", stdout);
241     fputs("#EOF\n", stderr);
242     if (seenError)
243         fputs("#EOF\n", stdout);
244     fflush(stdout);
245     fflush(stderr);
246 }
247
248 void TestInvocation::forceRepaintDoneCallback(WKErrorRef error, void* context)
249 {
250     // The context may not be valid any more, e.g. if WebKit is invalidating callbacks at process exit.
251     if (error)
252         return;
253
254     TestInvocation* testInvocation = static_cast<TestInvocation*>(context);
255     RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(testInvocation));
256
257     testInvocation->m_gotRepaint = true;
258     TestController::singleton().notifyDone();
259 }
260
261 void TestInvocation::dumpResults()
262 {
263     if (m_textOutput.length() || !m_audioResult)
264         dump(m_textOutput.toString().utf8().data());
265     else
266         dumpAudio(m_audioResult.get());
267
268     if (m_dumpPixels) {
269         if (m_pixelResult)
270             dumpPixelsAndCompareWithExpected(SnapshotResultType::WebContents, m_repaintRects.get(), m_pixelResult.get());
271         else if (m_pixelResultIsPending) {
272             m_gotRepaint = false;
273             WKPageForceRepaint(TestController::singleton().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback);
274             TestController::singleton().runUntil(m_gotRepaint, shortTimeout());
275             if (!m_gotRepaint) {
276                 m_errorMessage = "Timed out waiting for pre-pixel dump repaint\n";
277                 m_webProcessIsUnresponsive = true;
278                 return;
279             }
280
281             dumpPixelsAndCompareWithExpected(SnapshotResultType::WebView, m_repaintRects.get());
282         }
283     }
284
285     fputs("#EOF\n", stdout);
286     fflush(stdout);
287     fflush(stderr);
288 }
289
290 void TestInvocation::dumpAudio(WKDataRef audioData)
291 {
292     size_t length = WKDataGetSize(audioData);
293     if (!length)
294         return;
295
296     const unsigned char* data = WKDataGetBytes(audioData);
297
298     printf("Content-Type: audio/wav\n");
299     printf("Content-Length: %lu\n", static_cast<unsigned long>(length));
300
301     fwrite(data, 1, length, stdout);
302     printf("#EOF\n");
303     fprintf(stderr, "#EOF\n");
304 }
305
306 bool TestInvocation::compareActualHashToExpectedAndDumpResults(const char actualHash[33])
307 {
308     // Compute the hash of the bitmap context pixels
309     fprintf(stdout, "\nActualHash: %s\n", actualHash);
310
311     if (!m_expectedPixelHash.length())
312         return false;
313
314     ASSERT(m_expectedPixelHash.length() == 32);
315     fprintf(stdout, "\nExpectedHash: %s\n", m_expectedPixelHash.c_str());
316
317     // FIXME: Do case insensitive compare.
318     return m_expectedPixelHash == actualHash;
319 }
320
321 void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
322 {
323     if (WKStringIsEqualToUTF8CString(messageName, "Error")) {
324         // Set all states to true to stop spinning the runloop.
325         m_gotInitialResponse = true;
326         m_gotFinalMessage = true;
327         m_error = true;
328         m_errorMessage = "FAIL\n";
329         TestController::singleton().notifyDone();
330         return;
331     }
332
333     if (WKStringIsEqualToUTF8CString(messageName, "Ack")) {
334         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
335         WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody);
336         if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) {
337             m_gotInitialResponse = true;
338             TestController::singleton().notifyDone();
339             return;
340         }
341
342         ASSERT_NOT_REACHED();
343     }
344
345     if (WKStringIsEqualToUTF8CString(messageName, "Done")) {
346         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
347         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
348
349         WKRetainPtr<WKStringRef> pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending"));
350         WKBooleanRef pixelResultIsPending = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultIsPendingKey.get()));
351         m_pixelResultIsPending = WKBooleanGetValue(pixelResultIsPending);
352
353         if (!m_pixelResultIsPending) {
354             WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
355             m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get()));
356             ASSERT(!m_pixelResult || m_dumpPixels);
357         }
358
359         WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
360         m_repaintRects = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get()));
361
362         WKRetainPtr<WKStringRef> audioResultKey =  adoptWK(WKStringCreateWithUTF8CString("AudioResult"));
363         m_audioResult = static_cast<WKDataRef>(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get()));
364
365         m_gotFinalMessage = true;
366         TestController::singleton().notifyDone();
367         return;
368     }
369
370     if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) {
371         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
372         WKStringRef textOutput = static_cast<WKStringRef>(messageBody);
373         m_textOutput.append(toWTFString(textOutput));
374         return;
375     }
376
377     if (WKStringIsEqualToUTF8CString(messageName, "DumpToStdErr")) {
378         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
379         WKStringRef textOutput = static_cast<WKStringRef>(messageBody);
380         fprintf(stderr, "%s", toWTFString(textOutput).utf8().data());
381         return;
382     }
383
384     if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) {
385         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
386         WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody);
387         TestController::singleton().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
388         return;
389     }
390     
391     if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) {
392         TestController::singleton().mainWebView()->addChromeInputField();
393         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback"));
394         WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
395         return;
396     }
397
398     if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) {
399         TestController::singleton().mainWebView()->removeChromeInputField();
400         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback"));
401         WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
402         return;
403     }
404     
405     if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) {
406         TestController::singleton().mainWebView()->makeWebViewFirstResponder();
407         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback"));
408         WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
409         return;
410     }
411
412     if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) {
413         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
414         double backingScaleFactor = WKDoubleGetValue(static_cast<WKDoubleRef>(messageBody));
415         WKPageSetCustomBackingScaleFactor(TestController::singleton().mainWebView()->page(), backingScaleFactor);
416
417         WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback"));
418         WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
419         return;
420     }
421
422     if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) {
423         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
424         uint64_t notificationID = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
425         TestController::singleton().simulateWebNotificationClick(notificationID);
426         return;
427     }
428
429     if (WKStringIsEqualToUTF8CString(messageName, "SetAddsVisitedLinks")) {
430         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
431         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
432         WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), WKBooleanGetValue(enabledWK));
433         return;
434     }
435
436     if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) {
437         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
438         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
439         TestController::singleton().setGeolocationPermission(WKBooleanGetValue(enabledWK));
440         return;
441     }
442
443     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) {
444         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
445         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
446
447         WKRetainPtr<WKStringRef> latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude"));
448         WKDoubleRef latitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, latitudeKeyWK.get()));
449         double latitude = WKDoubleGetValue(latitudeWK);
450
451         WKRetainPtr<WKStringRef> longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude"));
452         WKDoubleRef longitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, longitudeKeyWK.get()));
453         double longitude = WKDoubleGetValue(longitudeWK);
454
455         WKRetainPtr<WKStringRef> accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy"));
456         WKDoubleRef accuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, accuracyKeyWK.get()));
457         double accuracy = WKDoubleGetValue(accuracyWK);
458
459         WKRetainPtr<WKStringRef> providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude"));
460         WKBooleanRef providesAltitudeWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeKeyWK.get()));
461         bool providesAltitude = WKBooleanGetValue(providesAltitudeWK);
462
463         WKRetainPtr<WKStringRef> altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude"));
464         WKDoubleRef altitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeKeyWK.get()));
465         double altitude = WKDoubleGetValue(altitudeWK);
466
467         WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy"));
468         WKBooleanRef providesAltitudeAccuracyWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeAccuracyKeyWK.get()));
469         bool providesAltitudeAccuracy = WKBooleanGetValue(providesAltitudeAccuracyWK);
470
471         WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy"));
472         WKDoubleRef altitudeAccuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeAccuracyKeyWK.get()));
473         double altitudeAccuracy = WKDoubleGetValue(altitudeAccuracyWK);
474
475         WKRetainPtr<WKStringRef> providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading"));
476         WKBooleanRef providesHeadingWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesHeadingKeyWK.get()));
477         bool providesHeading = WKBooleanGetValue(providesHeadingWK);
478
479         WKRetainPtr<WKStringRef> headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading"));
480         WKDoubleRef headingWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, headingKeyWK.get()));
481         double heading = WKDoubleGetValue(headingWK);
482
483         WKRetainPtr<WKStringRef> providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed"));
484         WKBooleanRef providesSpeedWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesSpeedKeyWK.get()));
485         bool providesSpeed = WKBooleanGetValue(providesSpeedWK);
486
487         WKRetainPtr<WKStringRef> speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed"));
488         WKDoubleRef speedWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get()));
489         double speed = WKDoubleGetValue(speedWK);
490
491         TestController::singleton().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
492         return;
493     }
494
495     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) {
496         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
497         WKStringRef errorMessage = static_cast<WKStringRef>(messageBody);
498         TestController::singleton().setMockGeolocationPositionUnavailableError(errorMessage);
499         return;
500     }
501
502     if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermission")) {
503         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
504         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
505         TestController::singleton().setUserMediaPermission(WKBooleanGetValue(enabledWK));
506         return;
507     }
508
509     if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPersistentPermissionForOrigin")) {
510         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
511         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
512
513         WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission"));
514         WKBooleanRef permissionWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissionKeyWK.get()));
515         bool permission = WKBooleanGetValue(permissionWK);
516
517         WKRetainPtr<WKStringRef> originKey(AdoptWK, WKStringCreateWithUTF8CString("origin"));
518         WKStringRef originWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get()));
519
520         WKRetainPtr<WKStringRef> parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
521         WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
522
523         TestController::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK, parentOriginWK);
524         return;
525     }
526
527     if (WKStringIsEqualToUTF8CString(messageName, "ResetUserMediaPermissionRequestCountForOrigin")) {
528         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
529         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
530
531         WKRetainPtr<WKStringRef> originKey(AdoptWK, WKStringCreateWithUTF8CString("origin"));
532         WKStringRef originWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get()));
533
534         WKRetainPtr<WKStringRef> parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
535         WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
536         
537         TestController::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK, parentOriginWK);
538         return;
539     }
540
541     if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) {
542         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
543         uint64_t model = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
544         WKContextSetCacheModel(TestController::singleton().context(), model);
545         return;
546     }
547
548     if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) {
549         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
550         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
551
552         WKRetainPtr<WKStringRef> enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled"));
553         WKBooleanRef enabledWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, enabledKeyWK.get()));
554         bool enabled = WKBooleanGetValue(enabledWK);
555
556         WKRetainPtr<WKStringRef> permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive"));
557         WKBooleanRef permissiveWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get()));
558         bool permissive = WKBooleanGetValue(permissiveWK);
559
560         TestController::singleton().setCustomPolicyDelegate(enabled, permissive);
561         return;
562     }
563
564     if (WKStringIsEqualToUTF8CString(messageName, "SetHidden")) {
565         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
566         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
567
568         WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden"));
569         WKBooleanRef hiddenWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get()));
570         bool hidden = WKBooleanGetValue(hiddenWK);
571
572         TestController::singleton().setHidden(hidden);
573         return;
574     }
575
576     if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) {
577         if (TestController::singleton().workQueueManager().processWorkQueue()) {
578             WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback"));
579             WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
580         }
581         return;
582     }
583
584     if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) {
585         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
586         uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
587         TestController::singleton().workQueueManager().queueBackNavigation(stepCount);
588         return;
589     }
590
591     if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) {
592         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
593         uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
594         TestController::singleton().workQueueManager().queueForwardNavigation(stepCount);
595         return;
596     }
597
598     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) {
599         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
600         WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
601
602         WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
603         WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, urlKey.get()));
604
605         WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target"));
606         WKStringRef targetWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get()));
607
608         WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs"));
609         WKBooleanRef shouldOpenExternalURLsValueWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(loadDataDictionary, shouldOpenExternalURLsKey.get()));
610
611         TestController::singleton().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK), WKBooleanGetValue(shouldOpenExternalURLsValueWK));
612         return;
613     }
614
615     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) {
616         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
617         WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
618
619         WKRetainPtr<WKStringRef> contentKey(AdoptWK, WKStringCreateWithUTF8CString("content"));
620         WKStringRef contentWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, contentKey.get()));
621
622         WKRetainPtr<WKStringRef> baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL"));
623         WKStringRef baseURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, baseURLKey.get()));
624
625         WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL"));
626         WKStringRef unreachableURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get()));
627
628         TestController::singleton().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String());
629         return;
630     }
631
632     if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) {
633         TestController::singleton().workQueueManager().queueReload();
634         return;
635     }
636
637     if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) {
638         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
639         WKStringRef script = static_cast<WKStringRef>(messageBody);
640         TestController::singleton().workQueueManager().queueLoadingScript(toWTFString(script));
641         return;
642     }
643
644     if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) {
645         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
646         WKStringRef script = static_cast<WKStringRef>(messageBody);
647         TestController::singleton().workQueueManager().queueNonLoadingScript(toWTFString(script));
648         return;
649     }
650
651     if (WKStringIsEqualToUTF8CString(messageName, "SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")) {
652         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
653         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
654         TestController::singleton().setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(WKBooleanGetValue(value));
655         return;
656     }
657
658     if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenges")) {
659         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
660         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
661         TestController::singleton().setHandlesAuthenticationChallenges(WKBooleanGetValue(value));
662         return;
663     }
664
665     if (WKStringIsEqualToUTF8CString(messageName, "SetShouldLogCanAuthenticateAgainstProtectionSpace")) {
666         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
667         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
668         TestController::singleton().setShouldLogCanAuthenticateAgainstProtectionSpace(WKBooleanGetValue(value));
669         return;
670     }
671
672     if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) {
673         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
674         WKStringRef username = static_cast<WKStringRef>(messageBody);
675         TestController::singleton().setAuthenticationUsername(toWTFString(username));
676         return;
677     }
678
679     if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) {
680         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
681         WKStringRef password = static_cast<WKStringRef>(messageBody);
682         TestController::singleton().setAuthenticationPassword(toWTFString(password));
683         return;
684     }
685
686     if (WKStringIsEqualToUTF8CString(messageName, "SetBlockAllPlugins")) {
687         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
688         WKBooleanRef shouldBlock = static_cast<WKBooleanRef>(messageBody);
689         TestController::singleton().setBlockAllPlugins(WKBooleanGetValue(shouldBlock));
690         return;
691     }
692
693     if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDecideNavigationPolicyAfterDelay")) {
694         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
695         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
696         TestController::singleton().setShouldDecideNavigationPolicyAfterDelay(WKBooleanGetValue(value));
697         return;
698     }
699
700     if (WKStringIsEqualToUTF8CString(messageName, "SetNavigationGesturesEnabled")) {
701         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
702         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
703         TestController::singleton().setNavigationGesturesEnabled(WKBooleanGetValue(value));
704         return;
705     }
706     
707     if (WKStringIsEqualToUTF8CString(messageName, "SetIgnoresViewportScaleLimits")) {
708         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
709         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
710         TestController::singleton().setIgnoresViewportScaleLimits(WKBooleanGetValue(value));
711         return;
712     }
713
714     if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDownloadUndisplayableMIMETypes")) {
715         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
716         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
717         TestController::singleton().setShouldDownloadUndisplayableMIMETypes(WKBooleanGetValue(value));
718         return;
719     }
720
721     if (WKStringIsEqualToUTF8CString(messageName, "TerminateNetworkProcess")) {
722         ASSERT(!messageBody);
723         TestController::singleton().terminateNetworkProcess();
724         return;
725     }
726
727     if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScript")) {
728         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
729         WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
730         WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
731
732         UIScriptInvocationData* invocationData = new UIScriptInvocationData();
733         invocationData->testInvocation = this;
734         invocationData->callbackID = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get())));
735         invocationData->scriptString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, scriptKey.get()));
736         m_pendingUIScriptInvocationData = invocationData;
737         WKPageCallAfterNextPresentationUpdate(TestController::singleton().mainWebView()->page(), invocationData, runUISideScriptAfterUpdateCallback);
738         return;
739     }
740
741     if (WKStringIsEqualToUTF8CString(messageName, "SetOpenPanelFileURLs")) {
742         TestController::singleton().setOpenPanelFileURLs(static_cast<WKArrayRef>(messageBody));
743         return;
744     }
745
746     ASSERT_NOT_REACHED();
747 }
748
749 WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
750 {
751     if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) {
752         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
753         WKBooleanRef isKeyValue = static_cast<WKBooleanRef>(messageBody);
754         TestController::singleton().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue));
755         return nullptr;
756     }
757
758     if (WKStringIsEqualToUTF8CString(messageName, "SetViewSize")) {
759         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
760
761         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
762         WKRetainPtr<WKStringRef> widthKey(AdoptWK, WKStringCreateWithUTF8CString("width"));
763         WKRetainPtr<WKStringRef> heightKey(AdoptWK, WKStringCreateWithUTF8CString("height"));
764
765         WKDoubleRef widthWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, widthKey.get()));
766         WKDoubleRef heightWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, heightKey.get()));
767
768         TestController::singleton().mainWebView()->resizeTo(WKDoubleGetValue(widthWK), WKDoubleGetValue(heightWK));
769         return nullptr;
770     }
771
772     if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) {
773         bool isActive = TestController::singleton().isGeolocationProviderActive();
774         WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isActive));
775         return result;
776     }
777
778     if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) {
779         bool isEmpty = TestController::singleton().workQueueManager().isWorkQueueEmpty();
780         WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isEmpty));
781         return result;
782     }
783
784     if (WKStringIsEqualToUTF8CString(messageName, "SecureEventInputIsEnabled")) {
785 #if PLATFORM(MAC) && !PLATFORM(IOS)
786         WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(IsSecureEventInputEnabled()));
787 #else
788         WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(false));
789 #endif
790         return result;
791     }
792
793     if (WKStringIsEqualToUTF8CString(messageName, "SetAlwaysAcceptCookies")) {
794         WKBooleanRef accept = static_cast<WKBooleanRef>(messageBody);
795         WKHTTPCookieAcceptPolicy policy = WKBooleanGetValue(accept) ? kWKHTTPCookieAcceptPolicyAlways : kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
796         // FIXME: This updates the policy in WebProcess and in NetworkProcess asynchronously, which might break some tests' expectations.
797         WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), policy);
798         return nullptr;
799     }
800
801     if (WKStringIsEqualToUTF8CString(messageName, "SetCookieStoragePartitioningEnabled")) {
802         WKBooleanRef accept = static_cast<WKBooleanRef>(messageBody);
803         WKCookieManagerSetCookieStoragePartitioningEnabled(WKContextGetCookieManager(TestController::singleton().context()), WKBooleanGetValue(accept));
804         return nullptr;
805     }
806
807     if (WKStringIsEqualToUTF8CString(messageName, "SetAllowsAnySSLCertificate")) {
808         TestController::singleton().setAllowsAnySSLCertificate(WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody)));
809         return nullptr;
810     }
811
812     if (WKStringIsEqualToUTF8CString(messageName, "ImageCountInGeneralPasteboard")) {
813         unsigned count = TestController::singleton().imageCountInGeneralPasteboard();
814         WKRetainPtr<WKUInt64Ref> result(AdoptWK, WKUInt64Create(count));
815         return result;
816     }
817     
818     if (WKStringIsEqualToUTF8CString(messageName, "DeleteAllIndexedDatabases")) {
819         WKWebsiteDataStoreRemoveAllIndexedDatabases(WKContextGetWebsiteDataStore(TestController::singleton().context()));
820         return nullptr;
821     }
822
823 #if PLATFORM(MAC)
824     if (WKStringIsEqualToUTF8CString(messageName, "ConnectMockGamepad")) {
825         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
826
827         uint64_t index = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
828         WebCoreTestSupport::connectMockGamepad(index);
829         
830         return nullptr;
831     }
832
833     if (WKStringIsEqualToUTF8CString(messageName, "DisconnectMockGamepad")) {
834         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
835
836         uint64_t index = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
837         WebCoreTestSupport::disconnectMockGamepad(index);
838
839         return nullptr;
840     }
841
842     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadDetails")) {
843         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
844
845         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
846         WKRetainPtr<WKStringRef> gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex"));
847         WKRetainPtr<WKStringRef> gamepadIDKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadID"));
848         WKRetainPtr<WKStringRef> axisCountKey(AdoptWK, WKStringCreateWithUTF8CString("AxisCount"));
849         WKRetainPtr<WKStringRef> buttonCountKey(AdoptWK, WKStringCreateWithUTF8CString("ButtonCount"));
850
851         WKUInt64Ref gamepadIndex = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get()));
852         WKStringRef gamepadID = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIDKey.get()));
853         WKUInt64Ref axisCount = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, axisCountKey.get()));
854         WKUInt64Ref buttonCount = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonCountKey.get()));
855
856         WebCoreTestSupport::setMockGamepadDetails(WKUInt64GetValue(gamepadIndex), toWTFString(gamepadID), WKUInt64GetValue(axisCount), WKUInt64GetValue(buttonCount));
857         return nullptr;
858     }
859
860     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadAxisValue")) {
861         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
862
863         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
864         WKRetainPtr<WKStringRef> gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex"));
865         WKRetainPtr<WKStringRef> axisIndexKey(AdoptWK, WKStringCreateWithUTF8CString("AxisIndex"));
866         WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value"));
867
868         WKUInt64Ref gamepadIndex = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get()));
869         WKUInt64Ref axisIndex = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, axisIndexKey.get()));
870         WKDoubleRef value = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
871
872         WebCoreTestSupport::setMockGamepadAxisValue(WKUInt64GetValue(gamepadIndex), WKUInt64GetValue(axisIndex), WKDoubleGetValue(value));
873
874         return nullptr;
875     }
876
877     if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadButtonValue")) {
878         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
879
880         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
881         WKRetainPtr<WKStringRef> gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex"));
882         WKRetainPtr<WKStringRef> buttonIndexKey(AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex"));
883         WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value"));
884
885         WKUInt64Ref gamepadIndex = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get()));
886         WKUInt64Ref buttonIndex = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonIndexKey.get()));
887         WKDoubleRef value = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
888
889         WebCoreTestSupport::setMockGamepadButtonValue(WKUInt64GetValue(gamepadIndex), WKUInt64GetValue(buttonIndex), WKDoubleGetValue(value));
890
891         return nullptr;
892     }
893 #endif // PLATFORM(MAC)
894
895     if (WKStringIsEqualToUTF8CString(messageName, "UserMediaPermissionRequestCountForOrigin")) {
896         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
897         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
898
899         WKRetainPtr<WKStringRef> originKey(AdoptWK, WKStringCreateWithUTF8CString("origin"));
900         WKStringRef originWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get()));
901
902         WKRetainPtr<WKStringRef> parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
903         WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
904         
905         unsigned count = TestController::singleton().userMediaPermissionRequestCountForOrigin(originWK, parentOriginWK);
906         WKRetainPtr<WKUInt64Ref> result(AdoptWK, WKUInt64Create(count));
907         return result;
908     }
909
910     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsPrevalentResource")) {
911         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
912
913         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
914         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
915         WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value"));
916
917         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
918         WKBooleanRef value = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
919
920         TestController::singleton().setStatisticsPrevalentResource(hostName, WKBooleanGetValue(value));
921         return nullptr;
922     }
923
924     if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsPrevalentResource")) {
925         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
926
927         WKStringRef hostName = static_cast<WKStringRef>(messageBody);
928         bool isPrevalent = TestController::singleton().isStatisticsPrevalentResource(hostName);
929         WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isPrevalent));
930         return result;
931     }
932
933     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsHasHadUserInteraction")) {
934         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
935         
936         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
937         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
938         WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value"));
939         
940         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
941         WKBooleanRef value = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
942         
943         TestController::singleton().setStatisticsHasHadUserInteraction(hostName, WKBooleanGetValue(value));
944         return nullptr;
945     }
946
947     if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsHasHadUserInteraction")) {
948         ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
949         
950         WKStringRef hostName = static_cast<WKStringRef>(messageBody);
951         bool hasHadUserInteraction = TestController::singleton().isStatisticsHasHadUserInteraction(hostName);
952         WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(hasHadUserInteraction));
953         return result;
954     }
955     
956     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubframeUnderTopFrameOrigin")) {
957         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
958         
959         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
960         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
961         WKRetainPtr<WKStringRef> topFrameHostNameKey(AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName"));
962         
963         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
964         WKStringRef topFrameHostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, topFrameHostNameKey.get()));
965
966         TestController::singleton().setStatisticsSubframeUnderTopFrameOrigin(hostName, topFrameHostName);
967         return nullptr;
968     }
969     
970     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUnderTopFrameOrigin")) {
971         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
972         
973         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
974         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
975         WKRetainPtr<WKStringRef> topFrameHostNameKey(AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName"));
976         
977         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
978         WKStringRef topFrameHostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, topFrameHostNameKey.get()));
979         
980         TestController::singleton().setStatisticsSubresourceUnderTopFrameOrigin(hostName, topFrameHostName);
981         return nullptr;
982     }
983     
984     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUniqueRedirectTo")) {
985         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
986         
987         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
988         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
989         WKRetainPtr<WKStringRef> hostNameRedirectedToKey(AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo"));
990         
991         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
992         WKStringRef hostNameRedirectedTo = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameRedirectedToKey.get()));
993         
994         TestController::singleton().setStatisticsSubresourceUniqueRedirectTo(hostName, hostNameRedirectedTo);
995         return nullptr;
996     }
997
998     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTimeToLiveUserInteraction")) {
999         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
1000         WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);
1001         TestController::singleton().setStatisticsTimeToLiveUserInteraction(WKDoubleGetValue(seconds));
1002         return nullptr;
1003     }
1004     
1005     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTimeToLiveCookiePartitionFree")) {
1006         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
1007         WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);
1008         TestController::singleton().setStatisticsTimeToLiveCookiePartitionFree(WKDoubleGetValue(seconds));
1009         return nullptr;
1010     }
1011
1012     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsFireDataModificationHandler")) {
1013         TestController::singleton().statisticsFireDataModificationHandler();
1014         return nullptr;
1015     }
1016     
1017     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsFireShouldPartitionCookiesHandler")) {
1018         TestController::singleton().statisticsFireShouldPartitionCookiesHandler();
1019         return nullptr;
1020     }
1021
1022     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsFireShouldPartitionCookiesHandlerForOneDomain")) {
1023         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
1024         
1025         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
1026         WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
1027         WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value"));
1028         
1029         WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
1030         WKBooleanRef value = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
1031         
1032         TestController::singleton().statisticsFireShouldPartitionCookiesHandlerForOneDomain(hostName, WKBooleanGetValue(value));
1033         return nullptr;
1034     }
1035     
1036     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsNotifyPagesWhenDataRecordsWereScanned")) {
1037         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
1038         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
1039         TestController::singleton().setStatisticsNotifyPagesWhenDataRecordsWereScanned(WKBooleanGetValue(value));
1040         return nullptr;
1041     }
1042
1043     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval")) {
1044         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
1045         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
1046         TestController::singleton().setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(WKBooleanGetValue(value));
1047         return nullptr;
1048     }
1049
1050     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsMinimumTimeBetweeenDataRecordsRemoval")) {
1051         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
1052         WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);
1053         TestController::singleton().setStatisticsMinimumTimeBetweeenDataRecordsRemoval(WKDoubleGetValue(seconds));
1054         return nullptr;
1055     }
1056     
1057     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsClearInMemoryAndPersistentStore")) {
1058         TestController::singleton().statisticsClearInMemoryAndPersistentStore();
1059         return nullptr;
1060     }
1061     
1062     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours")) {
1063         ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
1064         WKUInt64Ref hours = static_cast<WKUInt64Ref>(messageBody);
1065         TestController::singleton().statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(WKUInt64GetValue(hours));
1066         return nullptr;
1067     }
1068     
1069     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsResetToConsistentState")) {
1070         TestController::singleton().statisticsResetToConsistentState();
1071         return nullptr;
1072     }
1073
1074     ASSERT_NOT_REACHED();
1075     return nullptr;
1076 }
1077
1078 void TestInvocation::runUISideScriptAfterUpdateCallback(WKErrorRef, void* context)
1079 {
1080     UIScriptInvocationData* data = static_cast<UIScriptInvocationData*>(context);
1081     if (TestInvocation* invocation = data->testInvocation) {
1082         RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(invocation));
1083         invocation->runUISideScript(data->scriptString.get(), data->callbackID);
1084     }
1085     delete data;
1086 }
1087
1088 void TestInvocation::runUISideScript(WKStringRef script, unsigned scriptCallbackID)
1089 {
1090     m_pendingUIScriptInvocationData = nullptr;
1091
1092     if (!m_UIScriptContext)
1093         m_UIScriptContext = std::make_unique<UIScriptContext>(*this);
1094     
1095     m_UIScriptContext->runUIScript(toWTFString(script), scriptCallbackID);
1096 }
1097
1098 void TestInvocation::uiScriptDidComplete(const String& result, unsigned scriptCallbackID)
1099 {
1100     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallUISideScriptCallback"));
1101
1102     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
1103     WKRetainPtr<WKStringRef> resultKey(AdoptWK, WKStringCreateWithUTF8CString("Result"));
1104     WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
1105     WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(scriptCallbackID));
1106
1107     WKDictionarySetItem(messageBody.get(), resultKey.get(), toWK(result).get());
1108     WKDictionarySetItem(messageBody.get(), callbackIDKey.get(), callbackIDValue.get());
1109
1110     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), messageBody.get());
1111 }
1112
1113 void TestInvocation::outputText(const WTF::String& text)
1114 {
1115     m_textOutput.append(text);
1116 }
1117
1118 void TestInvocation::didBeginSwipe()
1119 {
1120     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidBeginSwipeCallback"));
1121     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
1122 }
1123
1124 void TestInvocation::willEndSwipe()
1125 {
1126     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallWillEndSwipeCallback"));
1127     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
1128 }
1129
1130 void TestInvocation::didEndSwipe()
1131 {
1132     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidEndSwipeCallback"));
1133     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
1134 }
1135
1136 void TestInvocation::didRemoveSwipeSnapshot()
1137 {
1138     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidRemoveSwipeSnapshotCallback"));
1139     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
1140 }
1141
1142 void TestInvocation::notifyDownloadDone()
1143 {
1144     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("NotifyDownloadDone"));
1145     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
1146 }
1147
1148 } // namespace WTR