[CMake] Properly test if compiler supports compiler flags
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / TestRunner.cpp
1 /*
2  * Copyright (C) 2010-2017 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 "TestRunner.h"
28
29 #include "InjectedBundle.h"
30 #include "InjectedBundlePage.h"
31 #include "JSTestRunner.h"
32 #include "PlatformWebView.h"
33 #include "StringFunctions.h"
34 #include "TestController.h"
35 #include <JavaScriptCore/JSCTestRunnerUtils.h>
36 #include <WebCore/ResourceLoadObserver.h>
37 #include <WebKit/WKBundle.h>
38 #include <WebKit/WKBundleBackForwardList.h>
39 #include <WebKit/WKBundleFrame.h>
40 #include <WebKit/WKBundleFramePrivate.h>
41 #include <WebKit/WKBundleInspector.h>
42 #include <WebKit/WKBundleNodeHandlePrivate.h>
43 #include <WebKit/WKBundlePage.h>
44 #include <WebKit/WKBundlePagePrivate.h>
45 #include <WebKit/WKBundlePrivate.h>
46 #include <WebKit/WKBundleScriptWorld.h>
47 #include <WebKit/WKData.h>
48 #include <WebKit/WKPagePrivate.h>
49 #include <WebKit/WKRetainPtr.h>
50 #include <WebKit/WKSerializedScriptValue.h>
51 #include <WebKit/WebKit2_C.h>
52 #include <wtf/CurrentTime.h>
53 #include <wtf/HashMap.h>
54 #include <wtf/StdLibExtras.h>
55 #include <wtf/text/CString.h>
56 #include <wtf/text/StringBuilder.h>
57
58 namespace WTR {
59
60 Ref<TestRunner> TestRunner::create()
61 {
62     return adoptRef(*new TestRunner);
63 }
64
65 TestRunner::TestRunner()
66     : m_whatToDump(RenderTree)
67     , m_shouldDumpAllFrameScrollPositions(false)
68     , m_shouldDumpBackForwardListsForAllWindows(false)
69     , m_shouldAllowEditing(true)
70     , m_shouldCloseExtraWindows(false)
71     , m_dumpEditingCallbacks(false)
72     , m_dumpStatusCallbacks(false)
73     , m_dumpTitleChanges(false)
74     , m_dumpPixels(true)
75     , m_dumpSelectionRect(false)
76     , m_dumpFullScreenCallbacks(false)
77     , m_dumpFrameLoadCallbacks(false)
78     , m_dumpProgressFinishedCallback(false)
79     , m_dumpResourceLoadCallbacks(false)
80     , m_dumpResourceResponseMIMETypes(false)
81     , m_dumpWillCacheResponse(false)
82     , m_dumpApplicationCacheDelegateCallbacks(false)
83     , m_dumpDatabaseCallbacks(false)
84     , m_disallowIncreaseForApplicationCacheQuota(false)
85     , m_waitToDump(false)
86     , m_testRepaint(false)
87     , m_testRepaintSweepHorizontally(false)
88     , m_isPrinting(false)
89     , m_willSendRequestReturnsNull(false)
90     , m_willSendRequestReturnsNullOnRedirect(false)
91     , m_shouldStopProvisionalFrameLoads(false)
92     , m_policyDelegateEnabled(false)
93     , m_policyDelegatePermissive(false)
94     , m_globalFlag(false)
95     , m_customFullScreenBehavior(false)
96     , m_timeout(30000)
97     , m_databaseDefaultQuota(-1)
98     , m_databaseMaxQuota(-1)
99     , m_userStyleSheetEnabled(false)
100     , m_userStyleSheetLocation(adoptWK(WKStringCreateWithUTF8CString("")))
101 #if PLATFORM(GTK) || PLATFORM(WPE)
102     , m_waitToDumpWatchdogTimer(RunLoop::main(), this, &TestRunner::waitToDumpWatchdogTimerFired)
103 #endif
104 {
105     platformInitialize();
106 }
107
108 TestRunner::~TestRunner()
109 {
110 }
111
112 JSClassRef TestRunner::wrapperClass()
113 {
114     return JSTestRunner::testRunnerClass();
115 }
116
117 void TestRunner::display()
118 {
119     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
120     WKBundlePageForceRepaint(page);
121 }
122
123 void TestRunner::displayAndTrackRepaints()
124 {
125     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
126     WKBundlePageForceRepaint(page);
127     WKBundlePageSetTracksRepaints(page, true);
128     WKBundlePageResetTrackedRepaints(page);
129 }
130
131 void TestRunner::dumpAsText(bool dumpPixels)
132 {
133     if (m_whatToDump < MainFrameText)
134         m_whatToDump = MainFrameText;
135     m_dumpPixels = dumpPixels;
136 }
137
138 void TestRunner::setCustomPolicyDelegate(bool enabled, bool permissive)
139 {
140     m_policyDelegateEnabled = enabled;
141     m_policyDelegatePermissive = permissive;
142
143     InjectedBundle::singleton().setCustomPolicyDelegate(enabled, permissive);
144 }
145
146 void TestRunner::waitForPolicyDelegate()
147 {
148     setCustomPolicyDelegate(true);
149     waitUntilDone();
150 }
151
152 void TestRunner::waitUntilDownloadFinished()
153 {
154     m_shouldFinishAfterDownload = true;
155     waitUntilDone();
156 }
157
158 void TestRunner::waitUntilDone()
159 {
160     m_waitToDump = true;
161     if (InjectedBundle::singleton().useWaitToDumpWatchdogTimer())
162         initializeWaitToDumpWatchdogTimerIfNeeded();
163 }
164
165 void TestRunner::waitToDumpWatchdogTimerFired()
166 {
167     invalidateWaitToDumpWatchdogTimer();
168     auto& injectedBundle = InjectedBundle::singleton();
169 #if PLATFORM(COCOA)
170     char buffer[1024];
171     snprintf(buffer, sizeof(buffer), "#PID UNRESPONSIVE - %s (pid %d)\n", getprogname(), getpid());
172     injectedBundle.outputText(buffer);
173 #endif
174     injectedBundle.outputText("FAIL: Timed out waiting for notifyDone to be called\n\n");
175     injectedBundle.done();
176 }
177
178 void TestRunner::notifyDone()
179 {
180     auto& injectedBundle = InjectedBundle::singleton();
181     if (!injectedBundle.isTestRunning())
182         return;
183
184     if (m_waitToDump && !injectedBundle.topLoadingFrame())
185         injectedBundle.page()->dump();
186
187     // We don't call invalidateWaitToDumpWatchdogTimer() here, even if we continue to wait for a load to finish.
188     // The test is still subject to timeout checking - it is better to detect an async timeout inside WebKitTestRunner
189     // than to let webkitpy do that, because WebKitTestRunner will dump partial results.
190
191     m_waitToDump = false;
192 }
193
194 unsigned TestRunner::imageCountInGeneralPasteboard() const
195 {
196     return InjectedBundle::singleton().imageCountInGeneralPasteboard();
197 }
198
199 void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
200 {
201     WKRetainPtr<WKStringRef> sourceWK = toWK(source);
202
203     WKBundlePageAddUserScript(InjectedBundle::singleton().page()->page(), sourceWK.get(),
204         (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
205         (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
206 }
207
208 void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
209 {
210     WKRetainPtr<WKStringRef> sourceWK = toWK(source);
211
212     WKBundlePageAddUserStyleSheet(InjectedBundle::singleton().page()->page(), sourceWK.get(),
213         (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
214 }
215
216 void TestRunner::keepWebHistory()
217 {
218     InjectedBundle::singleton().postSetAddsVisitedLinks(true);
219 }
220
221 void TestRunner::execCommand(JSStringRef name, JSStringRef argument)
222 {
223     WKBundlePageExecuteEditingCommand(InjectedBundle::singleton().page()->page(), toWK(name).get(), toWK(argument).get());
224 }
225
226 bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
227 {
228     WKFindOptions options = 0;
229
230     auto& injectedBundle = InjectedBundle::singleton();
231     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
232     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
233     JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
234     JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
235     JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
236     if (!JSValueIsNumber(context, lengthValue))
237         return false;
238
239     size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
240     for (size_t i = 0; i < length; ++i) {
241         JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
242         if (!JSValueIsString(context, value))
243             continue;
244
245         JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
246
247         if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
248             options |= kWKFindOptionsCaseInsensitive;
249         else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
250             options |= kWKFindOptionsAtWordStarts;
251         else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
252             options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
253         else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
254             options |= kWKFindOptionsBackwards;
255         else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
256             options |= kWKFindOptionsWrapAround;
257         else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
258             // FIXME: No kWKFindOptionsStartInSelection.
259         }
260     }
261
262     return WKBundlePageFindString(injectedBundle.page()->page(), toWK(target).get(), options);
263 }
264
265 void TestRunner::clearAllDatabases()
266 {
267     WKBundleClearAllDatabases(InjectedBundle::singleton().bundle());
268
269     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DeleteAllIndexedDatabases"));
270     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
271
272     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
273 }
274
275 void TestRunner::setDatabaseQuota(uint64_t quota)
276 {
277     return WKBundleSetDatabaseQuota(InjectedBundle::singleton().bundle(), quota);
278 }
279
280 void TestRunner::clearAllApplicationCaches()
281 {
282     WKBundlePageClearApplicationCache(InjectedBundle::singleton().page()->page());
283 }
284
285 void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin)
286 {
287     WKBundlePageClearApplicationCacheForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
288 }
289
290 void TestRunner::setAppCacheMaximumSize(uint64_t size)
291 {
292     WKBundlePageSetAppCacheMaximumSize(InjectedBundle::singleton().page()->page(), size);
293 }
294
295 long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef origin)
296 {
297     return WKBundlePageGetAppCacheUsageForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
298 }
299
300 void TestRunner::disallowIncreaseForApplicationCacheQuota()
301 {
302     m_disallowIncreaseForApplicationCacheQuota = true;
303 }
304
305 static inline JSValueRef stringArrayToJS(JSContextRef context, WKArrayRef strings)
306 {
307     const size_t count = WKArrayGetSize(strings);
308
309     JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
310     JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
311     for (size_t i = 0; i < count; ++i) {
312         WKStringRef stringRef = static_cast<WKStringRef>(WKArrayGetItemAtIndex(strings, i));
313         JSRetainPtr<JSStringRef> stringJS = toJS(stringRef);
314         JSObjectSetPropertyAtIndex(context, arrayObj, i, JSValueMakeString(context, stringJS.get()), 0);
315     }
316
317     return arrayResult;
318 }
319
320 JSValueRef TestRunner::originsWithApplicationCache()
321 {
322     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
323
324     WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundlePageCopyOriginsWithApplicationCache(page));
325
326     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
327     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
328
329     return stringArrayToJS(context, origins.get());
330 }
331
332 bool TestRunner::isCommandEnabled(JSStringRef name)
333 {
334     return WKBundlePageIsEditingCommandEnabled(InjectedBundle::singleton().page()->page(), toWK(name).get());
335 }
336
337 void TestRunner::setCanOpenWindows(bool)
338 {
339     // The test plugins/get-url-with-blank-target.html requires that the embedding client forbid
340     // opening windows (by omitting a call to this function) so as to test that NPN_GetURL()
341     // with a blank target will return an error.
342     //
343     // It is not clear if we should implement this functionality or remove it and plugins/get-url-with-blank-target.html
344     // per the remark in <https://trac.webkit.org/changeset/64504/trunk/LayoutTests/platform/mac-wk2/Skipped>.
345     // For now, just ignore this setting.
346 }
347
348 void TestRunner::setXSSAuditorEnabled(bool enabled)
349 {
350     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitXSSAuditorEnabled"));
351     auto& injectedBundle = InjectedBundle::singleton();
352     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
353 }
354
355 void TestRunner::setMediaDevicesEnabled(bool enabled)
356 {
357     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitMediaDevicesEnabled"));
358     auto& injectedBundle = InjectedBundle::singleton();
359     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
360 }
361
362 void TestRunner::setWebRTCLegacyAPIEnabled(bool enabled)
363 {
364     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebRTCLegacyAPIEnabled"));
365     auto& injectedBundle = InjectedBundle::singleton();
366     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
367 }
368
369 void TestRunner::setModernMediaControlsEnabled(bool enabled)
370 {
371     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitModernMediaControlsEnabled"));
372     auto& injectedBundle = InjectedBundle::singleton();
373     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
374 }
375
376 void TestRunner::setWebGL2Enabled(bool enabled)
377 {
378     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGL2Enabled"));
379     auto& injectedBundle = InjectedBundle::singleton();
380     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
381 }
382
383 void TestRunner::setWebGPUEnabled(bool enabled)
384 {
385     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGPUEnabled"));
386     auto& injectedBundle = InjectedBundle::singleton();
387     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
388 }
389
390 void TestRunner::setCacheAPIEnabled(bool enabled)
391 {
392     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitCacheAPIEnabled"));
393     auto& injectedBundle = InjectedBundle::singleton();
394     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
395 }
396
397 void TestRunner::setWritableStreamAPIEnabled(bool enabled)
398 {
399     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWritableStreamAPIEnabled"));
400     auto& injectedBundle = InjectedBundle::singleton();
401     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
402 }
403
404 void TestRunner::setReadableByteStreamAPIEnabled(bool enabled)
405 {
406     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitReadableByteStreamAPIEnabled"));
407     auto& injectedBundle = InjectedBundle::singleton();
408     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
409 }
410
411 void TestRunner::setEncryptedMediaAPIEnabled(bool enabled)
412 {
413     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitEncryptedMediaAPIEnabled"));
414     auto& injectedBundle = InjectedBundle::singleton();
415     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
416 }
417
418 void TestRunner::setAllowsAnySSLCertificate(bool enabled)
419 {
420     auto& injectedBundle = InjectedBundle::singleton();
421     injectedBundle.setAllowsAnySSLCertificate(enabled);
422
423     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAllowsAnySSLCertificate"));
424     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
425     WKBundlePagePostSynchronousMessageForTesting(injectedBundle.page()->page(), messageName.get(), messageBody.get(), nullptr);
426 }
427
428 void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled)
429 {
430     auto& injectedBundle = InjectedBundle::singleton();
431     WKBundleSetAllowUniversalAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
432 }
433
434 void TestRunner::setAllowFileAccessFromFileURLs(bool enabled)
435 {
436     auto& injectedBundle = InjectedBundle::singleton();
437     WKBundleSetAllowFileAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
438 }
439
440 void TestRunner::setNeedsStorageAccessFromFileURLsQuirk(bool needsQuirk)
441 {
442     auto& injectedBundle = InjectedBundle::singleton();
443     WKBundleSetAllowStorageAccessFromFileURLS(injectedBundle.bundle(), injectedBundle.pageGroup(), needsQuirk);
444 }
445     
446 void TestRunner::setPluginsEnabled(bool enabled)
447 {
448     WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitPluginsEnabled"));
449     auto& injectedBundle = InjectedBundle::singleton();
450     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
451 }
452
453 void TestRunner::setJavaScriptCanAccessClipboard(bool enabled)
454 {
455     auto& injectedBundle = InjectedBundle::singleton();
456     WKBundleSetJavaScriptCanAccessClipboard(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
457 }
458
459 void TestRunner::setPrivateBrowsingEnabled(bool enabled)
460 {
461     auto& injectedBundle = InjectedBundle::singleton();
462     WKBundleSetPrivateBrowsingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
463 }
464
465 void TestRunner::setUseDashboardCompatibilityMode(bool enabled)
466 {
467 #if ENABLE(DASHBOARD_SUPPORT)
468     auto& injectedBundle = InjectedBundle::singleton();
469     WKBundleSetUseDashboardCompatibilityMode(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
470 #else
471     UNUSED_PARAM(enabled);
472 #endif
473 }
474     
475 void TestRunner::setPopupBlockingEnabled(bool enabled)
476 {
477     auto& injectedBundle = InjectedBundle::singleton();
478     WKBundleSetPopupBlockingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
479 }
480
481 void TestRunner::setAuthorAndUserStylesEnabled(bool enabled)
482 {
483     auto& injectedBundle = InjectedBundle::singleton();
484     WKBundleSetAuthorAndUserStylesEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
485 }
486
487 void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
488 {
489     WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
490 }
491
492 void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
493 {
494     WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
495 }
496
497 bool TestRunner::isPageBoxVisible(int pageIndex)
498 {
499     auto& injectedBundle = InjectedBundle::singleton();
500     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
501     return WKBundleIsPageBoxVisible(injectedBundle.bundle(), mainFrame, pageIndex);
502 }
503
504 void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
505 {
506     if (!element || !JSValueIsObject(context, element))
507         return;
508
509     WKRetainPtr<WKBundleNodeHandleRef> nodeHandle(AdoptWK, WKBundleNodeHandleCreate(context, const_cast<JSObjectRef>(element)));
510     WKBundleNodeHandleSetHTMLInputElementValueForUser(nodeHandle.get(), toWK(value).get());
511 }
512
513 void TestRunner::setAudioResult(JSContextRef context, JSValueRef data)
514 {
515     auto& injectedBundle = InjectedBundle::singleton();
516     // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
517     WKRetainPtr<WKDataRef> audioData(AdoptWK, WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data));
518     injectedBundle.setAudioResult(audioData.get());
519     m_whatToDump = Audio;
520     m_dumpPixels = false;
521 }
522
523 unsigned TestRunner::windowCount()
524 {
525     return InjectedBundle::singleton().pageCount();
526 }
527
528 void TestRunner::clearBackForwardList()
529 {
530     WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::singleton().page()->page()));
531 }
532
533 // Object Creation
534
535 void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
536 {
537     setProperty(context, windowObject, "testRunner", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
538 }
539
540 void TestRunner::showWebInspector()
541 {
542     WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
543 }
544
545 void TestRunner::closeWebInspector()
546 {
547     WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
548 }
549
550 void TestRunner::evaluateInWebInspector(JSStringRef script)
551 {
552     WKRetainPtr<WKStringRef> scriptWK = toWK(script);
553     WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()), scriptWK.get());
554 }
555
556 typedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
557 static WorldMap& worldMap()
558 {
559     static WorldMap& map = *new WorldMap;
560     return map;
561 }
562
563 unsigned TestRunner::worldIDForWorld(WKBundleScriptWorldRef world)
564 {
565     WorldMap::const_iterator end = worldMap().end();
566     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
567         if (it->value == world)
568             return it->key;
569     }
570
571     return 0;
572 }
573
574 void TestRunner::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
575 {
576     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
577     // that is created once and cached forever.
578     WKRetainPtr<WKBundleScriptWorldRef> world;
579     if (!worldID)
580         world.adopt(WKBundleScriptWorldCreateWorld());
581     else {
582         WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, nullptr).iterator->value;
583         if (!worldSlot)
584             worldSlot.adopt(WKBundleScriptWorldCreateWorld());
585         world = worldSlot;
586     }
587
588     WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
589     if (!frame)
590         frame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
591
592     JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
593     JSEvaluateScript(jsContext, script, 0, 0, 0, 0); 
594 }
595
596 void TestRunner::setPOSIXLocale(JSStringRef locale)
597 {
598     char localeBuf[32];
599     JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
600     setlocale(LC_ALL, localeBuf);
601 }
602
603 void TestRunner::setTextDirection(JSStringRef direction)
604 {
605     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
606     return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get());
607 }
608     
609 void TestRunner::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage)
610 {
611     InjectedBundle::singleton().postNewBeforeUnloadReturnValue(!shouldStayOnPage);
612 }
613
614 void TestRunner::setDefersLoading(bool shouldDeferLoading)
615 {
616     WKBundlePageSetDefersLoading(InjectedBundle::singleton().page()->page(), shouldDeferLoading);
617 }
618
619 void TestRunner::setPageVisibility(JSStringRef state)
620 {
621     InjectedBundle::singleton().setHidden(JSStringIsEqualToUTF8CString(state, "hidden") || JSStringIsEqualToUTF8CString(state, "prerender"));
622 }
623
624 void TestRunner::resetPageVisibility()
625 {
626     InjectedBundle::singleton().setHidden(false);
627 }
628
629 typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
630 static CallbackMap& callbackMap()
631 {
632     static CallbackMap& map = *new CallbackMap;
633     return map;
634 }
635
636 enum {
637     AddChromeInputFieldCallbackID = 1,
638     RemoveChromeInputFieldCallbackID,
639     FocusWebViewCallbackID,
640     SetBackingScaleFactorCallbackID,
641     DidBeginSwipeCallbackID,
642     WillEndSwipeCallbackID,
643     DidEndSwipeCallbackID,
644     DidRemoveSwipeSnapshotCallbackID,
645     StatisticsDidModifyDataRecordsCallbackID,
646     StatisticsDidScanDataRecordsCallbackID,
647     StatisticsDidRunTelemetryCallbackID,
648     DidRemoveAllSessionCredentialsCallbackID,
649     FirstUIScriptCallbackID = 100
650 };
651
652 static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
653 {
654     if (!callback)
655         return;
656
657     if (callbackMap().contains(index)) {
658         InjectedBundle::singleton().outputText(String::format("FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n\n", index));
659         return;
660     }
661
662     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
663     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
664     JSValueProtect(context, callback);
665     callbackMap().add(index, callback);
666 }
667
668 static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr)
669 {
670     if (!callbackMap().contains(index))
671         return;
672     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
673     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
674     JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
675     JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
676     JSValueUnprotect(context, callback);
677 }
678
679 void TestRunner::clearTestRunnerCallbacks()
680 {
681     for (auto& iter : callbackMap()) {
682         WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
683         JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
684         JSObjectRef callback = JSValueToObject(context, iter.value, 0);
685         JSValueUnprotect(context, callback);
686     }
687
688     callbackMap().clear();
689 }
690
691 void TestRunner::accummulateLogsForChannel(JSStringRef)
692 {
693     // FIXME: Implement getting the call to all processes.
694 }
695
696 void TestRunner::addChromeInputField(JSValueRef callback)
697 {
698     cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
699     InjectedBundle::singleton().postAddChromeInputField();
700 }
701
702 void TestRunner::removeChromeInputField(JSValueRef callback)
703 {
704     cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
705     InjectedBundle::singleton().postRemoveChromeInputField();
706 }
707
708 void TestRunner::focusWebView(JSValueRef callback)
709 {
710     cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
711     InjectedBundle::singleton().postFocusWebView();
712 }
713
714 void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
715 {
716     cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
717     InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor);
718 }
719
720 void TestRunner::setWindowIsKey(bool isKey)
721 {
722     InjectedBundle::singleton().postSetWindowIsKey(isKey);
723 }
724
725 void TestRunner::setViewSize(double width, double height)
726 {
727     InjectedBundle::singleton().postSetViewSize(width, height);
728 }
729
730 void TestRunner::callAddChromeInputFieldCallback()
731 {
732     callTestRunnerCallback(AddChromeInputFieldCallbackID);
733 }
734
735 void TestRunner::callRemoveChromeInputFieldCallback()
736 {
737     callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
738 }
739
740 void TestRunner::callFocusWebViewCallback()
741 {
742     callTestRunnerCallback(FocusWebViewCallbackID);
743 }
744
745 void TestRunner::callSetBackingScaleFactorCallback()
746 {
747     callTestRunnerCallback(SetBackingScaleFactorCallbackID);
748 }
749
750 static inline bool toBool(JSStringRef value)
751 {
752     return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
753 }
754
755 void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
756 {
757     auto& injectedBundle = InjectedBundle::singleton();
758     // FIXME: handle non-boolean preferences.
759     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value));
760 }
761
762 void TestRunner::setAlwaysAcceptCookies(bool accept)
763 {
764     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies"));
765
766     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(accept));
767
768     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
769 }
770
771 void TestRunner::setCookieStoragePartitioningEnabled(bool enabled)
772 {
773     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCookieStoragePartitioningEnabled"));
774
775     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
776
777     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
778 }
779
780 double TestRunner::preciseTime()
781 {
782     return currentTime();
783 }
784
785 void TestRunner::setUserStyleSheetEnabled(bool enabled)
786 {
787     m_userStyleSheetEnabled = enabled;
788
789     WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
790     WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
791     auto& injectedBundle = InjectedBundle::singleton();
792     WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location);
793 }
794
795 void TestRunner::setUserStyleSheetLocation(JSStringRef location)
796 {
797     m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
798
799     if (m_userStyleSheetEnabled)
800         setUserStyleSheetEnabled(true);
801 }
802
803 void TestRunner::setSpatialNavigationEnabled(bool enabled)
804 {
805     auto& injectedBundle = InjectedBundle::singleton();
806     WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
807 }
808
809 void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
810 {
811     auto& injectedBundle = InjectedBundle::singleton();
812     WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled);
813 }
814
815 void TestRunner::setSerializeHTTPLoads()
816 {
817     // WK2 doesn't reorder loads.
818 }
819
820 void TestRunner::dispatchPendingLoadRequests()
821 {
822     // WK2 doesn't keep pending requests.
823 }
824
825 void TestRunner::setCacheModel(int model)
826 {
827     InjectedBundle::singleton().setCacheModel(model);
828 }
829
830 void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled)
831 {
832     auto& injectedBundle = InjectedBundle::singleton();
833     WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
834 }
835
836 void TestRunner::grantWebNotificationPermission(JSStringRef origin)
837 {
838     WKRetainPtr<WKStringRef> originWK = toWK(origin);
839     auto& injectedBundle = InjectedBundle::singleton();
840     WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true);
841 }
842
843 void TestRunner::denyWebNotificationPermission(JSStringRef origin)
844 {
845     WKRetainPtr<WKStringRef> originWK = toWK(origin);
846     auto& injectedBundle = InjectedBundle::singleton();
847     WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false);
848 }
849
850 void TestRunner::removeAllWebNotificationPermissions()
851 {
852     auto& injectedBundle = InjectedBundle::singleton();
853     WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page());
854 }
855
856 void TestRunner::simulateWebNotificationClick(JSValueRef notification)
857 {
858     auto& injectedBundle = InjectedBundle::singleton();
859     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
860     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
861     uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification);
862     injectedBundle.postSimulateWebNotificationClick(notificationID);
863 }
864
865 void TestRunner::setGeolocationPermission(bool enabled)
866 {
867     // FIXME: this should be done by frame.
868     InjectedBundle::singleton().setGeolocationPermission(enabled);
869 }
870
871 bool TestRunner::isGeolocationProviderActive()
872 {
873     return InjectedBundle::singleton().isGeolocationProviderActive();
874 }
875
876 void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed)
877 {
878     auto& injectedBundle = InjectedBundle::singleton();
879     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
880     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
881
882     bool providesAltitude = false;
883     double altitude = 0.;
884     if (!JSValueIsUndefined(context, jsAltitude)) {
885         providesAltitude = true;
886         altitude = JSValueToNumber(context, jsAltitude, 0);
887     }
888
889     bool providesAltitudeAccuracy = false;
890     double altitudeAccuracy = 0.;
891     if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
892         providesAltitudeAccuracy = true;
893         altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
894     }
895
896     bool providesHeading = false;
897     double heading = 0.;
898     if (!JSValueIsUndefined(context, jsHeading)) {
899         providesHeading = true;
900         heading = JSValueToNumber(context, jsHeading, 0);
901     }
902
903     bool providesSpeed = false;
904     double speed = 0.;
905     if (!JSValueIsUndefined(context, jsSpeed)) {
906         providesSpeed = true;
907         speed = JSValueToNumber(context, jsSpeed, 0);
908     }
909
910     injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
911 }
912
913 void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
914 {
915     WKRetainPtr<WKStringRef> messageWK = toWK(message);
916     InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get());
917 }
918
919 void TestRunner::setUserMediaPermission(bool enabled)
920 {
921     // FIXME: this should be done by frame.
922     InjectedBundle::singleton().setUserMediaPermission(enabled);
923 }
924
925 void TestRunner::resetUserMediaPermission()
926 {
927     // FIXME: this should be done by frame.
928     InjectedBundle::singleton().resetUserMediaPermission();
929 }
930
931 void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
932 {
933     WKRetainPtr<WKStringRef> originWK = toWK(origin);
934     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
935     InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
936 }
937
938 unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
939 {
940     WKRetainPtr<WKStringRef> originWK = toWK(origin);
941     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
942     return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
943 }
944
945 void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
946 {
947     WKRetainPtr<WKStringRef> originWK = toWK(origin);
948     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
949     InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
950 }
951
952 bool TestRunner::callShouldCloseOnWebView()
953 {
954     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
955     return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
956 }
957
958 void TestRunner::queueBackNavigation(unsigned howFarBackward)
959 {
960     InjectedBundle::singleton().queueBackNavigation(howFarBackward);
961 }
962
963 void TestRunner::queueForwardNavigation(unsigned howFarForward)
964 {
965     InjectedBundle::singleton().queueForwardNavigation(howFarForward);
966 }
967
968 void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs)
969 {
970     auto& injectedBundle = InjectedBundle::singleton();
971     WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page())));
972     WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
973     WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get()));
974
975     injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs);
976 }
977
978 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
979 {
980     WKRetainPtr<WKStringRef> contentWK = toWK(content);
981     WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
982     WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
983
984     InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
985 }
986
987 void TestRunner::queueReload()
988 {
989     InjectedBundle::singleton().queueReload();
990 }
991
992 void TestRunner::queueLoadingScript(JSStringRef script)
993 {
994     WKRetainPtr<WKStringRef> scriptWK = toWK(script);
995     InjectedBundle::singleton().queueLoadingScript(scriptWK.get());
996 }
997
998 void TestRunner::queueNonLoadingScript(JSStringRef script)
999 {
1000     WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1001     InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get());
1002 }
1003
1004 void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value)
1005 {
1006     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges"));
1007     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1008     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1009 }
1010     
1011 void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
1012 {
1013     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges"));
1014     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges));
1015     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1016 }
1017
1018 void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value)
1019 {
1020     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace"));
1021     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1022     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1023 }
1024
1025 void TestRunner::setAuthenticationUsername(JSStringRef username)
1026 {
1027     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername"));
1028     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(username));
1029     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1030 }
1031
1032 void TestRunner::setAuthenticationPassword(JSStringRef password)
1033 {
1034     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationPassword"));
1035     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(password));
1036     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1037 }
1038
1039 bool TestRunner::secureEventInputIsEnabled() const
1040 {
1041     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SecureEventInputIsEnabled"));
1042     WKTypeRef returnData = 0;
1043
1044     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), 0, &returnData);
1045     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1046 }
1047
1048 void TestRunner::setBlockAllPlugins(bool shouldBlock)
1049 {
1050     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBlockAllPlugins"));
1051     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldBlock));
1052     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1053 }
1054
1055 JSValueRef TestRunner::failNextNewCodeBlock()
1056 {
1057     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1058     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1059     return JSC::failNextNewCodeBlock(context);
1060 }
1061
1062 JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction)
1063 {
1064     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1065     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1066     return JSC::numberOfDFGCompiles(context, theFunction);
1067 }
1068
1069 JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction)
1070 {
1071     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1072     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1073     return JSC::setNeverInline(context, theFunction);
1074 }
1075
1076 void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value)
1077 {
1078     m_shouldDecideNavigationPolicyAfterDelay = value;
1079     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay"));
1080     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1081     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1082 }
1083
1084 void TestRunner::setNavigationGesturesEnabled(bool value)
1085 {
1086     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled"));
1087     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1088     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1089 }
1090
1091 void TestRunner::setIgnoresViewportScaleLimits(bool value)
1092 {
1093     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits"));
1094     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1095     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1096 }
1097
1098 void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value)
1099 {
1100     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes"));
1101     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1102     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1103 }
1104
1105 void TestRunner::terminateNetworkProcess()
1106 {
1107     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateNetworkProcess"));
1108     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1109 }
1110
1111 static unsigned nextUIScriptCallbackID()
1112 {
1113     static unsigned callbackID = FirstUIScriptCallbackID;
1114     return callbackID++;
1115 }
1116
1117 void TestRunner::runUIScript(JSStringRef script, JSValueRef callback)
1118 {
1119     unsigned callbackID = nextUIScriptCallbackID();
1120     cacheTestRunnerCallback(callbackID, callback);
1121
1122     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RunUIProcessScript"));
1123
1124     WKRetainPtr<WKMutableDictionaryRef> testDictionary(AdoptWK, WKMutableDictionaryCreate());
1125
1126     WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
1127     WKRetainPtr<WKStringRef> scriptValue(AdoptWK, WKStringCreateWithJSString(script));
1128
1129     WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
1130     WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID));
1131
1132     WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get());
1133     WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get());
1134
1135     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get());
1136 }
1137
1138 void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result)
1139 {
1140     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1141     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1142
1143     JSValueRef resultValue = JSValueMakeString(context, result);
1144     callTestRunnerCallback(callbackID, 1, &resultValue);
1145 }
1146
1147 void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
1148 {
1149     cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
1150 }
1151
1152 void TestRunner::installWillEndSwipeCallback(JSValueRef callback)
1153 {
1154     cacheTestRunnerCallback(WillEndSwipeCallbackID, callback);
1155 }
1156
1157 void TestRunner::installDidEndSwipeCallback(JSValueRef callback)
1158 {
1159     cacheTestRunnerCallback(DidEndSwipeCallbackID, callback);
1160 }
1161
1162 void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback)
1163 {
1164     cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback);
1165 }
1166
1167 void TestRunner::callDidBeginSwipeCallback()
1168 {
1169     callTestRunnerCallback(DidBeginSwipeCallbackID);
1170 }
1171
1172 void TestRunner::callWillEndSwipeCallback()
1173 {
1174     callTestRunnerCallback(WillEndSwipeCallbackID);
1175 }
1176
1177 void TestRunner::callDidEndSwipeCallback()
1178 {
1179     callTestRunnerCallback(DidEndSwipeCallbackID);
1180 }
1181
1182 void TestRunner::callDidRemoveSwipeSnapshotCallback()
1183 {
1184     callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
1185 }
1186
1187 void TestRunner::setStatisticsLastSeen(JSStringRef hostName, double seconds)
1188 {
1189     Vector<WKRetainPtr<WKStringRef>> keys;
1190     Vector<WKRetainPtr<WKTypeRef>> values;
1191     
1192     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1193     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1194     
1195     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1196     values.append({ AdoptWK, WKDoubleCreate(seconds) });
1197     
1198     Vector<WKStringRef> rawKeys(keys.size());
1199     Vector<WKTypeRef> rawValues(values.size());
1200     
1201     for (size_t i = 0; i < keys.size(); ++i) {
1202         rawKeys[i] = keys[i].get();
1203         rawValues[i] = values[i].get();
1204     }
1205     
1206     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsLastSeen"));
1207     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1208     
1209     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1210 }
1211     
1212 void TestRunner::setStatisticsPrevalentResource(JSStringRef hostName, bool value)
1213 {
1214     Vector<WKRetainPtr<WKStringRef>> keys;
1215     Vector<WKRetainPtr<WKTypeRef>> values;
1216
1217     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1218     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1219     
1220     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1221     values.append({ AdoptWK, WKBooleanCreate(value) });
1222     
1223     Vector<WKStringRef> rawKeys;
1224     Vector<WKTypeRef> rawValues;
1225     rawKeys.resize(keys.size());
1226     rawValues.resize(values.size());
1227     
1228     for (size_t i = 0; i < keys.size(); ++i) {
1229         rawKeys[i] = keys[i].get();
1230         rawValues[i] = values[i].get();
1231     }
1232     
1233     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsPrevalentResource"));
1234     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1235
1236     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1237 }
1238
1239 bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName)
1240 {
1241     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource"));
1242     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1243     WKTypeRef returnData = 0;
1244     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1245     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1246 }
1247
1248 void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value)
1249 {
1250     Vector<WKRetainPtr<WKStringRef>> keys;
1251     Vector<WKRetainPtr<WKTypeRef>> values;
1252     
1253     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1254     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1255     
1256     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1257     values.append({ AdoptWK, WKBooleanCreate(value) });
1258     
1259     Vector<WKStringRef> rawKeys;
1260     Vector<WKTypeRef> rawValues;
1261     rawKeys.resize(keys.size());
1262     rawValues.resize(values.size());
1263     
1264     for (size_t i = 0; i < keys.size(); ++i) {
1265         rawKeys[i] = keys[i].get();
1266         rawValues[i] = values[i].get();
1267     }
1268     
1269     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction"));
1270     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1271     
1272     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1273 }
1274
1275 bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName)
1276 {
1277     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction"));
1278     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1279     WKTypeRef returnData = 0;
1280     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1281     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1282 }
1283
1284 void TestRunner::setStatisticsGrandfathered(JSStringRef hostName, bool value)
1285 {
1286     Vector<WKRetainPtr<WKStringRef>> keys;
1287     Vector<WKRetainPtr<WKTypeRef>> values;
1288     
1289     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1290     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1291     
1292     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1293     values.append({ AdoptWK, WKBooleanCreate(value) });
1294     
1295     Vector<WKStringRef> rawKeys;
1296     Vector<WKTypeRef> rawValues;
1297     rawKeys.resize(keys.size());
1298     rawValues.resize(values.size());
1299     
1300     for (size_t i = 0; i < keys.size(); ++i) {
1301         rawKeys[i] = keys[i].get();
1302         rawValues[i] = values[i].get();
1303     }
1304     
1305     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfathered"));
1306     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1307     
1308     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1309 }
1310     
1311 bool TestRunner::isStatisticsGrandfathered(JSStringRef hostName)
1312 {
1313     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsGrandfathered"));
1314     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1315     WKTypeRef returnData = 0;
1316     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1317     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1318 }
1319
1320 void TestRunner::setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1321 {
1322     Vector<WKRetainPtr<WKStringRef>> keys;
1323     Vector<WKRetainPtr<WKTypeRef>> values;
1324     
1325     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1326     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1327     
1328     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1329     values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1330     
1331     Vector<WKStringRef> rawKeys(keys.size());
1332     Vector<WKTypeRef> rawValues(values.size());
1333     
1334     for (size_t i = 0; i < keys.size(); ++i) {
1335         rawKeys[i] = keys[i].get();
1336         rawValues[i] = values[i].get();
1337     }
1338     
1339     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubframeUnderTopFrameOrigin"));
1340     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1341     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1342 }
1343
1344 void TestRunner::setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1345 {
1346     Vector<WKRetainPtr<WKStringRef>> keys;
1347     Vector<WKRetainPtr<WKTypeRef>> values;
1348     
1349     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1350     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1351     
1352     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1353     values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1354     
1355     Vector<WKStringRef> rawKeys(keys.size());
1356     Vector<WKTypeRef> rawValues(values.size());
1357     
1358     for (size_t i = 0; i < keys.size(); ++i) {
1359         rawKeys[i] = keys[i].get();
1360         rawValues[i] = values[i].get();
1361     }
1362     
1363     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUnderTopFrameOrigin"));
1364     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1365     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1366 }
1367
1368 void TestRunner::setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1369 {
1370     Vector<WKRetainPtr<WKStringRef>> keys;
1371     Vector<WKRetainPtr<WKTypeRef>> values;
1372     
1373     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1374     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1375     
1376     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo") });
1377     values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedTo) });
1378     
1379     Vector<WKStringRef> rawKeys(keys.size());
1380     Vector<WKTypeRef> rawValues(values.size());
1381     
1382     for (size_t i = 0; i < keys.size(); ++i) {
1383         rawKeys[i] = keys[i].get();
1384         rawValues[i] = values[i].get();
1385     }
1386     
1387     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectTo"));
1388     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1389     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1390 }
1391
1392 void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
1393 {
1394     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));
1395     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1396     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1397 }
1398
1399 void TestRunner::setStatisticsTimeToLiveCookiePartitionFree(double seconds)
1400 {
1401     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveCookiePartitionFree"));
1402     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1403     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1404 }
1405
1406 void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback)
1407 {
1408     cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback);
1409 }
1410
1411 void TestRunner::statisticsDidModifyDataRecordsCallback()
1412 {
1413     callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID);
1414 }
1415
1416 void TestRunner::installStatisticsDidScanDataRecordsCallback(JSValueRef callback)
1417 {
1418     cacheTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID, callback);
1419 }
1420
1421 void TestRunner::statisticsDidScanDataRecordsCallback()
1422 {
1423     callTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID);
1424 }
1425
1426 void TestRunner::installStatisticsDidRunTelemetryCallback(JSValueRef callback)
1427 {
1428     cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
1429 }
1430     
1431 void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
1432 {
1433     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1434     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1435     
1436     StringBuilder stringBuilder;
1437     stringBuilder.appendLiteral("{ \"totalPrevalentResources\" : ");
1438     stringBuilder.appendNumber(totalPrevalentResources);
1439     stringBuilder.appendLiteral(", \"totalPrevalentResourcesWithUserInteraction\" : ");
1440     stringBuilder.appendNumber(totalPrevalentResourcesWithUserInteraction);
1441     stringBuilder.appendLiteral(", \"top3SubframeUnderTopFrameOrigins\" : ");
1442     stringBuilder.appendNumber(top3SubframeUnderTopFrameOrigins);
1443     stringBuilder.appendLiteral(" }");
1444     
1445     JSValueRef result = JSValueMakeFromJSONString(context, JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data()));
1446     
1447     callTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, 1, &result);
1448 }
1449     
1450 void TestRunner::statisticsProcessStatisticsAndDataRecords()
1451 {
1452     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsProcessStatisticsAndDataRecords"));
1453     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1454 }
1455
1456 void TestRunner::statisticsUpdateCookiePartitioning()
1457 {
1458     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsUpdateCookiePartitioning"));
1459     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1460 }
1461
1462 void TestRunner::statisticsSetShouldPartitionCookiesForHost(JSStringRef hostName, bool value)
1463 {
1464     Vector<WKRetainPtr<WKStringRef>> keys;
1465     Vector<WKRetainPtr<WKTypeRef>> values;
1466     
1467     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1468     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1469     
1470     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1471     values.append({ AdoptWK, WKBooleanCreate(value) });
1472     
1473     Vector<WKStringRef> rawKeys(keys.size());
1474     Vector<WKTypeRef> rawValues(values.size());
1475     
1476     for (size_t i = 0; i < keys.size(); ++i) {
1477         rawKeys[i] = keys[i].get();
1478         rawValues[i] = values[i].get();
1479     }
1480     
1481     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSetShouldPartitionCookiesForHost"));
1482     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1483     
1484     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1485 }
1486
1487 void TestRunner::statisticsSubmitTelemetry()
1488 {
1489     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSubmitTelemetry"));
1490     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1491 }
1492
1493 void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value)
1494 {
1495     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1496     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1497     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1498 }
1499
1500 void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
1501 {
1502     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval"));
1503     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1504     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1505 }
1506
1507 void TestRunner::setStatisticsNotifyPagesWhenTelemetryWasCaptured(bool value)
1508 {
1509     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenTelemetryWasCaptured"));
1510     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1511     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1512 }
1513
1514 void TestRunner::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
1515 {
1516     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweenDataRecordsRemoval"));
1517     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1518     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1519 }
1520
1521 void TestRunner::setStatisticsGrandfatheringTime(double seconds)
1522 {
1523     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfatheringTime"));
1524     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1525     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1526 }
1527
1528 void TestRunner::setStatisticsMaxStatisticsEntries(unsigned entries)
1529 {
1530     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMaxStatisticsEntries"));
1531     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1532     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1533 }
1534     
1535 void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
1536 {
1537     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetPruneEntriesDownTo"));
1538     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1539     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1540 }
1541     
1542 void TestRunner::statisticsClearInMemoryAndPersistentStore()
1543 {
1544     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
1545     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1546 }
1547
1548 void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours)
1549 {
1550     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
1551     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(hours));
1552     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1553 }
1554
1555 void TestRunner::statisticsResetToConsistentState()
1556 {
1557     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsResetToConsistentState"));
1558     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1559 }
1560
1561 #if PLATFORM(MAC)
1562 void TestRunner::connectMockGamepad(unsigned index)
1563 {
1564     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad"));
1565     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1566
1567     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1568 }
1569
1570 void TestRunner::disconnectMockGamepad(unsigned index)
1571 {
1572     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad"));
1573     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1574
1575     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1576 }
1577
1578 void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount)
1579 {
1580     Vector<WKRetainPtr<WKStringRef>> keys;
1581     Vector<WKRetainPtr<WKTypeRef>> values;
1582
1583     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") });
1584     values.append(toWK(gamepadID));
1585
1586     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1587     values.append({ AdoptWK, WKUInt64Create(index) });
1588
1589     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") });
1590     values.append({ AdoptWK, WKUInt64Create(axisCount) });
1591
1592     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") });
1593     values.append({ AdoptWK, WKUInt64Create(buttonCount) });
1594
1595     Vector<WKStringRef> rawKeys;
1596     Vector<WKTypeRef> rawValues;
1597     rawKeys.resize(keys.size());
1598     rawValues.resize(values.size());
1599
1600     for (size_t i = 0; i < keys.size(); ++i) {
1601         rawKeys[i] = keys[i].get();
1602         rawValues[i] = values[i].get();
1603     }
1604
1605     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails"));
1606     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1607
1608     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1609 }
1610
1611 void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value)
1612 {
1613     Vector<WKRetainPtr<WKStringRef>> keys;
1614     Vector<WKRetainPtr<WKTypeRef>> values;
1615
1616     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1617     values.append({ AdoptWK, WKUInt64Create(index) });
1618
1619     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") });
1620     values.append({ AdoptWK, WKUInt64Create(axisIndex) });
1621
1622     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1623     values.append({ AdoptWK, WKDoubleCreate(value) });
1624
1625     Vector<WKStringRef> rawKeys;
1626     Vector<WKTypeRef> rawValues;
1627     rawKeys.resize(keys.size());
1628     rawValues.resize(values.size());
1629
1630     for (size_t i = 0; i < keys.size(); ++i) {
1631         rawKeys[i] = keys[i].get();
1632         rawValues[i] = values[i].get();
1633     }
1634
1635     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue"));
1636     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1637
1638     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1639 }
1640
1641 void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value)
1642 {
1643     Vector<WKRetainPtr<WKStringRef>> keys;
1644     Vector<WKRetainPtr<WKTypeRef>> values;
1645
1646     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1647     values.append({ AdoptWK, WKUInt64Create(index) });
1648
1649     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") });
1650     values.append({ AdoptWK, WKUInt64Create(buttonIndex) });
1651
1652     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1653     values.append({ AdoptWK, WKDoubleCreate(value) });
1654
1655     Vector<WKStringRef> rawKeys;
1656     Vector<WKTypeRef> rawValues;
1657     rawKeys.resize(keys.size());
1658     rawValues.resize(values.size());
1659
1660     for (size_t i = 0; i < keys.size(); ++i) {
1661         rawKeys[i] = keys[i].get();
1662         rawValues[i] = values[i].get();
1663     }
1664
1665     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue"));
1666     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1667
1668     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1669 }
1670 #else
1671 void TestRunner::connectMockGamepad(unsigned)
1672 {
1673 }
1674
1675 void TestRunner::disconnectMockGamepad(unsigned)
1676 {
1677 }
1678
1679 void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned)
1680 {
1681 }
1682
1683 void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double)
1684 {
1685 }
1686
1687 void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double)
1688 {
1689 }
1690 #endif // PLATFORM(MAC)
1691
1692 void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
1693 {
1694     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
1695     JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
1696
1697     if (!JSValueIsArray(context, filesValue))
1698         return;
1699
1700     JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
1701     static auto lengthProperty = JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("length"));
1702     JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
1703     if (!JSValueIsNumber(context, filesLengthValue))
1704         return;
1705
1706     auto fileURLs = adoptWK(WKMutableArrayCreate());
1707     auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
1708     for (size_t i = 0; i < filesLength; ++i) {
1709         JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
1710         if (!JSValueIsString(context, fileValue))
1711             continue;
1712
1713         auto file = JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, fileValue, nullptr));
1714         size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
1715         auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
1716         JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
1717
1718         WKArrayAppendItem(fileURLs.get(), adoptWK(WKURLCreateWithBaseURL(m_testURL.get(), fileBuffer.get())).get());
1719     }
1720
1721     static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLs"));
1722     WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
1723 }
1724
1725 void TestRunner::removeAllSessionCredentials(JSValueRef callback)
1726 {
1727     cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
1728     
1729     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveAllSessionCredentials"));
1730     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
1731     
1732     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1733 }
1734
1735 void TestRunner::callDidRemoveAllSessionCredentialsCallback()
1736 {
1737     callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
1738 }
1739
1740 } // namespace WTR