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/WKNumber.h>
49#include <WebKit/WKPagePrivate.h>
50#include <WebKit/WKRetainPtr.h>
51#include <WebKit/WKSerializedScriptValue.h>
52#include <WebKit/WebKit2_C.h>
53#include <wtf/HashMap.h>
54#include <wtf/Optional.h>
55#include <wtf/StdLibExtras.h>
56#include <wtf/text/CString.h>
57#include <wtf/text/StringBuilder.h>
58#include <wtf/text/StringConcatenateNumbers.h>
59
60namespace WTR {
61
62Ref<TestRunner> TestRunner::create()
63{
64 return adoptRef(*new TestRunner);
65}
66
67TestRunner::TestRunner()
68 : m_userStyleSheetLocation(adoptWK(WKStringCreateWithUTF8CString("")))
69{
70 platformInitialize();
71}
72
73TestRunner::~TestRunner()
74{
75}
76
77JSClassRef TestRunner::wrapperClass()
78{
79 return JSTestRunner::testRunnerClass();
80}
81
82void TestRunner::display()
83{
84 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
85 WKBundlePageForceRepaint(page);
86}
87
88void TestRunner::displayAndTrackRepaints()
89{
90 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
91 WKBundlePageForceRepaint(page);
92 WKBundlePageSetTracksRepaints(page, true);
93 WKBundlePageResetTrackedRepaints(page);
94}
95
96bool TestRunner::shouldDumpPixels() const
97{
98 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("GetDumpPixels"));
99 WKTypeRef returnData = nullptr;
100 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, &returnData);
101 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
102 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
103}
104
105void TestRunner::setDumpPixels(bool dumpPixels)
106{
107 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetDumpPixels"));
108 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(dumpPixels));
109 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
110}
111
112void TestRunner::dumpAsText(bool dumpPixels)
113{
114 if (whatToDump() < WhatToDump::MainFrameText)
115 setWhatToDump(WhatToDump::MainFrameText);
116 setDumpPixels(dumpPixels);
117}
118
119WhatToDump TestRunner::whatToDump() const
120{
121 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("GetWhatToDump"));
122 WKTypeRef returnData = nullptr;
123 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, &returnData);
124 ASSERT(WKGetTypeID(returnData) == WKUInt64GetTypeID());
125 return static_cast<WhatToDump>(WKUInt64GetValue(adoptWK(static_cast<WKUInt64Ref>(returnData)).get()));
126}
127
128void TestRunner::setWhatToDump(WhatToDump whatToDump)
129{
130 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetWhatToDump"));
131 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(static_cast<uint64_t>(whatToDump)));
132 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
133}
134
135void TestRunner::setCustomPolicyDelegate(bool enabled, bool permissive)
136{
137 m_policyDelegateEnabled = enabled;
138 m_policyDelegatePermissive = permissive;
139
140 InjectedBundle::singleton().setCustomPolicyDelegate(enabled, permissive);
141}
142
143void TestRunner::waitForPolicyDelegate()
144{
145 setCustomPolicyDelegate(true);
146 waitUntilDone();
147}
148
149void TestRunner::waitUntilDownloadFinished()
150{
151 m_shouldFinishAfterDownload = true;
152 waitUntilDone();
153}
154
155void TestRunner::waitUntilDone()
156{
157 auto& injectedBundle = InjectedBundle::singleton();
158 RELEASE_ASSERT(injectedBundle.isTestRunning());
159
160 setWaitUntilDone(true);
161}
162
163void TestRunner::setWaitUntilDone(bool value)
164{
165 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetWaitUntilDone"));
166 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
167 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
168}
169
170bool TestRunner::shouldWaitUntilDone() const
171{
172 WKRetainPtr<WKStringRef> messsageName = adoptWK(WKStringCreateWithUTF8CString("GetWaitUntilDone"));
173 WKTypeRef returnData = nullptr;
174 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messsageName.get(), nullptr, &returnData);
175 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
176 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
177}
178
179void TestRunner::notifyDone()
180{
181 auto& injectedBundle = InjectedBundle::singleton();
182 if (!injectedBundle.isTestRunning())
183 return;
184
185 if (shouldWaitUntilDone() && !injectedBundle.topLoadingFrame())
186 injectedBundle.page()->dump();
187
188 // We don't call invalidateWaitToDumpWatchdogTimer() here, even if we continue to wait for a load to finish.
189 // The test is still subject to timeout checking - it is better to detect an async timeout inside WebKitTestRunner
190 // than to let webkitpy do that, because WebKitTestRunner will dump partial results.
191
192 setWaitUntilDone(false);
193}
194
195void TestRunner::forceImmediateCompletion()
196{
197 auto& injectedBundle = InjectedBundle::singleton();
198 if (!injectedBundle.isTestRunning())
199 return;
200
201 if (shouldWaitUntilDone() && injectedBundle.page())
202 injectedBundle.page()->dump();
203
204 setWaitUntilDone(false);
205}
206
207void TestRunner::setShouldDumpFrameLoadCallbacks(bool value)
208{
209 WKRetainPtr<WKStringRef> messsageName = adoptWK(WKStringCreateWithUTF8CString("SetDumpFrameLoadCallbacks"));
210 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
211 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messsageName.get(), messageBody.get(), nullptr);
212}
213
214bool TestRunner::shouldDumpFrameLoadCallbacks()
215{
216 WKRetainPtr<WKStringRef> messsageName = adoptWK(WKStringCreateWithUTF8CString("GetDumpFrameLoadCallbacks"));
217 WKTypeRef returnData = nullptr;
218 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messsageName.get(), nullptr, &returnData);
219 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
220 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
221}
222
223unsigned TestRunner::imageCountInGeneralPasteboard() const
224{
225 return InjectedBundle::singleton().imageCountInGeneralPasteboard();
226}
227
228void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
229{
230 WKRetainPtr<WKStringRef> sourceWK = toWK(source);
231
232 WKBundlePageAddUserScript(InjectedBundle::singleton().page()->page(), sourceWK.get(),
233 (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
234 (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
235}
236
237void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
238{
239 WKRetainPtr<WKStringRef> sourceWK = toWK(source);
240
241 WKBundlePageAddUserStyleSheet(InjectedBundle::singleton().page()->page(), sourceWK.get(),
242 (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
243}
244
245void TestRunner::keepWebHistory()
246{
247 InjectedBundle::singleton().postSetAddsVisitedLinks(true);
248}
249
250void TestRunner::execCommand(JSStringRef name, JSStringRef showUI, JSStringRef value)
251{
252 WKBundlePageExecuteEditingCommand(InjectedBundle::singleton().page()->page(), toWK(name).get(), toWK(value).get());
253}
254
255static Optional<WKFindOptions> findOptionsFromArray(JSValueRef optionsArrayAsValue)
256{
257 auto& injectedBundle = InjectedBundle::singleton();
258 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
259 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
260 auto lengthPropertyName = adopt(JSStringCreateWithUTF8CString("length"));
261 JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
262 JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
263 if (!JSValueIsNumber(context, lengthValue))
264 return WTF::nullopt;
265
266 WKFindOptions options = 0;
267 size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
268 for (size_t i = 0; i < length; ++i) {
269 JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
270 if (!JSValueIsString(context, value))
271 continue;
272
273 auto optionName = adopt(JSValueToStringCopy(context, value, 0));
274
275 if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
276 options |= kWKFindOptionsCaseInsensitive;
277 else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
278 options |= kWKFindOptionsAtWordStarts;
279 else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
280 options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
281 else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
282 options |= kWKFindOptionsBackwards;
283 else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
284 options |= kWKFindOptionsWrapAround;
285 else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
286 // FIXME: No kWKFindOptionsStartInSelection.
287 }
288 }
289 return options;
290}
291
292bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
293{
294 if (auto options = findOptionsFromArray(optionsArrayAsValue))
295 return WKBundlePageFindString(InjectedBundle::singleton().page()->page(), toWK(target).get(), *options);
296
297 return false;
298}
299
300void TestRunner::findStringMatchesInPage(JSStringRef target, JSValueRef optionsArrayAsValue)
301{
302 if (auto options = findOptionsFromArray(optionsArrayAsValue))
303 return WKBundlePageFindStringMatches(InjectedBundle::singleton().page()->page(), toWK(target).get(), *options);
304}
305
306void TestRunner::replaceFindMatchesAtIndices(JSValueRef matchIndicesAsValue, JSStringRef replacementText, bool selectionOnly)
307{
308 auto& bundle = InjectedBundle::singleton();
309 auto mainFrame = WKBundlePageGetMainFrame(bundle.page()->page());
310 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
311 auto lengthPropertyName = adopt(JSStringCreateWithUTF8CString("length"));
312 auto matchIndicesObject = JSValueToObject(context, matchIndicesAsValue, 0);
313 auto lengthValue = JSObjectGetProperty(context, matchIndicesObject, lengthPropertyName.get(), 0);
314 if (!JSValueIsNumber(context, lengthValue))
315 return;
316
317 auto indices = adoptWK(WKMutableArrayCreate());
318 auto length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
319 for (size_t i = 0; i < length; ++i) {
320 auto value = JSObjectGetPropertyAtIndex(context, matchIndicesObject, i, 0);
321 if (!JSValueIsNumber(context, value))
322 continue;
323
324 auto index = adoptWK(WKUInt64Create(std::round(JSValueToNumber(context, value, nullptr))));
325 WKArrayAppendItem(indices.get(), index.get());
326 }
327 WKBundlePageReplaceStringMatches(bundle.page()->page(), indices.get(), toWK(replacementText).get(), selectionOnly);
328}
329
330void TestRunner::clearAllDatabases()
331{
332 WKBundleClearAllDatabases(InjectedBundle::singleton().bundle());
333
334 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("DeleteAllIndexedDatabases"));
335 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(true));
336
337 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
338}
339
340void TestRunner::setDatabaseQuota(uint64_t quota)
341{
342 return WKBundleSetDatabaseQuota(InjectedBundle::singleton().bundle(), quota);
343}
344
345void TestRunner::clearAllApplicationCaches()
346{
347 WKBundlePageClearApplicationCache(InjectedBundle::singleton().page()->page());
348}
349
350void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin)
351{
352 WKBundlePageClearApplicationCacheForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
353}
354
355void TestRunner::setAppCacheMaximumSize(uint64_t size)
356{
357 WKBundlePageSetAppCacheMaximumSize(InjectedBundle::singleton().page()->page(), size);
358}
359
360long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef origin)
361{
362 return WKBundlePageGetAppCacheUsageForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
363}
364
365void TestRunner::disallowIncreaseForApplicationCacheQuota()
366{
367 m_disallowIncreaseForApplicationCacheQuota = true;
368}
369
370void TestRunner::setIDBPerOriginQuota(uint64_t quota)
371{
372 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetIDBPerOriginQuota"));
373 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(quota));
374 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
375}
376
377static inline JSValueRef stringArrayToJS(JSContextRef context, WKArrayRef strings)
378{
379 const size_t count = WKArrayGetSize(strings);
380
381 JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
382 JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
383 for (size_t i = 0; i < count; ++i) {
384 WKStringRef stringRef = static_cast<WKStringRef>(WKArrayGetItemAtIndex(strings, i));
385 JSRetainPtr<JSStringRef> stringJS = toJS(stringRef);
386 JSObjectSetPropertyAtIndex(context, arrayObj, i, JSValueMakeString(context, stringJS.get()), 0);
387 }
388
389 return arrayResult;
390}
391
392JSValueRef TestRunner::originsWithApplicationCache()
393{
394 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
395
396 WKRetainPtr<WKArrayRef> origins = adoptWK(WKBundlePageCopyOriginsWithApplicationCache(page));
397
398 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
399 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
400
401 return stringArrayToJS(context, origins.get());
402}
403
404bool TestRunner::isCommandEnabled(JSStringRef name)
405{
406 return WKBundlePageIsEditingCommandEnabled(InjectedBundle::singleton().page()->page(), toWK(name).get());
407}
408
409void TestRunner::setCanOpenWindows()
410{
411 WKRetainPtr<WKStringRef> messsageName = adoptWK(WKStringCreateWithUTF8CString("SetCanOpenWindows"));
412 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(true));
413 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messsageName.get(), messageBody.get(), nullptr);
414}
415
416void TestRunner::setXSSAuditorEnabled(bool enabled)
417{
418 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitXSSAuditorEnabled"));
419 auto& injectedBundle = InjectedBundle::singleton();
420 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
421}
422
423void TestRunner::setMediaDevicesEnabled(bool enabled)
424{
425 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitMediaDevicesEnabled"));
426 auto& injectedBundle = InjectedBundle::singleton();
427 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
428}
429
430void TestRunner::setWebRTCMDNSICECandidatesEnabled(bool enabled)
431{
432 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitWebRTCMDNSICECandidatesEnabled"));
433 auto& injectedBundle = InjectedBundle::singleton();
434 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
435}
436
437void TestRunner::setWebRTCUnifiedPlanEnabled(bool enabled)
438{
439 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitWebRTCUnifiedPlanEnabled"));
440 auto& injectedBundle = InjectedBundle::singleton();
441 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
442}
443
444void TestRunner::setCustomUserAgent(JSStringRef userAgent)
445{
446 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetCustomUserAgent"));
447 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), toWK(userAgent).get(), nullptr);
448}
449
450void TestRunner::setWebAPIStatisticsEnabled(bool enabled)
451{
452 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitWebAPIStatisticsEnabled"));
453 auto& injectedBundle = InjectedBundle::singleton();
454 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
455}
456
457void TestRunner::setModernMediaControlsEnabled(bool enabled)
458{
459 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitModernMediaControlsEnabled"));
460 auto& injectedBundle = InjectedBundle::singleton();
461 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
462}
463
464void TestRunner::setWebGL2Enabled(bool enabled)
465{
466 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitWebGL2Enabled"));
467 auto& injectedBundle = InjectedBundle::singleton();
468 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
469}
470
471void TestRunner::setWritableStreamAPIEnabled(bool enabled)
472{
473 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitWritableStreamAPIEnabled"));
474 auto& injectedBundle = InjectedBundle::singleton();
475 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
476}
477
478void TestRunner::setReadableByteStreamAPIEnabled(bool enabled)
479{
480 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitReadableByteStreamAPIEnabled"));
481 auto& injectedBundle = InjectedBundle::singleton();
482 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
483}
484
485void TestRunner::setEncryptedMediaAPIEnabled(bool enabled)
486{
487 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitEncryptedMediaAPIEnabled"));
488 auto& injectedBundle = InjectedBundle::singleton();
489 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
490}
491
492void TestRunner::setAllowsAnySSLCertificate(bool enabled)
493{
494 auto& injectedBundle = InjectedBundle::singleton();
495 injectedBundle.setAllowsAnySSLCertificate(enabled);
496
497 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAllowsAnySSLCertificate"));
498 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(enabled));
499 WKBundlePagePostSynchronousMessageForTesting(injectedBundle.page()->page(), messageName.get(), messageBody.get(), nullptr);
500}
501
502void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled)
503{
504 auto& injectedBundle = InjectedBundle::singleton();
505 WKBundleSetAllowUniversalAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
506}
507
508void TestRunner::setAllowFileAccessFromFileURLs(bool enabled)
509{
510 auto& injectedBundle = InjectedBundle::singleton();
511 WKBundleSetAllowFileAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
512}
513
514void TestRunner::setNeedsStorageAccessFromFileURLsQuirk(bool needsQuirk)
515{
516 auto& injectedBundle = InjectedBundle::singleton();
517 WKBundleSetAllowStorageAccessFromFileURLS(injectedBundle.bundle(), injectedBundle.pageGroup(), needsQuirk);
518}
519
520void TestRunner::setPluginsEnabled(bool enabled)
521{
522 WKRetainPtr<WKStringRef> key = adoptWK(WKStringCreateWithUTF8CString("WebKitPluginsEnabled"));
523 auto& injectedBundle = InjectedBundle::singleton();
524 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
525}
526
527void TestRunner::setJavaScriptCanAccessClipboard(bool enabled)
528{
529 auto& injectedBundle = InjectedBundle::singleton();
530 WKBundleSetJavaScriptCanAccessClipboard(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
531}
532
533void TestRunner::setPrivateBrowsingEnabled(bool enabled)
534{
535 auto& injectedBundle = InjectedBundle::singleton();
536 WKBundleSetPrivateBrowsingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
537}
538
539void TestRunner::setUseDashboardCompatibilityMode(bool enabled)
540{
541#if ENABLE(DASHBOARD_SUPPORT)
542 auto& injectedBundle = InjectedBundle::singleton();
543 WKBundleSetUseDashboardCompatibilityMode(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
544#else
545 UNUSED_PARAM(enabled);
546#endif
547}
548
549void TestRunner::setPopupBlockingEnabled(bool enabled)
550{
551 auto& injectedBundle = InjectedBundle::singleton();
552 WKBundleSetPopupBlockingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
553}
554
555void TestRunner::setAuthorAndUserStylesEnabled(bool enabled)
556{
557 auto& injectedBundle = InjectedBundle::singleton();
558 WKBundleSetAuthorAndUserStylesEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
559}
560
561void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
562{
563 WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
564}
565
566void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
567{
568 WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
569}
570
571bool TestRunner::isPageBoxVisible(int pageIndex)
572{
573 auto& injectedBundle = InjectedBundle::singleton();
574 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
575 return WKBundleIsPageBoxVisible(injectedBundle.bundle(), mainFrame, pageIndex);
576}
577
578void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
579{
580 if (!element || !JSValueIsObject(context, element))
581 return;
582
583 WKRetainPtr<WKBundleNodeHandleRef> nodeHandle = adoptWK(WKBundleNodeHandleCreate(context, const_cast<JSObjectRef>(element)));
584 WKBundleNodeHandleSetHTMLInputElementValueForUser(nodeHandle.get(), toWK(value).get());
585}
586
587void TestRunner::setAudioResult(JSContextRef context, JSValueRef data)
588{
589 auto& injectedBundle = InjectedBundle::singleton();
590 // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
591 WKRetainPtr<WKDataRef> audioData = adoptWK(WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data));
592 injectedBundle.setAudioResult(audioData.get());
593 setWhatToDump(WhatToDump::Audio);
594 setDumpPixels(false);
595}
596
597unsigned TestRunner::windowCount()
598{
599 return InjectedBundle::singleton().pageCount();
600}
601
602void TestRunner::clearBackForwardList()
603{
604 WKBundleClearHistoryForTesting(InjectedBundle::singleton().page()->page());
605}
606
607// Object Creation
608
609void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
610{
611 setProperty(context, windowObject, "testRunner", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
612}
613
614void TestRunner::showWebInspector()
615{
616 WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
617}
618
619void TestRunner::closeWebInspector()
620{
621 WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
622}
623
624void TestRunner::evaluateInWebInspector(JSStringRef script)
625{
626 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
627 WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()), scriptWK.get());
628}
629
630typedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
631static WorldMap& worldMap()
632{
633 static WorldMap& map = *new WorldMap;
634 return map;
635}
636
637unsigned TestRunner::worldIDForWorld(WKBundleScriptWorldRef world)
638{
639 WorldMap::const_iterator end = worldMap().end();
640 for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
641 if (it->value == world)
642 return it->key;
643 }
644
645 return 0;
646}
647
648void TestRunner::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
649{
650 // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
651 // that is created once and cached forever.
652 WKRetainPtr<WKBundleScriptWorldRef> world;
653 if (!worldID)
654 world.adopt(WKBundleScriptWorldCreateWorld());
655 else {
656 WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, nullptr).iterator->value;
657 if (!worldSlot)
658 worldSlot.adopt(WKBundleScriptWorldCreateWorld());
659 world = worldSlot;
660 }
661
662 WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
663 if (!frame)
664 frame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
665
666 JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
667 JSEvaluateScript(jsContext, script, 0, 0, 0, 0);
668}
669
670void TestRunner::setPOSIXLocale(JSStringRef locale)
671{
672 char localeBuf[32];
673 JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
674 setlocale(LC_ALL, localeBuf);
675}
676
677void TestRunner::setTextDirection(JSStringRef direction)
678{
679 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
680 return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get());
681}
682
683void TestRunner::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage)
684{
685 InjectedBundle::singleton().postNewBeforeUnloadReturnValue(!shouldStayOnPage);
686}
687
688bool TestRunner::didReceiveServerRedirectForProvisionalNavigation() const
689{
690 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("DidReceiveServerRedirectForProvisionalNavigation"));
691 WKTypeRef returnData = nullptr;
692 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
693 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
694 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
695}
696
697void TestRunner::clearDidReceiveServerRedirectForProvisionalNavigation()
698{
699 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ClearDidReceiveServerRedirectForProvisionalNavigation"));
700 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
701}
702
703void TestRunner::setPageVisibility(JSStringRef state)
704{
705 InjectedBundle::singleton().setHidden(JSStringIsEqualToUTF8CString(state, "hidden") || JSStringIsEqualToUTF8CString(state, "prerender"));
706}
707
708void TestRunner::resetPageVisibility()
709{
710 InjectedBundle::singleton().setHidden(false);
711}
712
713typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
714static CallbackMap& callbackMap()
715{
716 static CallbackMap& map = *new CallbackMap;
717 return map;
718}
719
720enum {
721 AddChromeInputFieldCallbackID = 1,
722 RemoveChromeInputFieldCallbackID,
723 FocusWebViewCallbackID,
724 SetBackingScaleFactorCallbackID,
725 DidBeginSwipeCallbackID,
726 WillEndSwipeCallbackID,
727 DidEndSwipeCallbackID,
728 DidRemoveSwipeSnapshotCallbackID,
729 SetStatisticsDebugModeCallbackID,
730 SetStatisticsPrevalentResourceForDebugModeCallbackID,
731 SetStatisticsLastSeenCallbackID,
732 SetStatisticsPrevalentResourceCallbackID,
733 SetStatisticsVeryPrevalentResourceCallbackID,
734 SetStatisticsHasHadUserInteractionCallbackID,
735 StatisticsDidModifyDataRecordsCallbackID,
736 StatisticsDidScanDataRecordsCallbackID,
737 StatisticsDidRunTelemetryCallbackID,
738 StatisticsDidClearThroughWebsiteDataRemovalCallbackID,
739 StatisticsDidResetToConsistentStateCallbackID,
740 StatisticsDidSetBlockCookiesForHostCallbackID,
741 AllStorageAccessEntriesCallbackID,
742 DidRemoveAllSessionCredentialsCallbackID,
743 GetApplicationManifestCallbackID,
744 TextDidChangeInTextFieldCallbackID,
745 TextFieldDidBeginEditingCallbackID,
746 TextFieldDidEndEditingCallbackID,
747 CustomMenuActionCallbackID,
748 FirstUIScriptCallbackID = 100
749};
750
751static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
752{
753 if (!callback)
754 return;
755
756 if (callbackMap().contains(index)) {
757 InjectedBundle::singleton().outputText(makeString("FAIL: Tried to install a second TestRunner callback for the same event (id ", index, ")\n\n"));
758 return;
759 }
760
761 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
762 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
763 JSValueProtect(context, callback);
764 callbackMap().add(index, callback);
765}
766
767static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr)
768{
769 if (!callbackMap().contains(index))
770 return;
771 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
772 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
773 JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
774 JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
775 JSValueUnprotect(context, callback);
776}
777
778void TestRunner::clearTestRunnerCallbacks()
779{
780 for (auto& iter : callbackMap()) {
781 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
782 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
783 JSObjectRef callback = JSValueToObject(context, iter.value, 0);
784 JSValueUnprotect(context, callback);
785 }
786
787 callbackMap().clear();
788}
789
790void TestRunner::accummulateLogsForChannel(JSStringRef)
791{
792 // FIXME: Implement getting the call to all processes.
793}
794
795void TestRunner::addChromeInputField(JSValueRef callback)
796{
797 cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
798 InjectedBundle::singleton().postAddChromeInputField();
799}
800
801void TestRunner::removeChromeInputField(JSValueRef callback)
802{
803 cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
804 InjectedBundle::singleton().postRemoveChromeInputField();
805}
806
807void TestRunner::focusWebView(JSValueRef callback)
808{
809 cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
810 InjectedBundle::singleton().postFocusWebView();
811}
812
813void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
814{
815 cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
816 InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor);
817}
818
819void TestRunner::setWindowIsKey(bool isKey)
820{
821 InjectedBundle::singleton().postSetWindowIsKey(isKey);
822}
823
824void TestRunner::setViewSize(double width, double height)
825{
826 InjectedBundle::singleton().postSetViewSize(width, height);
827}
828
829void TestRunner::callAddChromeInputFieldCallback()
830{
831 callTestRunnerCallback(AddChromeInputFieldCallbackID);
832}
833
834void TestRunner::callRemoveChromeInputFieldCallback()
835{
836 callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
837}
838
839void TestRunner::callFocusWebViewCallback()
840{
841 callTestRunnerCallback(FocusWebViewCallbackID);
842}
843
844void TestRunner::callSetBackingScaleFactorCallback()
845{
846 callTestRunnerCallback(SetBackingScaleFactorCallbackID);
847}
848
849static inline bool toBool(JSStringRef value)
850{
851 return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
852}
853
854void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
855{
856 auto& injectedBundle = InjectedBundle::singleton();
857 // FIXME: handle non-boolean preferences.
858 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value));
859}
860
861void TestRunner::setAlwaysAcceptCookies(bool accept)
862{
863 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies"));
864
865 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(accept));
866
867 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
868}
869
870void TestRunner::setOnlyAcceptFirstPartyCookies(bool accept)
871{
872 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetOnlyAcceptFirstPartyCookies"));
873
874 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(accept));
875
876 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
877}
878
879double TestRunner::preciseTime()
880{
881 return WallTime::now().secondsSinceEpoch().seconds();
882}
883
884void TestRunner::setRenderTreeDumpOptions(unsigned short options)
885{
886 m_renderTreeDumpOptions = options;
887}
888
889void TestRunner::setUserStyleSheetEnabled(bool enabled)
890{
891 m_userStyleSheetEnabled = enabled;
892
893 WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
894 WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
895 auto& injectedBundle = InjectedBundle::singleton();
896 WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location);
897}
898
899void TestRunner::setUserStyleSheetLocation(JSStringRef location)
900{
901 m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
902
903 if (m_userStyleSheetEnabled)
904 setUserStyleSheetEnabled(true);
905}
906
907void TestRunner::setSpatialNavigationEnabled(bool enabled)
908{
909 auto& injectedBundle = InjectedBundle::singleton();
910 WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
911}
912
913void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
914{
915 auto& injectedBundle = InjectedBundle::singleton();
916 WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled);
917}
918
919void TestRunner::setSerializeHTTPLoads()
920{
921 // WK2 doesn't reorder loads.
922}
923
924void TestRunner::dispatchPendingLoadRequests()
925{
926 // WK2 doesn't keep pending requests.
927}
928
929void TestRunner::setCacheModel(int model)
930{
931 InjectedBundle::singleton().setCacheModel(model);
932}
933
934void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled)
935{
936 auto& injectedBundle = InjectedBundle::singleton();
937 WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
938}
939
940void TestRunner::grantWebNotificationPermission(JSStringRef origin)
941{
942 WKRetainPtr<WKStringRef> originWK = toWK(origin);
943 auto& injectedBundle = InjectedBundle::singleton();
944 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true);
945}
946
947void TestRunner::denyWebNotificationPermission(JSStringRef origin)
948{
949 WKRetainPtr<WKStringRef> originWK = toWK(origin);
950 auto& injectedBundle = InjectedBundle::singleton();
951 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false);
952}
953
954void TestRunner::removeAllWebNotificationPermissions()
955{
956 auto& injectedBundle = InjectedBundle::singleton();
957 WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page());
958}
959
960void TestRunner::simulateWebNotificationClick(JSValueRef notification)
961{
962 auto& injectedBundle = InjectedBundle::singleton();
963 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
964 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
965 uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification);
966 injectedBundle.postSimulateWebNotificationClick(notificationID);
967}
968
969void TestRunner::setGeolocationPermission(bool enabled)
970{
971 // FIXME: this should be done by frame.
972 InjectedBundle::singleton().setGeolocationPermission(enabled);
973}
974
975bool TestRunner::isGeolocationProviderActive()
976{
977 return InjectedBundle::singleton().isGeolocationProviderActive();
978}
979
980void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed, JSValueRef jsFloorLevel)
981{
982 auto& injectedBundle = InjectedBundle::singleton();
983 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
984 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
985
986 bool providesAltitude = false;
987 double altitude = 0.;
988 if (!JSValueIsUndefined(context, jsAltitude)) {
989 providesAltitude = true;
990 altitude = JSValueToNumber(context, jsAltitude, 0);
991 }
992
993 bool providesAltitudeAccuracy = false;
994 double altitudeAccuracy = 0.;
995 if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
996 providesAltitudeAccuracy = true;
997 altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
998 }
999
1000 bool providesHeading = false;
1001 double heading = 0.;
1002 if (!JSValueIsUndefined(context, jsHeading)) {
1003 providesHeading = true;
1004 heading = JSValueToNumber(context, jsHeading, 0);
1005 }
1006
1007 bool providesSpeed = false;
1008 double speed = 0.;
1009 if (!JSValueIsUndefined(context, jsSpeed)) {
1010 providesSpeed = true;
1011 speed = JSValueToNumber(context, jsSpeed, 0);
1012 }
1013
1014 bool providesFloorLevel = false;
1015 double floorLevel = 0.;
1016 if (!JSValueIsUndefined(context, jsFloorLevel)) {
1017 providesFloorLevel = true;
1018 floorLevel = JSValueToNumber(context, jsFloorLevel, 0);
1019 }
1020
1021 injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed, providesFloorLevel, floorLevel);
1022}
1023
1024void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
1025{
1026 WKRetainPtr<WKStringRef> messageWK = toWK(message);
1027 InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get());
1028}
1029
1030void TestRunner::setUserMediaPermission(bool enabled)
1031{
1032 // FIXME: this should be done by frame.
1033 InjectedBundle::singleton().setUserMediaPermission(enabled);
1034}
1035
1036void TestRunner::resetUserMediaPermission()
1037{
1038 // FIXME: this should be done by frame.
1039 InjectedBundle::singleton().resetUserMediaPermission();
1040}
1041
1042bool TestRunner::isDoingMediaCapture() const
1043{
1044 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsDoingMediaCapture"));
1045 WKTypeRef returnData = nullptr;
1046 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
1047 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1048 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1049}
1050
1051void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
1052{
1053 WKRetainPtr<WKStringRef> originWK = toWK(origin);
1054 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
1055 InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
1056}
1057
1058unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
1059{
1060 WKRetainPtr<WKStringRef> originWK = toWK(origin);
1061 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
1062 return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
1063}
1064
1065void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
1066{
1067 WKRetainPtr<WKStringRef> originWK = toWK(origin);
1068 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
1069 InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
1070}
1071
1072bool TestRunner::callShouldCloseOnWebView()
1073{
1074 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1075 return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
1076}
1077
1078void TestRunner::queueBackNavigation(unsigned howFarBackward)
1079{
1080 InjectedBundle::singleton().queueBackNavigation(howFarBackward);
1081}
1082
1083void TestRunner::queueForwardNavigation(unsigned howFarForward)
1084{
1085 InjectedBundle::singleton().queueForwardNavigation(howFarForward);
1086}
1087
1088void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs)
1089{
1090 auto& injectedBundle = InjectedBundle::singleton();
1091 WKRetainPtr<WKURLRef> baseURLWK = adoptWK(WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page())));
1092 WKRetainPtr<WKURLRef> urlWK = adoptWK(WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
1093 WKRetainPtr<WKStringRef> urlStringWK = adoptWK(WKURLCopyString(urlWK.get()));
1094
1095 injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs);
1096}
1097
1098void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
1099{
1100 WKRetainPtr<WKStringRef> contentWK = toWK(content);
1101 WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
1102 WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
1103
1104 InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
1105}
1106
1107void TestRunner::queueReload()
1108{
1109 InjectedBundle::singleton().queueReload();
1110}
1111
1112void TestRunner::queueLoadingScript(JSStringRef script)
1113{
1114 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1115 InjectedBundle::singleton().queueLoadingScript(scriptWK.get());
1116}
1117
1118void TestRunner::queueNonLoadingScript(JSStringRef script)
1119{
1120 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1121 InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get());
1122}
1123
1124void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value)
1125{
1126 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges"));
1127 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1128 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1129}
1130
1131void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
1132{
1133 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges"));
1134 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(handlesAuthenticationChallenges));
1135 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1136}
1137
1138void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value)
1139{
1140 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace"));
1141 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1142 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1143}
1144
1145void TestRunner::setShouldLogDownloadCallbacks(bool value)
1146{
1147 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldLogDownloadCallbacks"));
1148 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1149 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1150}
1151
1152void TestRunner::setAuthenticationUsername(JSStringRef username)
1153{
1154 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAuthenticationUsername"));
1155 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(username));
1156 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1157}
1158
1159void TestRunner::setAuthenticationPassword(JSStringRef password)
1160{
1161 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAuthenticationPassword"));
1162 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(password));
1163 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1164}
1165
1166bool TestRunner::secureEventInputIsEnabled() const
1167{
1168 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SecureEventInputIsEnabled"));
1169 WKTypeRef returnData = nullptr;
1170 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
1171 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1172 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1173}
1174
1175void TestRunner::setBlockAllPlugins(bool shouldBlock)
1176{
1177 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetBlockAllPlugins"));
1178 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(shouldBlock));
1179 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1180}
1181
1182void TestRunner::setPluginSupportedMode(JSStringRef mode)
1183{
1184 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetPluginSupportedMode"));
1185 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(mode));
1186 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1187}
1188
1189JSValueRef TestRunner::failNextNewCodeBlock()
1190{
1191 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1192 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1193 return JSC::failNextNewCodeBlock(context);
1194}
1195
1196JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction)
1197{
1198 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1199 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1200 return JSC::numberOfDFGCompiles(context, theFunction);
1201}
1202
1203JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction)
1204{
1205 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1206 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1207 return JSC::setNeverInline(context, theFunction);
1208}
1209
1210void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value)
1211{
1212 m_shouldDecideNavigationPolicyAfterDelay = value;
1213 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay"));
1214 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1215 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1216}
1217
1218void TestRunner::setShouldDecideResponsePolicyAfterDelay(bool value)
1219{
1220 m_shouldDecideResponsePolicyAfterDelay = value;
1221 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldDecideResponsePolicyAfterDelay"));
1222 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1223 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1224}
1225
1226void TestRunner::setNavigationGesturesEnabled(bool value)
1227{
1228 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled"));
1229 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1230 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1231}
1232
1233void TestRunner::setIgnoresViewportScaleLimits(bool value)
1234{
1235 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits"));
1236 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1237 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1238}
1239
1240void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value)
1241{
1242 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes"));
1243 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1244 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1245}
1246
1247void TestRunner::setShouldAllowDeviceOrientationAndMotionAccess(bool value)
1248{
1249 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetShouldAllowDeviceOrientationAndMotionAccess"));
1250 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1251 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1252}
1253
1254void TestRunner::terminateNetworkProcess()
1255{
1256 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("TerminateNetworkProcess"));
1257 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
1258}
1259
1260void TestRunner::terminateServiceWorkerProcess()
1261{
1262 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("TerminateServiceWorkerProcess"));
1263 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
1264}
1265
1266static unsigned nextUIScriptCallbackID()
1267{
1268 static unsigned callbackID = FirstUIScriptCallbackID;
1269 return callbackID++;
1270}
1271
1272void TestRunner::runUIScript(JSStringRef script, JSValueRef callback)
1273{
1274 unsigned callbackID = nextUIScriptCallbackID();
1275 cacheTestRunnerCallback(callbackID, callback);
1276
1277 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("RunUIProcessScript"));
1278
1279 WKRetainPtr<WKMutableDictionaryRef> testDictionary = adoptWK(WKMutableDictionaryCreate());
1280
1281 WKRetainPtr<WKStringRef> scriptKey = adoptWK(WKStringCreateWithUTF8CString("Script"));
1282 WKRetainPtr<WKStringRef> scriptValue = adoptWK(WKStringCreateWithJSString(script));
1283
1284 WKRetainPtr<WKStringRef> callbackIDKey = adoptWK(WKStringCreateWithUTF8CString("CallbackID"));
1285 WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID));
1286
1287 WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get());
1288 WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get());
1289
1290 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get());
1291}
1292
1293void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result)
1294{
1295 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1296 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1297
1298 JSValueRef resultValue = JSValueMakeString(context, result);
1299 callTestRunnerCallback(callbackID, 1, &resultValue);
1300}
1301
1302void TestRunner::setAllowedMenuActions(JSValueRef actions)
1303{
1304 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAllowedMenuActions"));
1305 WKRetainPtr<WKMutableArrayRef> messageBody = adoptWK(WKMutableArrayCreate());
1306
1307 auto page = InjectedBundle::singleton().page()->page();
1308 auto mainFrame = WKBundlePageGetMainFrame(page);
1309 auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
1310 auto lengthPropertyName = adopt(JSStringCreateWithUTF8CString("length"));
1311 auto actionsArray = JSValueToObject(context, actions, nullptr);
1312 auto lengthValue = JSObjectGetProperty(context, actionsArray, lengthPropertyName.get(), nullptr);
1313 if (!JSValueIsNumber(context, lengthValue))
1314 return;
1315
1316 auto length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
1317 for (size_t i = 0; i < length; ++i) {
1318 auto value = JSObjectGetPropertyAtIndex(context, actionsArray, i, 0);
1319 if (!JSValueIsString(context, value))
1320 continue;
1321
1322 auto actionName = adopt(JSValueToStringCopy(context, value, 0));
1323 WKRetainPtr<WKStringRef> action = adoptWK(WKStringCreateWithJSString(actionName.get()));
1324 WKArrayAppendItem(messageBody.get(), action.get());
1325 }
1326
1327 WKBundlePagePostMessage(page, messageName.get(), messageBody.get());
1328}
1329
1330void TestRunner::installCustomMenuAction(JSStringRef name, bool dismissesAutomatically, JSValueRef callback)
1331{
1332 cacheTestRunnerCallback(CustomMenuActionCallbackID, callback);
1333
1334 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("InstallCustomMenuAction"));
1335 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
1336
1337 WKRetainPtr<WKStringRef> nameKey = adoptWK(WKStringCreateWithUTF8CString("name"));
1338 WKRetainPtr<WKStringRef> nameValue = adoptWK(WKStringCreateWithJSString(name));
1339 WKDictionarySetItem(messageBody.get(), nameKey.get(), nameValue.get());
1340
1341 WKRetainPtr<WKStringRef> dismissesAutomaticallyKey = adoptWK(WKStringCreateWithUTF8CString("dismissesAutomatically"));
1342 WKRetainPtr<WKBooleanRef> dismissesAutomaticallyValue = adoptWK(WKBooleanCreate(dismissesAutomatically));
1343 WKDictionarySetItem(messageBody.get(), dismissesAutomaticallyKey.get(), dismissesAutomaticallyValue.get());
1344
1345 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1346}
1347
1348void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
1349{
1350 cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
1351}
1352
1353void TestRunner::installWillEndSwipeCallback(JSValueRef callback)
1354{
1355 cacheTestRunnerCallback(WillEndSwipeCallbackID, callback);
1356}
1357
1358void TestRunner::installDidEndSwipeCallback(JSValueRef callback)
1359{
1360 cacheTestRunnerCallback(DidEndSwipeCallbackID, callback);
1361}
1362
1363void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback)
1364{
1365 cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback);
1366}
1367
1368void TestRunner::callDidBeginSwipeCallback()
1369{
1370 callTestRunnerCallback(DidBeginSwipeCallbackID);
1371}
1372
1373void TestRunner::callWillEndSwipeCallback()
1374{
1375 callTestRunnerCallback(WillEndSwipeCallbackID);
1376}
1377
1378void TestRunner::callDidEndSwipeCallback()
1379{
1380 callTestRunnerCallback(DidEndSwipeCallbackID);
1381}
1382
1383void TestRunner::callDidRemoveSwipeSnapshotCallback()
1384{
1385 callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
1386}
1387
1388void TestRunner::setStatisticsDebugMode(bool value, JSValueRef completionHandler)
1389{
1390 cacheTestRunnerCallback(SetStatisticsDebugModeCallbackID, completionHandler);
1391
1392 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsDebugMode"));
1393 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1394 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1395
1396}
1397
1398void TestRunner::statisticsCallDidSetDebugModeCallback()
1399{
1400 callTestRunnerCallback(SetStatisticsDebugModeCallbackID);
1401}
1402
1403void TestRunner::setStatisticsPrevalentResourceForDebugMode(JSStringRef hostName, JSValueRef completionHandler)
1404{
1405 cacheTestRunnerCallback(SetStatisticsPrevalentResourceForDebugModeCallbackID, completionHandler);
1406
1407 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsPrevalentResourceForDebugMode"));
1408 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(hostName));
1409 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1410}
1411
1412void TestRunner::statisticsCallDidSetPrevalentResourceForDebugModeCallback()
1413{
1414 callTestRunnerCallback(SetStatisticsPrevalentResourceForDebugModeCallbackID);
1415}
1416
1417void TestRunner::setStatisticsLastSeen(JSStringRef hostName, double seconds, JSValueRef completionHandler)
1418{
1419 cacheTestRunnerCallback(SetStatisticsLastSeenCallbackID, completionHandler);
1420
1421 Vector<WKRetainPtr<WKStringRef>> keys;
1422 Vector<WKRetainPtr<WKTypeRef>> values;
1423
1424 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1425 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1426
1427 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
1428 values.append(adoptWK(WKDoubleCreate(seconds)));
1429
1430 Vector<WKStringRef> rawKeys(keys.size());
1431 Vector<WKTypeRef> rawValues(values.size());
1432
1433 for (size_t i = 0; i < keys.size(); ++i) {
1434 rawKeys[i] = keys[i].get();
1435 rawValues[i] = values[i].get();
1436 }
1437
1438 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsLastSeen"));
1439 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1440
1441 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1442}
1443
1444void TestRunner::statisticsCallDidSetLastSeenCallback()
1445{
1446 callTestRunnerCallback(SetStatisticsLastSeenCallbackID);
1447}
1448
1449void TestRunner::setStatisticsPrevalentResource(JSStringRef hostName, bool value, JSValueRef completionHandler)
1450{
1451 cacheTestRunnerCallback(SetStatisticsPrevalentResourceCallbackID, completionHandler);
1452
1453 Vector<WKRetainPtr<WKStringRef>> keys;
1454 Vector<WKRetainPtr<WKTypeRef>> values;
1455
1456 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1457 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1458
1459 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
1460 values.append(adoptWK(WKBooleanCreate(value)));
1461
1462 Vector<WKStringRef> rawKeys;
1463 Vector<WKTypeRef> rawValues;
1464 rawKeys.resize(keys.size());
1465 rawValues.resize(values.size());
1466
1467 for (size_t i = 0; i < keys.size(); ++i) {
1468 rawKeys[i] = keys[i].get();
1469 rawValues[i] = values[i].get();
1470 }
1471
1472 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsPrevalentResource"));
1473 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1474
1475 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1476}
1477
1478void TestRunner::statisticsCallDidSetPrevalentResourceCallback()
1479{
1480 callTestRunnerCallback(SetStatisticsPrevalentResourceCallbackID);
1481}
1482
1483void TestRunner::setStatisticsVeryPrevalentResource(JSStringRef hostName, bool value, JSValueRef completionHandler)
1484{
1485 cacheTestRunnerCallback(SetStatisticsVeryPrevalentResourceCallbackID, completionHandler);
1486
1487 Vector<WKRetainPtr<WKStringRef>> keys;
1488 Vector<WKRetainPtr<WKTypeRef>> values;
1489
1490 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1491 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1492
1493 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
1494 values.append(adoptWK(WKBooleanCreate(value)));
1495
1496 Vector<WKStringRef> rawKeys;
1497 Vector<WKTypeRef> rawValues;
1498 rawKeys.resize(keys.size());
1499 rawValues.resize(values.size());
1500
1501 for (size_t i = 0; i < keys.size(); ++i) {
1502 rawKeys[i] = keys[i].get();
1503 rawValues[i] = values[i].get();
1504 }
1505
1506 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsVeryPrevalentResource"));
1507 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1508
1509 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1510}
1511
1512void TestRunner::statisticsCallDidSetVeryPrevalentResourceCallback()
1513{
1514 callTestRunnerCallback(SetStatisticsVeryPrevalentResourceCallbackID);
1515}
1516
1517void TestRunner::dumpResourceLoadStatistics()
1518{
1519 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("dumpResourceLoadStatistics"));
1520 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
1521}
1522
1523bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName)
1524{
1525 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource"));
1526 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(hostName));
1527 WKTypeRef returnData = nullptr;
1528 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1529 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1530 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1531}
1532
1533bool TestRunner::isStatisticsVeryPrevalentResource(JSStringRef hostName)
1534{
1535 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsVeryPrevalentResource"));
1536 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(hostName));
1537 WKTypeRef returnData = nullptr;
1538 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1539 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1540 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1541}
1542
1543bool TestRunner::isStatisticsRegisteredAsSubresourceUnder(JSStringRef subresourceHost, JSStringRef topFrameHost)
1544{
1545 Vector<WKRetainPtr<WKStringRef>> keys;
1546 Vector<WKRetainPtr<WKTypeRef>> values;
1547
1548 keys.append(adoptWK(WKStringCreateWithUTF8CString("SubresourceHost")));
1549 values.append(adoptWK(WKStringCreateWithJSString(subresourceHost)));
1550
1551 keys.append(adoptWK(WKStringCreateWithUTF8CString("TopFrameHost")));
1552 values.append(adoptWK(WKStringCreateWithJSString(topFrameHost)));
1553
1554 Vector<WKStringRef> rawKeys(keys.size());
1555 Vector<WKTypeRef> rawValues(values.size());
1556
1557 for (size_t i = 0; i < keys.size(); ++i) {
1558 rawKeys[i] = keys[i].get();
1559 rawValues[i] = values[i].get();
1560 }
1561
1562 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubresourceUnder"));
1563 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1564 WKTypeRef returnData = nullptr;
1565 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1566 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1567 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1568}
1569
1570bool TestRunner::isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost)
1571{
1572 Vector<WKRetainPtr<WKStringRef>> keys;
1573 Vector<WKRetainPtr<WKTypeRef>> values;
1574
1575 keys.append(adoptWK(WKStringCreateWithUTF8CString("SubFrameHost")));
1576 values.append(adoptWK(WKStringCreateWithJSString(subFrameHost)));
1577
1578 keys.append(adoptWK(WKStringCreateWithUTF8CString("TopFrameHost")));
1579 values.append(adoptWK(WKStringCreateWithJSString(topFrameHost)));
1580
1581 Vector<WKStringRef> rawKeys(keys.size());
1582 Vector<WKTypeRef> rawValues(values.size());
1583
1584 for (size_t i = 0; i < keys.size(); ++i) {
1585 rawKeys[i] = keys[i].get();
1586 rawValues[i] = values[i].get();
1587 }
1588
1589 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubFrameUnder"));
1590 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1591 WKTypeRef returnData = nullptr;
1592 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1593 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1594 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1595}
1596
1597bool TestRunner::isStatisticsRegisteredAsRedirectingTo(JSStringRef hostRedirectedFrom, JSStringRef hostRedirectedTo)
1598{
1599 Vector<WKRetainPtr<WKStringRef>> keys;
1600 Vector<WKRetainPtr<WKTypeRef>> values;
1601
1602 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostRedirectedFrom")));
1603 values.append(adoptWK(WKStringCreateWithJSString(hostRedirectedFrom)));
1604
1605 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostRedirectedTo")));
1606 values.append(adoptWK(WKStringCreateWithJSString(hostRedirectedTo)));
1607
1608 Vector<WKStringRef> rawKeys(keys.size());
1609 Vector<WKTypeRef> rawValues(values.size());
1610
1611 for (size_t i = 0; i < keys.size(); ++i) {
1612 rawKeys[i] = keys[i].get();
1613 rawValues[i] = values[i].get();
1614 }
1615
1616 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsRedirectingTo"));
1617 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1618 WKTypeRef returnData = nullptr;
1619 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1620 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1621 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1622}
1623
1624void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value, JSValueRef completionHandler)
1625{
1626 cacheTestRunnerCallback(SetStatisticsHasHadUserInteractionCallbackID, completionHandler);
1627
1628 Vector<WKRetainPtr<WKStringRef>> keys;
1629 Vector<WKRetainPtr<WKTypeRef>> values;
1630
1631 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1632 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1633
1634 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
1635 values.append(adoptWK(WKBooleanCreate(value)));
1636
1637 Vector<WKStringRef> rawKeys;
1638 Vector<WKTypeRef> rawValues;
1639 rawKeys.resize(keys.size());
1640 rawValues.resize(values.size());
1641
1642 for (size_t i = 0; i < keys.size(); ++i) {
1643 rawKeys[i] = keys[i].get();
1644 rawValues[i] = values[i].get();
1645 }
1646
1647 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction"));
1648 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1649
1650 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1651}
1652
1653void TestRunner::statisticsCallDidSetHasHadUserInteractionCallback()
1654{
1655 callTestRunnerCallback(SetStatisticsHasHadUserInteractionCallbackID);
1656}
1657
1658bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName)
1659{
1660 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction"));
1661 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(hostName));
1662 WKTypeRef returnData = nullptr;
1663 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1664 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1665 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1666}
1667
1668void TestRunner::setStatisticsGrandfathered(JSStringRef hostName, bool value)
1669{
1670 Vector<WKRetainPtr<WKStringRef>> keys;
1671 Vector<WKRetainPtr<WKTypeRef>> values;
1672
1673 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1674 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1675
1676 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
1677 values.append(adoptWK(WKBooleanCreate(value)));
1678
1679 Vector<WKStringRef> rawKeys;
1680 Vector<WKTypeRef> rawValues;
1681 rawKeys.resize(keys.size());
1682 rawValues.resize(values.size());
1683
1684 for (size_t i = 0; i < keys.size(); ++i) {
1685 rawKeys[i] = keys[i].get();
1686 rawValues[i] = values[i].get();
1687 }
1688
1689 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsGrandfathered"));
1690 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1691
1692 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1693}
1694
1695bool TestRunner::isStatisticsGrandfathered(JSStringRef hostName)
1696{
1697 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsGrandfathered"));
1698 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(hostName));
1699 WKTypeRef returnData = nullptr;
1700 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1701 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
1702 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
1703}
1704
1705void TestRunner::setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1706{
1707 Vector<WKRetainPtr<WKStringRef>> keys;
1708 Vector<WKRetainPtr<WKTypeRef>> values;
1709
1710 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1711 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1712
1713 keys.append(adoptWK(WKStringCreateWithUTF8CString("TopFrameHostName")));
1714 values.append(adoptWK(WKStringCreateWithJSString(topFrameHostName)));
1715
1716 Vector<WKStringRef> rawKeys(keys.size());
1717 Vector<WKTypeRef> rawValues(values.size());
1718
1719 for (size_t i = 0; i < keys.size(); ++i) {
1720 rawKeys[i] = keys[i].get();
1721 rawValues[i] = values[i].get();
1722 }
1723
1724 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsSubframeUnderTopFrameOrigin"));
1725 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1726 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1727}
1728
1729void TestRunner::setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1730{
1731 Vector<WKRetainPtr<WKStringRef>> keys;
1732 Vector<WKRetainPtr<WKTypeRef>> values;
1733
1734 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1735 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1736
1737 keys.append(adoptWK(WKStringCreateWithUTF8CString("TopFrameHostName")));
1738 values.append(adoptWK(WKStringCreateWithJSString(topFrameHostName)));
1739
1740 Vector<WKStringRef> rawKeys(keys.size());
1741 Vector<WKTypeRef> rawValues(values.size());
1742
1743 for (size_t i = 0; i < keys.size(); ++i) {
1744 rawKeys[i] = keys[i].get();
1745 rawValues[i] = values[i].get();
1746 }
1747
1748 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsSubresourceUnderTopFrameOrigin"));
1749 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1750 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1751}
1752
1753void TestRunner::setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1754{
1755 Vector<WKRetainPtr<WKStringRef>> keys;
1756 Vector<WKRetainPtr<WKTypeRef>> values;
1757
1758 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1759 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1760
1761 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostNameRedirectedTo")));
1762 values.append(adoptWK(WKStringCreateWithJSString(hostNameRedirectedTo)));
1763
1764 Vector<WKStringRef> rawKeys(keys.size());
1765 Vector<WKTypeRef> rawValues(values.size());
1766
1767 for (size_t i = 0; i < keys.size(); ++i) {
1768 rawKeys[i] = keys[i].get();
1769 rawValues[i] = values[i].get();
1770 }
1771
1772 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectTo"));
1773 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1774 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1775}
1776
1777
1778void TestRunner::setStatisticsSubresourceUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom)
1779{
1780 Vector<WKRetainPtr<WKStringRef>> keys;
1781 Vector<WKRetainPtr<WKTypeRef>> values;
1782
1783 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1784 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1785
1786 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostNameRedirectedFrom")));
1787 values.append(adoptWK(WKStringCreateWithJSString(hostNameRedirectedFrom)));
1788
1789 Vector<WKStringRef> rawKeys(keys.size());
1790 Vector<WKTypeRef> rawValues(values.size());
1791
1792 for (size_t i = 0; i < keys.size(); ++i) {
1793 rawKeys[i] = keys[i].get();
1794 rawValues[i] = values[i].get();
1795 }
1796
1797 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectFrom"));
1798 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1799 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1800}
1801
1802void TestRunner::setStatisticsTopFrameUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1803{
1804 Vector<WKRetainPtr<WKStringRef>> keys;
1805 Vector<WKRetainPtr<WKTypeRef>> values;
1806
1807 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1808 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1809
1810 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostNameRedirectedTo")));
1811 values.append(adoptWK(WKStringCreateWithJSString(hostNameRedirectedTo)));
1812
1813 Vector<WKStringRef> rawKeys(keys.size());
1814 Vector<WKTypeRef> rawValues(values.size());
1815
1816 for (size_t i = 0; i < keys.size(); ++i) {
1817 rawKeys[i] = keys[i].get();
1818 rawValues[i] = values[i].get();
1819 }
1820
1821 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsTopFrameUniqueRedirectTo"));
1822 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1823 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1824}
1825
1826void TestRunner::setStatisticsTopFrameUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom)
1827{
1828 Vector<WKRetainPtr<WKStringRef>> keys;
1829 Vector<WKRetainPtr<WKTypeRef>> values;
1830
1831 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
1832 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
1833
1834 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostNameRedirectedFrom")));
1835 values.append(adoptWK(WKStringCreateWithJSString(hostNameRedirectedFrom)));
1836
1837 Vector<WKStringRef> rawKeys(keys.size());
1838 Vector<WKTypeRef> rawValues(values.size());
1839
1840 for (size_t i = 0; i < keys.size(); ++i) {
1841 rawKeys[i] = keys[i].get();
1842 rawValues[i] = values[i].get();
1843 }
1844
1845 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsTopFrameUniqueRedirectFrom"));
1846 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1847 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1848}
1849
1850void TestRunner::setStatisticsCrossSiteLoadWithLinkDecoration(JSStringRef fromHost, JSStringRef toHost)
1851{
1852 Vector<WKRetainPtr<WKStringRef>> keys;
1853 Vector<WKRetainPtr<WKTypeRef>> values;
1854
1855 keys.append(adoptWK(WKStringCreateWithUTF8CString("FromHost")));
1856 values.append(adoptWK(WKStringCreateWithJSString(fromHost)));
1857
1858 keys.append(adoptWK(WKStringCreateWithUTF8CString("ToHost")));
1859 values.append(adoptWK(WKStringCreateWithJSString(toHost)));
1860
1861 Vector<WKStringRef> rawKeys(keys.size());
1862 Vector<WKTypeRef> rawValues(values.size());
1863
1864 for (size_t i = 0; i < keys.size(); ++i) {
1865 rawKeys[i] = keys[i].get();
1866 rawValues[i] = values[i].get();
1867 }
1868
1869 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsCrossSiteLoadWithLinkDecoration"));
1870 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1871 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1872}
1873
1874void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
1875{
1876 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));
1877 WKRetainPtr<WKDoubleRef> messageBody = adoptWK(WKDoubleCreate(seconds));
1878 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1879}
1880
1881void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback)
1882{
1883 cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback);
1884}
1885
1886void TestRunner::statisticsDidModifyDataRecordsCallback()
1887{
1888 callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID);
1889}
1890
1891void TestRunner::installStatisticsDidScanDataRecordsCallback(JSValueRef callback)
1892{
1893 cacheTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID, callback);
1894
1895 bool notifyPagesWhenDataRecordsWereScanned = !!callback;
1896
1897 // Setting a callback implies we expect to receive callbacks. So register for them.
1898 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1899 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(notifyPagesWhenDataRecordsWereScanned));
1900 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1901}
1902
1903void TestRunner::statisticsDidScanDataRecordsCallback()
1904{
1905 callTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID);
1906}
1907
1908void TestRunner::installStatisticsDidRunTelemetryCallback(JSValueRef callback)
1909{
1910 cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
1911}
1912
1913void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
1914{
1915 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1916 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1917
1918 StringBuilder stringBuilder;
1919 stringBuilder.appendLiteral("{ \"totalPrevalentResources\" : ");
1920 stringBuilder.appendNumber(totalPrevalentResources);
1921 stringBuilder.appendLiteral(", \"totalPrevalentResourcesWithUserInteraction\" : ");
1922 stringBuilder.appendNumber(totalPrevalentResourcesWithUserInteraction);
1923 stringBuilder.appendLiteral(", \"top3SubframeUnderTopFrameOrigins\" : ");
1924 stringBuilder.appendNumber(top3SubframeUnderTopFrameOrigins);
1925 stringBuilder.appendLiteral(" }");
1926
1927 JSValueRef result = JSValueMakeFromJSONString(context, adopt(JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data())).get());
1928
1929 callTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, 1, &result);
1930}
1931
1932void TestRunner::statisticsNotifyObserver()
1933{
1934 InjectedBundle::singleton().statisticsNotifyObserver();
1935}
1936
1937void TestRunner::statisticsProcessStatisticsAndDataRecords()
1938{
1939 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsProcessStatisticsAndDataRecords"));
1940 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1941}
1942
1943void TestRunner::statisticsUpdateCookieBlocking(JSValueRef completionHandler)
1944{
1945 cacheTestRunnerCallback(StatisticsDidSetBlockCookiesForHostCallbackID, completionHandler);
1946
1947 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsUpdateCookieBlocking"));
1948 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1949}
1950
1951void TestRunner::statisticsCallDidSetBlockCookiesForHostCallback()
1952{
1953 callTestRunnerCallback(StatisticsDidSetBlockCookiesForHostCallbackID);
1954}
1955
1956void TestRunner::statisticsSubmitTelemetry()
1957{
1958 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsSubmitTelemetry"));
1959 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1960}
1961
1962void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value)
1963{
1964 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1965 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1966 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1967}
1968
1969void TestRunner::setStatisticsIsRunningTest(bool value)
1970{
1971 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsSetIsRunningTest"));
1972 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1973 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1974}
1975
1976void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
1977{
1978 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval"));
1979 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1980 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1981}
1982
1983void TestRunner::setStatisticsNotifyPagesWhenTelemetryWasCaptured(bool value)
1984{
1985 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenTelemetryWasCaptured"));
1986 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
1987 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1988}
1989
1990void TestRunner::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
1991{
1992 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweenDataRecordsRemoval"));
1993 WKRetainPtr<WKDoubleRef> messageBody = adoptWK(WKDoubleCreate(seconds));
1994 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1995}
1996
1997void TestRunner::setStatisticsGrandfatheringTime(double seconds)
1998{
1999 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsGrandfatheringTime"));
2000 WKRetainPtr<WKDoubleRef> messageBody = adoptWK(WKDoubleCreate(seconds));
2001 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2002}
2003
2004void TestRunner::setStatisticsMaxStatisticsEntries(unsigned entries)
2005{
2006 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMaxStatisticsEntries"));
2007 WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(entries));
2008 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2009}
2010
2011void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
2012{
2013 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetPruneEntriesDownTo"));
2014 WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(entries));
2015 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2016}
2017
2018void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
2019{
2020 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
2021
2022 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
2023 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2024}
2025
2026void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback)
2027{
2028 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
2029
2030 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
2031 WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(hours));
2032 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2033}
2034
2035void TestRunner::statisticsClearThroughWebsiteDataRemoval(JSValueRef callback)
2036{
2037 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
2038
2039 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsClearThroughWebsiteDataRemoval"));
2040 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2041}
2042
2043void TestRunner::statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies)
2044{
2045 Vector<WKRetainPtr<WKStringRef>> keys;
2046 Vector<WKRetainPtr<WKTypeRef>> values;
2047
2048 keys.append(adoptWK(WKStringCreateWithUTF8CString("HostName")));
2049 values.append(adoptWK(WKStringCreateWithJSString(hostName)));
2050
2051 keys.append(adoptWK(WKStringCreateWithUTF8CString("IncludeHttpOnlyCookies")));
2052 values.append(adoptWK(WKBooleanCreate(includeHttpOnlyCookies)));
2053
2054 Vector<WKStringRef> rawKeys;
2055 Vector<WKTypeRef> rawValues;
2056 rawKeys.resize(keys.size());
2057 rawValues.resize(values.size());
2058
2059 for (size_t i = 0; i < keys.size(); ++i) {
2060 rawKeys[i] = keys[i].get();
2061 rawValues[i] = values[i].get();
2062 }
2063
2064 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsDeleteCookiesForHost"));
2065 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2066 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2067}
2068
2069bool TestRunner::isStatisticsHasLocalStorage(JSStringRef hostName)
2070{
2071 auto messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsHasLocalStorage"));
2072 auto messageBody = adoptWK(WKStringCreateWithJSString(hostName));
2073 WKTypeRef returnData = nullptr;
2074 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
2075 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
2076 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
2077}
2078
2079void TestRunner::setStatisticsCacheMaxAgeCap(double seconds)
2080{
2081 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsCacheMaxAgeCap"));
2082 WKRetainPtr<WKDoubleRef> messageBody = adoptWK(WKDoubleCreate(seconds));
2083 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2084}
2085
2086void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
2087{
2088 callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
2089}
2090
2091void TestRunner::statisticsResetToConsistentState(JSValueRef completionHandler)
2092{
2093 cacheTestRunnerCallback(StatisticsDidResetToConsistentStateCallbackID, completionHandler);
2094
2095 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsResetToConsistentState"));
2096 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2097}
2098
2099void TestRunner::statisticsCallDidResetToConsistentStateCallback()
2100{
2101 callTestRunnerCallback(StatisticsDidResetToConsistentStateCallbackID);
2102}
2103
2104void TestRunner::installTextDidChangeInTextFieldCallback(JSValueRef callback)
2105{
2106 cacheTestRunnerCallback(TextDidChangeInTextFieldCallbackID, callback);
2107}
2108
2109void TestRunner::textDidChangeInTextFieldCallback()
2110{
2111 callTestRunnerCallback(TextDidChangeInTextFieldCallbackID);
2112}
2113
2114void TestRunner::installTextFieldDidBeginEditingCallback(JSValueRef callback)
2115{
2116 cacheTestRunnerCallback(TextFieldDidBeginEditingCallbackID, callback);
2117}
2118
2119void TestRunner::textFieldDidBeginEditingCallback()
2120{
2121 callTestRunnerCallback(TextFieldDidBeginEditingCallbackID);
2122}
2123
2124void TestRunner::installTextFieldDidEndEditingCallback(JSValueRef callback)
2125{
2126 cacheTestRunnerCallback(TextFieldDidEndEditingCallbackID, callback);
2127}
2128
2129void TestRunner::textFieldDidEndEditingCallback()
2130{
2131 callTestRunnerCallback(TextFieldDidEndEditingCallbackID);
2132}
2133
2134void TestRunner::setStorageAccessAPIEnabled(bool enabled)
2135{
2136 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
2137
2138 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(enabled));
2139
2140 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2141}
2142
2143void TestRunner::getAllStorageAccessEntries(JSValueRef callback)
2144{
2145 cacheTestRunnerCallback(AllStorageAccessEntriesCallbackID, callback);
2146
2147 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("GetAllStorageAccessEntries"));
2148 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2149}
2150
2151void TestRunner::callDidReceiveAllStorageAccessEntriesCallback(Vector<String>& domains)
2152{
2153 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
2154 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2155
2156 StringBuilder stringBuilder;
2157 stringBuilder.appendLiteral("[");
2158 bool firstDomain = true;
2159 for (auto& domain : domains) {
2160 if (firstDomain)
2161 firstDomain = false;
2162 else
2163 stringBuilder.appendLiteral(", ");
2164 stringBuilder.appendLiteral("\"");
2165 stringBuilder.append(domain);
2166 stringBuilder.appendLiteral("\"");
2167 }
2168 stringBuilder.appendLiteral("]");
2169
2170 JSValueRef result = JSValueMakeFromJSONString(context, adopt(JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data())).get());
2171
2172 callTestRunnerCallback(AllStorageAccessEntriesCallbackID, 1, &result);
2173}
2174
2175void TestRunner::addMockMediaDevice(JSStringRef persistentId, JSStringRef label, const char* type)
2176{
2177 Vector<WKRetainPtr<WKStringRef>> keys;
2178 Vector<WKRetainPtr<WKTypeRef>> values;
2179
2180 keys.append(adoptWK(WKStringCreateWithUTF8CString("PersistentID")));
2181 values.append(toWK(persistentId));
2182
2183 keys.append(adoptWK(WKStringCreateWithUTF8CString("Label")));
2184 values.append(toWK(label));
2185
2186 keys.append(adoptWK(WKStringCreateWithUTF8CString("Type")));
2187 values.append(adoptWK(WKStringCreateWithUTF8CString(type)));
2188
2189 Vector<WKStringRef> rawKeys;
2190 Vector<WKTypeRef> rawValues;
2191 rawKeys.resize(keys.size());
2192 rawValues.resize(values.size());
2193
2194 for (size_t i = 0; i < keys.size(); ++i) {
2195 rawKeys[i] = keys[i].get();
2196 rawValues[i] = values[i].get();
2197 }
2198
2199 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("AddMockMediaDevice"));
2200 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2201
2202 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2203}
2204
2205void TestRunner::addMockCameraDevice(JSStringRef persistentId, JSStringRef label)
2206{
2207 addMockMediaDevice(persistentId, label, "camera");
2208}
2209
2210void TestRunner::addMockMicrophoneDevice(JSStringRef persistentId, JSStringRef label)
2211{
2212 addMockMediaDevice(persistentId, label, "microphone");
2213}
2214
2215void TestRunner::addMockScreenDevice(JSStringRef persistentId, JSStringRef label)
2216{
2217 addMockMediaDevice(persistentId, label, "screen");
2218}
2219
2220void TestRunner::clearMockMediaDevices()
2221{
2222 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ClearMockMediaDevices"));
2223 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2224}
2225
2226void TestRunner::removeMockMediaDevice(JSStringRef persistentId)
2227{
2228 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("RemoveMockMediaDevice"));
2229 WKRetainPtr<WKTypeRef> messageBody(toWK(persistentId));
2230
2231 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2232}
2233
2234void TestRunner::resetMockMediaDevices()
2235{
2236 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ResetMockMediaDevices"));
2237 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2238}
2239
2240#if PLATFORM(MAC)
2241void TestRunner::connectMockGamepad(unsigned index)
2242{
2243 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ConnectMockGamepad"));
2244 WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(index));
2245
2246 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2247}
2248
2249void TestRunner::disconnectMockGamepad(unsigned index)
2250{
2251 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("DisconnectMockGamepad"));
2252 WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(index));
2253
2254 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2255}
2256
2257void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount)
2258{
2259 Vector<WKRetainPtr<WKStringRef>> keys;
2260 Vector<WKRetainPtr<WKTypeRef>> values;
2261
2262 keys.append(adoptWK(WKStringCreateWithUTF8CString("GamepadID")));
2263 values.append(toWK(gamepadID));
2264
2265 keys.append(adoptWK(WKStringCreateWithUTF8CString("GamepadIndex")));
2266 values.append(adoptWK(WKUInt64Create(index)));
2267
2268 keys.append(adoptWK(WKStringCreateWithUTF8CString("AxisCount")));
2269 values.append(adoptWK(WKUInt64Create(axisCount)));
2270
2271 keys.append(adoptWK(WKStringCreateWithUTF8CString("ButtonCount")));
2272 values.append(adoptWK(WKUInt64Create(buttonCount)));
2273
2274 Vector<WKStringRef> rawKeys;
2275 Vector<WKTypeRef> rawValues;
2276 rawKeys.resize(keys.size());
2277 rawValues.resize(values.size());
2278
2279 for (size_t i = 0; i < keys.size(); ++i) {
2280 rawKeys[i] = keys[i].get();
2281 rawValues[i] = values[i].get();
2282 }
2283
2284 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMockGamepadDetails"));
2285 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2286
2287 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2288}
2289
2290void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value)
2291{
2292 Vector<WKRetainPtr<WKStringRef>> keys;
2293 Vector<WKRetainPtr<WKTypeRef>> values;
2294
2295 keys.append(adoptWK(WKStringCreateWithUTF8CString("GamepadIndex")));
2296 values.append(adoptWK(WKUInt64Create(index)));
2297
2298 keys.append(adoptWK(WKStringCreateWithUTF8CString("AxisIndex")));
2299 values.append(adoptWK(WKUInt64Create(axisIndex)));
2300
2301 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
2302 values.append(adoptWK(WKDoubleCreate(value)));
2303
2304 Vector<WKStringRef> rawKeys;
2305 Vector<WKTypeRef> rawValues;
2306 rawKeys.resize(keys.size());
2307 rawValues.resize(values.size());
2308
2309 for (size_t i = 0; i < keys.size(); ++i) {
2310 rawKeys[i] = keys[i].get();
2311 rawValues[i] = values[i].get();
2312 }
2313
2314 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMockGamepadAxisValue"));
2315 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2316
2317 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2318}
2319
2320void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value)
2321{
2322 Vector<WKRetainPtr<WKStringRef>> keys;
2323 Vector<WKRetainPtr<WKTypeRef>> values;
2324
2325 keys.append(adoptWK(WKStringCreateWithUTF8CString("GamepadIndex")));
2326 values.append(adoptWK(WKUInt64Create(index)));
2327
2328 keys.append(adoptWK(WKStringCreateWithUTF8CString("ButtonIndex")));
2329 values.append(adoptWK(WKUInt64Create(buttonIndex)));
2330
2331 keys.append(adoptWK(WKStringCreateWithUTF8CString("Value")));
2332 values.append(adoptWK(WKDoubleCreate(value)));
2333
2334 Vector<WKStringRef> rawKeys;
2335 Vector<WKTypeRef> rawValues;
2336 rawKeys.resize(keys.size());
2337 rawValues.resize(values.size());
2338
2339 for (size_t i = 0; i < keys.size(); ++i) {
2340 rawKeys[i] = keys[i].get();
2341 rawValues[i] = values[i].get();
2342 }
2343
2344 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMockGamepadButtonValue"));
2345 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2346
2347 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2348}
2349#else
2350void TestRunner::connectMockGamepad(unsigned)
2351{
2352}
2353
2354void TestRunner::disconnectMockGamepad(unsigned)
2355{
2356}
2357
2358void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned)
2359{
2360}
2361
2362void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double)
2363{
2364}
2365
2366void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double)
2367{
2368}
2369#endif // PLATFORM(MAC)
2370
2371void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
2372{
2373 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
2374 JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
2375
2376 if (!JSValueIsArray(context, filesValue))
2377 return;
2378
2379 JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
2380 static auto lengthProperty = adopt(JSStringCreateWithUTF8CString("length"));
2381 JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
2382 if (!JSValueIsNumber(context, filesLengthValue))
2383 return;
2384
2385 auto fileURLs = adoptWK(WKMutableArrayCreate());
2386 auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
2387 for (size_t i = 0; i < filesLength; ++i) {
2388 JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
2389 if (!JSValueIsString(context, fileValue))
2390 continue;
2391
2392 auto file = adopt(JSValueToStringCopy(context, fileValue, nullptr));
2393 size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
2394 auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
2395 JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
2396
2397 WKArrayAppendItem(fileURLs.get(), adoptWK(WKURLCreateWithBaseURL(m_testURL.get(), fileBuffer.get())).get());
2398 }
2399
2400 static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLs"));
2401 WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
2402}
2403
2404#if PLATFORM(IOS_FAMILY)
2405void TestRunner::setOpenPanelFilesMediaIcon(JSValueRef data)
2406{
2407 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
2408 JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
2409
2410 auto& injectedBundle = InjectedBundle::singleton();
2411 // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
2412 WKRetainPtr<WKDataRef> iconData = adoptWK(WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data));
2413
2414 static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLsMediaIcon"));
2415 WKBundlePagePostMessage(page, messageName.get(), iconData.get());
2416}
2417#else
2418void TestRunner::setOpenPanelFilesMediaIcon(JSValueRef)
2419{
2420}
2421#endif // PLATFORM(IOS_FAMILY)
2422
2423void TestRunner::removeAllSessionCredentials(JSValueRef callback)
2424{
2425 cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
2426
2427 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("RemoveAllSessionCredentials"));
2428 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(true));
2429
2430 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2431}
2432
2433void TestRunner::callDidRemoveAllSessionCredentialsCallback()
2434{
2435 callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
2436}
2437
2438void TestRunner::clearDOMCache(JSStringRef origin)
2439{
2440 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ClearDOMCache"));
2441 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(origin));
2442 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2443}
2444
2445void TestRunner::clearDOMCaches()
2446{
2447 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ClearDOMCaches"));
2448 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2449}
2450
2451bool TestRunner::hasDOMCache(JSStringRef origin)
2452{
2453 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("HasDOMCache"));
2454 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(origin));
2455 WKTypeRef returnData = nullptr;
2456 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
2457 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
2458 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
2459}
2460
2461uint64_t TestRunner::domCacheSize(JSStringRef origin)
2462{
2463 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("DOMCacheSize"));
2464 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(origin));
2465 WKTypeRef returnData = nullptr;
2466 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
2467 return WKUInt64GetValue(static_cast<WKUInt64Ref>(returnData));
2468}
2469
2470void TestRunner::setAllowStorageQuotaIncrease(bool willIncrease)
2471{
2472 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAllowStorageQuotaIncrease"));
2473 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(willIncrease));
2474 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2475}
2476
2477void TestRunner::getApplicationManifestThen(JSValueRef callback)
2478{
2479 cacheTestRunnerCallback(GetApplicationManifestCallbackID, callback);
2480
2481 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("GetApplicationManifest"));
2482 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2483}
2484
2485void TestRunner::didGetApplicationManifest()
2486{
2487 callTestRunnerCallback(GetApplicationManifestCallbackID);
2488}
2489
2490void TestRunner::performCustomMenuAction()
2491{
2492 callTestRunnerCallback(CustomMenuActionCallbackID);
2493}
2494
2495size_t TestRunner::userScriptInjectedCount() const
2496{
2497 return InjectedBundle::singleton().userScriptInjectedCount();
2498}
2499
2500void TestRunner::injectUserScript(JSStringRef script)
2501{
2502 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("InjectUserScript"));
2503 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(script));
2504 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), nullptr);
2505}
2506
2507void TestRunner::sendDisplayConfigurationChangedMessageForTesting()
2508{
2509 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SendDisplayConfigurationChangedMessageForTesting"));
2510 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2511}
2512
2513// WebAuthN
2514void TestRunner::setWebAuthenticationMockConfiguration(JSValueRef configurationValue)
2515{
2516 auto& injectedBundle = InjectedBundle::singleton();
2517 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
2518 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2519 if (!JSValueIsObject(context, configurationValue))
2520 return;
2521 JSObjectRef configuration = JSValueToObject(context, configurationValue, 0);
2522
2523 Vector<WKRetainPtr<WKStringRef>> configurationKeys;
2524 Vector<WKRetainPtr<WKTypeRef>> configurationValues;
2525
2526 JSRetainPtr<JSStringRef> silentFailurePropertyName(Adopt, JSStringCreateWithUTF8CString("silentFailure"));
2527 JSValueRef silentFailureValue = JSObjectGetProperty(context, configuration, silentFailurePropertyName.get(), 0);
2528 if (!JSValueIsUndefined(context, silentFailureValue)) {
2529 if (!JSValueIsBoolean(context, silentFailureValue))
2530 return;
2531 bool silentFailure = JSValueToBoolean(context, silentFailureValue);
2532 configurationKeys.append(adoptWK(WKStringCreateWithUTF8CString("SilentFailure")));
2533 configurationValues.append(adoptWK(WKBooleanCreate(silentFailure)).get());
2534 }
2535
2536 JSRetainPtr<JSStringRef> localPropertyName(Adopt, JSStringCreateWithUTF8CString("local"));
2537 JSValueRef localValue = JSObjectGetProperty(context, configuration, localPropertyName.get(), 0);
2538 if (!JSValueIsUndefined(context, localValue) && !JSValueIsNull(context, localValue)) {
2539 if (!JSValueIsObject(context, localValue))
2540 return;
2541 JSObjectRef local = JSValueToObject(context, localValue, 0);
2542
2543 JSRetainPtr<JSStringRef> acceptAuthenticationPropertyName(Adopt, JSStringCreateWithUTF8CString("acceptAuthentication"));
2544 JSValueRef acceptAuthenticationValue = JSObjectGetProperty(context, local, acceptAuthenticationPropertyName.get(), 0);
2545 if (!JSValueIsBoolean(context, acceptAuthenticationValue))
2546 return;
2547 bool acceptAuthentication = JSValueToBoolean(context, acceptAuthenticationValue);
2548
2549 JSRetainPtr<JSStringRef> acceptAttestationPropertyName(Adopt, JSStringCreateWithUTF8CString("acceptAttestation"));
2550 JSValueRef acceptAttestationValue = JSObjectGetProperty(context, local, acceptAttestationPropertyName.get(), 0);
2551 if (!JSValueIsBoolean(context, acceptAttestationValue))
2552 return;
2553 bool acceptAttestation = JSValueToBoolean(context, acceptAttestationValue);
2554
2555 Vector<WKRetainPtr<WKStringRef>> localKeys;
2556 Vector<WKRetainPtr<WKTypeRef>> localValues;
2557 localKeys.append(adoptWK(WKStringCreateWithUTF8CString("AcceptAuthentication")));
2558 localValues.append(adoptWK(WKBooleanCreate(acceptAuthentication)).get());
2559 localKeys.append(adoptWK(WKStringCreateWithUTF8CString("AcceptAttestation")));
2560 localValues.append(adoptWK(WKBooleanCreate(acceptAttestation)).get());
2561
2562 if (acceptAttestation) {
2563 JSRetainPtr<JSStringRef> privateKeyBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("privateKeyBase64"));
2564 JSValueRef privateKeyBase64Value = JSObjectGetProperty(context, local, privateKeyBase64PropertyName.get(), 0);
2565 if (!JSValueIsString(context, privateKeyBase64Value))
2566 return;
2567
2568 JSRetainPtr<JSStringRef> userCertificateBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("userCertificateBase64"));
2569 JSValueRef userCertificateBase64Value = JSObjectGetProperty(context, local, userCertificateBase64PropertyName.get(), 0);
2570 if (!JSValueIsString(context, userCertificateBase64Value))
2571 return;
2572
2573 JSRetainPtr<JSStringRef> intermediateCACertificateBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("intermediateCACertificateBase64"));
2574 JSValueRef intermediateCACertificateBase64Value = JSObjectGetProperty(context, local, intermediateCACertificateBase64PropertyName.get(), 0);
2575 if (!JSValueIsString(context, intermediateCACertificateBase64Value))
2576 return;
2577
2578 localKeys.append(adoptWK(WKStringCreateWithUTF8CString("PrivateKeyBase64")));
2579 localValues.append(toWK(adopt(JSValueToStringCopy(context, privateKeyBase64Value, 0)).get()));
2580 localKeys.append(adoptWK(WKStringCreateWithUTF8CString("UserCertificateBase64")));
2581 localValues.append(toWK(adopt(JSValueToStringCopy(context, userCertificateBase64Value, 0)).get()));
2582 localKeys.append(adoptWK(WKStringCreateWithUTF8CString("IntermediateCACertificateBase64")));
2583 localValues.append(toWK(adopt(JSValueToStringCopy(context, intermediateCACertificateBase64Value, 0)).get()));
2584 }
2585
2586 Vector<WKStringRef> rawLocalKeys;
2587 Vector<WKTypeRef> rawLocalValues;
2588 rawLocalKeys.resize(localKeys.size());
2589 rawLocalValues.resize(localValues.size());
2590 for (size_t i = 0; i < localKeys.size(); ++i) {
2591 rawLocalKeys[i] = localKeys[i].get();
2592 rawLocalValues[i] = localValues[i].get();
2593 }
2594
2595 configurationKeys.append(adoptWK(WKStringCreateWithUTF8CString("Local")));
2596 configurationValues.append(adoptWK(WKDictionaryCreate(rawLocalKeys.data(), rawLocalValues.data(), rawLocalKeys.size())));
2597 }
2598
2599 JSRetainPtr<JSStringRef> hidPropertyName(Adopt, JSStringCreateWithUTF8CString("hid"));
2600 JSValueRef hidValue = JSObjectGetProperty(context, configuration, hidPropertyName.get(), 0);
2601 if (!JSValueIsUndefined(context, hidValue) && !JSValueIsNull(context, hidValue)) {
2602 if (!JSValueIsObject(context, hidValue))
2603 return;
2604 JSObjectRef hid = JSValueToObject(context, hidValue, 0);
2605
2606 JSRetainPtr<JSStringRef> stagePropertyName(Adopt, JSStringCreateWithUTF8CString("stage"));
2607 JSValueRef stageValue = JSObjectGetProperty(context, hid, stagePropertyName.get(), 0);
2608 if (!JSValueIsString(context, stageValue))
2609 return;
2610
2611 JSRetainPtr<JSStringRef> subStagePropertyName(Adopt, JSStringCreateWithUTF8CString("subStage"));
2612 JSValueRef subStageValue = JSObjectGetProperty(context, hid, subStagePropertyName.get(), 0);
2613 if (!JSValueIsString(context, subStageValue))
2614 return;
2615
2616 JSRetainPtr<JSStringRef> errorPropertyName(Adopt, JSStringCreateWithUTF8CString("error"));
2617 JSValueRef errorValue = JSObjectGetProperty(context, hid, errorPropertyName.get(), 0);
2618 if (!JSValueIsString(context, errorValue))
2619 return;
2620
2621 Vector<WKRetainPtr<WKStringRef>> hidKeys;
2622 Vector<WKRetainPtr<WKTypeRef>> hidValues;
2623 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("Stage")));
2624 hidValues.append(toWK(adopt(JSValueToStringCopy(context, stageValue, 0)).get()));
2625 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("SubStage")));
2626 hidValues.append(toWK(adopt(JSValueToStringCopy(context, subStageValue, 0)).get()));
2627 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("Error")));
2628 hidValues.append(toWK(adopt(JSValueToStringCopy(context, errorValue, 0)).get()));
2629
2630 JSRetainPtr<JSStringRef> payloadBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("payloadBase64"));
2631 JSValueRef payloadBase64Value = JSObjectGetProperty(context, hid, payloadBase64PropertyName.get(), 0);
2632 if (!JSValueIsUndefined(context, payloadBase64Value) && !JSValueIsNull(context, payloadBase64Value)) {
2633 if (!JSValueIsArray(context, payloadBase64Value))
2634 return;
2635
2636 JSObjectRef payloadBase64 = JSValueToObject(context, payloadBase64Value, nullptr);
2637 static auto lengthProperty = adopt(JSStringCreateWithUTF8CString("length"));
2638 JSValueRef payloadBase64LengthValue = JSObjectGetProperty(context, payloadBase64, lengthProperty.get(), nullptr);
2639 if (!JSValueIsNumber(context, payloadBase64LengthValue))
2640 return;
2641
2642 auto payloadBase64s = adoptWK(WKMutableArrayCreate());
2643 auto payloadBase64Length = static_cast<size_t>(JSValueToNumber(context, payloadBase64LengthValue, nullptr));
2644 for (size_t i = 0; i < payloadBase64Length; ++i) {
2645 JSValueRef payloadBase64Value = JSObjectGetPropertyAtIndex(context, payloadBase64, i, nullptr);
2646 if (!JSValueIsString(context, payloadBase64Value))
2647 continue;
2648 WKArrayAppendItem(payloadBase64s.get(), toWK(adopt(JSValueToStringCopy(context, payloadBase64Value, 0)).get()).get());
2649 }
2650
2651 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("PayloadBase64")));
2652 hidValues.append(payloadBase64s);
2653 }
2654
2655 JSRetainPtr<JSStringRef> isU2fPropertyName(Adopt, JSStringCreateWithUTF8CString("isU2f"));
2656 JSValueRef isU2fValue = JSObjectGetProperty(context, hid, isU2fPropertyName.get(), 0);
2657 if (!JSValueIsUndefined(context, isU2fValue) && !JSValueIsNull(context, isU2fValue)) {
2658 if (!JSValueIsBoolean(context, isU2fValue))
2659 return;
2660 bool isU2f = JSValueToBoolean(context, isU2fValue);
2661 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("IsU2f")));
2662 hidValues.append(adoptWK(WKBooleanCreate(isU2f)).get());
2663 }
2664
2665 JSRetainPtr<JSStringRef> keepAlivePropertyName(Adopt, JSStringCreateWithUTF8CString("keepAlive"));
2666 JSValueRef keepAliveValue = JSObjectGetProperty(context, hid, keepAlivePropertyName.get(), 0);
2667 if (!JSValueIsUndefined(context, keepAliveValue) && !JSValueIsNull(context, keepAliveValue)) {
2668 if (!JSValueIsBoolean(context, keepAliveValue))
2669 return;
2670 bool keepAlive = JSValueToBoolean(context, keepAliveValue);
2671 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("KeepAlive")));
2672 hidValues.append(adoptWK(WKBooleanCreate(keepAlive)).get());
2673 }
2674
2675 JSRetainPtr<JSStringRef> fastDataArrivalPropertyName(Adopt, JSStringCreateWithUTF8CString("fastDataArrival"));
2676 JSValueRef fastDataArrivalValue = JSObjectGetProperty(context, hid, fastDataArrivalPropertyName.get(), 0);
2677 if (!JSValueIsUndefined(context, fastDataArrivalValue) && !JSValueIsNull(context, fastDataArrivalValue)) {
2678 if (!JSValueIsBoolean(context, fastDataArrivalValue))
2679 return;
2680 bool fastDataArrival = JSValueToBoolean(context, fastDataArrivalValue);
2681 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("FastDataArrival")));
2682 hidValues.append(adoptWK(WKBooleanCreate(fastDataArrival)).get());
2683 }
2684
2685 JSRetainPtr<JSStringRef> continueAfterErrorDataPropertyName(Adopt, JSStringCreateWithUTF8CString("continueAfterErrorData"));
2686 JSValueRef continueAfterErrorDataValue = JSObjectGetProperty(context, hid, continueAfterErrorDataPropertyName.get(), 0);
2687 if (!JSValueIsUndefined(context, continueAfterErrorDataValue) && !JSValueIsNull(context, continueAfterErrorDataValue)) {
2688 if (!JSValueIsBoolean(context, continueAfterErrorDataValue))
2689 return;
2690 bool continueAfterErrorData = JSValueToBoolean(context, continueAfterErrorDataValue);
2691 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("ContinueAfterErrorData")));
2692 hidValues.append(adoptWK(WKBooleanCreate(continueAfterErrorData)).get());
2693 }
2694
2695 JSRetainPtr<JSStringRef> canDowngradePropertyName(Adopt, JSStringCreateWithUTF8CString("canDowngrade"));
2696 JSValueRef canDowngradeValue = JSObjectGetProperty(context, hid, canDowngradePropertyName.get(), 0);
2697 if (!JSValueIsUndefined(context, canDowngradeValue) && !JSValueIsNull(context, canDowngradeValue)) {
2698 if (!JSValueIsBoolean(context, canDowngradeValue))
2699 return;
2700 bool canDowngrade = JSValueToBoolean(context, canDowngradeValue);
2701 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("CanDowngrade")));
2702 hidValues.append(adoptWK(WKBooleanCreate(canDowngrade)).get());
2703 }
2704
2705 Vector<WKStringRef> rawHidKeys;
2706 Vector<WKTypeRef> rawHidValues;
2707 rawHidKeys.resize(hidKeys.size());
2708 rawHidValues.resize(hidValues.size());
2709 for (size_t i = 0; i < hidKeys.size(); ++i) {
2710 rawHidKeys[i] = hidKeys[i].get();
2711 rawHidValues[i] = hidValues[i].get();
2712 }
2713
2714 configurationKeys.append(adoptWK(WKStringCreateWithUTF8CString("Hid")));
2715 configurationValues.append(adoptWK(WKDictionaryCreate(rawHidKeys.data(), rawHidValues.data(), rawHidKeys.size())));
2716 }
2717
2718 Vector<WKStringRef> rawConfigurationKeys;
2719 Vector<WKTypeRef> rawConfigurationValues;
2720 rawConfigurationKeys.resize(configurationKeys.size());
2721 rawConfigurationValues.resize(configurationValues.size());
2722 for (size_t i = 0; i < configurationKeys.size(); ++i) {
2723 rawConfigurationKeys[i] = configurationKeys[i].get();
2724 rawConfigurationValues[i] = configurationValues[i].get();
2725 }
2726
2727 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetWebAuthenticationMockConfiguration"));
2728 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawConfigurationKeys.data(), rawConfigurationValues.data(), rawConfigurationKeys.size()));
2729
2730 WKBundlePostSynchronousMessage(injectedBundle.bundle(), messageName.get(), messageBody.get(), nullptr);
2731}
2732
2733void TestRunner::addTestKeyToKeychain(JSStringRef privateKeyBase64, JSStringRef attrLabel, JSStringRef applicationTagBase64)
2734{
2735 Vector<WKRetainPtr<WKStringRef>> keys;
2736 Vector<WKRetainPtr<WKTypeRef>> values;
2737
2738 keys.append(adoptWK(WKStringCreateWithUTF8CString("PrivateKey")));
2739 values.append(toWK(privateKeyBase64));
2740
2741 keys.append(adoptWK(WKStringCreateWithUTF8CString("AttrLabel")));
2742 values.append(toWK(attrLabel));
2743
2744 keys.append(adoptWK(WKStringCreateWithUTF8CString("ApplicationTag")));
2745 values.append(toWK(applicationTagBase64));
2746
2747 Vector<WKStringRef> rawKeys;
2748 Vector<WKTypeRef> rawValues;
2749 rawKeys.resize(keys.size());
2750 rawValues.resize(values.size());
2751
2752 for (size_t i = 0; i < keys.size(); ++i) {
2753 rawKeys[i] = keys[i].get();
2754 rawValues[i] = values[i].get();
2755 }
2756
2757 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("AddTestKeyToKeychain"));
2758 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2759
2760 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2761}
2762
2763void TestRunner::cleanUpKeychain(JSStringRef attrLabel)
2764{
2765 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CleanUpKeychain"));
2766 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(attrLabel));
2767
2768 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2769}
2770
2771bool TestRunner::keyExistsInKeychain(JSStringRef attrLabel, JSStringRef applicationTagBase64)
2772{
2773 Vector<WKRetainPtr<WKStringRef>> keys;
2774 Vector<WKRetainPtr<WKTypeRef>> values;
2775
2776 keys.append(adoptWK(WKStringCreateWithUTF8CString("AttrLabel")));
2777 values.append(toWK(attrLabel));
2778
2779 keys.append(adoptWK(WKStringCreateWithUTF8CString("ApplicationTag")));
2780 values.append(toWK(applicationTagBase64));
2781
2782 Vector<WKStringRef> rawKeys;
2783 Vector<WKTypeRef> rawValues;
2784 rawKeys.resize(keys.size());
2785 rawValues.resize(values.size());
2786
2787 for (size_t i = 0; i < keys.size(); ++i) {
2788 rawKeys[i] = keys[i].get();
2789 rawValues[i] = values[i].get();
2790 }
2791
2792 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("KeyExistsInKeychain"));
2793 WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
2794
2795 WKTypeRef returnData = nullptr;
2796 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), &returnData);
2797 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
2798 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
2799}
2800
2801void TestRunner::setCanHandleHTTPSServerTrustEvaluation(bool canHandle)
2802{
2803 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetCanHandleHTTPSServerTrustEvaluation"));
2804 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(canHandle));
2805 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2806}
2807
2808bool TestRunner::canDoServerTrustEvaluationInNetworkProcess()
2809{
2810 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CanDoServerTrustEvaluationInNetworkProcess"));
2811 WKTypeRef returnData = nullptr;
2812 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
2813 ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
2814 return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
2815}
2816
2817unsigned long TestRunner::serverTrustEvaluationCallbackCallsCount()
2818{
2819 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ServerTrustEvaluationCallbackCallsCount"));
2820 WKTypeRef returnData = nullptr;
2821 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
2822 ASSERT(WKGetTypeID(returnData) == WKUInt64GetTypeID());
2823 return WKUInt64GetValue(adoptWK(static_cast<WKUInt64Ref>(returnData)).get());
2824}
2825
2826void TestRunner::setShouldDismissJavaScriptAlertsAsynchronously(bool shouldDismissAsynchronously)
2827{
2828 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ShouldDismissJavaScriptAlertsAsynchronously"));
2829 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(shouldDismissAsynchronously));
2830 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
2831}
2832
2833void TestRunner::abortModal()
2834{
2835 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("AbortModal"));
2836 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2837}
2838
2839void TestRunner::dumpAdClickAttribution()
2840{
2841 auto messageName = adoptWK(WKStringCreateWithUTF8CString("DumpAdClickAttribution"));
2842 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
2843}
2844
2845void TestRunner::clearAdClickAttribution()
2846{
2847 auto messageName = adoptWK(WKStringCreateWithUTF8CString("ClearAdClickAttribution"));
2848 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
2849}
2850
2851void TestRunner::clearAdClickAttributionsThroughWebsiteDataRemoval()
2852{
2853 auto messageName = adoptWK(WKStringCreateWithUTF8CString("ClearAdClickAttributionsThroughWebsiteDataRemoval"));
2854 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
2855}
2856
2857void TestRunner::setAdClickAttributionOverrideTimerForTesting(bool value)
2858{
2859 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAdClickAttributionOverrideTimerForTesting"));
2860 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
2861 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), nullptr);
2862}
2863
2864void TestRunner::setAdClickAttributionConversionURLForTesting(JSStringRef urlString)
2865{
2866 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAdClickAttributionConversionURLForTesting"));
2867 auto wtfURLString = toWTFString(WKStringCreateWithJSString(urlString));
2868 WKRetainPtr<WKURLRef> messageBody = adoptWK(WKURLCreateWithUTF8CString(wtfURLString.utf8().data()));
2869 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), nullptr);
2870}
2871
2872void TestRunner::markAdClickAttributionsAsExpiredForTesting()
2873{
2874 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("MarkAdClickAttributionsAsExpiredForTesting"));
2875 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
2876}
2877
2878} // namespace WTR
2879