2 * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "TestRunner.h"
29 #include "InjectedBundle.h"
30 #include "InjectedBundlePage.h"
31 #include "JSTestRunner.h"
32 #include "PlatformWebView.h"
33 #include "StringFunctions.h"
34 #include "TestController.h"
35 #include <JavaScriptCore/JSCTestRunnerUtils.h>
36 #include <WebCore/ResourceLoadObserver.h>
37 #include <WebKit/WKBundle.h>
38 #include <WebKit/WKBundleBackForwardList.h>
39 #include <WebKit/WKBundleFrame.h>
40 #include <WebKit/WKBundleFramePrivate.h>
41 #include <WebKit/WKBundleInspector.h>
42 #include <WebKit/WKBundleNodeHandlePrivate.h>
43 #include <WebKit/WKBundlePage.h>
44 #include <WebKit/WKBundlePagePrivate.h>
45 #include <WebKit/WKBundlePrivate.h>
46 #include <WebKit/WKBundleScriptWorld.h>
47 #include <WebKit/WKData.h>
48 #include <WebKit/WKPagePrivate.h>
49 #include <WebKit/WKRetainPtr.h>
50 #include <WebKit/WKSerializedScriptValue.h>
51 #include <WebKit/WebKit2_C.h>
52 #include <wtf/CurrentTime.h>
53 #include <wtf/HashMap.h>
54 #include <wtf/StdLibExtras.h>
55 #include <wtf/text/CString.h>
56 #include <wtf/text/StringBuilder.h>
60 Ref<TestRunner> TestRunner::create()
62 return adoptRef(*new TestRunner);
65 TestRunner::TestRunner()
66 : m_whatToDump(RenderTree)
67 , m_shouldDumpAllFrameScrollPositions(false)
68 , m_shouldDumpBackForwardListsForAllWindows(false)
69 , m_shouldAllowEditing(true)
70 , m_shouldCloseExtraWindows(false)
71 , m_dumpEditingCallbacks(false)
72 , m_dumpStatusCallbacks(false)
73 , m_dumpTitleChanges(false)
75 , m_dumpSelectionRect(false)
76 , m_dumpFullScreenCallbacks(false)
77 , m_dumpFrameLoadCallbacks(false)
78 , m_dumpProgressFinishedCallback(false)
79 , m_dumpResourceLoadCallbacks(false)
80 , m_dumpResourceResponseMIMETypes(false)
81 , m_dumpWillCacheResponse(false)
82 , m_dumpApplicationCacheDelegateCallbacks(false)
83 , m_dumpDatabaseCallbacks(false)
84 , m_disallowIncreaseForApplicationCacheQuota(false)
86 , m_testRepaint(false)
87 , m_testRepaintSweepHorizontally(false)
89 , m_willSendRequestReturnsNull(false)
90 , m_willSendRequestReturnsNullOnRedirect(false)
91 , m_shouldStopProvisionalFrameLoads(false)
92 , m_policyDelegateEnabled(false)
93 , m_policyDelegatePermissive(false)
95 , m_customFullScreenBehavior(false)
97 , m_databaseDefaultQuota(-1)
98 , m_databaseMaxQuota(-1)
99 , m_userStyleSheetEnabled(false)
100 , m_userStyleSheetLocation(adoptWK(WKStringCreateWithUTF8CString("")))
101 #if PLATFORM(GTK) || PLATFORM(WPE)
102 , m_waitToDumpWatchdogTimer(RunLoop::main(), this, &TestRunner::waitToDumpWatchdogTimerFired)
105 platformInitialize();
108 TestRunner::~TestRunner()
112 JSClassRef TestRunner::wrapperClass()
114 return JSTestRunner::testRunnerClass();
117 void TestRunner::display()
119 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
120 WKBundlePageForceRepaint(page);
123 void TestRunner::displayAndTrackRepaints()
125 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
126 WKBundlePageForceRepaint(page);
127 WKBundlePageSetTracksRepaints(page, true);
128 WKBundlePageResetTrackedRepaints(page);
131 void TestRunner::dumpAsText(bool dumpPixels)
133 if (m_whatToDump < MainFrameText)
134 m_whatToDump = MainFrameText;
135 m_dumpPixels = dumpPixels;
138 void TestRunner::setCustomPolicyDelegate(bool enabled, bool permissive)
140 m_policyDelegateEnabled = enabled;
141 m_policyDelegatePermissive = permissive;
143 InjectedBundle::singleton().setCustomPolicyDelegate(enabled, permissive);
146 void TestRunner::waitForPolicyDelegate()
148 setCustomPolicyDelegate(true);
152 void TestRunner::waitUntilDownloadFinished()
154 m_shouldFinishAfterDownload = true;
158 void TestRunner::waitUntilDone()
161 if (InjectedBundle::singleton().useWaitToDumpWatchdogTimer())
162 initializeWaitToDumpWatchdogTimerIfNeeded();
165 void TestRunner::waitToDumpWatchdogTimerFired()
167 invalidateWaitToDumpWatchdogTimer();
168 auto& injectedBundle = InjectedBundle::singleton();
171 snprintf(buffer, sizeof(buffer), "#PID UNRESPONSIVE - %s (pid %d)\n", getprogname(), getpid());
172 injectedBundle.outputText(buffer);
174 injectedBundle.outputText("FAIL: Timed out waiting for notifyDone to be called\n\n");
175 injectedBundle.done();
178 void TestRunner::notifyDone()
180 auto& injectedBundle = InjectedBundle::singleton();
181 if (!injectedBundle.isTestRunning())
184 if (m_waitToDump && !injectedBundle.topLoadingFrame())
185 injectedBundle.page()->dump();
187 // We don't call invalidateWaitToDumpWatchdogTimer() here, even if we continue to wait for a load to finish.
188 // The test is still subject to timeout checking - it is better to detect an async timeout inside WebKitTestRunner
189 // than to let webkitpy do that, because WebKitTestRunner will dump partial results.
191 m_waitToDump = false;
194 void TestRunner::forceImmediateCompletion()
196 auto& injectedBundle = InjectedBundle::singleton();
197 if (!injectedBundle.isTestRunning())
200 if (m_waitToDump && injectedBundle.page())
201 injectedBundle.page()->dump();
203 m_waitToDump = false;
206 unsigned TestRunner::imageCountInGeneralPasteboard() const
208 return InjectedBundle::singleton().imageCountInGeneralPasteboard();
211 void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
213 WKRetainPtr<WKStringRef> sourceWK = toWK(source);
215 WKBundlePageAddUserScript(InjectedBundle::singleton().page()->page(), sourceWK.get(),
216 (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
217 (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
220 void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
222 WKRetainPtr<WKStringRef> sourceWK = toWK(source);
224 WKBundlePageAddUserStyleSheet(InjectedBundle::singleton().page()->page(), sourceWK.get(),
225 (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
228 void TestRunner::keepWebHistory()
230 InjectedBundle::singleton().postSetAddsVisitedLinks(true);
233 void TestRunner::execCommand(JSStringRef name, JSStringRef argument)
235 WKBundlePageExecuteEditingCommand(InjectedBundle::singleton().page()->page(), toWK(name).get(), toWK(argument).get());
238 bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
240 WKFindOptions options = 0;
242 auto& injectedBundle = InjectedBundle::singleton();
243 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
244 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
245 JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
246 JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
247 JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
248 if (!JSValueIsNumber(context, lengthValue))
251 size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
252 for (size_t i = 0; i < length; ++i) {
253 JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
254 if (!JSValueIsString(context, value))
257 JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
259 if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
260 options |= kWKFindOptionsCaseInsensitive;
261 else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
262 options |= kWKFindOptionsAtWordStarts;
263 else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
264 options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
265 else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
266 options |= kWKFindOptionsBackwards;
267 else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
268 options |= kWKFindOptionsWrapAround;
269 else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
270 // FIXME: No kWKFindOptionsStartInSelection.
274 return WKBundlePageFindString(injectedBundle.page()->page(), toWK(target).get(), options);
277 void TestRunner::clearAllDatabases()
279 WKBundleClearAllDatabases(InjectedBundle::singleton().bundle());
281 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DeleteAllIndexedDatabases"));
282 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
284 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
287 void TestRunner::setDatabaseQuota(uint64_t quota)
289 return WKBundleSetDatabaseQuota(InjectedBundle::singleton().bundle(), quota);
292 void TestRunner::clearAllApplicationCaches()
294 WKBundlePageClearApplicationCache(InjectedBundle::singleton().page()->page());
297 void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin)
299 WKBundlePageClearApplicationCacheForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
302 void TestRunner::setAppCacheMaximumSize(uint64_t size)
304 WKBundlePageSetAppCacheMaximumSize(InjectedBundle::singleton().page()->page(), size);
307 long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef origin)
309 return WKBundlePageGetAppCacheUsageForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get());
312 void TestRunner::disallowIncreaseForApplicationCacheQuota()
314 m_disallowIncreaseForApplicationCacheQuota = true;
317 static inline JSValueRef stringArrayToJS(JSContextRef context, WKArrayRef strings)
319 const size_t count = WKArrayGetSize(strings);
321 JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
322 JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
323 for (size_t i = 0; i < count; ++i) {
324 WKStringRef stringRef = static_cast<WKStringRef>(WKArrayGetItemAtIndex(strings, i));
325 JSRetainPtr<JSStringRef> stringJS = toJS(stringRef);
326 JSObjectSetPropertyAtIndex(context, arrayObj, i, JSValueMakeString(context, stringJS.get()), 0);
332 JSValueRef TestRunner::originsWithApplicationCache()
334 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
336 WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundlePageCopyOriginsWithApplicationCache(page));
338 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
339 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
341 return stringArrayToJS(context, origins.get());
344 bool TestRunner::isCommandEnabled(JSStringRef name)
346 return WKBundlePageIsEditingCommandEnabled(InjectedBundle::singleton().page()->page(), toWK(name).get());
349 void TestRunner::setCanOpenWindows(bool)
351 // The test plugins/get-url-with-blank-target.html requires that the embedding client forbid
352 // opening windows (by omitting a call to this function) so as to test that NPN_GetURL()
353 // with a blank target will return an error.
355 // It is not clear if we should implement this functionality or remove it and plugins/get-url-with-blank-target.html
356 // per the remark in <https://trac.webkit.org/changeset/64504/trunk/LayoutTests/platform/mac-wk2/Skipped>.
357 // For now, just ignore this setting.
360 void TestRunner::setXSSAuditorEnabled(bool enabled)
362 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitXSSAuditorEnabled"));
363 auto& injectedBundle = InjectedBundle::singleton();
364 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
367 void TestRunner::setMediaDevicesEnabled(bool enabled)
369 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitMediaDevicesEnabled"));
370 auto& injectedBundle = InjectedBundle::singleton();
371 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
374 void TestRunner::setWebRTCLegacyAPIEnabled(bool enabled)
376 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebRTCLegacyAPIEnabled"));
377 auto& injectedBundle = InjectedBundle::singleton();
378 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
381 void TestRunner::setModernMediaControlsEnabled(bool enabled)
383 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitModernMediaControlsEnabled"));
384 auto& injectedBundle = InjectedBundle::singleton();
385 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
388 void TestRunner::setWebGL2Enabled(bool enabled)
390 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGL2Enabled"));
391 auto& injectedBundle = InjectedBundle::singleton();
392 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
395 void TestRunner::setWebGPUEnabled(bool enabled)
397 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGPUEnabled"));
398 auto& injectedBundle = InjectedBundle::singleton();
399 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
402 void TestRunner::setWritableStreamAPIEnabled(bool enabled)
404 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWritableStreamAPIEnabled"));
405 auto& injectedBundle = InjectedBundle::singleton();
406 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
409 void TestRunner::setReadableByteStreamAPIEnabled(bool enabled)
411 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitReadableByteStreamAPIEnabled"));
412 auto& injectedBundle = InjectedBundle::singleton();
413 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
416 void TestRunner::setEncryptedMediaAPIEnabled(bool enabled)
418 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitEncryptedMediaAPIEnabled"));
419 auto& injectedBundle = InjectedBundle::singleton();
420 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
423 void TestRunner::setAllowsAnySSLCertificate(bool enabled)
425 auto& injectedBundle = InjectedBundle::singleton();
426 injectedBundle.setAllowsAnySSLCertificate(enabled);
428 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAllowsAnySSLCertificate"));
429 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
430 WKBundlePagePostSynchronousMessageForTesting(injectedBundle.page()->page(), messageName.get(), messageBody.get(), nullptr);
433 void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled)
435 auto& injectedBundle = InjectedBundle::singleton();
436 WKBundleSetAllowUniversalAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
439 void TestRunner::setAllowFileAccessFromFileURLs(bool enabled)
441 auto& injectedBundle = InjectedBundle::singleton();
442 WKBundleSetAllowFileAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
445 void TestRunner::setNeedsStorageAccessFromFileURLsQuirk(bool needsQuirk)
447 auto& injectedBundle = InjectedBundle::singleton();
448 WKBundleSetAllowStorageAccessFromFileURLS(injectedBundle.bundle(), injectedBundle.pageGroup(), needsQuirk);
451 void TestRunner::setPluginsEnabled(bool enabled)
453 WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitPluginsEnabled"));
454 auto& injectedBundle = InjectedBundle::singleton();
455 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled);
458 void TestRunner::setJavaScriptCanAccessClipboard(bool enabled)
460 auto& injectedBundle = InjectedBundle::singleton();
461 WKBundleSetJavaScriptCanAccessClipboard(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
464 void TestRunner::setPrivateBrowsingEnabled(bool enabled)
466 auto& injectedBundle = InjectedBundle::singleton();
467 WKBundleSetPrivateBrowsingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
470 void TestRunner::setUseDashboardCompatibilityMode(bool enabled)
472 #if ENABLE(DASHBOARD_SUPPORT)
473 auto& injectedBundle = InjectedBundle::singleton();
474 WKBundleSetUseDashboardCompatibilityMode(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
476 UNUSED_PARAM(enabled);
480 void TestRunner::setPopupBlockingEnabled(bool enabled)
482 auto& injectedBundle = InjectedBundle::singleton();
483 WKBundleSetPopupBlockingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
486 void TestRunner::setAuthorAndUserStylesEnabled(bool enabled)
488 auto& injectedBundle = InjectedBundle::singleton();
489 WKBundleSetAuthorAndUserStylesEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
492 void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
494 WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
497 void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
499 WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains);
502 bool TestRunner::isPageBoxVisible(int pageIndex)
504 auto& injectedBundle = InjectedBundle::singleton();
505 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
506 return WKBundleIsPageBoxVisible(injectedBundle.bundle(), mainFrame, pageIndex);
509 void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
511 if (!element || !JSValueIsObject(context, element))
514 WKRetainPtr<WKBundleNodeHandleRef> nodeHandle(AdoptWK, WKBundleNodeHandleCreate(context, const_cast<JSObjectRef>(element)));
515 WKBundleNodeHandleSetHTMLInputElementValueForUser(nodeHandle.get(), toWK(value).get());
518 void TestRunner::setAudioResult(JSContextRef context, JSValueRef data)
520 auto& injectedBundle = InjectedBundle::singleton();
521 // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
522 WKRetainPtr<WKDataRef> audioData(AdoptWK, WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data));
523 injectedBundle.setAudioResult(audioData.get());
524 m_whatToDump = Audio;
525 m_dumpPixels = false;
528 unsigned TestRunner::windowCount()
530 return InjectedBundle::singleton().pageCount();
533 void TestRunner::clearBackForwardList()
535 WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::singleton().page()->page()));
540 void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
542 setProperty(context, windowObject, "testRunner", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
545 void TestRunner::showWebInspector()
547 WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
550 void TestRunner::closeWebInspector()
552 WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()));
555 void TestRunner::evaluateInWebInspector(JSStringRef script)
557 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
558 WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()), scriptWK.get());
561 typedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
562 static WorldMap& worldMap()
564 static WorldMap& map = *new WorldMap;
568 unsigned TestRunner::worldIDForWorld(WKBundleScriptWorldRef world)
570 WorldMap::const_iterator end = worldMap().end();
571 for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
572 if (it->value == world)
579 void TestRunner::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
581 // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
582 // that is created once and cached forever.
583 WKRetainPtr<WKBundleScriptWorldRef> world;
585 world.adopt(WKBundleScriptWorldCreateWorld());
587 WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, nullptr).iterator->value;
589 worldSlot.adopt(WKBundleScriptWorldCreateWorld());
593 WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
595 frame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
597 JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
598 JSEvaluateScript(jsContext, script, 0, 0, 0, 0);
601 void TestRunner::setPOSIXLocale(JSStringRef locale)
604 JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
605 setlocale(LC_ALL, localeBuf);
608 void TestRunner::setTextDirection(JSStringRef direction)
610 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
611 return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get());
614 void TestRunner::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage)
616 InjectedBundle::singleton().postNewBeforeUnloadReturnValue(!shouldStayOnPage);
619 void TestRunner::setDefersLoading(bool shouldDeferLoading)
621 WKBundlePageSetDefersLoading(InjectedBundle::singleton().page()->page(), shouldDeferLoading);
624 void TestRunner::setPageVisibility(JSStringRef state)
626 InjectedBundle::singleton().setHidden(JSStringIsEqualToUTF8CString(state, "hidden") || JSStringIsEqualToUTF8CString(state, "prerender"));
629 void TestRunner::resetPageVisibility()
631 InjectedBundle::singleton().setHidden(false);
634 typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
635 static CallbackMap& callbackMap()
637 static CallbackMap& map = *new CallbackMap;
642 AddChromeInputFieldCallbackID = 1,
643 RemoveChromeInputFieldCallbackID,
644 FocusWebViewCallbackID,
645 SetBackingScaleFactorCallbackID,
646 DidBeginSwipeCallbackID,
647 WillEndSwipeCallbackID,
648 DidEndSwipeCallbackID,
649 DidRemoveSwipeSnapshotCallbackID,
650 StatisticsDidModifyDataRecordsCallbackID,
651 StatisticsDidScanDataRecordsCallbackID,
652 StatisticsDidRunTelemetryCallbackID,
653 StatisticsDidClearThroughWebsiteDataRemovalCallbackID,
654 StatisticsDidSetPartitionOrBlockCookiesForHostCallbackID,
655 DidRemoveAllSessionCredentialsCallbackID,
656 GetApplicationManifestCallbackID,
657 FirstUIScriptCallbackID = 100
660 static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
665 if (callbackMap().contains(index)) {
666 InjectedBundle::singleton().outputText(String::format("FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n\n", index));
670 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
671 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
672 JSValueProtect(context, callback);
673 callbackMap().add(index, callback);
676 static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr)
678 if (!callbackMap().contains(index))
680 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
681 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
682 JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
683 JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
684 JSValueUnprotect(context, callback);
687 void TestRunner::clearTestRunnerCallbacks()
689 for (auto& iter : callbackMap()) {
690 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
691 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
692 JSObjectRef callback = JSValueToObject(context, iter.value, 0);
693 JSValueUnprotect(context, callback);
696 callbackMap().clear();
699 void TestRunner::accummulateLogsForChannel(JSStringRef)
701 // FIXME: Implement getting the call to all processes.
704 void TestRunner::addChromeInputField(JSValueRef callback)
706 cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
707 InjectedBundle::singleton().postAddChromeInputField();
710 void TestRunner::removeChromeInputField(JSValueRef callback)
712 cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
713 InjectedBundle::singleton().postRemoveChromeInputField();
716 void TestRunner::focusWebView(JSValueRef callback)
718 cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
719 InjectedBundle::singleton().postFocusWebView();
722 void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
724 cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
725 InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor);
728 void TestRunner::setWindowIsKey(bool isKey)
730 InjectedBundle::singleton().postSetWindowIsKey(isKey);
733 void TestRunner::setViewSize(double width, double height)
735 InjectedBundle::singleton().postSetViewSize(width, height);
738 void TestRunner::callAddChromeInputFieldCallback()
740 callTestRunnerCallback(AddChromeInputFieldCallbackID);
743 void TestRunner::callRemoveChromeInputFieldCallback()
745 callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
748 void TestRunner::callFocusWebViewCallback()
750 callTestRunnerCallback(FocusWebViewCallbackID);
753 void TestRunner::callSetBackingScaleFactorCallback()
755 callTestRunnerCallback(SetBackingScaleFactorCallbackID);
758 static inline bool toBool(JSStringRef value)
760 return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
763 void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
765 auto& injectedBundle = InjectedBundle::singleton();
766 // FIXME: handle non-boolean preferences.
767 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value));
770 void TestRunner::setAlwaysAcceptCookies(bool accept)
772 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies"));
774 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(accept));
776 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
779 void TestRunner::setCookieStoragePartitioningEnabled(bool enabled)
781 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCookieStoragePartitioningEnabled"));
783 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
785 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
788 void TestRunner::setStorageAccessAPIEnabled(bool enabled)
790 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
792 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
794 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
797 double TestRunner::preciseTime()
799 return currentTime();
802 void TestRunner::setUserStyleSheetEnabled(bool enabled)
804 m_userStyleSheetEnabled = enabled;
806 WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
807 WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
808 auto& injectedBundle = InjectedBundle::singleton();
809 WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location);
812 void TestRunner::setUserStyleSheetLocation(JSStringRef location)
814 m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
816 if (m_userStyleSheetEnabled)
817 setUserStyleSheetEnabled(true);
820 void TestRunner::setSpatialNavigationEnabled(bool enabled)
822 auto& injectedBundle = InjectedBundle::singleton();
823 WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
826 void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
828 auto& injectedBundle = InjectedBundle::singleton();
829 WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled);
832 void TestRunner::setSerializeHTTPLoads()
834 // WK2 doesn't reorder loads.
837 void TestRunner::dispatchPendingLoadRequests()
839 // WK2 doesn't keep pending requests.
842 void TestRunner::setCacheModel(int model)
844 InjectedBundle::singleton().setCacheModel(model);
847 void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled)
849 auto& injectedBundle = InjectedBundle::singleton();
850 WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
853 void TestRunner::grantWebNotificationPermission(JSStringRef origin)
855 WKRetainPtr<WKStringRef> originWK = toWK(origin);
856 auto& injectedBundle = InjectedBundle::singleton();
857 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true);
860 void TestRunner::denyWebNotificationPermission(JSStringRef origin)
862 WKRetainPtr<WKStringRef> originWK = toWK(origin);
863 auto& injectedBundle = InjectedBundle::singleton();
864 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false);
867 void TestRunner::removeAllWebNotificationPermissions()
869 auto& injectedBundle = InjectedBundle::singleton();
870 WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page());
873 void TestRunner::simulateWebNotificationClick(JSValueRef notification)
875 auto& injectedBundle = InjectedBundle::singleton();
876 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
877 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
878 uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification);
879 injectedBundle.postSimulateWebNotificationClick(notificationID);
882 void TestRunner::setGeolocationPermission(bool enabled)
884 // FIXME: this should be done by frame.
885 InjectedBundle::singleton().setGeolocationPermission(enabled);
888 bool TestRunner::isGeolocationProviderActive()
890 return InjectedBundle::singleton().isGeolocationProviderActive();
893 void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed, JSValueRef jsFloorLevel)
895 auto& injectedBundle = InjectedBundle::singleton();
896 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
897 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
899 bool providesAltitude = false;
900 double altitude = 0.;
901 if (!JSValueIsUndefined(context, jsAltitude)) {
902 providesAltitude = true;
903 altitude = JSValueToNumber(context, jsAltitude, 0);
906 bool providesAltitudeAccuracy = false;
907 double altitudeAccuracy = 0.;
908 if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
909 providesAltitudeAccuracy = true;
910 altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
913 bool providesHeading = false;
915 if (!JSValueIsUndefined(context, jsHeading)) {
916 providesHeading = true;
917 heading = JSValueToNumber(context, jsHeading, 0);
920 bool providesSpeed = false;
922 if (!JSValueIsUndefined(context, jsSpeed)) {
923 providesSpeed = true;
924 speed = JSValueToNumber(context, jsSpeed, 0);
927 bool providesFloorLevel = false;
928 double floorLevel = 0.;
929 if (!JSValueIsUndefined(context, jsFloorLevel)) {
930 providesFloorLevel = true;
931 floorLevel = JSValueToNumber(context, jsFloorLevel, 0);
934 injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed, providesFloorLevel, floorLevel);
937 void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
939 WKRetainPtr<WKStringRef> messageWK = toWK(message);
940 InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get());
943 void TestRunner::setUserMediaPermission(bool enabled)
945 // FIXME: this should be done by frame.
946 InjectedBundle::singleton().setUserMediaPermission(enabled);
949 void TestRunner::resetUserMediaPermission()
951 // FIXME: this should be done by frame.
952 InjectedBundle::singleton().resetUserMediaPermission();
955 void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
957 WKRetainPtr<WKStringRef> originWK = toWK(origin);
958 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
959 InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
962 unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
964 WKRetainPtr<WKStringRef> originWK = toWK(origin);
965 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
966 return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
969 void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
971 WKRetainPtr<WKStringRef> originWK = toWK(origin);
972 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
973 InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
976 bool TestRunner::callShouldCloseOnWebView()
978 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
979 return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
982 void TestRunner::queueBackNavigation(unsigned howFarBackward)
984 InjectedBundle::singleton().queueBackNavigation(howFarBackward);
987 void TestRunner::queueForwardNavigation(unsigned howFarForward)
989 InjectedBundle::singleton().queueForwardNavigation(howFarForward);
992 void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs)
994 auto& injectedBundle = InjectedBundle::singleton();
995 WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page())));
996 WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
997 WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get()));
999 injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs);
1002 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
1004 WKRetainPtr<WKStringRef> contentWK = toWK(content);
1005 WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
1006 WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
1008 InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
1011 void TestRunner::queueReload()
1013 InjectedBundle::singleton().queueReload();
1016 void TestRunner::queueLoadingScript(JSStringRef script)
1018 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1019 InjectedBundle::singleton().queueLoadingScript(scriptWK.get());
1022 void TestRunner::queueNonLoadingScript(JSStringRef script)
1024 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1025 InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get());
1028 void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value)
1030 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges"));
1031 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1032 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1035 void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
1037 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges"));
1038 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges));
1039 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1042 void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value)
1044 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace"));
1045 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1046 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1049 void TestRunner::setShouldLogDownloadCallbacks(bool value)
1051 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogDownloadCallbacks"));
1052 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1053 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1056 void TestRunner::setAuthenticationUsername(JSStringRef username)
1058 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername"));
1059 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(username));
1060 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1063 void TestRunner::setAuthenticationPassword(JSStringRef password)
1065 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationPassword"));
1066 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(password));
1067 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1070 bool TestRunner::secureEventInputIsEnabled() const
1072 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SecureEventInputIsEnabled"));
1073 WKTypeRef returnData = 0;
1075 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), 0, &returnData);
1076 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1079 void TestRunner::setBlockAllPlugins(bool shouldBlock)
1081 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBlockAllPlugins"));
1082 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldBlock));
1083 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1086 JSValueRef TestRunner::failNextNewCodeBlock()
1088 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1089 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1090 return JSC::failNextNewCodeBlock(context);
1093 JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction)
1095 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1096 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1097 return JSC::numberOfDFGCompiles(context, theFunction);
1100 JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction)
1102 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1103 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1104 return JSC::setNeverInline(context, theFunction);
1107 void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value)
1109 m_shouldDecideNavigationPolicyAfterDelay = value;
1110 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay"));
1111 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1112 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1115 void TestRunner::setNavigationGesturesEnabled(bool value)
1117 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled"));
1118 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1119 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1122 void TestRunner::setIgnoresViewportScaleLimits(bool value)
1124 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits"));
1125 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1126 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1129 void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value)
1131 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes"));
1132 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1133 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1136 void TestRunner::terminateNetworkProcess()
1138 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateNetworkProcess"));
1139 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1142 void TestRunner::terminateServiceWorkerProcess()
1144 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateServiceWorkerProcess"));
1145 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1148 static unsigned nextUIScriptCallbackID()
1150 static unsigned callbackID = FirstUIScriptCallbackID;
1151 return callbackID++;
1154 void TestRunner::runUIScript(JSStringRef script, JSValueRef callback)
1156 unsigned callbackID = nextUIScriptCallbackID();
1157 cacheTestRunnerCallback(callbackID, callback);
1159 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RunUIProcessScript"));
1161 WKRetainPtr<WKMutableDictionaryRef> testDictionary(AdoptWK, WKMutableDictionaryCreate());
1163 WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
1164 WKRetainPtr<WKStringRef> scriptValue(AdoptWK, WKStringCreateWithJSString(script));
1166 WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
1167 WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID));
1169 WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get());
1170 WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get());
1172 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get());
1175 void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result)
1177 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1178 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1180 JSValueRef resultValue = JSValueMakeString(context, result);
1181 callTestRunnerCallback(callbackID, 1, &resultValue);
1184 void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
1186 cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
1189 void TestRunner::installWillEndSwipeCallback(JSValueRef callback)
1191 cacheTestRunnerCallback(WillEndSwipeCallbackID, callback);
1194 void TestRunner::installDidEndSwipeCallback(JSValueRef callback)
1196 cacheTestRunnerCallback(DidEndSwipeCallbackID, callback);
1199 void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback)
1201 cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback);
1204 void TestRunner::callDidBeginSwipeCallback()
1206 callTestRunnerCallback(DidBeginSwipeCallbackID);
1209 void TestRunner::callWillEndSwipeCallback()
1211 callTestRunnerCallback(WillEndSwipeCallbackID);
1214 void TestRunner::callDidEndSwipeCallback()
1216 callTestRunnerCallback(DidEndSwipeCallbackID);
1219 void TestRunner::callDidRemoveSwipeSnapshotCallback()
1221 callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
1224 void TestRunner::setStatisticsLastSeen(JSStringRef hostName, double seconds)
1226 Vector<WKRetainPtr<WKStringRef>> keys;
1227 Vector<WKRetainPtr<WKTypeRef>> values;
1229 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1230 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1232 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1233 values.append({ AdoptWK, WKDoubleCreate(seconds) });
1235 Vector<WKStringRef> rawKeys(keys.size());
1236 Vector<WKTypeRef> rawValues(values.size());
1238 for (size_t i = 0; i < keys.size(); ++i) {
1239 rawKeys[i] = keys[i].get();
1240 rawValues[i] = values[i].get();
1243 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsLastSeen"));
1244 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1246 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1249 void TestRunner::setStatisticsPrevalentResource(JSStringRef hostName, bool value)
1251 Vector<WKRetainPtr<WKStringRef>> keys;
1252 Vector<WKRetainPtr<WKTypeRef>> values;
1254 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1255 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1257 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1258 values.append({ AdoptWK, WKBooleanCreate(value) });
1260 Vector<WKStringRef> rawKeys;
1261 Vector<WKTypeRef> rawValues;
1262 rawKeys.resize(keys.size());
1263 rawValues.resize(values.size());
1265 for (size_t i = 0; i < keys.size(); ++i) {
1266 rawKeys[i] = keys[i].get();
1267 rawValues[i] = values[i].get();
1270 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsPrevalentResource"));
1271 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1273 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1276 bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName)
1278 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource"));
1279 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1280 WKTypeRef returnData = 0;
1281 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1282 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1285 bool TestRunner::isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost)
1287 Vector<WKRetainPtr<WKStringRef>> keys;
1288 Vector<WKRetainPtr<WKTypeRef>> values;
1290 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("SubFrameHost") });
1291 values.append({ AdoptWK, WKStringCreateWithJSString(subFrameHost) });
1293 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHost") });
1294 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHost) });
1296 Vector<WKStringRef> rawKeys(keys.size());
1297 Vector<WKTypeRef> rawValues(values.size());
1299 for (size_t i = 0; i < keys.size(); ++i) {
1300 rawKeys[i] = keys[i].get();
1301 rawValues[i] = values[i].get();
1304 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubFrameUnder"));
1305 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1306 WKTypeRef returnData = 0;
1307 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1308 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1311 bool TestRunner::isStatisticsRegisteredAsRedirectingTo(JSStringRef hostRedirectedFrom, JSStringRef hostRedirectedTo)
1313 Vector<WKRetainPtr<WKStringRef>> keys;
1314 Vector<WKRetainPtr<WKTypeRef>> values;
1316 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedFrom") });
1317 values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedFrom) });
1319 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedTo") });
1320 values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedTo) });
1322 Vector<WKStringRef> rawKeys(keys.size());
1323 Vector<WKTypeRef> rawValues(values.size());
1325 for (size_t i = 0; i < keys.size(); ++i) {
1326 rawKeys[i] = keys[i].get();
1327 rawValues[i] = values[i].get();
1330 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsRedirectingTo"));
1331 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1332 WKTypeRef returnData = 0;
1333 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1334 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1337 void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value)
1339 Vector<WKRetainPtr<WKStringRef>> keys;
1340 Vector<WKRetainPtr<WKTypeRef>> values;
1342 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1343 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1345 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1346 values.append({ AdoptWK, WKBooleanCreate(value) });
1348 Vector<WKStringRef> rawKeys;
1349 Vector<WKTypeRef> rawValues;
1350 rawKeys.resize(keys.size());
1351 rawValues.resize(values.size());
1353 for (size_t i = 0; i < keys.size(); ++i) {
1354 rawKeys[i] = keys[i].get();
1355 rawValues[i] = values[i].get();
1358 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction"));
1359 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1361 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1364 void TestRunner::setStatisticsHasHadNonRecentUserInteraction(JSStringRef hostName)
1366 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadNonRecentUserInteraction"));
1367 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1368 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1371 bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName)
1373 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction"));
1374 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1375 WKTypeRef returnData = 0;
1376 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1377 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1380 void TestRunner::setStatisticsGrandfathered(JSStringRef hostName, bool value)
1382 Vector<WKRetainPtr<WKStringRef>> keys;
1383 Vector<WKRetainPtr<WKTypeRef>> values;
1385 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1386 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1388 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1389 values.append({ AdoptWK, WKBooleanCreate(value) });
1391 Vector<WKStringRef> rawKeys;
1392 Vector<WKTypeRef> rawValues;
1393 rawKeys.resize(keys.size());
1394 rawValues.resize(values.size());
1396 for (size_t i = 0; i < keys.size(); ++i) {
1397 rawKeys[i] = keys[i].get();
1398 rawValues[i] = values[i].get();
1401 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfathered"));
1402 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1404 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1407 bool TestRunner::isStatisticsGrandfathered(JSStringRef hostName)
1409 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsGrandfathered"));
1410 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1411 WKTypeRef returnData = 0;
1412 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1413 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1416 void TestRunner::setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1418 Vector<WKRetainPtr<WKStringRef>> keys;
1419 Vector<WKRetainPtr<WKTypeRef>> values;
1421 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1422 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1424 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1425 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1427 Vector<WKStringRef> rawKeys(keys.size());
1428 Vector<WKTypeRef> rawValues(values.size());
1430 for (size_t i = 0; i < keys.size(); ++i) {
1431 rawKeys[i] = keys[i].get();
1432 rawValues[i] = values[i].get();
1435 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubframeUnderTopFrameOrigin"));
1436 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1437 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1440 void TestRunner::setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1442 Vector<WKRetainPtr<WKStringRef>> keys;
1443 Vector<WKRetainPtr<WKTypeRef>> values;
1445 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1446 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1448 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1449 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1451 Vector<WKStringRef> rawKeys(keys.size());
1452 Vector<WKTypeRef> rawValues(values.size());
1454 for (size_t i = 0; i < keys.size(); ++i) {
1455 rawKeys[i] = keys[i].get();
1456 rawValues[i] = values[i].get();
1459 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUnderTopFrameOrigin"));
1460 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1461 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1464 void TestRunner::setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1466 Vector<WKRetainPtr<WKStringRef>> keys;
1467 Vector<WKRetainPtr<WKTypeRef>> values;
1469 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1470 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1472 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo") });
1473 values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedTo) });
1475 Vector<WKStringRef> rawKeys(keys.size());
1476 Vector<WKTypeRef> rawValues(values.size());
1478 for (size_t i = 0; i < keys.size(); ++i) {
1479 rawKeys[i] = keys[i].get();
1480 rawValues[i] = values[i].get();
1483 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectTo"));
1484 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1485 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1488 void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
1490 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));
1491 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1492 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1495 void TestRunner::setStatisticsTimeToLiveCookiePartitionFree(double seconds)
1497 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveCookiePartitionFree"));
1498 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1499 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1502 void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback)
1504 cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback);
1507 void TestRunner::statisticsDidModifyDataRecordsCallback()
1509 callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID);
1512 void TestRunner::installStatisticsDidScanDataRecordsCallback(JSValueRef callback)
1514 cacheTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID, callback);
1517 void TestRunner::statisticsDidScanDataRecordsCallback()
1519 callTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID);
1522 void TestRunner::installStatisticsDidRunTelemetryCallback(JSValueRef callback)
1524 cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
1527 void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
1529 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1530 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1532 StringBuilder stringBuilder;
1533 stringBuilder.appendLiteral("{ \"totalPrevalentResources\" : ");
1534 stringBuilder.appendNumber(totalPrevalentResources);
1535 stringBuilder.appendLiteral(", \"totalPrevalentResourcesWithUserInteraction\" : ");
1536 stringBuilder.appendNumber(totalPrevalentResourcesWithUserInteraction);
1537 stringBuilder.appendLiteral(", \"top3SubframeUnderTopFrameOrigins\" : ");
1538 stringBuilder.appendNumber(top3SubframeUnderTopFrameOrigins);
1539 stringBuilder.appendLiteral(" }");
1541 JSValueRef result = JSValueMakeFromJSONString(context, JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data()));
1543 callTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, 1, &result);
1546 void TestRunner::statisticsNotifyObserver()
1548 InjectedBundle::singleton().statisticsNotifyObserver();
1551 void TestRunner::statisticsProcessStatisticsAndDataRecords()
1553 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsProcessStatisticsAndDataRecords"));
1554 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1557 void TestRunner::statisticsUpdateCookiePartitioning(JSValueRef callback)
1559 cacheTestRunnerCallback(StatisticsDidSetPartitionOrBlockCookiesForHostCallbackID, callback);
1561 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsUpdateCookiePartitioning"));
1562 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1565 void TestRunner::statisticsSetShouldPartitionCookiesForHost(JSStringRef hostName, bool value, JSValueRef callback)
1567 cacheTestRunnerCallback(StatisticsDidSetPartitionOrBlockCookiesForHostCallbackID, callback);
1569 Vector<WKRetainPtr<WKStringRef>> keys;
1570 Vector<WKRetainPtr<WKTypeRef>> values;
1572 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1573 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1575 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1576 values.append({ AdoptWK, WKBooleanCreate(value) });
1578 Vector<WKStringRef> rawKeys(keys.size());
1579 Vector<WKTypeRef> rawValues(values.size());
1581 for (size_t i = 0; i < keys.size(); ++i) {
1582 rawKeys[i] = keys[i].get();
1583 rawValues[i] = values[i].get();
1586 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSetShouldPartitionCookiesForHost"));
1587 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1589 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1592 void TestRunner::statisticsCallDidSetPartitionOrBlockCookiesForHostCallback()
1594 callTestRunnerCallback(StatisticsDidSetPartitionOrBlockCookiesForHostCallbackID);
1597 void TestRunner::statisticsSubmitTelemetry()
1599 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSubmitTelemetry"));
1600 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1603 void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value)
1605 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1606 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1607 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1610 void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
1612 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval"));
1613 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1614 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1617 void TestRunner::setStatisticsNotifyPagesWhenTelemetryWasCaptured(bool value)
1619 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenTelemetryWasCaptured"));
1620 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1621 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1624 void TestRunner::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
1626 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweenDataRecordsRemoval"));
1627 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1628 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1631 void TestRunner::setStatisticsGrandfatheringTime(double seconds)
1633 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfatheringTime"));
1634 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1635 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1638 void TestRunner::setStatisticsMaxStatisticsEntries(unsigned entries)
1640 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMaxStatisticsEntries"));
1641 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1642 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1645 void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
1647 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetPruneEntriesDownTo"));
1648 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1649 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1652 void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
1654 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1656 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
1657 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1660 void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback)
1662 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1664 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
1665 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(hours));
1666 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1669 void TestRunner::statisticsClearThroughWebsiteDataRemoval(JSValueRef callback)
1671 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1673 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearThroughWebsiteDataRemoval"));
1674 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1677 void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
1679 callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
1682 void TestRunner::statisticsResetToConsistentState()
1684 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsResetToConsistentState"));
1685 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1689 void TestRunner::connectMockGamepad(unsigned index)
1691 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad"));
1692 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1694 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1697 void TestRunner::disconnectMockGamepad(unsigned index)
1699 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad"));
1700 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1702 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1705 void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount)
1707 Vector<WKRetainPtr<WKStringRef>> keys;
1708 Vector<WKRetainPtr<WKTypeRef>> values;
1710 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") });
1711 values.append(toWK(gamepadID));
1713 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1714 values.append({ AdoptWK, WKUInt64Create(index) });
1716 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") });
1717 values.append({ AdoptWK, WKUInt64Create(axisCount) });
1719 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") });
1720 values.append({ AdoptWK, WKUInt64Create(buttonCount) });
1722 Vector<WKStringRef> rawKeys;
1723 Vector<WKTypeRef> rawValues;
1724 rawKeys.resize(keys.size());
1725 rawValues.resize(values.size());
1727 for (size_t i = 0; i < keys.size(); ++i) {
1728 rawKeys[i] = keys[i].get();
1729 rawValues[i] = values[i].get();
1732 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails"));
1733 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1735 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1738 void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value)
1740 Vector<WKRetainPtr<WKStringRef>> keys;
1741 Vector<WKRetainPtr<WKTypeRef>> values;
1743 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1744 values.append({ AdoptWK, WKUInt64Create(index) });
1746 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") });
1747 values.append({ AdoptWK, WKUInt64Create(axisIndex) });
1749 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1750 values.append({ AdoptWK, WKDoubleCreate(value) });
1752 Vector<WKStringRef> rawKeys;
1753 Vector<WKTypeRef> rawValues;
1754 rawKeys.resize(keys.size());
1755 rawValues.resize(values.size());
1757 for (size_t i = 0; i < keys.size(); ++i) {
1758 rawKeys[i] = keys[i].get();
1759 rawValues[i] = values[i].get();
1762 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue"));
1763 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1765 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1768 void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value)
1770 Vector<WKRetainPtr<WKStringRef>> keys;
1771 Vector<WKRetainPtr<WKTypeRef>> values;
1773 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1774 values.append({ AdoptWK, WKUInt64Create(index) });
1776 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") });
1777 values.append({ AdoptWK, WKUInt64Create(buttonIndex) });
1779 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1780 values.append({ AdoptWK, WKDoubleCreate(value) });
1782 Vector<WKStringRef> rawKeys;
1783 Vector<WKTypeRef> rawValues;
1784 rawKeys.resize(keys.size());
1785 rawValues.resize(values.size());
1787 for (size_t i = 0; i < keys.size(); ++i) {
1788 rawKeys[i] = keys[i].get();
1789 rawValues[i] = values[i].get();
1792 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue"));
1793 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1795 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1798 void TestRunner::connectMockGamepad(unsigned)
1802 void TestRunner::disconnectMockGamepad(unsigned)
1806 void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned)
1810 void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double)
1814 void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double)
1817 #endif // PLATFORM(MAC)
1819 void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
1821 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
1822 JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
1824 if (!JSValueIsArray(context, filesValue))
1827 JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
1828 static auto lengthProperty = JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("length"));
1829 JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
1830 if (!JSValueIsNumber(context, filesLengthValue))
1833 auto fileURLs = adoptWK(WKMutableArrayCreate());
1834 auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
1835 for (size_t i = 0; i < filesLength; ++i) {
1836 JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
1837 if (!JSValueIsString(context, fileValue))
1840 auto file = JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, fileValue, nullptr));
1841 size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
1842 auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
1843 JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
1845 WKArrayAppendItem(fileURLs.get(), adoptWK(WKURLCreateWithBaseURL(m_testURL.get(), fileBuffer.get())).get());
1848 static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLs"));
1849 WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
1852 void TestRunner::removeAllSessionCredentials(JSValueRef callback)
1854 cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
1856 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveAllSessionCredentials"));
1857 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
1859 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1862 void TestRunner::callDidRemoveAllSessionCredentialsCallback()
1864 callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
1867 void TestRunner::clearDOMCache(JSStringRef origin)
1869 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCache"));
1870 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1871 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1874 void TestRunner::clearDOMCaches()
1876 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCaches"));
1877 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1880 bool TestRunner::hasDOMCache(JSStringRef origin)
1882 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("HasDOMCache"));
1883 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1884 WKTypeRef returnData = 0;
1885 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1886 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1889 uint64_t TestRunner::domCacheSize(JSStringRef origin)
1891 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DOMCacheSize"));
1892 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1893 WKTypeRef returnData = 0;
1894 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1895 return WKUInt64GetValue(static_cast<WKUInt64Ref>(returnData));
1898 void TestRunner::getApplicationManifestThen(JSValueRef callback)
1900 cacheTestRunnerCallback(GetApplicationManifestCallbackID, callback);
1902 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("GetApplicationManifest"));
1903 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1906 void TestRunner::didGetApplicationManifest()
1908 callTestRunnerCallback(GetApplicationManifestCallbackID);