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