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