6476adfb038b7998c2fcd7ae4fb33d777aa65b92
[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     GetApplicationManifestCallbackID,
656     FirstUIScriptCallbackID = 100
657 };
658
659 static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
660 {
661     if (!callback)
662         return;
663
664     if (callbackMap().contains(index)) {
665         InjectedBundle::singleton().outputText(String::format("FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n\n", index));
666         return;
667     }
668
669     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
670     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
671     JSValueProtect(context, callback);
672     callbackMap().add(index, callback);
673 }
674
675 static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr)
676 {
677     if (!callbackMap().contains(index))
678         return;
679     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
680     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
681     JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
682     JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
683     JSValueUnprotect(context, callback);
684 }
685
686 void TestRunner::clearTestRunnerCallbacks()
687 {
688     for (auto& iter : callbackMap()) {
689         WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
690         JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
691         JSObjectRef callback = JSValueToObject(context, iter.value, 0);
692         JSValueUnprotect(context, callback);
693     }
694
695     callbackMap().clear();
696 }
697
698 void TestRunner::accummulateLogsForChannel(JSStringRef)
699 {
700     // FIXME: Implement getting the call to all processes.
701 }
702
703 void TestRunner::addChromeInputField(JSValueRef callback)
704 {
705     cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
706     InjectedBundle::singleton().postAddChromeInputField();
707 }
708
709 void TestRunner::removeChromeInputField(JSValueRef callback)
710 {
711     cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
712     InjectedBundle::singleton().postRemoveChromeInputField();
713 }
714
715 void TestRunner::focusWebView(JSValueRef callback)
716 {
717     cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
718     InjectedBundle::singleton().postFocusWebView();
719 }
720
721 void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
722 {
723     cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
724     InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor);
725 }
726
727 void TestRunner::setWindowIsKey(bool isKey)
728 {
729     InjectedBundle::singleton().postSetWindowIsKey(isKey);
730 }
731
732 void TestRunner::setViewSize(double width, double height)
733 {
734     InjectedBundle::singleton().postSetViewSize(width, height);
735 }
736
737 void TestRunner::callAddChromeInputFieldCallback()
738 {
739     callTestRunnerCallback(AddChromeInputFieldCallbackID);
740 }
741
742 void TestRunner::callRemoveChromeInputFieldCallback()
743 {
744     callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
745 }
746
747 void TestRunner::callFocusWebViewCallback()
748 {
749     callTestRunnerCallback(FocusWebViewCallbackID);
750 }
751
752 void TestRunner::callSetBackingScaleFactorCallback()
753 {
754     callTestRunnerCallback(SetBackingScaleFactorCallbackID);
755 }
756
757 static inline bool toBool(JSStringRef value)
758 {
759     return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
760 }
761
762 void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
763 {
764     auto& injectedBundle = InjectedBundle::singleton();
765     // FIXME: handle non-boolean preferences.
766     WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value));
767 }
768
769 void TestRunner::setAlwaysAcceptCookies(bool accept)
770 {
771     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies"));
772
773     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(accept));
774
775     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
776 }
777
778 void TestRunner::setCookieStoragePartitioningEnabled(bool enabled)
779 {
780     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCookieStoragePartitioningEnabled"));
781
782     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
783
784     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
785 }
786
787 void TestRunner::setStorageAccessAPIEnabled(bool enabled)
788 {
789     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
790     
791     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
792     
793     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
794 }
795     
796 double TestRunner::preciseTime()
797 {
798     return currentTime();
799 }
800
801 void TestRunner::setUserStyleSheetEnabled(bool enabled)
802 {
803     m_userStyleSheetEnabled = enabled;
804
805     WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
806     WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
807     auto& injectedBundle = InjectedBundle::singleton();
808     WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location);
809 }
810
811 void TestRunner::setUserStyleSheetLocation(JSStringRef location)
812 {
813     m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
814
815     if (m_userStyleSheetEnabled)
816         setUserStyleSheetEnabled(true);
817 }
818
819 void TestRunner::setSpatialNavigationEnabled(bool enabled)
820 {
821     auto& injectedBundle = InjectedBundle::singleton();
822     WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
823 }
824
825 void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
826 {
827     auto& injectedBundle = InjectedBundle::singleton();
828     WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled);
829 }
830
831 void TestRunner::setSerializeHTTPLoads()
832 {
833     // WK2 doesn't reorder loads.
834 }
835
836 void TestRunner::dispatchPendingLoadRequests()
837 {
838     // WK2 doesn't keep pending requests.
839 }
840
841 void TestRunner::setCacheModel(int model)
842 {
843     InjectedBundle::singleton().setCacheModel(model);
844 }
845
846 void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled)
847 {
848     auto& injectedBundle = InjectedBundle::singleton();
849     WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
850 }
851
852 void TestRunner::grantWebNotificationPermission(JSStringRef origin)
853 {
854     WKRetainPtr<WKStringRef> originWK = toWK(origin);
855     auto& injectedBundle = InjectedBundle::singleton();
856     WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true);
857 }
858
859 void TestRunner::denyWebNotificationPermission(JSStringRef origin)
860 {
861     WKRetainPtr<WKStringRef> originWK = toWK(origin);
862     auto& injectedBundle = InjectedBundle::singleton();
863     WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false);
864 }
865
866 void TestRunner::removeAllWebNotificationPermissions()
867 {
868     auto& injectedBundle = InjectedBundle::singleton();
869     WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page());
870 }
871
872 void TestRunner::simulateWebNotificationClick(JSValueRef notification)
873 {
874     auto& injectedBundle = InjectedBundle::singleton();
875     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
876     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
877     uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification);
878     injectedBundle.postSimulateWebNotificationClick(notificationID);
879 }
880
881 void TestRunner::setGeolocationPermission(bool enabled)
882 {
883     // FIXME: this should be done by frame.
884     InjectedBundle::singleton().setGeolocationPermission(enabled);
885 }
886
887 bool TestRunner::isGeolocationProviderActive()
888 {
889     return InjectedBundle::singleton().isGeolocationProviderActive();
890 }
891
892 void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed, JSValueRef jsFloorLevel)
893 {
894     auto& injectedBundle = InjectedBundle::singleton();
895     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
896     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
897
898     bool providesAltitude = false;
899     double altitude = 0.;
900     if (!JSValueIsUndefined(context, jsAltitude)) {
901         providesAltitude = true;
902         altitude = JSValueToNumber(context, jsAltitude, 0);
903     }
904
905     bool providesAltitudeAccuracy = false;
906     double altitudeAccuracy = 0.;
907     if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
908         providesAltitudeAccuracy = true;
909         altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
910     }
911
912     bool providesHeading = false;
913     double heading = 0.;
914     if (!JSValueIsUndefined(context, jsHeading)) {
915         providesHeading = true;
916         heading = JSValueToNumber(context, jsHeading, 0);
917     }
918
919     bool providesSpeed = false;
920     double speed = 0.;
921     if (!JSValueIsUndefined(context, jsSpeed)) {
922         providesSpeed = true;
923         speed = JSValueToNumber(context, jsSpeed, 0);
924     }
925
926     bool providesFloorLevel = false;
927     double floorLevel = 0.;
928     if (!JSValueIsUndefined(context, jsFloorLevel)) {
929         providesFloorLevel = true;
930         floorLevel = JSValueToNumber(context, jsFloorLevel, 0);
931     }
932
933     injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed, providesFloorLevel, floorLevel);
934 }
935
936 void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
937 {
938     WKRetainPtr<WKStringRef> messageWK = toWK(message);
939     InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get());
940 }
941
942 void TestRunner::setUserMediaPermission(bool enabled)
943 {
944     // FIXME: this should be done by frame.
945     InjectedBundle::singleton().setUserMediaPermission(enabled);
946 }
947
948 void TestRunner::resetUserMediaPermission()
949 {
950     // FIXME: this should be done by frame.
951     InjectedBundle::singleton().resetUserMediaPermission();
952 }
953
954 void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
955 {
956     WKRetainPtr<WKStringRef> originWK = toWK(origin);
957     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
958     InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
959 }
960
961 unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
962 {
963     WKRetainPtr<WKStringRef> originWK = toWK(origin);
964     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
965     return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
966 }
967
968 void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
969 {
970     WKRetainPtr<WKStringRef> originWK = toWK(origin);
971     WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
972     InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
973 }
974
975 bool TestRunner::callShouldCloseOnWebView()
976 {
977     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
978     return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
979 }
980
981 void TestRunner::queueBackNavigation(unsigned howFarBackward)
982 {
983     InjectedBundle::singleton().queueBackNavigation(howFarBackward);
984 }
985
986 void TestRunner::queueForwardNavigation(unsigned howFarForward)
987 {
988     InjectedBundle::singleton().queueForwardNavigation(howFarForward);
989 }
990
991 void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs)
992 {
993     auto& injectedBundle = InjectedBundle::singleton();
994     WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page())));
995     WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
996     WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get()));
997
998     injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs);
999 }
1000
1001 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
1002 {
1003     WKRetainPtr<WKStringRef> contentWK = toWK(content);
1004     WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
1005     WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
1006
1007     InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
1008 }
1009
1010 void TestRunner::queueReload()
1011 {
1012     InjectedBundle::singleton().queueReload();
1013 }
1014
1015 void TestRunner::queueLoadingScript(JSStringRef script)
1016 {
1017     WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1018     InjectedBundle::singleton().queueLoadingScript(scriptWK.get());
1019 }
1020
1021 void TestRunner::queueNonLoadingScript(JSStringRef script)
1022 {
1023     WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1024     InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get());
1025 }
1026
1027 void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value)
1028 {
1029     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges"));
1030     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1031     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1032 }
1033     
1034 void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
1035 {
1036     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges"));
1037     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges));
1038     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1039 }
1040
1041 void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value)
1042 {
1043     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace"));
1044     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1045     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1046 }
1047
1048 void TestRunner::setShouldLogDownloadCallbacks(bool value)
1049 {
1050     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogDownloadCallbacks"));
1051     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1052     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1053 }
1054
1055 void TestRunner::setAuthenticationUsername(JSStringRef username)
1056 {
1057     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername"));
1058     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(username));
1059     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1060 }
1061
1062 void TestRunner::setAuthenticationPassword(JSStringRef password)
1063 {
1064     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationPassword"));
1065     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(password));
1066     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1067 }
1068
1069 bool TestRunner::secureEventInputIsEnabled() const
1070 {
1071     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SecureEventInputIsEnabled"));
1072     WKTypeRef returnData = 0;
1073
1074     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), 0, &returnData);
1075     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1076 }
1077
1078 void TestRunner::setBlockAllPlugins(bool shouldBlock)
1079 {
1080     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBlockAllPlugins"));
1081     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldBlock));
1082     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1083 }
1084
1085 JSValueRef TestRunner::failNextNewCodeBlock()
1086 {
1087     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1088     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1089     return JSC::failNextNewCodeBlock(context);
1090 }
1091
1092 JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction)
1093 {
1094     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1095     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1096     return JSC::numberOfDFGCompiles(context, theFunction);
1097 }
1098
1099 JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction)
1100 {
1101     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1102     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1103     return JSC::setNeverInline(context, theFunction);
1104 }
1105
1106 void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value)
1107 {
1108     m_shouldDecideNavigationPolicyAfterDelay = value;
1109     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay"));
1110     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1111     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1112 }
1113
1114 void TestRunner::setNavigationGesturesEnabled(bool value)
1115 {
1116     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled"));
1117     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1118     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1119 }
1120
1121 void TestRunner::setIgnoresViewportScaleLimits(bool value)
1122 {
1123     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits"));
1124     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1125     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1126 }
1127
1128 void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value)
1129 {
1130     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes"));
1131     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1132     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1133 }
1134
1135 void TestRunner::terminateNetworkProcess()
1136 {
1137     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateNetworkProcess"));
1138     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1139 }
1140
1141 void TestRunner::terminateServiceWorkerProcess()
1142 {
1143     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateServiceWorkerProcess"));
1144     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1145 }
1146
1147 static unsigned nextUIScriptCallbackID()
1148 {
1149     static unsigned callbackID = FirstUIScriptCallbackID;
1150     return callbackID++;
1151 }
1152
1153 void TestRunner::runUIScript(JSStringRef script, JSValueRef callback)
1154 {
1155     unsigned callbackID = nextUIScriptCallbackID();
1156     cacheTestRunnerCallback(callbackID, callback);
1157
1158     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RunUIProcessScript"));
1159
1160     WKRetainPtr<WKMutableDictionaryRef> testDictionary(AdoptWK, WKMutableDictionaryCreate());
1161
1162     WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
1163     WKRetainPtr<WKStringRef> scriptValue(AdoptWK, WKStringCreateWithJSString(script));
1164
1165     WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
1166     WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID));
1167
1168     WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get());
1169     WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get());
1170
1171     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get());
1172 }
1173
1174 void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result)
1175 {
1176     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1177     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1178
1179     JSValueRef resultValue = JSValueMakeString(context, result);
1180     callTestRunnerCallback(callbackID, 1, &resultValue);
1181 }
1182
1183 void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
1184 {
1185     cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
1186 }
1187
1188 void TestRunner::installWillEndSwipeCallback(JSValueRef callback)
1189 {
1190     cacheTestRunnerCallback(WillEndSwipeCallbackID, callback);
1191 }
1192
1193 void TestRunner::installDidEndSwipeCallback(JSValueRef callback)
1194 {
1195     cacheTestRunnerCallback(DidEndSwipeCallbackID, callback);
1196 }
1197
1198 void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback)
1199 {
1200     cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback);
1201 }
1202
1203 void TestRunner::callDidBeginSwipeCallback()
1204 {
1205     callTestRunnerCallback(DidBeginSwipeCallbackID);
1206 }
1207
1208 void TestRunner::callWillEndSwipeCallback()
1209 {
1210     callTestRunnerCallback(WillEndSwipeCallbackID);
1211 }
1212
1213 void TestRunner::callDidEndSwipeCallback()
1214 {
1215     callTestRunnerCallback(DidEndSwipeCallbackID);
1216 }
1217
1218 void TestRunner::callDidRemoveSwipeSnapshotCallback()
1219 {
1220     callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
1221 }
1222
1223 void TestRunner::setStatisticsLastSeen(JSStringRef hostName, double seconds)
1224 {
1225     Vector<WKRetainPtr<WKStringRef>> keys;
1226     Vector<WKRetainPtr<WKTypeRef>> values;
1227     
1228     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1229     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1230     
1231     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1232     values.append({ AdoptWK, WKDoubleCreate(seconds) });
1233     
1234     Vector<WKStringRef> rawKeys(keys.size());
1235     Vector<WKTypeRef> rawValues(values.size());
1236     
1237     for (size_t i = 0; i < keys.size(); ++i) {
1238         rawKeys[i] = keys[i].get();
1239         rawValues[i] = values[i].get();
1240     }
1241     
1242     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsLastSeen"));
1243     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1244     
1245     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1246 }
1247     
1248 void TestRunner::setStatisticsPrevalentResource(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("SetStatisticsPrevalentResource"));
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::isStatisticsPrevalentResource(JSStringRef hostName)
1276 {
1277     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource"));
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 bool TestRunner::isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost)
1285 {
1286     Vector<WKRetainPtr<WKStringRef>> keys;
1287     Vector<WKRetainPtr<WKTypeRef>> values;
1288
1289     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("SubFrameHost") });
1290     values.append({ AdoptWK, WKStringCreateWithJSString(subFrameHost) });
1291     
1292     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHost") });
1293     values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHost) });
1294     
1295     Vector<WKStringRef> rawKeys(keys.size());
1296     Vector<WKTypeRef> rawValues(values.size());
1297
1298     for (size_t i = 0; i < keys.size(); ++i) {
1299         rawKeys[i] = keys[i].get();
1300         rawValues[i] = values[i].get();
1301     }
1302
1303     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubFrameUnder"));
1304     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1305     WKTypeRef returnData = 0;
1306     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1307     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1308 }
1309
1310 bool TestRunner::isStatisticsRegisteredAsRedirectingTo(JSStringRef hostRedirectedFrom, JSStringRef hostRedirectedTo)
1311 {
1312     Vector<WKRetainPtr<WKStringRef>> keys;
1313     Vector<WKRetainPtr<WKTypeRef>> values;
1314     
1315     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedFrom") });
1316     values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedFrom) });
1317     
1318     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedTo") });
1319     values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedTo) });
1320     
1321     Vector<WKStringRef> rawKeys(keys.size());
1322     Vector<WKTypeRef> rawValues(values.size());
1323
1324     for (size_t i = 0; i < keys.size(); ++i) {
1325         rawKeys[i] = keys[i].get();
1326         rawValues[i] = values[i].get();
1327     }
1328     
1329     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsRedirectingTo"));
1330     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1331     WKTypeRef returnData = 0;
1332     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1333     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1334 }
1335
1336 void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value)
1337 {
1338     Vector<WKRetainPtr<WKStringRef>> keys;
1339     Vector<WKRetainPtr<WKTypeRef>> values;
1340     
1341     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1342     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1343     
1344     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1345     values.append({ AdoptWK, WKBooleanCreate(value) });
1346     
1347     Vector<WKStringRef> rawKeys;
1348     Vector<WKTypeRef> rawValues;
1349     rawKeys.resize(keys.size());
1350     rawValues.resize(values.size());
1351     
1352     for (size_t i = 0; i < keys.size(); ++i) {
1353         rawKeys[i] = keys[i].get();
1354         rawValues[i] = values[i].get();
1355     }
1356     
1357     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction"));
1358     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1359     
1360     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1361 }
1362
1363 void TestRunner::setStatisticsHasHadNonRecentUserInteraction(JSStringRef hostName)
1364 {
1365     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadNonRecentUserInteraction"));
1366     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1367     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1368 }
1369
1370 bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName)
1371 {
1372     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction"));
1373     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1374     WKTypeRef returnData = 0;
1375     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1376     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1377 }
1378
1379 void TestRunner::setStatisticsGrandfathered(JSStringRef hostName, bool value)
1380 {
1381     Vector<WKRetainPtr<WKStringRef>> keys;
1382     Vector<WKRetainPtr<WKTypeRef>> values;
1383     
1384     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1385     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1386     
1387     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1388     values.append({ AdoptWK, WKBooleanCreate(value) });
1389     
1390     Vector<WKStringRef> rawKeys;
1391     Vector<WKTypeRef> rawValues;
1392     rawKeys.resize(keys.size());
1393     rawValues.resize(values.size());
1394     
1395     for (size_t i = 0; i < keys.size(); ++i) {
1396         rawKeys[i] = keys[i].get();
1397         rawValues[i] = values[i].get();
1398     }
1399     
1400     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfathered"));
1401     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1402     
1403     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1404 }
1405     
1406 bool TestRunner::isStatisticsGrandfathered(JSStringRef hostName)
1407 {
1408     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsGrandfathered"));
1409     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1410     WKTypeRef returnData = 0;
1411     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1412     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1413 }
1414
1415 void TestRunner::setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1416 {
1417     Vector<WKRetainPtr<WKStringRef>> keys;
1418     Vector<WKRetainPtr<WKTypeRef>> values;
1419     
1420     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1421     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1422     
1423     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1424     values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1425     
1426     Vector<WKStringRef> rawKeys(keys.size());
1427     Vector<WKTypeRef> rawValues(values.size());
1428     
1429     for (size_t i = 0; i < keys.size(); ++i) {
1430         rawKeys[i] = keys[i].get();
1431         rawValues[i] = values[i].get();
1432     }
1433     
1434     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubframeUnderTopFrameOrigin"));
1435     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1436     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1437 }
1438
1439 void TestRunner::setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1440 {
1441     Vector<WKRetainPtr<WKStringRef>> keys;
1442     Vector<WKRetainPtr<WKTypeRef>> values;
1443     
1444     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1445     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1446     
1447     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1448     values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1449     
1450     Vector<WKStringRef> rawKeys(keys.size());
1451     Vector<WKTypeRef> rawValues(values.size());
1452     
1453     for (size_t i = 0; i < keys.size(); ++i) {
1454         rawKeys[i] = keys[i].get();
1455         rawValues[i] = values[i].get();
1456     }
1457     
1458     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUnderTopFrameOrigin"));
1459     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1460     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1461 }
1462
1463 void TestRunner::setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1464 {
1465     Vector<WKRetainPtr<WKStringRef>> keys;
1466     Vector<WKRetainPtr<WKTypeRef>> values;
1467     
1468     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1469     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1470     
1471     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo") });
1472     values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedTo) });
1473     
1474     Vector<WKStringRef> rawKeys(keys.size());
1475     Vector<WKTypeRef> rawValues(values.size());
1476     
1477     for (size_t i = 0; i < keys.size(); ++i) {
1478         rawKeys[i] = keys[i].get();
1479         rawValues[i] = values[i].get();
1480     }
1481     
1482     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectTo"));
1483     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1484     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1485 }
1486
1487 void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
1488 {
1489     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));
1490     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1491     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1492 }
1493
1494 void TestRunner::setStatisticsTimeToLiveCookiePartitionFree(double seconds)
1495 {
1496     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveCookiePartitionFree"));
1497     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1498     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1499 }
1500
1501 void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback)
1502 {
1503     cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback);
1504 }
1505
1506 void TestRunner::statisticsDidModifyDataRecordsCallback()
1507 {
1508     callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID);
1509 }
1510
1511 void TestRunner::installStatisticsDidScanDataRecordsCallback(JSValueRef callback)
1512 {
1513     cacheTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID, callback);
1514 }
1515
1516 void TestRunner::statisticsDidScanDataRecordsCallback()
1517 {
1518     callTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID);
1519 }
1520
1521 void TestRunner::installStatisticsDidRunTelemetryCallback(JSValueRef callback)
1522 {
1523     cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
1524 }
1525     
1526 void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
1527 {
1528     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1529     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1530     
1531     StringBuilder stringBuilder;
1532     stringBuilder.appendLiteral("{ \"totalPrevalentResources\" : ");
1533     stringBuilder.appendNumber(totalPrevalentResources);
1534     stringBuilder.appendLiteral(", \"totalPrevalentResourcesWithUserInteraction\" : ");
1535     stringBuilder.appendNumber(totalPrevalentResourcesWithUserInteraction);
1536     stringBuilder.appendLiteral(", \"top3SubframeUnderTopFrameOrigins\" : ");
1537     stringBuilder.appendNumber(top3SubframeUnderTopFrameOrigins);
1538     stringBuilder.appendLiteral(" }");
1539     
1540     JSValueRef result = JSValueMakeFromJSONString(context, JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data()));
1541     
1542     callTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, 1, &result);
1543 }
1544
1545 void TestRunner::statisticsNotifyObserver()
1546 {
1547     InjectedBundle::singleton().statisticsNotifyObserver();
1548 }
1549
1550 void TestRunner::statisticsProcessStatisticsAndDataRecords()
1551 {
1552     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsProcessStatisticsAndDataRecords"));
1553     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1554 }
1555
1556 void TestRunner::statisticsUpdateCookiePartitioning()
1557 {
1558     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsUpdateCookiePartitioning"));
1559     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1560 }
1561
1562 void TestRunner::statisticsSetShouldPartitionCookiesForHost(JSStringRef hostName, bool value)
1563 {
1564     Vector<WKRetainPtr<WKStringRef>> keys;
1565     Vector<WKRetainPtr<WKTypeRef>> values;
1566     
1567     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1568     values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1569     
1570     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1571     values.append({ AdoptWK, WKBooleanCreate(value) });
1572     
1573     Vector<WKStringRef> rawKeys(keys.size());
1574     Vector<WKTypeRef> rawValues(values.size());
1575     
1576     for (size_t i = 0; i < keys.size(); ++i) {
1577         rawKeys[i] = keys[i].get();
1578         rawValues[i] = values[i].get();
1579     }
1580     
1581     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSetShouldPartitionCookiesForHost"));
1582     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1583     
1584     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1585 }
1586
1587 void TestRunner::statisticsSubmitTelemetry()
1588 {
1589     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSubmitTelemetry"));
1590     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1591 }
1592
1593 void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value)
1594 {
1595     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1596     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1597     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1598 }
1599
1600 void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
1601 {
1602     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval"));
1603     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1604     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1605 }
1606
1607 void TestRunner::setStatisticsNotifyPagesWhenTelemetryWasCaptured(bool value)
1608 {
1609     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenTelemetryWasCaptured"));
1610     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1611     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1612 }
1613
1614 void TestRunner::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
1615 {
1616     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweenDataRecordsRemoval"));
1617     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1618     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1619 }
1620
1621 void TestRunner::setStatisticsGrandfatheringTime(double seconds)
1622 {
1623     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfatheringTime"));
1624     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1625     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1626 }
1627
1628 void TestRunner::setStatisticsMaxStatisticsEntries(unsigned entries)
1629 {
1630     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMaxStatisticsEntries"));
1631     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1632     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1633 }
1634     
1635 void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
1636 {
1637     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetPruneEntriesDownTo"));
1638     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1639     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1640 }
1641     
1642 void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
1643 {
1644     cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1645
1646     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
1647     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1648 }
1649
1650 void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback)
1651 {
1652     cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1653
1654     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
1655     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(hours));
1656     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1657 }
1658
1659 void TestRunner::statisticsClearThroughWebsiteDataRemoval(JSValueRef callback)
1660 {
1661     cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1662     
1663     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearThroughWebsiteDataRemoval"));
1664     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1665 }
1666
1667 void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
1668 {
1669     callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
1670 }
1671
1672 void TestRunner::statisticsResetToConsistentState()
1673 {
1674     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsResetToConsistentState"));
1675     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1676 }
1677
1678 #if PLATFORM(MAC)
1679 void TestRunner::connectMockGamepad(unsigned index)
1680 {
1681     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad"));
1682     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1683
1684     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1685 }
1686
1687 void TestRunner::disconnectMockGamepad(unsigned index)
1688 {
1689     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad"));
1690     WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1691
1692     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1693 }
1694
1695 void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount)
1696 {
1697     Vector<WKRetainPtr<WKStringRef>> keys;
1698     Vector<WKRetainPtr<WKTypeRef>> values;
1699
1700     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") });
1701     values.append(toWK(gamepadID));
1702
1703     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1704     values.append({ AdoptWK, WKUInt64Create(index) });
1705
1706     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") });
1707     values.append({ AdoptWK, WKUInt64Create(axisCount) });
1708
1709     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") });
1710     values.append({ AdoptWK, WKUInt64Create(buttonCount) });
1711
1712     Vector<WKStringRef> rawKeys;
1713     Vector<WKTypeRef> rawValues;
1714     rawKeys.resize(keys.size());
1715     rawValues.resize(values.size());
1716
1717     for (size_t i = 0; i < keys.size(); ++i) {
1718         rawKeys[i] = keys[i].get();
1719         rawValues[i] = values[i].get();
1720     }
1721
1722     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails"));
1723     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1724
1725     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1726 }
1727
1728 void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value)
1729 {
1730     Vector<WKRetainPtr<WKStringRef>> keys;
1731     Vector<WKRetainPtr<WKTypeRef>> values;
1732
1733     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1734     values.append({ AdoptWK, WKUInt64Create(index) });
1735
1736     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") });
1737     values.append({ AdoptWK, WKUInt64Create(axisIndex) });
1738
1739     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1740     values.append({ AdoptWK, WKDoubleCreate(value) });
1741
1742     Vector<WKStringRef> rawKeys;
1743     Vector<WKTypeRef> rawValues;
1744     rawKeys.resize(keys.size());
1745     rawValues.resize(values.size());
1746
1747     for (size_t i = 0; i < keys.size(); ++i) {
1748         rawKeys[i] = keys[i].get();
1749         rawValues[i] = values[i].get();
1750     }
1751
1752     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue"));
1753     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1754
1755     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1756 }
1757
1758 void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value)
1759 {
1760     Vector<WKRetainPtr<WKStringRef>> keys;
1761     Vector<WKRetainPtr<WKTypeRef>> values;
1762
1763     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1764     values.append({ AdoptWK, WKUInt64Create(index) });
1765
1766     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") });
1767     values.append({ AdoptWK, WKUInt64Create(buttonIndex) });
1768
1769     keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1770     values.append({ AdoptWK, WKDoubleCreate(value) });
1771
1772     Vector<WKStringRef> rawKeys;
1773     Vector<WKTypeRef> rawValues;
1774     rawKeys.resize(keys.size());
1775     rawValues.resize(values.size());
1776
1777     for (size_t i = 0; i < keys.size(); ++i) {
1778         rawKeys[i] = keys[i].get();
1779         rawValues[i] = values[i].get();
1780     }
1781
1782     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue"));
1783     WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1784
1785     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1786 }
1787 #else
1788 void TestRunner::connectMockGamepad(unsigned)
1789 {
1790 }
1791
1792 void TestRunner::disconnectMockGamepad(unsigned)
1793 {
1794 }
1795
1796 void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned)
1797 {
1798 }
1799
1800 void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double)
1801 {
1802 }
1803
1804 void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double)
1805 {
1806 }
1807 #endif // PLATFORM(MAC)
1808
1809 void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
1810 {
1811     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
1812     JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
1813
1814     if (!JSValueIsArray(context, filesValue))
1815         return;
1816
1817     JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
1818     static auto lengthProperty = JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("length"));
1819     JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
1820     if (!JSValueIsNumber(context, filesLengthValue))
1821         return;
1822
1823     auto fileURLs = adoptWK(WKMutableArrayCreate());
1824     auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
1825     for (size_t i = 0; i < filesLength; ++i) {
1826         JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
1827         if (!JSValueIsString(context, fileValue))
1828             continue;
1829
1830         auto file = JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, fileValue, nullptr));
1831         size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
1832         auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
1833         JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
1834
1835         WKArrayAppendItem(fileURLs.get(), adoptWK(WKURLCreateWithBaseURL(m_testURL.get(), fileBuffer.get())).get());
1836     }
1837
1838     static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLs"));
1839     WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
1840 }
1841
1842 void TestRunner::removeAllSessionCredentials(JSValueRef callback)
1843 {
1844     cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
1845     
1846     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveAllSessionCredentials"));
1847     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
1848     
1849     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1850 }
1851
1852 void TestRunner::callDidRemoveAllSessionCredentialsCallback()
1853 {
1854     callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
1855 }
1856
1857 void TestRunner::clearDOMCache(JSStringRef origin)
1858 {
1859     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCache"));
1860     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1861     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1862 }
1863
1864 void TestRunner::clearDOMCaches()
1865 {
1866     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCaches"));
1867     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1868 }
1869
1870 bool TestRunner::hasDOMCache(JSStringRef origin)
1871 {
1872     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("HasDOMCache"));
1873     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1874     WKTypeRef returnData = 0;
1875     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1876     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1877 }
1878
1879 uint64_t TestRunner::domCacheSize(JSStringRef origin)
1880 {
1881     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DOMCacheSize"));
1882     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1883     WKTypeRef returnData = 0;
1884     WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1885     return WKUInt64GetValue(static_cast<WKUInt64Ref>(returnData));
1886 }
1887
1888 void TestRunner::getApplicationManifestThen(JSValueRef callback)
1889 {
1890     cacheTestRunnerCallback(GetApplicationManifestCallbackID, callback);
1891     
1892     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("GetApplicationManifest"));
1893     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1894 }
1895
1896 void TestRunner::didGetApplicationManifest()
1897 {
1898     callTestRunnerCallback(GetApplicationManifestCallbackID);
1899 }
1900
1901 } // namespace WTR