1/*
2 * Copyright (C) 2010-2018 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 <JavaScriptCore/Options.h>
34#include <WebKit/WKBundle.h>
35#include <WebKit/WKBundlePage.h>
36#include <WebKit/WKBundlePagePrivate.h>
37#include <WebKit/WKBundlePrivate.h>
38#include <WebKit/WKRetainPtr.h>
39#include <WebKit/WebKit2_C.h>
40#include <wtf/text/CString.h>
41#include <wtf/text/StringBuilder.h>
42#include <wtf/Vector.h>
43
44namespace WTR {
45
46static void handleTextDidChangeInTextField(WKBundlePageRef, WKBundleNodeHandleRef, WKBundleFrameRef, const void* context)
47{
48 static_cast<InjectedBundle*>(const_cast<void*>(context))->textDidChangeInTextField();
49}
50
51static void handleTextFieldDidBeginEditing(WKBundlePageRef, WKBundleNodeHandleRef, WKBundleFrameRef, const void* context)
52{
53 static_cast<InjectedBundle*>(const_cast<void*>(context))->textFieldDidBeginEditing();
54}
55
56static void handleTextFieldDidEndEditing(WKBundlePageRef, WKBundleNodeHandleRef, WKBundleFrameRef, const void* context)
57{
58 static_cast<InjectedBundle*>(const_cast<void*>(context))->textFieldDidEndEditing();
59}
60
61InjectedBundle& InjectedBundle::singleton()
62{
63 static InjectedBundle& shared = *new InjectedBundle;
64 return shared;
65}
66
67void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
68{
69 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page);
70}
71
72void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
73{
74 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page);
75}
76
77void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo)
78{
79 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup);
80}
81
82void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
83{
84 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody);
85}
86
87void InjectedBundle::didReceiveMessageToPage(WKBundleRef bundle, WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
88{
89 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessageToPage(page, messageName, messageBody);
90}
91
92void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)
93{
94 m_bundle = bundle;
95
96 WKBundleClientV1 client = {
97 { 1, this },
98 didCreatePage,
99 willDestroyPage,
100 didInitializePageGroup,
101 didReceiveMessage,
102 didReceiveMessageToPage
103 };
104 WKBundleSetClient(m_bundle, &client.base);
105 WKBundleSetServiceWorkerProxyCreationCallback(m_bundle, WebCoreTestSupport::setupNewlyCreatedServiceWorker);
106 platformInitialize(initializationUserData);
107
108 activateFonts();
109}
110
111void InjectedBundle::didCreatePage(WKBundlePageRef page)
112{
113 bool isMainPage = m_pages.isEmpty();
114 m_pages.append(std::make_unique<InjectedBundlePage>(page));
115
116 setUpInjectedBundleClients(page);
117
118 if (!isMainPage)
119 return;
120
121 WKRetainPtr<WKStringRef> messsageName = adoptWK(WKStringCreateWithUTF8CString("Initialization"));
122 WKTypeRef result = nullptr;
123 WKBundlePostSynchronousMessage(m_bundle, messsageName.get(), nullptr, &result);
124 ASSERT(WKGetTypeID(result) == WKDictionaryGetTypeID());
125 WKRetainPtr<WKDictionaryRef> initializationDictionary = adoptWK(static_cast<WKDictionaryRef>(result));
126
127 WKRetainPtr<WKStringRef> resumeTestingKey = adoptWK(WKStringCreateWithUTF8CString("ResumeTesting"));
128 WKTypeRef resumeTestingValue = WKDictionaryGetItemForKey(initializationDictionary.get(), resumeTestingKey.get());
129 ASSERT(WKGetTypeID(resumeTestingValue) == WKBooleanGetTypeID());
130 if (WKBooleanGetValue(static_cast<WKBooleanRef>(resumeTestingValue)))
131 beginTesting(initializationDictionary.get(), BegingTestingMode::Resume);
132}
133
134void InjectedBundle::willDestroyPage(WKBundlePageRef page)
135{
136 m_pages.removeFirstMatching([page](auto& current) {
137 return current->page() == page;
138 });
139}
140
141void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
142{
143 m_pageGroup = pageGroup;
144}
145
146void InjectedBundle::setUpInjectedBundleClients(WKBundlePageRef page)
147{
148 WKBundlePageFormClientV2 formClient = {
149 { 2, this },
150 handleTextFieldDidBeginEditing,
151 handleTextFieldDidEndEditing,
152 handleTextDidChangeInTextField,
153 0, // textDidChangeInTextArea
154 0, // shouldPerformActionInTextField
155 0, // willSubmitForm
156 0, // willSendSubmitEvent
157 0, // didFocusTextField
158 0, // shouldNotifyOnFormChanges
159 0, // didAssociateFormControls
160 };
161 WKBundlePageSetFormClient(page, &formClient.base);
162}
163
164InjectedBundlePage* InjectedBundle::page() const
165{
166 // It might be better to have the UI process send over a reference to the main
167 // page instead of just assuming it's the first one.
168 return m_pages[0].get();
169}
170
171void InjectedBundle::resetLocalSettings()
172{
173 setlocale(LC_ALL, "");
174}
175
176void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
177{
178 WKRetainPtr<WKStringRef> errorMessageName = adoptWK(WKStringCreateWithUTF8CString("Error"));
179 WKRetainPtr<WKStringRef> errorMessageBody = adoptWK(WKStringCreateWithUTF8CString("Unknown"));
180 WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get());
181}
182
183static void postGCTask(void* context)
184{
185 WKBundlePageRef page = reinterpret_cast<WKBundlePageRef>(context);
186 InjectedBundle::singleton().reportLiveDocuments(page);
187 WKRelease(page);
188}
189
190void InjectedBundle::reportLiveDocuments(WKBundlePageRef page)
191{
192 // Release memory again, after the GC and timer fire. This is necessary to clear entries from CachedResourceLoader's m_documentResources in some scenarios.
193 WKBundleReleaseMemory(m_bundle);
194
195 const bool excludeDocumentsInPageGroup = true;
196 auto documentURLs = adoptWK(WKBundleGetLiveDocumentURLs(m_bundle, m_pageGroup, excludeDocumentsInPageGroup));
197 auto ackMessageName = adoptWK(WKStringCreateWithUTF8CString("LiveDocuments"));
198 WKBundlePagePostMessage(page, ackMessageName.get(), documentURLs.get());
199}
200
201void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody)
202{
203 if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) {
204 ASSERT(messageBody);
205 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
206 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
207
208 WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels"));
209 m_dumpPixels = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dumpPixelsKey.get())));
210
211 WKRetainPtr<WKStringRef> timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout"));
212 m_timeout = Seconds::fromMilliseconds(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeoutKey.get()))));
213
214 WKRetainPtr<WKStringRef> dumpJSConsoleLogInStdErrKey = adoptWK(WKStringCreateWithUTF8CString("DumpJSConsoleLogInStdErr"));
215 m_dumpJSConsoleLogInStdErr = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dumpJSConsoleLogInStdErrKey.get())));
216
217 WKRetainPtr<WKStringRef> ackMessageName = adoptWK(WKStringCreateWithUTF8CString("Ack"));
218 WKRetainPtr<WKStringRef> ackMessageBody = adoptWK(WKStringCreateWithUTF8CString("BeginTest"));
219 WKBundlePagePostMessage(page, ackMessageName.get(), ackMessageBody.get());
220
221 beginTesting(messageBodyDictionary, BegingTestingMode::New);
222 return;
223 }
224
225 if (WKStringIsEqualToUTF8CString(messageName, "Reset")) {
226 ASSERT(messageBody);
227 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
228 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
229 WKRetainPtr<WKStringRef> jscOptionsKey = adoptWK(WKStringCreateWithUTF8CString("JSCOptions"));
230 WKRetainPtr<WKStringRef> jscOptionsString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, jscOptionsKey.get()));
231 if (jscOptionsString) {
232 String options = toWTFString(jscOptionsString);
233 JSC::Options::setOptions(options.utf8().data());
234 }
235
236 WKRetainPtr<WKStringRef> shouldGCKey = adoptWK(WKStringCreateWithUTF8CString("ShouldGC"));
237 bool shouldGC = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, shouldGCKey.get())));
238 if (shouldGC)
239 WKBundleGarbageCollectJavaScriptObjects(m_bundle);
240
241 WKRetainPtr<WKStringRef> allowedHostsKey = adoptWK(WKStringCreateWithUTF8CString("AllowedHosts"));
242 WKTypeRef allowedHostsValue = WKDictionaryGetItemForKey(messageBodyDictionary, allowedHostsKey.get());
243 if (allowedHostsValue && WKGetTypeID(allowedHostsValue) == WKArrayGetTypeID()) {
244 m_allowedHosts.clear();
245
246 WKArrayRef allowedHostsArray = static_cast<WKArrayRef>(allowedHostsValue);
247 for (size_t i = 0, size = WKArrayGetSize(allowedHostsArray); i < size; ++i) {
248 WKTypeRef item = WKArrayGetItemAtIndex(allowedHostsArray, i);
249 if (item && WKGetTypeID(item) == WKStringGetTypeID())
250 m_allowedHosts.append(toWTFString(static_cast<WKStringRef>(item)));
251 }
252 }
253
254 m_state = Idle;
255 m_dumpPixels = false;
256 m_pixelResultIsPending = false;
257
258 resetLocalSettings();
259 TestRunner::removeAllWebNotificationPermissions();
260
261 InjectedBundle::page()->resetAfterTest();
262 return;
263 }
264
265 if (WKStringIsEqualToUTF8CString(messageName, "GetLiveDocuments")) {
266 const bool excludeDocumentsInPageGroup = false;
267 auto documentURLs = adoptWK(WKBundleGetLiveDocumentURLs(m_bundle, m_pageGroup, excludeDocumentsInPageGroup));
268 auto ackMessageName = adoptWK(WKStringCreateWithUTF8CString("LiveDocuments"));
269 WKBundlePagePostMessage(page, ackMessageName.get(), documentURLs.get());
270 return;
271 }
272
273 if (WKStringIsEqualToUTF8CString(messageName, "CheckForWorldLeaks")) {
274 WKBundleReleaseMemory(m_bundle);
275
276 WKRetain(page); // Balanced by the release in postGCTask.
277 WKBundlePageCallAfterTasksAndTimers(page, postGCTask, (void*)page);
278 return;
279 }
280
281 if (WKStringIsEqualToUTF8CString(messageName, "CallAddChromeInputFieldCallback")) {
282 m_testRunner->callAddChromeInputFieldCallback();
283 return;
284 }
285
286 if (WKStringIsEqualToUTF8CString(messageName, "CallRemoveChromeInputFieldCallback")) {
287 m_testRunner->callRemoveChromeInputFieldCallback();
288 return;
289 }
290
291 if (WKStringIsEqualToUTF8CString(messageName, "CallFocusWebViewCallback")) {
292 m_testRunner->callFocusWebViewCallback();
293 return;
294 }
295
296 if (WKStringIsEqualToUTF8CString(messageName, "CallSetBackingScaleFactorCallback")) {
297 m_testRunner->callSetBackingScaleFactorCallback();
298 return;
299 }
300
301 if (WKStringIsEqualToUTF8CString(messageName, "CallDidBeginSwipeCallback")) {
302 m_testRunner->callDidBeginSwipeCallback();
303 return;
304 }
305
306 if (WKStringIsEqualToUTF8CString(messageName, "CallWillEndSwipeCallback")) {
307 m_testRunner->callWillEndSwipeCallback();
308 return;
309 }
310
311 if (WKStringIsEqualToUTF8CString(messageName, "CallDidEndSwipeCallback")) {
312 m_testRunner->callDidEndSwipeCallback();
313 return;
314 }
315
316 if (WKStringIsEqualToUTF8CString(messageName, "CallDidRemoveSwipeSnapshotCallback")) {
317 m_testRunner->callDidRemoveSwipeSnapshotCallback();
318 return;
319 }
320
321 if (WKStringIsEqualToUTF8CString(messageName, "CallDidClearStatisticsThroughWebsiteDataRemoval")) {
322 m_testRunner->statisticsCallClearThroughWebsiteDataRemovalCallback();
323 return;
324 }
325
326 if (WKStringIsEqualToUTF8CString(messageName, "CallDidResetStatisticsToConsistentState")) {
327 m_testRunner->statisticsCallDidResetToConsistentStateCallback();
328 return;
329 }
330
331 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetBlockCookiesForHost")) {
332 m_testRunner->statisticsCallDidSetBlockCookiesForHostCallback();
333 return;
334 }
335
336 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetStatisticsDebugMode")) {
337 m_testRunner->statisticsCallDidSetDebugModeCallback();
338 return;
339 }
340
341 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetPrevalentResourceForDebugMode")) {
342 m_testRunner->statisticsCallDidSetPrevalentResourceForDebugModeCallback();
343 return;
344 }
345
346 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetLastSeen")) {
347 m_testRunner->statisticsCallDidSetLastSeenCallback();
348 return;
349 }
350
351 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetPrevalentResource")) {
352 m_testRunner->statisticsCallDidSetPrevalentResourceCallback();
353 return;
354 }
355
356 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetVeryPrevalentResource")) {
357 m_testRunner->statisticsCallDidSetVeryPrevalentResourceCallback();
358 return;
359 }
360
361 if (WKStringIsEqualToUTF8CString(messageName, "CallDidSetHasHadUserInteraction")) {
362 m_testRunner->statisticsCallDidSetHasHadUserInteractionCallback();
363 return;
364 }
365
366 if (WKStringIsEqualToUTF8CString(messageName, "CallDidReceiveAllStorageAccessEntries")) {
367 ASSERT(messageBody);
368 ASSERT(WKGetTypeID(messageBody) == WKArrayGetTypeID());
369
370 WKArrayRef domainsArray = static_cast<WKArrayRef>(messageBody);
371 auto size = WKArrayGetSize(domainsArray);
372 Vector<String> domains;
373 domains.reserveInitialCapacity(size);
374 for (size_t i = 0; i < size; ++i) {
375 WKTypeRef item = WKArrayGetItemAtIndex(domainsArray, i);
376 if (item && WKGetTypeID(item) == WKStringGetTypeID())
377 domains.append(toWTFString(static_cast<WKStringRef>(item)));
378 }
379
380 m_testRunner->callDidReceiveAllStorageAccessEntriesCallback(domains);
381 return;
382 }
383
384 if (WKStringIsEqualToUTF8CString(messageName, "CallDidRemoveAllSessionCredentialsCallback")) {
385 m_testRunner->callDidRemoveAllSessionCredentialsCallback();
386 return;
387 }
388
389 if (WKStringIsEqualToUTF8CString(messageName, "NotifyDownloadDone")) {
390 if (m_testRunner->shouldFinishAfterDownload())
391 m_testRunner->notifyDone();
392 return;
393 }
394
395 if (WKStringIsEqualToUTF8CString(messageName, "CallUISideScriptCallback")) {
396 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
397
398 WKRetainPtr<WKStringRef> resultKey = adoptWK(WKStringCreateWithUTF8CString("Result"));
399 WKRetainPtr<WKStringRef> callbackIDKey = adoptWK(WKStringCreateWithUTF8CString("CallbackID"));
400
401 unsigned callbackID = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get())));
402
403 WKStringRef resultString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, resultKey.get()));
404 auto resultJSString = toJS(resultString);
405
406 m_testRunner->runUIScriptCallback(callbackID, resultJSString.get());
407 return;
408 }
409
410 if (WKStringIsEqualToUTF8CString(messageName, "WorkQueueProcessedCallback")) {
411 if (!topLoadingFrame() && !m_testRunner->shouldWaitUntilDone())
412 InjectedBundle::page()->dump();
413 return;
414 }
415
416 if (WKStringIsEqualToUTF8CString(messageName, "WebsiteDataDeletionForRegistrableDomainsFinished")) {
417 m_testRunner->statisticsDidModifyDataRecordsCallback();
418 return;
419 }
420
421 if (WKStringIsEqualToUTF8CString(messageName, "WebsiteDataScanForRegistrableDomainsFinished")) {
422 m_testRunner->statisticsDidScanDataRecordsCallback();
423 return;
424 }
425
426 if (WKStringIsEqualToUTF8CString(messageName, "ResourceLoadStatisticsTelemetryFinished")) {
427 WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
428
429 WKRetainPtr<WKStringRef> totalPrevalentResourcesKey = adoptWK(WKStringCreateWithUTF8CString("TotalPrevalentResources"));
430 WKRetainPtr<WKStringRef> totalPrevalentResourcesWithUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("TotalPrevalentResourcesWithUserInteraction"));
431 WKRetainPtr<WKStringRef> top3SubframeUnderTopFrameOriginsKey = adoptWK(WKStringCreateWithUTF8CString("Top3SubframeUnderTopFrameOrigins"));
432
433 unsigned totalPrevalentResources = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, totalPrevalentResourcesKey.get())));
434 unsigned totalPrevalentResourcesWithUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, totalPrevalentResourcesWithUserInteractionKey.get())));
435 unsigned top3SubframeUnderTopFrameOrigins = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3SubframeUnderTopFrameOriginsKey.get())));
436
437 m_testRunner->statisticsDidRunTelemetryCallback(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
438 return;
439 }
440
441 if (WKStringIsEqualToUTF8CString(messageName, "DidGetApplicationManifest")) {
442 m_testRunner->didGetApplicationManifest();
443 return;
444 }
445
446 if (WKStringIsEqualToUTF8CString(messageName, "PerformCustomMenuAction")) {
447 m_testRunner->performCustomMenuAction();
448 return;
449 }
450
451 WKRetainPtr<WKStringRef> errorMessageName = adoptWK(WKStringCreateWithUTF8CString("Error"));
452 WKRetainPtr<WKStringRef> errorMessageBody = adoptWK(WKStringCreateWithUTF8CString("Unknown"));
453 WKBundlePagePostMessage(page, errorMessageName.get(), errorMessageBody.get());
454}
455
456bool InjectedBundle::booleanForKey(WKDictionaryRef dictionary, const char* key)
457{
458 WKRetainPtr<WKStringRef> wkKey = adoptWK(WKStringCreateWithUTF8CString(key));
459 WKTypeRef value = WKDictionaryGetItemForKey(dictionary, wkKey.get());
460 if (WKGetTypeID(value) != WKBooleanGetTypeID()) {
461 outputText(makeString("Boolean value for key", key, " not found in dictionary\n"));
462 return false;
463 }
464 return WKBooleanGetValue(static_cast<WKBooleanRef>(value));
465}
466
467String InjectedBundle::stringForKey(WKDictionaryRef dictionary, const char* key)
468{
469 WKRetainPtr<WKStringRef> wkKey = adoptWK(WKStringCreateWithUTF8CString(key));
470 WKStringRef value = static_cast<WKStringRef>(WKDictionaryGetItemForKey(dictionary, wkKey.get()));
471 if (!value) {
472 outputText(makeString("String value for key", key, " not found in dictionary\n"));
473 return emptyString();
474 }
475 return toWTFString(value);
476}
477
478void InjectedBundle::beginTesting(WKDictionaryRef settings, BegingTestingMode testingMode)
479{
480 m_state = Testing;
481
482 m_pixelResult.clear();
483 m_repaintRects.clear();
484
485 m_testRunner = TestRunner::create();
486 m_gcController = GCController::create();
487 m_eventSendingController = EventSendingController::create();
488 m_textInputController = TextInputController::create();
489#if HAVE(ACCESSIBILITY)
490 m_accessibilityController = AccessibilityController::create();
491#endif
492
493 // Don't change experimental or internal features here; those should be set in TestController::resetPreferencesToConsistentValues().
494 WKBundleSetAllowUniversalAccessFromFileURLs(m_bundle, m_pageGroup, true);
495 WKBundleSetJavaScriptCanAccessClipboard(m_bundle, m_pageGroup, true);
496 WKBundleSetPrivateBrowsingEnabled(m_bundle, m_pageGroup, false);
497 WKBundleSetUseDashboardCompatibilityMode(m_bundle, m_pageGroup, false);
498 WKBundleSetAuthorAndUserStylesEnabled(m_bundle, m_pageGroup, true);
499 WKBundleSetFrameFlatteningEnabled(m_bundle, m_pageGroup, false);
500 WKBundleSetMinimumLogicalFontSize(m_bundle, m_pageGroup, 9);
501 WKBundleSetSpatialNavigationEnabled(m_bundle, m_pageGroup, false);
502 WKBundleSetAllowFileAccessFromFileURLs(m_bundle, m_pageGroup, true);
503 WKBundleSetPopupBlockingEnabled(m_bundle, m_pageGroup, false);
504 WKBundleSetAllowStorageAccessFromFileURLS(m_bundle, m_pageGroup, false);
505
506#if PLATFORM(IOS_FAMILY)
507 WKBundlePageSetUseTestingViewportConfiguration(page()->page(), !booleanForKey(settings, "UseFlexibleViewport"));
508#endif
509
510#if PLATFORM(COCOA)
511 WebCoreTestSupport::setAdditionalSupportedImageTypesForTesting(stringForKey(settings, "additionalSupportedImageTypes"));
512#endif
513
514 m_testRunner->setPluginsEnabled(true);
515
516 m_testRunner->setUserStyleSheetEnabled(false);
517 m_testRunner->setXSSAuditorEnabled(false);
518
519 m_testRunner->setWebGL2Enabled(true);
520
521 m_testRunner->setWritableStreamAPIEnabled(true);
522 m_testRunner->setReadableByteStreamAPIEnabled(true);
523
524 m_testRunner->setEncryptedMediaAPIEnabled(true);
525
526 m_testRunner->setCloseRemainingWindowsWhenComplete(false);
527 m_testRunner->setAcceptsEditing(true);
528 m_testRunner->setTabKeyCyclesThroughElements(true);
529 m_testRunner->clearTestRunnerCallbacks();
530
531 if (m_timeout > 0_s)
532 m_testRunner->setCustomTimeout(m_timeout);
533
534 page()->prepare();
535
536 if (testingMode != BegingTestingMode::New)
537 return;
538
539 WKBundleClearAllDatabases(m_bundle);
540 WKBundlePageClearApplicationCache(page()->page());
541 WKBundleResetOriginAccessWhitelists(m_bundle);
542 WKBundleClearResourceLoadStatistics(m_bundle);
543
544 // [WK2] REGRESSION(r128623): It made layout tests extremely slow
545 // https://bugs.webkit.org/show_bug.cgi?id=96862
546 // WKBundleSetDatabaseQuota(m_bundle, 5 * 1024 * 1024);
547}
548
549void InjectedBundle::done()
550{
551 m_state = Stopping;
552
553 m_useWorkQueue = false;
554
555 page()->stopLoading();
556 setTopLoadingFrame(0);
557
558#if HAVE(ACCESSIBILITY)
559 m_accessibilityController->resetToConsistentState();
560#endif
561
562 WKRetainPtr<WKStringRef> doneMessageName = adoptWK(WKStringCreateWithUTF8CString("Done"));
563 WKRetainPtr<WKMutableDictionaryRef> doneMessageBody = adoptWK(WKMutableDictionaryCreate());
564
565 WKRetainPtr<WKStringRef> pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending"));
566 WKRetainPtr<WKBooleanRef> pixelResultIsPending = adoptWK(WKBooleanCreate(m_pixelResultIsPending));
567 WKDictionarySetItem(doneMessageBody.get(), pixelResultIsPendingKey.get(), pixelResultIsPending.get());
568
569 if (!m_pixelResultIsPending) {
570 WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
571 WKDictionarySetItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get());
572 }
573
574 WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
575 WKDictionarySetItem(doneMessageBody.get(), repaintRectsKey.get(), m_repaintRects.get());
576
577 WKRetainPtr<WKStringRef> audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult"));
578 WKDictionarySetItem(doneMessageBody.get(), audioResultKey.get(), m_audioResult.get());
579
580 WKBundlePagePostMessageIgnoringFullySynchronousMode(page()->page(), doneMessageName.get(), doneMessageBody.get());
581
582 closeOtherPages();
583
584 m_state = Idle;
585}
586
587void InjectedBundle::closeOtherPages()
588{
589 Vector<WKBundlePageRef> pagesToClose;
590 size_t size = m_pages.size();
591 for (size_t i = 1; i < size; ++i)
592 pagesToClose.append(m_pages[i]->page());
593 size = pagesToClose.size();
594 for (size_t i = 0; i < size; ++i)
595 WKBundlePageClose(pagesToClose[i]);
596}
597
598void InjectedBundle::dumpBackForwardListsForAllPages(StringBuilder& stringBuilder)
599{
600 size_t size = m_pages.size();
601 for (size_t i = 0; i < size; ++i)
602 stringBuilder.append(m_pages[i]->dumpHistory());
603}
604
605void InjectedBundle::dumpToStdErr(const String& output)
606{
607 if (m_state != Testing)
608 return;
609 if (output.isEmpty())
610 return;
611 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("DumpToStdErr"));
612 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(output.utf8().data()));
613 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
614}
615
616void InjectedBundle::outputText(const String& output)
617{
618 if (m_state != Testing)
619 return;
620 if (output.isEmpty())
621 return;
622 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("TextOutput"));
623 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(output.utf8().data()));
624 // We use WKBundlePagePostMessageIgnoringFullySynchronousMode() instead of WKBundlePagePostMessage() to make sure that all text output
625 // is done via asynchronous IPC, even if the connection is in fully synchronous mode due to a WKBundlePagePostSynchronousMessageForTesting()
626 // call. Otherwise, messages logged via sync and async IPC may end up out of order and cause flakiness.
627 WKBundlePagePostMessageIgnoringFullySynchronousMode(page()->page(), messageName.get(), messageBody.get());
628}
629
630void InjectedBundle::postNewBeforeUnloadReturnValue(bool value)
631{
632 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeforeUnloadReturnValue"));
633 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
634 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
635}
636
637void InjectedBundle::postAddChromeInputField()
638{
639 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("AddChromeInputField"));
640 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
641}
642
643void InjectedBundle::postRemoveChromeInputField()
644{
645 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("RemoveChromeInputField"));
646 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
647}
648
649void InjectedBundle::postFocusWebView()
650{
651 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("FocusWebView"));
652 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
653}
654
655void InjectedBundle::postSetBackingScaleFactor(double backingScaleFactor)
656{
657 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetBackingScaleFactor"));
658 WKRetainPtr<WKDoubleRef> messageBody = adoptWK(WKDoubleCreate(backingScaleFactor));
659 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
660}
661
662void InjectedBundle::postSetWindowIsKey(bool isKey)
663{
664 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetWindowIsKey"));
665 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(isKey));
666 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0);
667}
668
669void InjectedBundle::postSetViewSize(double width, double height)
670{
671 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetViewSize"));
672
673 WKRetainPtr<WKStringRef> widthKey = adoptWK(WKStringCreateWithUTF8CString("width"));
674 WKRetainPtr<WKStringRef> heightKey = adoptWK(WKStringCreateWithUTF8CString("height"));
675
676 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
677
678 WKRetainPtr<WKDoubleRef> widthWK = adoptWK(WKDoubleCreate(width));
679 WKDictionarySetItem(messageBody.get(), widthKey.get(), widthWK.get());
680
681 WKRetainPtr<WKDoubleRef> heightWK = adoptWK(WKDoubleCreate(height));
682 WKDictionarySetItem(messageBody.get(), heightKey.get(), heightWK.get());
683
684 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0);
685}
686
687void InjectedBundle::postSimulateWebNotificationClick(uint64_t notificationID)
688{
689 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SimulateWebNotificationClick"));
690 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(notificationID));
691 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
692}
693
694void InjectedBundle::postSetAddsVisitedLinks(bool addsVisitedLinks)
695{
696 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetAddsVisitedLinks"));
697 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(addsVisitedLinks));
698 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
699}
700
701void InjectedBundle::setGeolocationPermission(bool enabled)
702{
703 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetGeolocationPermission"));
704 WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(enabled));
705 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
706}
707
708void InjectedBundle::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed, bool providesFloorLevel, double floorLevel)
709{
710 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMockGeolocationPosition"));
711
712 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
713
714 WKRetainPtr<WKStringRef> latitudeKeyWK = adoptWK(WKStringCreateWithUTF8CString("latitude"));
715 WKRetainPtr<WKDoubleRef> latitudeWK = adoptWK(WKDoubleCreate(latitude));
716 WKDictionarySetItem(messageBody.get(), latitudeKeyWK.get(), latitudeWK.get());
717
718 WKRetainPtr<WKStringRef> longitudeKeyWK = adoptWK(WKStringCreateWithUTF8CString("longitude"));
719 WKRetainPtr<WKDoubleRef> longitudeWK = adoptWK(WKDoubleCreate(longitude));
720 WKDictionarySetItem(messageBody.get(), longitudeKeyWK.get(), longitudeWK.get());
721
722 WKRetainPtr<WKStringRef> accuracyKeyWK = adoptWK(WKStringCreateWithUTF8CString("accuracy"));
723 WKRetainPtr<WKDoubleRef> accuracyWK = adoptWK(WKDoubleCreate(accuracy));
724 WKDictionarySetItem(messageBody.get(), accuracyKeyWK.get(), accuracyWK.get());
725
726 WKRetainPtr<WKStringRef> providesAltitudeKeyWK = adoptWK(WKStringCreateWithUTF8CString("providesAltitude"));
727 WKRetainPtr<WKBooleanRef> providesAltitudeWK = adoptWK(WKBooleanCreate(providesAltitude));
728 WKDictionarySetItem(messageBody.get(), providesAltitudeKeyWK.get(), providesAltitudeWK.get());
729
730 WKRetainPtr<WKStringRef> altitudeKeyWK = adoptWK(WKStringCreateWithUTF8CString("altitude"));
731 WKRetainPtr<WKDoubleRef> altitudeWK = adoptWK(WKDoubleCreate(altitude));
732 WKDictionarySetItem(messageBody.get(), altitudeKeyWK.get(), altitudeWK.get());
733
734 WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK = adoptWK(WKStringCreateWithUTF8CString("providesAltitudeAccuracy"));
735 WKRetainPtr<WKBooleanRef> providesAltitudeAccuracyWK = adoptWK(WKBooleanCreate(providesAltitudeAccuracy));
736 WKDictionarySetItem(messageBody.get(), providesAltitudeAccuracyKeyWK.get(), providesAltitudeAccuracyWK.get());
737
738 WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK = adoptWK(WKStringCreateWithUTF8CString("altitudeAccuracy"));
739 WKRetainPtr<WKDoubleRef> altitudeAccuracyWK = adoptWK(WKDoubleCreate(altitudeAccuracy));
740 WKDictionarySetItem(messageBody.get(), altitudeAccuracyKeyWK.get(), altitudeAccuracyWK.get());
741
742 WKRetainPtr<WKStringRef> providesHeadingKeyWK = adoptWK(WKStringCreateWithUTF8CString("providesHeading"));
743 WKRetainPtr<WKBooleanRef> providesHeadingWK = adoptWK(WKBooleanCreate(providesHeading));
744 WKDictionarySetItem(messageBody.get(), providesHeadingKeyWK.get(), providesHeadingWK.get());
745
746 WKRetainPtr<WKStringRef> headingKeyWK = adoptWK(WKStringCreateWithUTF8CString("heading"));
747 WKRetainPtr<WKDoubleRef> headingWK = adoptWK(WKDoubleCreate(heading));
748 WKDictionarySetItem(messageBody.get(), headingKeyWK.get(), headingWK.get());
749
750 WKRetainPtr<WKStringRef> providesSpeedKeyWK = adoptWK(WKStringCreateWithUTF8CString("providesSpeed"));
751 WKRetainPtr<WKBooleanRef> providesSpeedWK = adoptWK(WKBooleanCreate(providesSpeed));
752 WKDictionarySetItem(messageBody.get(), providesSpeedKeyWK.get(), providesSpeedWK.get());
753
754 WKRetainPtr<WKStringRef> speedKeyWK = adoptWK(WKStringCreateWithUTF8CString("speed"));
755 WKRetainPtr<WKDoubleRef> speedWK = adoptWK(WKDoubleCreate(speed));
756 WKDictionarySetItem(messageBody.get(), speedKeyWK.get(), speedWK.get());
757
758 WKRetainPtr<WKStringRef> providesFloorLevelKeyWK = adoptWK(WKStringCreateWithUTF8CString("providesFloorLevel"));
759 WKRetainPtr<WKBooleanRef> providesFloorLevelWK = adoptWK(WKBooleanCreate(providesFloorLevel));
760 WKDictionarySetItem(messageBody.get(), providesFloorLevelKeyWK.get(), providesFloorLevelWK.get());
761
762 WKRetainPtr<WKStringRef> floorLevelKeyWK = adoptWK(WKStringCreateWithUTF8CString("floorLevel"));
763 WKRetainPtr<WKDoubleRef> floorLevelWK = adoptWK(WKDoubleCreate(floorLevel));
764 WKDictionarySetItem(messageBody.get(), floorLevelKeyWK.get(), floorLevelWK.get());
765
766 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
767}
768
769void InjectedBundle::setMockGeolocationPositionUnavailableError(WKStringRef errorMessage)
770{
771 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetMockGeolocationPositionUnavailableError"));
772 WKBundlePagePostMessage(page()->page(), messageName.get(), errorMessage);
773}
774
775bool InjectedBundle::isGeolocationProviderActive() const
776{
777 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsGeolocationClientActive"));
778 WKTypeRef resultToPass = 0;
779 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
780 WKRetainPtr<WKBooleanRef> isActive = adoptWK(static_cast<WKBooleanRef>(resultToPass));
781
782 return WKBooleanGetValue(isActive.get());
783}
784
785unsigned InjectedBundle::imageCountInGeneralPasteboard() const
786{
787 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ImageCountInGeneralPasteboard"));
788 WKTypeRef resultToPass = 0;
789 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
790 WKRetainPtr<WKUInt64Ref> imageCount = adoptWK(static_cast<WKUInt64Ref>(resultToPass));
791
792 return static_cast<unsigned>(WKUInt64GetValue(imageCount.get()));
793}
794
795void InjectedBundle::setUserMediaPermission(bool enabled)
796{
797 auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermission"));
798 auto messageBody = adoptWK(WKBooleanCreate(enabled));
799 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
800}
801
802void InjectedBundle::resetUserMediaPermission()
803{
804 auto messageName = adoptWK(WKStringCreateWithUTF8CString("ResetUserMediaPermission"));
805 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
806}
807
808void InjectedBundle::setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin)
809{
810 auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPersistentPermissionForOrigin"));
811 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
812
813 WKRetainPtr<WKStringRef> permissionKeyWK = adoptWK(WKStringCreateWithUTF8CString("permission"));
814 WKRetainPtr<WKBooleanRef> permissionWK = adoptWK(WKBooleanCreate(permission));
815 WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get());
816
817 WKRetainPtr<WKStringRef> originKeyWK = adoptWK(WKStringCreateWithUTF8CString("origin"));
818 WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
819
820 WKRetainPtr<WKStringRef> parentOriginKeyWK = adoptWK(WKStringCreateWithUTF8CString("parentOrigin"));
821 WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
822
823 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
824}
825
826unsigned InjectedBundle::userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const
827{
828 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("UserMediaPermissionRequestCountForOrigin"));
829 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
830
831 WKRetainPtr<WKStringRef> originKeyWK = adoptWK(WKStringCreateWithUTF8CString("origin"));
832 WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
833
834 WKRetainPtr<WKStringRef> parentOriginKeyWK = adoptWK(WKStringCreateWithUTF8CString("parentOrigin"));
835 WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
836
837 WKTypeRef resultToPass = 0;
838 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), &resultToPass);
839 WKRetainPtr<WKUInt64Ref> count = adoptWK(static_cast<WKUInt64Ref>(resultToPass));
840
841 return static_cast<unsigned>(WKUInt64GetValue(count.get()));
842}
843
844void InjectedBundle::resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin)
845{
846 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ResetUserMediaPermissionRequestCountForOrigin"));
847 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
848
849 WKRetainPtr<WKStringRef> originKeyWK = adoptWK(WKStringCreateWithUTF8CString("origin"));
850 WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
851
852 WKRetainPtr<WKStringRef> parentOriginKeyWK = adoptWK(WKStringCreateWithUTF8CString("parentOrigin"));
853 WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
854
855 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
856}
857
858void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive)
859{
860 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetCustomPolicyDelegate"));
861
862 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
863
864 WKRetainPtr<WKStringRef> enabledKeyWK = adoptWK(WKStringCreateWithUTF8CString("enabled"));
865 WKRetainPtr<WKBooleanRef> enabledWK = adoptWK(WKBooleanCreate(enabled));
866 WKDictionarySetItem(messageBody.get(), enabledKeyWK.get(), enabledWK.get());
867
868 WKRetainPtr<WKStringRef> permissiveKeyWK = adoptWK(WKStringCreateWithUTF8CString("permissive"));
869 WKRetainPtr<WKBooleanRef> permissiveWK = adoptWK(WKBooleanCreate(permissive));
870 WKDictionarySetItem(messageBody.get(), permissiveKeyWK.get(), permissiveWK.get());
871
872 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
873}
874
875void InjectedBundle::setHidden(bool hidden)
876{
877 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetHidden"));
878 WKRetainPtr<WKMutableDictionaryRef> messageBody = adoptWK(WKMutableDictionaryCreate());
879
880 WKRetainPtr<WKStringRef> isInitialKeyWK = adoptWK(WKStringCreateWithUTF8CString("hidden"));
881 WKRetainPtr<WKBooleanRef> isInitialWK = adoptWK(WKBooleanCreate(hidden));
882 WKDictionarySetItem(messageBody.get(), isInitialKeyWK.get(), isInitialWK.get());
883
884 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
885}
886
887void InjectedBundle::setCacheModel(int model)
888{
889 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetCacheModel"));
890 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(model));
891 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
892}
893
894bool InjectedBundle::shouldProcessWorkQueue() const
895{
896 if (!m_useWorkQueue)
897 return false;
898
899 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("IsWorkQueueEmpty"));
900 WKTypeRef resultToPass = 0;
901 WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass);
902 WKRetainPtr<WKBooleanRef> isEmpty = adoptWK(static_cast<WKBooleanRef>(resultToPass));
903
904 // The IPC failed. This happens when swapping processes on navigation because the WebPageProxy unregisters itself
905 // as a MessageReceiver from the old WebProcessProxy and register itself with the new WebProcessProxy instead.
906 if (!isEmpty)
907 return false;
908
909 return !WKBooleanGetValue(isEmpty.get());
910}
911
912void InjectedBundle::processWorkQueue()
913{
914 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ProcessWorkQueue"));
915 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
916}
917
918void InjectedBundle::queueBackNavigation(unsigned howFarBackward)
919{
920 m_useWorkQueue = true;
921
922 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueBackNavigation"));
923 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(howFarBackward));
924 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
925}
926
927void InjectedBundle::queueForwardNavigation(unsigned howFarForward)
928{
929 m_useWorkQueue = true;
930
931 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueForwardNavigation"));
932 WKRetainPtr<WKUInt64Ref> messageBody = adoptWK(WKUInt64Create(howFarForward));
933 WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
934}
935
936void InjectedBundle::queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs)
937{
938 m_useWorkQueue = true;
939
940 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueLoad"));
941
942 WKRetainPtr<WKMutableDictionaryRef> loadData = adoptWK(WKMutableDictionaryCreate());
943
944 WKRetainPtr<WKStringRef> urlKey = adoptWK(WKStringCreateWithUTF8CString("url"));
945 WKDictionarySetItem(loadData.get(), urlKey.get(), url);
946
947 WKRetainPtr<WKStringRef> targetKey = adoptWK(WKStringCreateWithUTF8CString("target"));
948 WKDictionarySetItem(loadData.get(), targetKey.get(), target);
949
950 WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey = adoptWK(WKStringCreateWithUTF8CString("shouldOpenExternalURLs"));
951 WKRetainPtr<WKBooleanRef> shouldOpenExternalURLsValue = adoptWK(WKBooleanCreate(shouldOpenExternalURLs));
952 WKDictionarySetItem(loadData.get(), shouldOpenExternalURLsKey.get(), shouldOpenExternalURLsValue.get());
953
954 WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get());
955}
956
957void InjectedBundle::queueLoadHTMLString(WKStringRef content, WKStringRef baseURL, WKStringRef unreachableURL)
958{
959 m_useWorkQueue = true;
960
961 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueLoadHTMLString"));
962
963 WKRetainPtr<WKMutableDictionaryRef> loadData = adoptWK(WKMutableDictionaryCreate());
964
965 WKRetainPtr<WKStringRef> contentKey = adoptWK(WKStringCreateWithUTF8CString("content"));
966 WKDictionarySetItem(loadData.get(), contentKey.get(), content);
967
968 if (baseURL) {
969 WKRetainPtr<WKStringRef> baseURLKey = adoptWK(WKStringCreateWithUTF8CString("baseURL"));
970 WKDictionarySetItem(loadData.get(), baseURLKey.get(), baseURL);
971 }
972
973 if (unreachableURL) {
974 WKRetainPtr<WKStringRef> unreachableURLKey = adoptWK(WKStringCreateWithUTF8CString("unreachableURL"));
975 WKDictionarySetItem(loadData.get(), unreachableURLKey.get(), unreachableURL);
976 }
977
978 WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get());
979}
980
981void InjectedBundle::queueReload()
982{
983 m_useWorkQueue = true;
984
985 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueReload"));
986 WKBundlePagePostMessage(page()->page(), messageName.get(), 0);
987}
988
989void InjectedBundle::queueLoadingScript(WKStringRef script)
990{
991 m_useWorkQueue = true;
992
993 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueLoadingScript"));
994 WKBundlePagePostMessage(page()->page(), messageName.get(), script);
995}
996
997void InjectedBundle::queueNonLoadingScript(WKStringRef script)
998{
999 m_useWorkQueue = true;
1000
1001 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("QueueNonLoadingScript"));
1002 WKBundlePagePostMessage(page()->page(), messageName.get(), script);
1003}
1004
1005bool InjectedBundle::isAllowedHost(WKStringRef host)
1006{
1007 if (m_allowedHosts.isEmpty())
1008 return false;
1009 return m_allowedHosts.contains(toWTFString(host));
1010}
1011
1012void InjectedBundle::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate)
1013{
1014 WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate);
1015}
1016
1017void InjectedBundle::statisticsNotifyObserver()
1018{
1019 WKBundleResourceLoadStatisticsNotifyObserver(m_bundle);
1020}
1021
1022void InjectedBundle::textDidChangeInTextField()
1023{
1024 m_testRunner->textDidChangeInTextFieldCallback();
1025}
1026
1027void InjectedBundle::textFieldDidBeginEditing()
1028{
1029 m_testRunner->textFieldDidBeginEditingCallback();
1030}
1031
1032void InjectedBundle::textFieldDidEndEditing()
1033{
1034 m_testRunner->textFieldDidEndEditingCallback();
1035}
1036
1037} // namespace WTR
1038