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 DidRemoveAllSessionCredentialsCallbackID,
655 GetApplicationManifestCallbackID,
656 FirstUIScriptCallbackID = 100
659 static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
664 if (callbackMap().contains(index)) {
665 InjectedBundle::singleton().outputText(String::format("FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n\n", index));
669 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
670 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
671 JSValueProtect(context, callback);
672 callbackMap().add(index, callback);
675 static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr)
677 if (!callbackMap().contains(index))
679 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
680 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
681 JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0);
682 JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
683 JSValueUnprotect(context, callback);
686 void TestRunner::clearTestRunnerCallbacks()
688 for (auto& iter : callbackMap()) {
689 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
690 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
691 JSObjectRef callback = JSValueToObject(context, iter.value, 0);
692 JSValueUnprotect(context, callback);
695 callbackMap().clear();
698 void TestRunner::accummulateLogsForChannel(JSStringRef)
700 // FIXME: Implement getting the call to all processes.
703 void TestRunner::addChromeInputField(JSValueRef callback)
705 cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
706 InjectedBundle::singleton().postAddChromeInputField();
709 void TestRunner::removeChromeInputField(JSValueRef callback)
711 cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback);
712 InjectedBundle::singleton().postRemoveChromeInputField();
715 void TestRunner::focusWebView(JSValueRef callback)
717 cacheTestRunnerCallback(FocusWebViewCallbackID, callback);
718 InjectedBundle::singleton().postFocusWebView();
721 void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback)
723 cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback);
724 InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor);
727 void TestRunner::setWindowIsKey(bool isKey)
729 InjectedBundle::singleton().postSetWindowIsKey(isKey);
732 void TestRunner::setViewSize(double width, double height)
734 InjectedBundle::singleton().postSetViewSize(width, height);
737 void TestRunner::callAddChromeInputFieldCallback()
739 callTestRunnerCallback(AddChromeInputFieldCallbackID);
742 void TestRunner::callRemoveChromeInputFieldCallback()
744 callTestRunnerCallback(RemoveChromeInputFieldCallbackID);
747 void TestRunner::callFocusWebViewCallback()
749 callTestRunnerCallback(FocusWebViewCallbackID);
752 void TestRunner::callSetBackingScaleFactorCallback()
754 callTestRunnerCallback(SetBackingScaleFactorCallbackID);
757 static inline bool toBool(JSStringRef value)
759 return JSStringIsEqualToUTF8CString(value, "true") || JSStringIsEqualToUTF8CString(value, "1");
762 void TestRunner::overridePreference(JSStringRef preference, JSStringRef value)
764 auto& injectedBundle = InjectedBundle::singleton();
765 // FIXME: handle non-boolean preferences.
766 WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value));
769 void TestRunner::setAlwaysAcceptCookies(bool accept)
771 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies"));
773 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(accept));
775 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
778 void TestRunner::setCookieStoragePartitioningEnabled(bool enabled)
780 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCookieStoragePartitioningEnabled"));
782 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
784 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
787 void TestRunner::setStorageAccessAPIEnabled(bool enabled)
789 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
791 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
793 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
796 double TestRunner::preciseTime()
798 return currentTime();
801 void TestRunner::setUserStyleSheetEnabled(bool enabled)
803 m_userStyleSheetEnabled = enabled;
805 WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString(""));
806 WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get();
807 auto& injectedBundle = InjectedBundle::singleton();
808 WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location);
811 void TestRunner::setUserStyleSheetLocation(JSStringRef location)
813 m_userStyleSheetLocation = adoptWK(WKStringCreateWithJSString(location));
815 if (m_userStyleSheetEnabled)
816 setUserStyleSheetEnabled(true);
819 void TestRunner::setSpatialNavigationEnabled(bool enabled)
821 auto& injectedBundle = InjectedBundle::singleton();
822 WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
825 void TestRunner::setTabKeyCyclesThroughElements(bool enabled)
827 auto& injectedBundle = InjectedBundle::singleton();
828 WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled);
831 void TestRunner::setSerializeHTTPLoads()
833 // WK2 doesn't reorder loads.
836 void TestRunner::dispatchPendingLoadRequests()
838 // WK2 doesn't keep pending requests.
841 void TestRunner::setCacheModel(int model)
843 InjectedBundle::singleton().setCacheModel(model);
846 void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled)
848 auto& injectedBundle = InjectedBundle::singleton();
849 WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled);
852 void TestRunner::grantWebNotificationPermission(JSStringRef origin)
854 WKRetainPtr<WKStringRef> originWK = toWK(origin);
855 auto& injectedBundle = InjectedBundle::singleton();
856 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true);
859 void TestRunner::denyWebNotificationPermission(JSStringRef origin)
861 WKRetainPtr<WKStringRef> originWK = toWK(origin);
862 auto& injectedBundle = InjectedBundle::singleton();
863 WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false);
866 void TestRunner::removeAllWebNotificationPermissions()
868 auto& injectedBundle = InjectedBundle::singleton();
869 WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page());
872 void TestRunner::simulateWebNotificationClick(JSValueRef notification)
874 auto& injectedBundle = InjectedBundle::singleton();
875 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
876 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
877 uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification);
878 injectedBundle.postSimulateWebNotificationClick(notificationID);
881 void TestRunner::setGeolocationPermission(bool enabled)
883 // FIXME: this should be done by frame.
884 InjectedBundle::singleton().setGeolocationPermission(enabled);
887 bool TestRunner::isGeolocationProviderActive()
889 return InjectedBundle::singleton().isGeolocationProviderActive();
892 void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed, JSValueRef jsFloorLevel)
894 auto& injectedBundle = InjectedBundle::singleton();
895 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page());
896 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
898 bool providesAltitude = false;
899 double altitude = 0.;
900 if (!JSValueIsUndefined(context, jsAltitude)) {
901 providesAltitude = true;
902 altitude = JSValueToNumber(context, jsAltitude, 0);
905 bool providesAltitudeAccuracy = false;
906 double altitudeAccuracy = 0.;
907 if (!JSValueIsUndefined(context, jsAltitudeAccuracy)) {
908 providesAltitudeAccuracy = true;
909 altitudeAccuracy = JSValueToNumber(context, jsAltitudeAccuracy, 0);
912 bool providesHeading = false;
914 if (!JSValueIsUndefined(context, jsHeading)) {
915 providesHeading = true;
916 heading = JSValueToNumber(context, jsHeading, 0);
919 bool providesSpeed = false;
921 if (!JSValueIsUndefined(context, jsSpeed)) {
922 providesSpeed = true;
923 speed = JSValueToNumber(context, jsSpeed, 0);
926 bool providesFloorLevel = false;
927 double floorLevel = 0.;
928 if (!JSValueIsUndefined(context, jsFloorLevel)) {
929 providesFloorLevel = true;
930 floorLevel = JSValueToNumber(context, jsFloorLevel, 0);
933 injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed, providesFloorLevel, floorLevel);
936 void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
938 WKRetainPtr<WKStringRef> messageWK = toWK(message);
939 InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get());
942 void TestRunner::setUserMediaPermission(bool enabled)
944 // FIXME: this should be done by frame.
945 InjectedBundle::singleton().setUserMediaPermission(enabled);
948 void TestRunner::resetUserMediaPermission()
950 // FIXME: this should be done by frame.
951 InjectedBundle::singleton().resetUserMediaPermission();
954 void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
956 WKRetainPtr<WKStringRef> originWK = toWK(origin);
957 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
958 InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
961 unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
963 WKRetainPtr<WKStringRef> originWK = toWK(origin);
964 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
965 return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
968 void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
970 WKRetainPtr<WKStringRef> originWK = toWK(origin);
971 WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
972 InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
975 bool TestRunner::callShouldCloseOnWebView()
977 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
978 return WKBundleFrameCallShouldCloseOnWebView(mainFrame);
981 void TestRunner::queueBackNavigation(unsigned howFarBackward)
983 InjectedBundle::singleton().queueBackNavigation(howFarBackward);
986 void TestRunner::queueForwardNavigation(unsigned howFarForward)
988 InjectedBundle::singleton().queueForwardNavigation(howFarForward);
991 void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs)
993 auto& injectedBundle = InjectedBundle::singleton();
994 WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page())));
995 WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data()));
996 WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get()));
998 injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs);
1001 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
1003 WKRetainPtr<WKStringRef> contentWK = toWK(content);
1004 WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>();
1005 WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>();
1007 InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get());
1010 void TestRunner::queueReload()
1012 InjectedBundle::singleton().queueReload();
1015 void TestRunner::queueLoadingScript(JSStringRef script)
1017 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1018 InjectedBundle::singleton().queueLoadingScript(scriptWK.get());
1021 void TestRunner::queueNonLoadingScript(JSStringRef script)
1023 WKRetainPtr<WKStringRef> scriptWK = toWK(script);
1024 InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get());
1027 void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value)
1029 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges"));
1030 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1031 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1034 void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
1036 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges"));
1037 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges));
1038 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1041 void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value)
1043 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace"));
1044 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1045 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1048 void TestRunner::setShouldLogDownloadCallbacks(bool value)
1050 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogDownloadCallbacks"));
1051 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1052 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1055 void TestRunner::setAuthenticationUsername(JSStringRef username)
1057 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername"));
1058 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(username));
1059 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1062 void TestRunner::setAuthenticationPassword(JSStringRef password)
1064 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationPassword"));
1065 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(password));
1066 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1069 bool TestRunner::secureEventInputIsEnabled() const
1071 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SecureEventInputIsEnabled"));
1072 WKTypeRef returnData = 0;
1074 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), 0, &returnData);
1075 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1078 void TestRunner::setBlockAllPlugins(bool shouldBlock)
1080 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBlockAllPlugins"));
1081 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldBlock));
1082 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1085 JSValueRef TestRunner::failNextNewCodeBlock()
1087 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1088 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1089 return JSC::failNextNewCodeBlock(context);
1092 JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction)
1094 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1095 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1096 return JSC::numberOfDFGCompiles(context, theFunction);
1099 JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction)
1101 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1102 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1103 return JSC::setNeverInline(context, theFunction);
1106 void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value)
1108 m_shouldDecideNavigationPolicyAfterDelay = value;
1109 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay"));
1110 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1111 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1114 void TestRunner::setNavigationGesturesEnabled(bool value)
1116 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled"));
1117 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1118 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1121 void TestRunner::setIgnoresViewportScaleLimits(bool value)
1123 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits"));
1124 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1125 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1128 void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value)
1130 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes"));
1131 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1132 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
1135 void TestRunner::terminateNetworkProcess()
1137 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateNetworkProcess"));
1138 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1141 void TestRunner::terminateServiceWorkerProcess()
1143 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TerminateServiceWorkerProcess"));
1144 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr);
1147 static unsigned nextUIScriptCallbackID()
1149 static unsigned callbackID = FirstUIScriptCallbackID;
1150 return callbackID++;
1153 void TestRunner::runUIScript(JSStringRef script, JSValueRef callback)
1155 unsigned callbackID = nextUIScriptCallbackID();
1156 cacheTestRunnerCallback(callbackID, callback);
1158 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RunUIProcessScript"));
1160 WKRetainPtr<WKMutableDictionaryRef> testDictionary(AdoptWK, WKMutableDictionaryCreate());
1162 WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
1163 WKRetainPtr<WKStringRef> scriptValue(AdoptWK, WKStringCreateWithJSString(script));
1165 WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
1166 WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID));
1168 WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get());
1169 WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get());
1171 WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get());
1174 void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result)
1176 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1177 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1179 JSValueRef resultValue = JSValueMakeString(context, result);
1180 callTestRunnerCallback(callbackID, 1, &resultValue);
1183 void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
1185 cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
1188 void TestRunner::installWillEndSwipeCallback(JSValueRef callback)
1190 cacheTestRunnerCallback(WillEndSwipeCallbackID, callback);
1193 void TestRunner::installDidEndSwipeCallback(JSValueRef callback)
1195 cacheTestRunnerCallback(DidEndSwipeCallbackID, callback);
1198 void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback)
1200 cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback);
1203 void TestRunner::callDidBeginSwipeCallback()
1205 callTestRunnerCallback(DidBeginSwipeCallbackID);
1208 void TestRunner::callWillEndSwipeCallback()
1210 callTestRunnerCallback(WillEndSwipeCallbackID);
1213 void TestRunner::callDidEndSwipeCallback()
1215 callTestRunnerCallback(DidEndSwipeCallbackID);
1218 void TestRunner::callDidRemoveSwipeSnapshotCallback()
1220 callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
1223 void TestRunner::setStatisticsLastSeen(JSStringRef hostName, double seconds)
1225 Vector<WKRetainPtr<WKStringRef>> keys;
1226 Vector<WKRetainPtr<WKTypeRef>> values;
1228 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1229 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1231 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1232 values.append({ AdoptWK, WKDoubleCreate(seconds) });
1234 Vector<WKStringRef> rawKeys(keys.size());
1235 Vector<WKTypeRef> rawValues(values.size());
1237 for (size_t i = 0; i < keys.size(); ++i) {
1238 rawKeys[i] = keys[i].get();
1239 rawValues[i] = values[i].get();
1242 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsLastSeen"));
1243 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1245 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1248 void TestRunner::setStatisticsPrevalentResource(JSStringRef hostName, bool value)
1250 Vector<WKRetainPtr<WKStringRef>> keys;
1251 Vector<WKRetainPtr<WKTypeRef>> values;
1253 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1254 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1256 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1257 values.append({ AdoptWK, WKBooleanCreate(value) });
1259 Vector<WKStringRef> rawKeys;
1260 Vector<WKTypeRef> rawValues;
1261 rawKeys.resize(keys.size());
1262 rawValues.resize(values.size());
1264 for (size_t i = 0; i < keys.size(); ++i) {
1265 rawKeys[i] = keys[i].get();
1266 rawValues[i] = values[i].get();
1269 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsPrevalentResource"));
1270 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1272 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1275 bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName)
1277 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource"));
1278 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1279 WKTypeRef returnData = 0;
1280 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1281 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1284 bool TestRunner::isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost)
1286 Vector<WKRetainPtr<WKStringRef>> keys;
1287 Vector<WKRetainPtr<WKTypeRef>> values;
1289 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("SubFrameHost") });
1290 values.append({ AdoptWK, WKStringCreateWithJSString(subFrameHost) });
1292 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHost") });
1293 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHost) });
1295 Vector<WKStringRef> rawKeys(keys.size());
1296 Vector<WKTypeRef> rawValues(values.size());
1298 for (size_t i = 0; i < keys.size(); ++i) {
1299 rawKeys[i] = keys[i].get();
1300 rawValues[i] = values[i].get();
1303 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubFrameUnder"));
1304 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1305 WKTypeRef returnData = 0;
1306 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1307 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1310 bool TestRunner::isStatisticsRegisteredAsRedirectingTo(JSStringRef hostRedirectedFrom, JSStringRef hostRedirectedTo)
1312 Vector<WKRetainPtr<WKStringRef>> keys;
1313 Vector<WKRetainPtr<WKTypeRef>> values;
1315 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedFrom") });
1316 values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedFrom) });
1318 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostRedirectedTo") });
1319 values.append({ AdoptWK, WKStringCreateWithJSString(hostRedirectedTo) });
1321 Vector<WKStringRef> rawKeys(keys.size());
1322 Vector<WKTypeRef> rawValues(values.size());
1324 for (size_t i = 0; i < keys.size(); ++i) {
1325 rawKeys[i] = keys[i].get();
1326 rawValues[i] = values[i].get();
1329 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsRedirectingTo"));
1330 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1331 WKTypeRef returnData = 0;
1332 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1333 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1336 void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value)
1338 Vector<WKRetainPtr<WKStringRef>> keys;
1339 Vector<WKRetainPtr<WKTypeRef>> values;
1341 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1342 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1344 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1345 values.append({ AdoptWK, WKBooleanCreate(value) });
1347 Vector<WKStringRef> rawKeys;
1348 Vector<WKTypeRef> rawValues;
1349 rawKeys.resize(keys.size());
1350 rawValues.resize(values.size());
1352 for (size_t i = 0; i < keys.size(); ++i) {
1353 rawKeys[i] = keys[i].get();
1354 rawValues[i] = values[i].get();
1357 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction"));
1358 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1360 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1363 void TestRunner::setStatisticsHasHadNonRecentUserInteraction(JSStringRef hostName)
1365 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadNonRecentUserInteraction"));
1366 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1367 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1370 bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName)
1372 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction"));
1373 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1374 WKTypeRef returnData = 0;
1375 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1376 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1379 void TestRunner::setStatisticsGrandfathered(JSStringRef hostName, bool value)
1381 Vector<WKRetainPtr<WKStringRef>> keys;
1382 Vector<WKRetainPtr<WKTypeRef>> values;
1384 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1385 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1387 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1388 values.append({ AdoptWK, WKBooleanCreate(value) });
1390 Vector<WKStringRef> rawKeys;
1391 Vector<WKTypeRef> rawValues;
1392 rawKeys.resize(keys.size());
1393 rawValues.resize(values.size());
1395 for (size_t i = 0; i < keys.size(); ++i) {
1396 rawKeys[i] = keys[i].get();
1397 rawValues[i] = values[i].get();
1400 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfathered"));
1401 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1403 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1406 bool TestRunner::isStatisticsGrandfathered(JSStringRef hostName)
1408 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsGrandfathered"));
1409 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName));
1410 WKTypeRef returnData = 0;
1411 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1412 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1415 void TestRunner::setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1417 Vector<WKRetainPtr<WKStringRef>> keys;
1418 Vector<WKRetainPtr<WKTypeRef>> values;
1420 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1421 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1423 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1424 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1426 Vector<WKStringRef> rawKeys(keys.size());
1427 Vector<WKTypeRef> rawValues(values.size());
1429 for (size_t i = 0; i < keys.size(); ++i) {
1430 rawKeys[i] = keys[i].get();
1431 rawValues[i] = values[i].get();
1434 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubframeUnderTopFrameOrigin"));
1435 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1436 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1439 void TestRunner::setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName)
1441 Vector<WKRetainPtr<WKStringRef>> keys;
1442 Vector<WKRetainPtr<WKTypeRef>> values;
1444 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1445 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1447 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHostName") });
1448 values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHostName) });
1450 Vector<WKStringRef> rawKeys(keys.size());
1451 Vector<WKTypeRef> rawValues(values.size());
1453 for (size_t i = 0; i < keys.size(); ++i) {
1454 rawKeys[i] = keys[i].get();
1455 rawValues[i] = values[i].get();
1458 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUnderTopFrameOrigin"));
1459 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1460 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1463 void TestRunner::setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
1465 Vector<WKRetainPtr<WKStringRef>> keys;
1466 Vector<WKRetainPtr<WKTypeRef>> values;
1468 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1469 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1471 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo") });
1472 values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedTo) });
1474 Vector<WKStringRef> rawKeys(keys.size());
1475 Vector<WKTypeRef> rawValues(values.size());
1477 for (size_t i = 0; i < keys.size(); ++i) {
1478 rawKeys[i] = keys[i].get();
1479 rawValues[i] = values[i].get();
1482 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectTo"));
1483 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1484 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1487 void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
1489 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));
1490 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1491 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1494 void TestRunner::setStatisticsTimeToLiveCookiePartitionFree(double seconds)
1496 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveCookiePartitionFree"));
1497 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1498 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1501 void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback)
1503 cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback);
1506 void TestRunner::statisticsDidModifyDataRecordsCallback()
1508 callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID);
1511 void TestRunner::installStatisticsDidScanDataRecordsCallback(JSValueRef callback)
1513 cacheTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID, callback);
1516 void TestRunner::statisticsDidScanDataRecordsCallback()
1518 callTestRunnerCallback(StatisticsDidScanDataRecordsCallbackID);
1521 void TestRunner::installStatisticsDidRunTelemetryCallback(JSValueRef callback)
1523 cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
1526 void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
1528 WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
1529 JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
1531 StringBuilder stringBuilder;
1532 stringBuilder.appendLiteral("{ \"totalPrevalentResources\" : ");
1533 stringBuilder.appendNumber(totalPrevalentResources);
1534 stringBuilder.appendLiteral(", \"totalPrevalentResourcesWithUserInteraction\" : ");
1535 stringBuilder.appendNumber(totalPrevalentResourcesWithUserInteraction);
1536 stringBuilder.appendLiteral(", \"top3SubframeUnderTopFrameOrigins\" : ");
1537 stringBuilder.appendNumber(top3SubframeUnderTopFrameOrigins);
1538 stringBuilder.appendLiteral(" }");
1540 JSValueRef result = JSValueMakeFromJSONString(context, JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data()));
1542 callTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, 1, &result);
1545 void TestRunner::statisticsNotifyObserver()
1547 InjectedBundle::singleton().statisticsNotifyObserver();
1550 void TestRunner::statisticsProcessStatisticsAndDataRecords()
1552 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsProcessStatisticsAndDataRecords"));
1553 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1556 void TestRunner::statisticsUpdateCookiePartitioning()
1558 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsUpdateCookiePartitioning"));
1559 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1562 void TestRunner::statisticsSetShouldPartitionCookiesForHost(JSStringRef hostName, bool value)
1564 Vector<WKRetainPtr<WKStringRef>> keys;
1565 Vector<WKRetainPtr<WKTypeRef>> values;
1567 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
1568 values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
1570 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1571 values.append({ AdoptWK, WKBooleanCreate(value) });
1573 Vector<WKStringRef> rawKeys(keys.size());
1574 Vector<WKTypeRef> rawValues(values.size());
1576 for (size_t i = 0; i < keys.size(); ++i) {
1577 rawKeys[i] = keys[i].get();
1578 rawValues[i] = values[i].get();
1581 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSetShouldPartitionCookiesForHost"));
1582 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1584 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1587 void TestRunner::statisticsSubmitTelemetry()
1589 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsSubmitTelemetry"));
1590 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1593 void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value)
1595 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned"));
1596 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1597 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1600 void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
1602 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval"));
1603 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1604 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1607 void TestRunner::setStatisticsNotifyPagesWhenTelemetryWasCaptured(bool value)
1609 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenTelemetryWasCaptured"));
1610 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
1611 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1614 void TestRunner::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
1616 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweenDataRecordsRemoval"));
1617 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1618 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1621 void TestRunner::setStatisticsGrandfatheringTime(double seconds)
1623 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsGrandfatheringTime"));
1624 WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
1625 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1628 void TestRunner::setStatisticsMaxStatisticsEntries(unsigned entries)
1630 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMaxStatisticsEntries"));
1631 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1632 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1635 void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
1637 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetPruneEntriesDownTo"));
1638 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(entries));
1639 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1642 void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
1644 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1646 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
1647 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1650 void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback)
1652 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1654 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
1655 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(hours));
1656 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1659 void TestRunner::statisticsClearThroughWebsiteDataRemoval(JSValueRef callback)
1661 cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
1663 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsClearThroughWebsiteDataRemoval"));
1664 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1667 void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
1669 callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
1672 void TestRunner::statisticsResetToConsistentState()
1674 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsResetToConsistentState"));
1675 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
1679 void TestRunner::connectMockGamepad(unsigned index)
1681 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad"));
1682 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1684 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1687 void TestRunner::disconnectMockGamepad(unsigned index)
1689 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad"));
1690 WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index));
1692 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1695 void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount)
1697 Vector<WKRetainPtr<WKStringRef>> keys;
1698 Vector<WKRetainPtr<WKTypeRef>> values;
1700 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") });
1701 values.append(toWK(gamepadID));
1703 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1704 values.append({ AdoptWK, WKUInt64Create(index) });
1706 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") });
1707 values.append({ AdoptWK, WKUInt64Create(axisCount) });
1709 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") });
1710 values.append({ AdoptWK, WKUInt64Create(buttonCount) });
1712 Vector<WKStringRef> rawKeys;
1713 Vector<WKTypeRef> rawValues;
1714 rawKeys.resize(keys.size());
1715 rawValues.resize(values.size());
1717 for (size_t i = 0; i < keys.size(); ++i) {
1718 rawKeys[i] = keys[i].get();
1719 rawValues[i] = values[i].get();
1722 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails"));
1723 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1725 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1728 void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value)
1730 Vector<WKRetainPtr<WKStringRef>> keys;
1731 Vector<WKRetainPtr<WKTypeRef>> values;
1733 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1734 values.append({ AdoptWK, WKUInt64Create(index) });
1736 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") });
1737 values.append({ AdoptWK, WKUInt64Create(axisIndex) });
1739 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1740 values.append({ AdoptWK, WKDoubleCreate(value) });
1742 Vector<WKStringRef> rawKeys;
1743 Vector<WKTypeRef> rawValues;
1744 rawKeys.resize(keys.size());
1745 rawValues.resize(values.size());
1747 for (size_t i = 0; i < keys.size(); ++i) {
1748 rawKeys[i] = keys[i].get();
1749 rawValues[i] = values[i].get();
1752 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue"));
1753 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1755 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1758 void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value)
1760 Vector<WKRetainPtr<WKStringRef>> keys;
1761 Vector<WKRetainPtr<WKTypeRef>> values;
1763 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") });
1764 values.append({ AdoptWK, WKUInt64Create(index) });
1766 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") });
1767 values.append({ AdoptWK, WKUInt64Create(buttonIndex) });
1769 keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") });
1770 values.append({ AdoptWK, WKDoubleCreate(value) });
1772 Vector<WKStringRef> rawKeys;
1773 Vector<WKTypeRef> rawValues;
1774 rawKeys.resize(keys.size());
1775 rawValues.resize(values.size());
1777 for (size_t i = 0; i < keys.size(); ++i) {
1778 rawKeys[i] = keys[i].get();
1779 rawValues[i] = values[i].get();
1782 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue"));
1783 WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
1785 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1788 void TestRunner::connectMockGamepad(unsigned)
1792 void TestRunner::disconnectMockGamepad(unsigned)
1796 void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned)
1800 void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double)
1804 void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double)
1807 #endif // PLATFORM(MAC)
1809 void TestRunner::setOpenPanelFiles(JSValueRef filesValue)
1811 WKBundlePageRef page = InjectedBundle::singleton().page()->page();
1812 JSContextRef context = WKBundleFrameGetJavaScriptContext(WKBundlePageGetMainFrame(page));
1814 if (!JSValueIsArray(context, filesValue))
1817 JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
1818 static auto lengthProperty = JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("length"));
1819 JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
1820 if (!JSValueIsNumber(context, filesLengthValue))
1823 auto fileURLs = adoptWK(WKMutableArrayCreate());
1824 auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
1825 for (size_t i = 0; i < filesLength; ++i) {
1826 JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
1827 if (!JSValueIsString(context, fileValue))
1830 auto file = JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, fileValue, nullptr));
1831 size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
1832 auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
1833 JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
1835 WKArrayAppendItem(fileURLs.get(), adoptWK(WKURLCreateWithBaseURL(m_testURL.get(), fileBuffer.get())).get());
1838 static auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetOpenPanelFileURLs"));
1839 WKBundlePagePostMessage(page, messageName.get(), fileURLs.get());
1842 void TestRunner::removeAllSessionCredentials(JSValueRef callback)
1844 cacheTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID, callback);
1846 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveAllSessionCredentials"));
1847 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true));
1849 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1852 void TestRunner::callDidRemoveAllSessionCredentialsCallback()
1854 callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
1857 void TestRunner::clearDOMCache(JSStringRef origin)
1859 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCache"));
1860 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1861 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
1864 void TestRunner::clearDOMCaches()
1866 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCaches"));
1867 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1870 bool TestRunner::hasDOMCache(JSStringRef origin)
1872 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("HasDOMCache"));
1873 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1874 WKTypeRef returnData = 0;
1875 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1876 return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
1879 uint64_t TestRunner::domCacheSize(JSStringRef origin)
1881 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DOMCacheSize"));
1882 WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
1883 WKTypeRef returnData = 0;
1884 WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
1885 return WKUInt64GetValue(static_cast<WKUInt64Ref>(returnData));
1888 void TestRunner::getApplicationManifestThen(JSValueRef callback)
1890 cacheTestRunnerCallback(GetApplicationManifestCallbackID, callback);
1892 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("GetApplicationManifest"));
1893 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
1896 void TestRunner::didGetApplicationManifest()
1898 callTestRunnerCallback(GetApplicationManifestCallbackID);