Resource Load Statistics: Grandfather domains for existing data records
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / InjectedBundle.cpp
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "InjectedBundle.h"
28
29 #include "ActivateFonts.h"
30 #include "InjectedBundlePage.h"
31 #include "StringFunctions.h"
32 #include "WebCoreTestSupport.h"
33 #include <WebKit/WKBundle.h>
34 #include <WebKit/WKBundlePage.h>
35 #include <WebKit/WKBundlePagePrivate.h>
36 #include <WebKit/WKBundlePrivate.h>
37 #include <WebKit/WKRetainPtr.h>
38 #include <WebKit/WebKit2_C.h>
39 #include <wtf/text/CString.h>
40 #include <wtf/text/StringBuilder.h>
41 #include <wtf/Vector.h>
42
43 namespace WTR {
44
45 InjectedBundle& InjectedBundle::singleton()
46 {
47     static InjectedBundle& shared = *new InjectedBundle;
48     return shared;
49 }
50
51 InjectedBundle::InjectedBundle()
52     : m_bundle(0)
53     , m_topLoadingFrame(0)
54     , m_state(Idle)
55     , m_dumpPixels(false)
56     , m_useWaitToDumpWatchdogTimer(true)
57     , m_useWorkQueue(false)
58     , m_timeout(0)
59 {
60 }
61
62 void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
63 {
64     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page);
65 }
66
67 void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
68 {
69     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page);
70 }
71
72 void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo)
73 {
74     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup);
75 }
76
77 void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
78 {
79     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody);
80 }
81
82 void InjectedBundle::didReceiveMessageToPage(WKBundleRef bundle, WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
83 {
84     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessageToPage(page, messageName, messageBody);
85 }
86
87 void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)
88 {
89     m_bundle = bundle;
90
91     WKBundleClientV1 client = {
92         { 1, this },
93         didCreatePage,
94         willDestroyPage,
95         didInitializePageGroup,
96         didReceiveMessage,
97         didReceiveMessageToPage
98     };
99     WKBundleSetClient(m_bundle, &client.base);
100
101     platformInitialize(initializationUserData);
102
103     activateFonts();
104 }
105
106 void InjectedBundle::didCreatePage(WKBundlePageRef page)
107 {
108     m_pages.append(std::make_unique<InjectedBundlePage>(page));
109 }
110
111 void InjectedBundle::willDestroyPage(WKBundlePageRef page)
112 {
113     m_pages.removeFirstMatching([page](auto& current) {
114         return current->page() == page;
115     });
116 }
117
118 void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
119 {
120     m_pageGroup = pageGroup;
121 }
122
123 InjectedBundlePage* InjectedBundle::page() const
124 {
125     // It might be better to have the UI process send over a reference to the main
126     // page instead of just assuming it's the first one.
127     return m_pages[0].get();
128 }
129
130 void InjectedBundle::resetLocalSettings()
131 {
132     setlocale(LC_ALL, "");
133 }
134
135 void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
136 {
137     WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error"));
138     WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown"));
139     WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get());
140 }
141
142 void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody)
143 {
144     if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) {
145         ASSERT(messageBody);
146         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
147         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
148
149         WKRetainPtr<WKStringRef> dumpPixelsKey(AdoptWK, WKStringCreateWithUTF8CString("DumpPixels"));
150         m_dumpPixels = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dumpPixelsKey.get())));
151
152         WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey(AdoptWK, WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer"));
153         m_useWaitToDumpWatchdogTimer = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, useWaitToDumpWatchdogTimerKey.get())));
154
155         WKRetainPtr<WKStringRef> timeoutKey(AdoptWK, WKStringCreateWithUTF8CString("Timeout"));
156         m_timeout = (int)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeoutKey.get())));
157
158         WKRetainPtr<WKStringRef> dumpJSConsoleLogInStdErrKey(AdoptWK, WKStringCreateWithUTF8CString("DumpJSConsoleLogInStdErr"));
159         m_dumpJSConsoleLogInStdErr = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dumpJSConsoleLogInStdErrKey.get())));
160
161         WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack"));
162         WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest"));
163         WKBundlePagePostMessage(page, ackMessageName.get(), ackMessageBody.get());
164
165         beginTesting(messageBodyDictionary);
166         return;
167     }
168
169     if (WKStringIsEqualToUTF8CString(messageName, "Reset")) {
170         ASSERT(messageBody);
171         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
172         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
173
174         WKRetainPtr<WKStringRef> shouldGCKey(AdoptWK, WKStringCreateWithUTF8CString("ShouldGC"));
175         bool shouldGC = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, shouldGCKey.get())));
176
177         if (shouldGC)
178             WKBundleGarbageCollectJavaScriptObjects(m_bundle);
179
180         WKRetainPtr<WKStringRef> allowedHostsKey(AdoptWK, WKStringCreateWithUTF8CString("AllowedHosts"));
181         WKTypeRef allowedHostsValue = WKDictionaryGetItemForKey(messageBodyDictionary, allowedHostsKey.get());
182         if (allowedHostsValue && WKGetTypeID(allowedHostsValue) == WKArrayGetTypeID()) {
183             WKArrayRef allowedHostsArray = static_cast<WKArrayRef>(allowedHostsValue);
184             for (size_t i = 0, size = WKArrayGetSize(allowedHostsArray); i < size; ++i) {
185                 WKTypeRef item = WKArrayGetItemAtIndex(allowedHostsArray, i);
186                 if (item && WKGetTypeID(item) == WKStringGetTypeID())
187                     m_allowedHosts.append(toWTFString(static_cast<WKStringRef>(item)));
188             }
189         }
190
191         m_state = Idle;
192         m_dumpPixels = false;
193         m_pixelResultIsPending = false;
194
195         resetLocalSettings();
196         TestRunner::removeAllWebNotificationPermissions();
197
198         InjectedBundle::page()->resetAfterTest();
199
200         return;
201     }
202
203     if (WKStringIsEqualToUTF8CString(messageName, "CallAddChromeInputFieldCallback")) {
204         m_testRunner->callAddChromeInputFieldCallback();
205         return;
206     }
207
208     if (WKStringIsEqualToUTF8CString(messageName, "CallRemoveChromeInputFieldCallback")) {
209         m_testRunner->callRemoveChromeInputFieldCallback();
210         return;
211     }
212
213     if (WKStringIsEqualToUTF8CString(messageName, "CallFocusWebViewCallback")) {
214         m_testRunner->callFocusWebViewCallback();
215         return;
216     }
217
218     if (WKStringIsEqualToUTF8CString(messageName, "CallSetBackingScaleFactorCallback")) {
219         m_testRunner->callSetBackingScaleFactorCallback();
220         return;
221     }
222
223     if (WKStringIsEqualToUTF8CString(messageName, "CallDidBeginSwipeCallback")) {
224         m_testRunner->callDidBeginSwipeCallback();
225         return;
226     }
227
228     if (WKStringIsEqualToUTF8CString(messageName, "CallWillEndSwipeCallback")) {
229         m_testRunner->callWillEndSwipeCallback();
230         return;
231     }
232
233     if (WKStringIsEqualToUTF8CString(messageName, "CallDidEndSwipeCallback")) {
234         m_testRunner->callDidEndSwipeCallback();
235         return;
236     }
237
238     if (WKStringIsEqualToUTF8CString(messageName, "CallDidRemoveSwipeSnapshotCallback")) {
239         m_testRunner->callDidRemoveSwipeSnapshotCallback();
240         return;
241     }
242
243     if (WKStringIsEqualToUTF8CString(messageName, "NotifyDownloadDone")) {
244         m_testRunner->notifyDone();
245         return;
246     }
247
248     if (WKStringIsEqualToUTF8CString(messageName, "CallUISideScriptCallback")) {
249         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
250
251         WKRetainPtr<WKStringRef> resultKey(AdoptWK, WKStringCreateWithUTF8CString("Result"));
252         WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
253
254         unsigned callbackID = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get())));
255
256         WKStringRef resultString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, resultKey.get()));
257         auto resultJSString = toJS(resultString);
258
259         m_testRunner->runUIScriptCallback(callbackID, resultJSString.get());
260         return;
261     }
262
263     if (WKStringIsEqualToUTF8CString(messageName, "WorkQueueProcessedCallback")) {
264         if (!topLoadingFrame() && !m_testRunner->waitToDump())
265             InjectedBundle::page()->dump();
266         return;
267     }
268
269     if (WKStringIsEqualToUTF8CString(messageName, "WebsiteDataDeletionForTopPrivatelyOwnedDomainsFinished")) {
270         m_testRunner->statisticsDidModifyDataRecordsCallback();
271         return;
272     }
273
274     if (WKStringIsEqualToUTF8CString(messageName, "WebsiteDataScanForTopPrivatelyControlledDomainsFinished")) {
275         m_testRunner->statisticsDidScanDataRecordsCallback();
276         return;
277     }
278
279     WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error"));
280     WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown"));
281     WKBundlePagePostMessage(page, errorMessageName.get(), errorMessageBody.get());
282 }
283
284 bool InjectedBundle::booleanForKey(WKDictionaryRef dictionary, const char* key)
285 {
286     WKRetainPtr<WKStringRef> wkKey(AdoptWK, WKStringCreateWithUTF8CString(key));
287     WKTypeRef value = WKDictionaryGetItemForKey(dictionary, wkKey.get());
288     if (WKGetTypeID(value) != WKBooleanGetTypeID()) {
289         outputText(makeString("Boolean value for key", key, " not found in dictionary\n"));
290         return false;
291     }
292     return WKBooleanGetValue(static_cast<WKBooleanRef>(value));
293 }
294
295 void InjectedBundle::beginTesting(WKDictionaryRef settings)
296 {
297     m_state = Testing;
298
299     m_pixelResult.clear();
300     m_repaintRects.clear();
301
302     m_testRunner = TestRunner::create();
303     m_gcController = GCController::create();
304     m_eventSendingController = EventSendingController::create();
305     m_textInputController = TextInputController::create();
306 #if HAVE(ACCESSIBILITY)
307     m_accessibilityController = AccessibilityController::create();
308 #endif
309
310     WKBundleSetAllowUniversalAccessFromFileURLs(m_bundle, m_pageGroup, true);
311     WKBundleSetJavaScriptCanAccessClipboard(m_bundle, m_pageGroup, true);
312     WKBundleSetPrivateBrowsingEnabled(m_bundle, m_pageGroup, false);
313     WKBundleSetUseDashboardCompatibilityMode(m_bundle, m_pageGroup, false);
314     WKBundleSetAuthorAndUserStylesEnabled(m_bundle, m_pageGroup, true);
315     WKBundleSetFrameFlatteningEnabled(m_bundle, m_pageGroup, false);
316     WKBundleSetMinimumLogicalFontSize(m_bundle, m_pageGroup, 9);
317     WKBundleSetSpatialNavigationEnabled(m_bundle, m_pageGroup, false);
318     WKBundleSetAllowFileAccessFromFileURLs(m_bundle, m_pageGroup, true);
319     WKBundleSetPopupBlockingEnabled(m_bundle, m_pageGroup, false);
320     WKBundleSetAllowStorageAccessFromFileURLS(m_bundle, m_pageGroup, false);
321
322 #if PLATFORM(IOS)
323     WKBundlePageSetUseTestingViewportConfiguration(page()->page(), !booleanForKey(settings, "UseFlexibleViewport"));
324 #endif
325
326     m_testRunner->setPluginsEnabled(true);
327
328     m_testRunner->setShouldDumpFrameLoadCallbacks(booleanForKey(settings, "DumpFrameLoadDelegates"));
329     m_testRunner->setUserStyleSheetEnabled(false);
330     m_testRunner->setXSSAuditorEnabled(false);
331
332     m_testRunner->setWebGL2Enabled(true);
333     m_testRunner->setWebGPUEnabled(true);
334
335     m_testRunner->setWritableStreamAPIEnabled(true);
336     m_testRunner->setReadableByteStreamAPIEnabled(true);
337
338     m_testRunner->setEncryptedMediaAPIEnabled(true);
339
340     m_testRunner->setCloseRemainingWindowsWhenComplete(false);
341     m_testRunner->setAcceptsEditing(true);
342     m_testRunner->setTabKeyCyclesThroughElements(true);
343     m_testRunner->clearTestRunnerCallbacks();
344
345     m_testRunner->setSubtleCryptoEnabled(true);
346
347     if (m_timeout > 0)
348         m_testRunner->setCustomTimeout(m_timeout);
349
350     page()->prepare();
351
352     WKBundleClearAllDatabases(m_bundle);
353     WKBundlePageClearApplicationCache(page()->page());
354     WKBundleResetOriginAccessWhitelists(m_bundle);
355
356     // [WK2] REGRESSION(r128623): It made layout tests extremely slow
357     // https://bugs.webkit.org/show_bug.cgi?id=96862
358     // WKBundleSetDatabaseQuota(m_bundle, 5 * 1024 * 1024);
359 }
360
361 void InjectedBundle::done()
362 {
363     m_state = Stopping;
364
365     m_useWorkQueue = false;
366
367     page()->stopLoading();
368     setTopLoadingFrame(0);
369
370     m_testRunner->invalidateWaitToDumpWatchdogTimer();
371
372     m_accessibilityController->resetToConsistentState();
373
374     WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done"));
375     WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate());
376
377     WKRetainPtr<WKStringRef> pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending"));
378     WKRetainPtr<WKBooleanRef> pixelResultIsPending(AdoptWK, WKBooleanCreate(m_pixelResultIsPending));
379     WKDictionarySetItem(doneMessageBody.get(), pixelResultIsPendingKey.get(), pixelResultIsPending.get());
380
381     if (!m_pixelResultIsPending) {
382         WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
383         WKDictionarySetItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get());
384     }
385
386     WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
387     WKDictionarySetItem(doneMessageBody.get(), repaintRectsKey.get(), m_repaintRects.get());
388
389     WKRetainPtr<WKStringRef> audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult"));
390     WKDictionarySetItem(doneMessageBody.get(), audioResultKey.get(), m_audioResult.get());
391
392     WKBundlePagePostMessage(page()->page(), doneMessageName.get(), doneMessageBody.get());
393
394     closeOtherPages();
395
396     m_state = Idle;
397 }
398
399 void InjectedBundle::closeOtherPages()
400 {
401     Vector<WKBundlePageRef> pagesToClose;
402     size_t size = m_pages.size();
403     for (size_t i = 1; i < size; ++i)
404         pagesToClose.append(m_pages[i]->page());
405     size = pagesToClose.size();
406     for (size_t i = 0; i < size; ++i)
407         WKBundlePageClose(pagesToClose[i]);
408 }
409
410 void InjectedBundle::dumpBackForwardListsForAllPages(StringBuilder& stringBuilder)
411 {
412     size_t size = m_pages.size();
413     for (size_t i = 0; i < size; ++i)
414         m_pages[i]->dumpBackForwardList(stringBuilder);
415 }
416
417 void InjectedBundle::dumpToStdErr(const String& output)
418 {
419     if (m_state != Testing)
420         return;
421     if (output.isEmpty())
422         return;
423     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DumpToStdErr"));
424     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(output.utf8().data()));
425     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
426 }
427
428 void InjectedBundle::outputText(const String& output)
429 {
430     if (m_state != Testing)
431         return;
432     if (output.isEmpty())
433         return;
434     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TextOutput"));
435     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(output.utf8().data()));
436     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
437 }
438
439 void InjectedBundle::postNewBeforeUnloadReturnValue(bool value)
440 {
441     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeforeUnloadReturnValue"));
442     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
443     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
444 }
445
446 void InjectedBundle::postAddChromeInputField()
447 {
448     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("AddChromeInputField"));
449     WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
450 }
451
452 void InjectedBundle::postRemoveChromeInputField()
453 {
454     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveChromeInputField"));
455     WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
456 }
457
458 void InjectedBundle::postFocusWebView()
459 {
460     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("FocusWebView"));
461     WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
462 }
463
464 void InjectedBundle::postSetBackingScaleFactor(double backingScaleFactor)
465 {
466     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBackingScaleFactor"));
467     WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(backingScaleFactor));
468     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
469 }
470
471 void InjectedBundle::postSetWindowIsKey(bool isKey)
472 {
473     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetWindowIsKey"));
474     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(isKey));
475     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0);
476 }
477
478 void InjectedBundle::postSetViewSize(double width, double height)
479 {
480     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetViewSize"));
481
482     WKRetainPtr<WKStringRef> widthKey(AdoptWK, WKStringCreateWithUTF8CString("width"));
483     WKRetainPtr<WKStringRef> heightKey(AdoptWK, WKStringCreateWithUTF8CString("height"));
484
485     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
486
487     WKRetainPtr<WKDoubleRef> widthWK(AdoptWK, WKDoubleCreate(width));
488     WKDictionarySetItem(messageBody.get(), widthKey.get(), widthWK.get());
489
490     WKRetainPtr<WKDoubleRef> heightWK(AdoptWK, WKDoubleCreate(height));
491     WKDictionarySetItem(messageBody.get(), heightKey.get(), heightWK.get());
492
493     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0);
494 }
495
496 void InjectedBundle::postSimulateWebNotificationClick(uint64_t notificationID)
497 {
498     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SimulateWebNotificationClick"));
499     WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(notificationID));
500     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
501 }
502
503 void InjectedBundle::postSetAddsVisitedLinks(bool addsVisitedLinks)
504 {
505     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAddsVisitedLinks"));
506     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(addsVisitedLinks));
507     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
508 }
509
510 void InjectedBundle::setGeolocationPermission(bool enabled)
511 {
512     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetGeolocationPermission"));
513     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
514     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
515 }
516
517 void InjectedBundle::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed)
518 {
519     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGeolocationPosition"));
520
521     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
522
523     WKRetainPtr<WKStringRef> latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude"));
524     WKRetainPtr<WKDoubleRef> latitudeWK(AdoptWK, WKDoubleCreate(latitude));
525     WKDictionarySetItem(messageBody.get(), latitudeKeyWK.get(), latitudeWK.get());
526
527     WKRetainPtr<WKStringRef> longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude"));
528     WKRetainPtr<WKDoubleRef> longitudeWK(AdoptWK, WKDoubleCreate(longitude));
529     WKDictionarySetItem(messageBody.get(), longitudeKeyWK.get(), longitudeWK.get());
530
531     WKRetainPtr<WKStringRef> accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy"));
532     WKRetainPtr<WKDoubleRef> accuracyWK(AdoptWK, WKDoubleCreate(accuracy));
533     WKDictionarySetItem(messageBody.get(), accuracyKeyWK.get(), accuracyWK.get());
534
535     WKRetainPtr<WKStringRef> providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude"));
536     WKRetainPtr<WKBooleanRef> providesAltitudeWK(AdoptWK, WKBooleanCreate(providesAltitude));
537     WKDictionarySetItem(messageBody.get(), providesAltitudeKeyWK.get(), providesAltitudeWK.get());
538
539     WKRetainPtr<WKStringRef> altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude"));
540     WKRetainPtr<WKDoubleRef> altitudeWK(AdoptWK, WKDoubleCreate(altitude));
541     WKDictionarySetItem(messageBody.get(), altitudeKeyWK.get(), altitudeWK.get());
542
543     WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy"));
544     WKRetainPtr<WKBooleanRef> providesAltitudeAccuracyWK(AdoptWK, WKBooleanCreate(providesAltitudeAccuracy));
545     WKDictionarySetItem(messageBody.get(), providesAltitudeAccuracyKeyWK.get(), providesAltitudeAccuracyWK.get());
546
547     WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy"));
548     WKRetainPtr<WKDoubleRef> altitudeAccuracyWK(AdoptWK, WKDoubleCreate(altitudeAccuracy));
549     WKDictionarySetItem(messageBody.get(), altitudeAccuracyKeyWK.get(), altitudeAccuracyWK.get());
550
551     WKRetainPtr<WKStringRef> providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading"));
552     WKRetainPtr<WKBooleanRef> providesHeadingWK(AdoptWK, WKBooleanCreate(providesHeading));
553     WKDictionarySetItem(messageBody.get(), providesHeadingKeyWK.get(), providesHeadingWK.get());
554
555     WKRetainPtr<WKStringRef> headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading"));
556     WKRetainPtr<WKDoubleRef> headingWK(AdoptWK, WKDoubleCreate(heading));
557     WKDictionarySetItem(messageBody.get(), headingKeyWK.get(), headingWK.get());
558
559     WKRetainPtr<WKStringRef> providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed"));
560     WKRetainPtr<WKBooleanRef> providesSpeedWK(AdoptWK, WKBooleanCreate(providesSpeed));
561     WKDictionarySetItem(messageBody.get(), providesSpeedKeyWK.get(), providesSpeedWK.get());
562
563     WKRetainPtr<WKStringRef> speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed"));
564     WKRetainPtr<WKDoubleRef> speedWK(AdoptWK, WKDoubleCreate(speed));
565     WKDictionarySetItem(messageBody.get(), speedKeyWK.get(), speedWK.get());
566
567     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
568 }
569
570 void InjectedBundle::setMockGeolocationPositionUnavailableError(WKStringRef errorMessage)
571 {
572     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGeolocationPositionUnavailableError"));
573     WKBundlePagePostMessage(page()->page(), messageName.get(), errorMessage);
574 }
575
576 bool InjectedBundle::isGeolocationProviderActive() const
577 {
578     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsGeolocationClientActive"));
579     WKTypeRef resultToPass = 0;
580     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
581     WKRetainPtr<WKBooleanRef> isActive(AdoptWK, static_cast<WKBooleanRef>(resultToPass));
582
583     return WKBooleanGetValue(isActive.get());
584 }
585
586 unsigned InjectedBundle::imageCountInGeneralPasteboard() const
587 {
588     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ImageCountInGeneralPasteboard"));
589     WKTypeRef resultToPass = 0;
590     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
591     WKRetainPtr<WKUInt64Ref> imageCount(AdoptWK, static_cast<WKUInt64Ref>(resultToPass));
592     
593     return static_cast<unsigned>(WKUInt64GetValue(imageCount.get()));
594 }
595
596 void InjectedBundle::setUserMediaPermission(bool enabled)
597 {
598     auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermission"));
599     auto messageBody = adoptWK(WKBooleanCreate(enabled));
600     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
601 }
602
603 void InjectedBundle::setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin)
604 {
605     auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPersistentPermissionForOrigin"));
606     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
607
608     WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission"));
609     WKRetainPtr<WKBooleanRef> permissionWK(AdoptWK, WKBooleanCreate(permission));
610     WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get());
611
612     WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
613     WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
614
615     WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
616     WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
617
618     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
619 }
620
621 unsigned InjectedBundle::userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const
622 {
623     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("UserMediaPermissionRequestCountForOrigin"));
624     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
625
626     WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
627     WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
628
629     WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
630     WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
631
632     WKTypeRef resultToPass = 0;
633     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), &resultToPass);
634     WKRetainPtr<WKUInt64Ref> count(AdoptWK, static_cast<WKUInt64Ref>(resultToPass));
635
636     return static_cast<unsigned>(WKUInt64GetValue(count.get()));
637 }
638
639 void InjectedBundle::resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin)
640 {
641     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ResetUserMediaPermissionRequestCountForOrigin"));
642     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
643
644     WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
645     WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
646
647     WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
648     WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
649
650     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
651 }
652
653 void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive)
654 {
655     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCustomPolicyDelegate"));
656
657     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
658
659     WKRetainPtr<WKStringRef> enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled"));
660     WKRetainPtr<WKBooleanRef> enabledWK(AdoptWK, WKBooleanCreate(enabled));
661     WKDictionarySetItem(messageBody.get(), enabledKeyWK.get(), enabledWK.get());
662
663     WKRetainPtr<WKStringRef> permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive"));
664     WKRetainPtr<WKBooleanRef> permissiveWK(AdoptWK, WKBooleanCreate(permissive));
665     WKDictionarySetItem(messageBody.get(), permissiveKeyWK.get(), permissiveWK.get());
666
667     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
668 }
669
670 void InjectedBundle::setHidden(bool hidden)
671 {
672     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHidden"));
673     WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
674
675     WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden"));
676     WKRetainPtr<WKBooleanRef> isInitialWK(AdoptWK, WKBooleanCreate(hidden));
677     WKDictionarySetItem(messageBody.get(), isInitialKeyWK.get(), isInitialWK.get());
678
679     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
680 }
681
682 void InjectedBundle::setCacheModel(int model)
683 {
684     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCacheModel"));
685     WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(model));
686     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
687 }
688
689 bool InjectedBundle::shouldProcessWorkQueue() const
690 {
691     if (!m_useWorkQueue)
692         return false;
693
694     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsWorkQueueEmpty"));
695     WKTypeRef resultToPass = 0;
696     WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
697     WKRetainPtr<WKBooleanRef> isEmpty(AdoptWK, static_cast<WKBooleanRef>(resultToPass));
698
699     return !WKBooleanGetValue(isEmpty.get());
700 }
701
702 void InjectedBundle::processWorkQueue()
703 {
704     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ProcessWorkQueue"));
705     WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
706 }
707
708 void InjectedBundle::queueBackNavigation(unsigned howFarBackward)
709 {
710     m_useWorkQueue = true;
711
712     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueBackNavigation"));
713     WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(howFarBackward));
714     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
715 }
716
717 void InjectedBundle::queueForwardNavigation(unsigned howFarForward)
718 {
719     m_useWorkQueue = true;
720
721     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueForwardNavigation"));
722     WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(howFarForward));
723     WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
724 }
725
726 void InjectedBundle::queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs)
727 {
728     m_useWorkQueue = true;
729
730     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueLoad"));
731
732     WKRetainPtr<WKMutableDictionaryRef> loadData(AdoptWK, WKMutableDictionaryCreate());
733
734     WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
735     WKDictionarySetItem(loadData.get(), urlKey.get(), url);
736
737     WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target"));
738     WKDictionarySetItem(loadData.get(), targetKey.get(), target);
739
740     WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs"));
741     WKRetainPtr<WKBooleanRef> shouldOpenExternalURLsValue(AdoptWK, WKBooleanCreate(shouldOpenExternalURLs));
742     WKDictionarySetItem(loadData.get(), shouldOpenExternalURLsKey.get(), shouldOpenExternalURLsValue.get());
743
744     WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get());
745 }
746
747 void InjectedBundle::queueLoadHTMLString(WKStringRef content, WKStringRef baseURL, WKStringRef unreachableURL)
748 {
749     m_useWorkQueue = true;
750
751     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueLoadHTMLString"));
752
753     WKRetainPtr<WKMutableDictionaryRef> loadData(AdoptWK, WKMutableDictionaryCreate());
754
755     WKRetainPtr<WKStringRef> contentKey(AdoptWK, WKStringCreateWithUTF8CString("content"));
756     WKDictionarySetItem(loadData.get(), contentKey.get(), content);
757
758     if (baseURL) {
759         WKRetainPtr<WKStringRef> baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL"));
760         WKDictionarySetItem(loadData.get(), baseURLKey.get(), baseURL);
761     }
762
763     if (unreachableURL) {
764         WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL"));
765         WKDictionarySetItem(loadData.get(), unreachableURLKey.get(), unreachableURL);
766     }
767
768     WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get());
769 }
770
771 void InjectedBundle::queueReload()
772 {
773     m_useWorkQueue = true;
774
775     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueReload"));
776     WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
777 }
778
779 void InjectedBundle::queueLoadingScript(WKStringRef script)
780 {
781     m_useWorkQueue = true;
782
783     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueLoadingScript"));
784     WKBundlePagePostMessage(page()->page(), messageName.get(), script);
785 }
786
787 void InjectedBundle::queueNonLoadingScript(WKStringRef script)
788 {
789     m_useWorkQueue = true;
790
791     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueNonLoadingScript"));
792     WKBundlePagePostMessage(page()->page(), messageName.get(), script);
793 }
794
795 bool InjectedBundle::isAllowedHost(WKStringRef host)
796 {
797     if (m_allowedHosts.isEmpty())
798         return false;
799     return m_allowedHosts.contains(toWTFString(host));
800 }
801
802 void InjectedBundle::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate)
803 {
804     WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate);
805 }
806
807 } // namespace WTR