Streamline JSRetainPtr, fix leaks of JSString and JSGlobalContext
[WebKit-https.git] / Tools / DumpRenderTree / TestRunner.cpp
1 /*
2  * Copyright (C) 2007-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Joone Hur <joone@kldp.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "TestRunner.h"
32
33 #include "WebCoreTestSupport.h"
34 #include "WorkQueue.h"
35 #include "WorkQueueItem.h"
36 #include <JavaScriptCore/APICast.h>
37 #include <JavaScriptCore/ArrayBufferView.h>
38 #include <JavaScriptCore/HeapInlines.h>
39 #include <JavaScriptCore/JSArrayBufferView.h>
40 #include <JavaScriptCore/JSCTestRunnerUtils.h>
41 #include <JavaScriptCore/JSContextRef.h>
42 #include <JavaScriptCore/JSObjectRef.h>
43 #include <JavaScriptCore/JSRetainPtr.h>
44 #include <JavaScriptCore/TypedArrayInlines.h>
45 #include <JavaScriptCore/VMInlines.h>
46 #include <WebCore/LogInitialization.h>
47 #include <cstring>
48 #include <locale.h>
49 #include <stdio.h>
50 #include <wtf/Assertions.h>
51 #include <wtf/LoggingAccumulator.h>
52 #include <wtf/MathExtras.h>
53 #include <wtf/RefPtr.h>
54 #include <wtf/RunLoop.h>
55 #include <wtf/StdLibExtras.h>
56 #include <wtf/WallTime.h>
57 #include <wtf/text/WTFString.h>
58
59 #if PLATFORM(IOS)
60 #include <WebCore/WebCoreThreadRun.h>
61 #include <wtf/BlockPtr.h>
62 #endif
63
64 #if PLATFORM(MAC) && !PLATFORM(IOS)
65 #include <Carbon/Carbon.h>
66 #endif
67
68 FILE* testResult = stdout;
69
70 const unsigned TestRunner::viewWidth = 800;
71 const unsigned TestRunner::viewHeight = 600;
72
73 const unsigned TestRunner::w3cSVGViewWidth = 480;
74 const unsigned TestRunner::w3cSVGViewHeight = 360;
75
76 TestRunner::TestRunner(const std::string& testURL, const std::string& expectedPixelHash)
77     : m_disallowIncreaseForApplicationCacheQuota(false)
78     , m_dumpApplicationCacheDelegateCallbacks(false)
79     , m_dumpAsAudio(false)
80     , m_dumpAsPDF(false)
81     , m_dumpAsText(false)
82     , m_dumpBackForwardList(false)
83     , m_dumpChildFrameScrollPositions(false)
84     , m_dumpChildFramesAsText(false)
85     , m_dumpDOMAsWebArchive(false)
86     , m_dumpDatabaseCallbacks(false)
87     , m_dumpEditingCallbacks(false)
88     , m_dumpFrameLoadCallbacks(false)
89     , m_dumpProgressFinishedCallback(false)
90     , m_dumpUserGestureInFrameLoadCallbacks(false)
91     , m_dumpHistoryDelegateCallbacks(false)
92     , m_dumpResourceLoadCallbacks(false)
93     , m_dumpResourceResponseMIMETypes(false)
94     , m_dumpSelectionRect(false)
95     , m_dumpSourceAsWebArchive(false)
96     , m_dumpStatusCallbacks(false)
97     , m_dumpTitleChanges(false)
98     , m_dumpVisitedLinksCallback(false)
99     , m_dumpWillCacheResponse(false)
100     , m_generatePixelResults(true)
101     , m_callCloseOnWebViews(true)
102     , m_canOpenWindows(false)
103     , m_closeRemainingWindowsWhenComplete(true)
104     , m_newWindowsCopyBackForwardList(false)
105     , m_stopProvisionalFrameLoads(false)
106     , m_testOnscreen(false)
107     , m_testRepaint(false)
108     , m_testRepaintSweepHorizontally(false)
109     , m_waitToDump(false)
110     , m_willSendRequestReturnsNull(false)
111     , m_willSendRequestReturnsNullOnRedirect(false)
112     , m_windowIsKey(true)
113     , m_alwaysAcceptCookies(false)
114     , m_globalFlag(false)
115     , m_isGeolocationPermissionSet(false)
116     , m_geolocationPermission(false)
117     , m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges(false)
118     , m_handlesAuthenticationChallenges(false)
119     , m_isPrinting(false)
120     , m_useDeferredFrameLoading(false)
121     , m_shouldPaintBrokenImage(true)
122     , m_shouldStayOnPageAfterHandlingBeforeUnload(false)
123     , m_areLegacyWebNotificationPermissionRequestsIgnored(false)
124     , m_customFullScreenBehavior(false) 
125     , m_hasPendingWebNotificationClick(false)
126     , m_databaseDefaultQuota(-1)
127     , m_databaseMaxQuota(-1)
128     , m_testURL(testURL)
129     , m_expectedPixelHash(expectedPixelHash)
130     , m_titleTextDirection("ltr")
131     , m_timeout(0)
132 {
133 }
134
135 Ref<TestRunner> TestRunner::create(const std::string& testURL, const std::string& expectedPixelHash)
136 {
137     return adoptRef(*new TestRunner(testURL, expectedPixelHash));
138 }
139
140 // Static Functions
141
142 static JSValueRef disallowIncreaseForApplicationCacheQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
143 {
144     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
145     controller->setDisallowIncreaseForApplicationCacheQuota(true);
146     return JSValueMakeUndefined(context);
147 }
148
149 static JSValueRef dumpApplicationCacheDelegateCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
150 {
151     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
152     controller->setDumpApplicationCacheDelegateCallbacks(true);
153     return JSValueMakeUndefined(context);
154 }
155
156 static JSValueRef dumpAsPDFCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
157 {
158     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
159     controller->setDumpAsPDF(true);
160     return JSValueMakeUndefined(context);
161 }
162
163 static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
164 {
165     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
166     controller->setDumpAsText(true);
167
168     // Optional paramater, describing whether it's allowed to dump pixel results in dumpAsText mode.
169     controller->setGeneratePixelResults(argumentCount > 0 ? JSValueToBoolean(context, arguments[0]) : false);
170
171     return JSValueMakeUndefined(context);
172 }
173
174 static JSValueRef dumpBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
175 {
176     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
177     controller->setDumpBackForwardList(true);
178     return JSValueMakeUndefined(context);
179 }
180
181 static JSValueRef dumpChildFramesAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
182 {
183     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
184     controller->setDumpChildFramesAsText(true);
185     return JSValueMakeUndefined(context);
186 }
187
188 static JSValueRef dumpChildFrameScrollPositionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
189 {
190     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
191     controller->setDumpChildFrameScrollPositions(true);
192     return JSValueMakeUndefined(context);
193 }
194
195 static JSValueRef dumpDatabaseCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
196 {
197     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
198     controller->setDumpDatabaseCallbacks(true);
199     return JSValueMakeUndefined(context);
200 }
201
202 static JSValueRef dumpDOMAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
203 {
204     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
205     controller->setDumpDOMAsWebArchive(true);
206     return JSValueMakeUndefined(context);
207 }
208
209 static JSValueRef dumpEditingCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
210 {
211     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
212     controller->setDumpEditingCallbacks(true);
213     return JSValueMakeUndefined(context);
214 }
215
216 static JSValueRef dumpFrameLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
217 {
218     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
219     controller->setDumpFrameLoadCallbacks(true);
220     return JSValueMakeUndefined(context);
221 }
222
223 static JSValueRef dumpProgressFinishedCallbackCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
224 {
225     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
226     controller->setDumpProgressFinishedCallback(true);
227     return JSValueMakeUndefined(context);
228 }
229
230 static JSValueRef dumpUserGestureInFrameLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
231 {
232     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
233     controller->setDumpUserGestureInFrameLoadCallbacks(true);
234     return JSValueMakeUndefined(context);
235 }
236
237 static JSValueRef dumpResourceLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
238 {
239     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
240     controller->setDumpResourceLoadCallbacks(true);
241     return JSValueMakeUndefined(context);
242 }
243
244 static JSValueRef dumpResourceResponseMIMETypesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
245 {
246     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
247     controller->setDumpResourceResponseMIMETypes(true);
248     return JSValueMakeUndefined(context);
249 }
250
251 static JSValueRef dumpSelectionRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
252 {
253     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
254     controller->setDumpSelectionRect(true);
255     return JSValueMakeUndefined(context);
256 }
257
258 static JSValueRef dumpSourceAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
259 {
260     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
261     controller->setDumpSourceAsWebArchive(true);
262     return JSValueMakeUndefined(context);
263 }
264
265 static JSValueRef dumpStatusCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
266 {
267     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
268     controller->setDumpStatusCallbacks(true);
269     return JSValueMakeUndefined(context);
270 }
271
272 static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
273 {
274     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
275     controller->setDumpTitleChanges(true);
276     return JSValueMakeUndefined(context);
277 }
278
279 static JSValueRef dumpWillCacheResponseCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
280 {
281     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
282     controller->setDumpWillCacheResponse(true);
283     return JSValueMakeUndefined(context);
284 }
285
286 static JSValueRef pathToLocalResourceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
287 {
288     if (argumentCount < 1)
289         return JSValueMakeUndefined(context);
290
291     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
292     auto localPath = adopt(JSValueToStringCopy(context, arguments[0], exception));
293     ASSERT(!*exception);
294
295     auto convertedPath = controller->pathToLocalResource(context, localPath.get());
296     if (!convertedPath)
297         return JSValueMakeUndefined(context);
298
299     return JSValueMakeString(context, convertedPath.get());
300 }
301
302 static JSValueRef removeAllVisitedLinksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
303 {
304     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
305     controller->setDumpVisitedLinksCallback(true);
306     controller->removeAllVisitedLinks();
307     return JSValueMakeUndefined(context);
308 }
309
310 static JSValueRef repaintSweepHorizontallyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
311 {
312     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
313     controller->setTestRepaintSweepHorizontally(true);
314     return JSValueMakeUndefined(context);
315 }
316
317 static JSValueRef setCallCloseOnWebViewsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
318 {
319     if (argumentCount < 1)
320         return JSValueMakeUndefined(context);
321
322     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
323     controller->setCallCloseOnWebViews(JSValueToBoolean(context, arguments[0]));
324     return JSValueMakeUndefined(context);
325 }
326
327 static JSValueRef setCanOpenWindowsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
328 {
329     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
330     controller->setCanOpenWindows(true);
331     return JSValueMakeUndefined(context);
332 }
333
334 static JSValueRef setCloseRemainingWindowsWhenCompleteCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
335 {
336     if (argumentCount < 1)
337         return JSValueMakeUndefined(context);
338
339     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
340     controller->setCloseRemainingWindowsWhenComplete(JSValueToBoolean(context, arguments[0]));
341     return JSValueMakeUndefined(context);
342 }
343
344 static JSValueRef setAudioResultCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
345 {
346     if (argumentCount < 1)
347         return JSValueMakeUndefined(context);
348
349     // FIXME (123058): Use a JSC API to get buffer contents once such is exposed.
350     JSC::VM& vm = toJS(context)->vm();
351     JSC::JSLockHolder lock(vm);
352
353     JSC::JSArrayBufferView* jsBufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(vm, toJS(toJS(context), arguments[0]));
354     ASSERT(jsBufferView);
355     RefPtr<JSC::ArrayBufferView> bufferView = jsBufferView->unsharedImpl();
356     const char* buffer = static_cast<const char*>(bufferView->baseAddress());
357     std::vector<char> audioData(buffer, buffer + bufferView->byteLength());
358
359     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
360     controller->setAudioResult(audioData);
361     controller->setDumpAsAudio(true);
362
363     return JSValueMakeUndefined(context);
364 }
365
366 static JSValueRef testOnscreenCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
367 {
368     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
369     controller->setTestOnscreen(true);
370     return JSValueMakeUndefined(context);
371 }
372
373 static JSValueRef testRepaintCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
374 {
375     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
376     controller->setTestRepaint(true);
377     return JSValueMakeUndefined(context);
378 }
379
380 static JSValueRef addDisallowedURLCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
381 {
382     // Has mac implementation
383     if (argumentCount < 1)
384         return JSValueMakeUndefined(context);
385
386     auto url = adopt(JSValueToStringCopy(context, arguments[0], exception));
387     ASSERT(!*exception);
388
389     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
390     controller->addDisallowedURL(url.get());
391
392     return JSValueMakeUndefined(context);
393 }
394
395 static JSValueRef addURLToRedirectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
396 {
397     if (argumentCount < 2)
398         return JSValueMakeUndefined(context);
399
400     auto origin = adopt(JSValueToStringCopy(context, arguments[0], exception));
401     ASSERT(!*exception);
402
403     auto destination = adopt(JSValueToStringCopy(context, arguments[1], exception));
404     ASSERT(!*exception);
405
406     size_t maxLength = JSStringGetMaximumUTF8CStringSize(origin.get());
407     auto originBuffer = std::make_unique<char[]>(maxLength + 1);
408     JSStringGetUTF8CString(origin.get(), originBuffer.get(), maxLength + 1);
409
410     maxLength = JSStringGetMaximumUTF8CStringSize(destination.get());
411     auto destinationBuffer = std::make_unique<char[]>(maxLength + 1);
412     JSStringGetUTF8CString(destination.get(), destinationBuffer.get(), maxLength + 1);
413
414     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
415     controller->addURLToRedirect(originBuffer.get(), destinationBuffer.get());
416
417     return JSValueMakeUndefined(context);
418 }
419
420 static JSValueRef callShouldCloseOnWebViewCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
421 {
422     // Has mac & windows implementation
423     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
424
425     return JSValueMakeBoolean(context, controller->callShouldCloseOnWebView());
426 }
427
428 static JSValueRef clearAllApplicationCachesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
429 {
430     // Has mac implementation
431     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
432     controller->clearAllApplicationCaches();
433
434     return JSValueMakeUndefined(context);
435 }
436
437 static JSValueRef clearApplicationCacheForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
438 {
439     if (argumentCount < 1)
440         return JSValueMakeUndefined(context);
441
442     auto originURL = adopt(JSValueToStringCopy(context, arguments[0], exception));
443     ASSERT(!*exception);
444
445     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
446     controller->clearApplicationCacheForOrigin(originURL.get());
447     
448     return JSValueMakeUndefined(context);
449 }
450
451 static JSValueRef applicationCacheDiskUsageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
452 {
453     if (argumentCount < 1)
454         return JSValueMakeUndefined(context);
455
456     auto originURL = adopt(JSValueToStringCopy(context, arguments[0], exception));
457     ASSERT(!*exception);
458     
459     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
460
461     return JSValueMakeNumber(context, controller->applicationCacheDiskUsageForOrigin(originURL.get()));
462 }
463
464 static JSValueRef originsWithApplicationCacheCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
465 {
466     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
467     return controller->originsWithApplicationCache(context);
468 }
469
470 static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
471 {
472     // Has mac & windows implementation
473     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
474     controller->clearAllDatabases();
475
476     return JSValueMakeUndefined(context);
477 }
478
479 static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
480 {
481     // Has mac & windows implementation
482     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
483     controller->clearBackForwardList();
484
485     return JSValueMakeUndefined(context);
486 }
487
488 static JSValueRef clearPersistentUserStyleSheetCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
489 {
490     // Has mac & windows implementation
491     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
492     controller->clearPersistentUserStyleSheet();
493
494     return JSValueMakeUndefined(context);
495 }
496
497 static JSValueRef decodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
498 {
499     // Has mac implementation
500     if (argumentCount < 1)
501         return JSValueMakeUndefined(context);
502
503     auto name = adopt(JSValueToStringCopy(context, arguments[0], exception));
504     ASSERT(!*exception);
505
506     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
507     auto decodedHostName = controller->copyDecodedHostName(name.get());
508     return JSValueMakeString(context, decodedHostName.get());
509 }
510
511 static JSValueRef dispatchPendingLoadRequestsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
512 {
513     // Has mac implementation, needs windows implementation
514     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
515     controller->dispatchPendingLoadRequests();
516     
517     return JSValueMakeUndefined(context);
518 }
519
520 static JSValueRef displayCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
521 {
522     // Has mac & windows implementation
523     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
524     controller->display();
525
526     return JSValueMakeUndefined(context);
527 }
528
529 static JSValueRef displayAndTrackRepaintsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
530 {
531     // Has mac & windows implementation
532     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
533     controller->displayAndTrackRepaints();
534
535     return JSValueMakeUndefined(context);
536 }
537
538 static JSValueRef encodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
539 {
540     // Has mac implementation
541     if (argumentCount < 1)
542         return JSValueMakeUndefined(context);
543
544     auto name = adopt(JSValueToStringCopy(context, arguments[0], exception));
545     ASSERT(!*exception);
546
547     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
548     auto encodedHostName = controller->copyEncodedHostName(name.get());
549     return JSValueMakeString(context, encodedHostName.get());
550 }
551
552 static JSValueRef execCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
553 {
554     // Has Mac & Windows implementations.
555     if (argumentCount < 1)
556         return JSValueMakeUndefined(context);
557
558     auto name = adopt(JSValueToStringCopy(context, arguments[0], exception));
559     ASSERT(!*exception);
560
561     // Ignoring the second parameter (userInterface), as this command emulates a manual action.
562
563     JSRetainPtr<JSStringRef> value;
564     if (argumentCount >= 3) {
565         value = adopt(JSValueToStringCopy(context, arguments[2], exception));
566         ASSERT(!*exception);
567     } else
568         value = adopt(JSStringCreateWithUTF8CString(""));
569
570
571     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
572     controller->execCommand(name.get(), value.get());
573
574     return JSValueMakeUndefined(context);
575 }
576
577 static JSValueRef findStringCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
578 {
579     // Has Mac implementation.
580     if (argumentCount < 2)
581         return JSValueMakeUndefined(context);
582
583     auto target = adopt(JSValueToStringCopy(context, arguments[0], exception));
584     ASSERT(!*exception);
585
586     JSObjectRef options = JSValueToObject(context, arguments[1], exception);
587     ASSERT(!*exception);
588
589     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
590     return JSValueMakeBoolean(context, controller->findString(context, target.get(), options));
591 }
592
593 static JSValueRef goBackCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
594 {
595     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
596     controller->goBack();
597     
598     return JSValueMakeUndefined(context);
599 }
600
601 static JSValueRef isCommandEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
602 {
603     // Has Mac implementation.
604
605     if (argumentCount < 1)
606         return JSValueMakeUndefined(context);
607
608     auto name = adopt(JSValueToStringCopy(context, arguments[0], exception));
609     ASSERT(!*exception);
610
611     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
612
613     return JSValueMakeBoolean(context, controller->isCommandEnabled(name.get()));
614 }
615
616 static JSValueRef overridePreferenceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
617 {
618     if (argumentCount < 2)
619         return JSValueMakeUndefined(context);
620
621     auto key = adopt(JSValueToStringCopy(context, arguments[0], exception));
622     ASSERT(!*exception);
623     auto value = adopt(JSValueToStringCopy(context, arguments[1], exception));
624     ASSERT(!*exception);
625
626     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
627     controller->overridePreference(key.get(), value.get());
628
629     return JSValueMakeUndefined(context);
630 }
631
632 static JSValueRef keepWebHistoryCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
633 {
634     // Has mac implementation
635     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
636     controller->keepWebHistory();
637
638     return JSValueMakeUndefined(context);
639 }
640
641 static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
642 {
643     // Has mac & windows implementation
644     // May be able to be made platform independant by using shared WorkQueue
645     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
646     controller->notifyDone();
647     return JSValueMakeUndefined(context);
648 }
649
650 static JSValueRef numberOfPendingGeolocationPermissionRequestsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
651 {
652     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
653     return JSValueMakeNumber(context, controller->numberOfPendingGeolocationPermissionRequests());
654 }
655
656 static JSValueRef isGeolocationProviderActiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
657 {
658     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
659     return JSValueMakeBoolean(context, controller->isGeolocationProviderActive());
660 }
661
662 static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
663 {
664     // Has mac & windows implementation
665     // May be able to be made platform independant by using shared WorkQueue
666     if (argumentCount < 1)
667         return JSValueMakeUndefined(context);
668
669     double howFarBackDouble = JSValueToNumber(context, arguments[0], exception);
670     ASSERT(!*exception);
671
672     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
673     controller->queueBackNavigation(static_cast<int>(howFarBackDouble));
674
675     return JSValueMakeUndefined(context);
676 }
677
678 static JSValueRef queueForwardNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
679 {
680     // Has mac & windows implementation
681     // May be able to be made platform independant by using shared WorkQueue
682     if (argumentCount < 1)
683         return JSValueMakeUndefined(context);
684
685     double howFarForwardDouble = JSValueToNumber(context, arguments[0], exception);
686     ASSERT(!*exception);
687
688     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
689     controller->queueForwardNavigation(static_cast<int>(howFarForwardDouble));
690
691     return JSValueMakeUndefined(context);
692 }
693
694 static JSValueRef queueLoadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
695 {
696     // Has mac & windows implementation
697     // May be able to be made platform independant by using shared WorkQueue
698     if (argumentCount < 1)
699         return JSValueMakeUndefined(context);
700
701     auto url = adopt(JSValueToStringCopy(context, arguments[0], exception));
702     ASSERT(!*exception);
703
704     JSRetainPtr<JSStringRef> target;
705     if (argumentCount >= 2) {
706         target = adopt(JSValueToStringCopy(context, arguments[1], exception));
707         ASSERT(!*exception);
708     } else
709         target = adopt(JSStringCreateWithUTF8CString(""));
710
711     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
712     controller->queueLoad(url.get(), target.get());
713
714     return JSValueMakeUndefined(context);
715 }
716
717 static JSValueRef queueLoadHTMLStringCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
718 {
719     // Has Mac & Windows implementation
720     if (argumentCount < 1)
721         return JSValueMakeUndefined(context);
722
723     auto content = adopt(JSValueToStringCopy(context, arguments[0], exception));
724     ASSERT(!*exception);
725
726     JSRetainPtr<JSStringRef> baseURL;
727     if (argumentCount >= 2) {
728         baseURL = adopt(JSValueToStringCopy(context, arguments[1], exception));
729         ASSERT(!*exception);
730     } else
731         baseURL = adopt(JSStringCreateWithUTF8CString(""));
732
733     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
734
735     if (argumentCount >= 3) {
736         auto unreachableURL = adopt(JSValueToStringCopy(context, arguments[2], exception));
737         ASSERT(!*exception);
738         controller->queueLoadAlternateHTMLString(content.get(), baseURL.get(), unreachableURL.get());
739         return JSValueMakeUndefined(context);
740     }
741
742     controller->queueLoadHTMLString(content.get(), baseURL.get());
743     return JSValueMakeUndefined(context);
744 }
745
746 static JSValueRef queueReloadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
747 {
748     // Has mac & windows implementation
749     // May be able to be made platform independant by using shared WorkQueue
750
751     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
752     controller->queueReload();
753
754     return JSValueMakeUndefined(context);
755 }
756
757 static JSValueRef queueLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
758 {
759     // Has mac & windows implementation
760     // May be able to be made platform independant by using shared WorkQueue
761     if (argumentCount < 1)
762         return JSValueMakeUndefined(context);
763
764     auto script = adopt(JSValueToStringCopy(context, arguments[0], exception));
765     ASSERT(!*exception);
766
767     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
768     controller->queueLoadingScript(script.get());
769
770     return JSValueMakeUndefined(context);
771 }
772
773 static JSValueRef queueNonLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
774 {
775     // Has mac & windows implementation
776     // May be able to be made platform independant by using shared WorkQueue
777     if (argumentCount < 1)
778         return JSValueMakeUndefined(context);
779
780     auto script = adopt(JSValueToStringCopy(context, arguments[0], exception));
781     ASSERT(!*exception);
782
783     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
784     controller->queueNonLoadingScript(script.get());
785
786     return JSValueMakeUndefined(context);
787 }
788
789 static JSValueRef setAcceptsEditingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
790 {
791     // Has mac & windows implementation
792     if (argumentCount < 1)
793         return JSValueMakeUndefined(context);
794
795     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
796     controller->setAcceptsEditing(JSValueToBoolean(context, arguments[0]));
797
798     return JSValueMakeUndefined(context);
799 }
800
801 static JSValueRef setAlwaysAcceptCookiesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
802 {
803     // Has mac & windows implementation
804     if (argumentCount < 1)
805         return JSValueMakeUndefined(context);
806
807     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
808     controller->setAlwaysAcceptCookies(JSValueToBoolean(context, arguments[0]));
809
810     return JSValueMakeUndefined(context);
811 }
812
813 static JSValueRef setAppCacheMaximumSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
814 {
815     // Has mac implementation
816     if (argumentCount < 1)
817         return JSValueMakeUndefined(context);
818
819     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
820
821     double size = JSValueToNumber(context, arguments[0], NULL);
822     if (!std::isnan(size))
823         controller->setAppCacheMaximumSize(static_cast<unsigned long long>(size));
824         
825     return JSValueMakeUndefined(context);
826 }
827
828 static JSValueRef setAuthenticationPasswordCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
829 {
830     // Has mac & windows implementation
831     if (argumentCount < 1)
832         return JSValueMakeUndefined(context);
833
834     auto password = adopt(JSValueToStringCopy(context, arguments[0], exception));
835     ASSERT(!*exception);
836
837     size_t maxLength = JSStringGetMaximumUTF8CStringSize(password.get());
838     char* passwordBuffer = new char[maxLength + 1];
839     JSStringGetUTF8CString(password.get(), passwordBuffer, maxLength + 1);
840     
841     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
842     controller->setAuthenticationPassword(passwordBuffer);
843     delete[] passwordBuffer;
844
845     return JSValueMakeUndefined(context);
846 }
847
848 static JSValueRef setAuthenticationUsernameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
849 {
850     // Has mac & windows implementation
851     if (argumentCount < 1)
852         return JSValueMakeUndefined(context);
853
854     auto username = adopt(JSValueToStringCopy(context, arguments[0], exception));
855     ASSERT(!*exception);
856
857     size_t maxLength = JSStringGetMaximumUTF8CStringSize(username.get());
858     char* usernameBuffer = new char[maxLength + 1];
859     JSStringGetUTF8CString(username.get(), usernameBuffer, maxLength + 1);
860     
861     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
862     controller->setAuthenticationUsername(usernameBuffer);
863     delete[] usernameBuffer;
864
865     return JSValueMakeUndefined(context);
866 }
867
868 static JSValueRef setAuthorAndUserStylesEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
869 {
870     // Has mac & windows implementation
871     if (argumentCount < 1)
872         return JSValueMakeUndefined(context);
873
874     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
875     controller->setAuthorAndUserStylesEnabled(JSValueToBoolean(context, arguments[0]));
876
877     return JSValueMakeUndefined(context);
878 }
879
880 static JSValueRef setCacheModelCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
881 {
882     // Has Mac implementation.
883     if (argumentCount < 1)
884         return JSValueMakeUndefined(context);
885
886     int cacheModel = JSValueToNumber(context, arguments[0], exception);
887     ASSERT(!*exception);
888
889     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
890     controller->setCacheModel(cacheModel);
891
892     return JSValueMakeUndefined(context);
893 }
894
895 static JSValueRef setCustomPolicyDelegateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
896 {
897     // Has mac implementation
898     if (argumentCount < 1)
899         return JSValueMakeUndefined(context);
900     
901     bool permissive = false;
902     if (argumentCount >= 2)
903         permissive = JSValueToBoolean(context, arguments[1]);
904
905     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
906     controller->setCustomPolicyDelegate(JSValueToBoolean(context, arguments[0]), permissive);
907
908     return JSValueMakeUndefined(context);
909 }
910
911 static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
912 {
913     // Has mac implementation
914     if (argumentCount < 1)
915         return JSValueMakeUndefined(context);
916
917     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
918
919     double quota = JSValueToNumber(context, arguments[0], NULL);
920     if (!std::isnan(quota))
921         controller->setDatabaseQuota(static_cast<unsigned long long>(quota));
922         
923     return JSValueMakeUndefined(context);
924 }
925
926 static JSValueRef setDefersLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
927 {
928     if (argumentCount < 1)
929         return JSValueMakeUndefined(context);
930
931     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
932     controller->setDefersLoading(JSValueToBoolean(context, arguments[0]));
933
934     return JSValueMakeUndefined(context);
935 }
936
937 static JSValueRef setUseDeferredFrameLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
938 {
939     if (argumentCount < 1)
940         return JSValueMakeUndefined(context);
941
942     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
943     controller->setUseDeferredFrameLoading(JSValueToBoolean(context, arguments[0]));
944
945     return JSValueMakeUndefined(context);
946 }
947
948 static JSValueRef setDomainRelaxationForbiddenForURLSchemeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
949 {
950     // Has Mac and Windows implementation
951     if (argumentCount < 2)
952         return JSValueMakeUndefined(context);
953
954     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
955
956     bool forbidden = JSValueToBoolean(context, arguments[0]);
957     auto scheme = adopt(JSValueToStringCopy(context, arguments[1], 0));
958     controller->setDomainRelaxationForbiddenForURLScheme(forbidden, scheme.get());
959
960     return JSValueMakeUndefined(context);
961 }
962
963 static JSValueRef setMockDeviceOrientationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
964 {
965     if (argumentCount < 6)
966         return JSValueMakeUndefined(context);
967
968     bool canProvideAlpha = JSValueToBoolean(context, arguments[0]);
969     double alpha = JSValueToNumber(context, arguments[1], exception);
970     ASSERT(!*exception);
971     bool canProvideBeta = JSValueToBoolean(context, arguments[2]);
972     double beta = JSValueToNumber(context, arguments[3], exception);
973     ASSERT(!*exception);
974     bool canProvideGamma = JSValueToBoolean(context, arguments[4]);
975     double gamma = JSValueToNumber(context, arguments[5], exception);
976     ASSERT(!*exception);
977
978     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
979     controller->setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
980
981     return JSValueMakeUndefined(context);
982 }
983
984 static JSValueRef setMockGeolocationPositionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
985 {
986     if (argumentCount < 3)
987         return JSValueMakeUndefined(context);
988
989     double latitude = JSValueToNumber(context, arguments[0], 0);
990     double longitude = JSValueToNumber(context, arguments[1], 0);
991     double accuracy = JSValueToNumber(context, arguments[2], 0);
992
993     bool canProvideAltitude = false;
994     double altitude = 0.;
995     if (argumentCount > 3 && !JSValueIsUndefined(context, arguments[3])) {
996         canProvideAltitude = true;
997         altitude = JSValueToNumber(context, arguments[3], 0);
998     }
999
1000     bool canProvideAltitudeAccuracy = false;
1001     double altitudeAccuracy = 0.;
1002     if (argumentCount > 4 && !JSValueIsUndefined(context, arguments[4])) {
1003         canProvideAltitudeAccuracy = true;
1004         altitudeAccuracy = JSValueToNumber(context, arguments[4], 0);
1005     }
1006
1007     bool canProvideHeading = false;
1008     double heading = 0.;
1009     if (argumentCount > 5 && !JSValueIsUndefined(context, arguments[5])) {
1010         canProvideHeading = true;
1011         heading = JSValueToNumber(context, arguments[5], 0);
1012     }
1013
1014     bool canProvideSpeed = false;
1015     double speed = 0.;
1016     if (argumentCount > 6 && !JSValueIsUndefined(context, arguments[6])) {
1017         canProvideSpeed = true;
1018         speed = JSValueToNumber(context, arguments[6], 0);
1019     }
1020
1021     bool canProvideFloorLevel = false;
1022     double floorLevel = 0.;
1023     if (argumentCount > 7 && !JSValueIsUndefined(context, arguments[7])) {
1024         canProvideFloorLevel = true;
1025         floorLevel = JSValueToNumber(context, arguments[7], 0);
1026     }
1027
1028     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1029     controller->setMockGeolocationPosition(latitude, longitude, accuracy, canProvideAltitude, altitude, canProvideAltitudeAccuracy, altitudeAccuracy, canProvideHeading, heading, canProvideSpeed, speed, canProvideFloorLevel, floorLevel);
1030
1031     return JSValueMakeUndefined(context);
1032 }
1033
1034 static JSValueRef setMockGeolocationPositionUnavailableErrorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1035 {
1036     if (argumentCount != 1)
1037         return JSValueMakeUndefined(context);
1038
1039     auto message = adopt(JSValueToStringCopy(context, arguments[0], exception));
1040     ASSERT(!*exception);
1041
1042     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1043     controller->setMockGeolocationPositionUnavailableError(message.get());
1044
1045     return JSValueMakeUndefined(context);
1046 }
1047
1048 static JSValueRef setNewWindowsCopyBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1049 {
1050     // Has mac implementation
1051     if (argumentCount < 1)
1052         return JSValueMakeUndefined(context);
1053     
1054     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1055     controller->setNewWindowsCopyBackForwardList(JSValueToBoolean(context, arguments[0]));
1056
1057     return JSValueMakeUndefined(context);
1058 }
1059
1060 static JSValueRef setGeolocationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1061 {
1062     // Has mac implementation
1063     if (argumentCount < 1)
1064         return JSValueMakeUndefined(context);
1065
1066     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1067     controller->setGeolocationPermission(JSValueToBoolean(context, arguments[0]));
1068
1069     return JSValueMakeUndefined(context);
1070 }
1071
1072 static JSValueRef setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1073 {
1074     // Has mac & windows implementation
1075     if (argumentCount < 1)
1076         return JSValueMakeUndefined(context);
1077     
1078     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1079     controller->setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(JSValueToBoolean(context, arguments[0]));
1080     
1081     return JSValueMakeUndefined(context);
1082 }
1083
1084 static JSValueRef setHandlesAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1085 {
1086     // Has mac & windows implementation
1087     if (argumentCount < 1)
1088         return JSValueMakeUndefined(context);
1089
1090     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1091     controller->setHandlesAuthenticationChallenges(JSValueToBoolean(context, arguments[0]));
1092
1093     return JSValueMakeUndefined(context);
1094 }
1095
1096 static JSValueRef setPOSIXLocaleCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1097 {
1098     if (argumentCount < 1)
1099         return JSValueMakeUndefined(context);
1100
1101     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1102     auto locale = adopt(JSValueToStringCopy(context, arguments[0], exception));
1103     ASSERT(!*exception);
1104     controller->setPOSIXLocale(locale.get());
1105
1106     return JSValueMakeUndefined(context);
1107 }
1108
1109 static JSValueRef setIconDatabaseEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1110 {
1111     // Has mac & windows implementation
1112     if (argumentCount < 1)
1113         return JSValueMakeUndefined(context);
1114
1115     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1116     controller->setIconDatabaseEnabled(JSValueToBoolean(context, arguments[0]));
1117
1118     return JSValueMakeUndefined(context);
1119 }
1120
1121 static JSValueRef setMainFrameIsFirstResponderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1122 {
1123     // Has mac implementation
1124     if (argumentCount < 1)
1125         return JSValueMakeUndefined(context);
1126
1127     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1128     controller->setMainFrameIsFirstResponder(JSValueToBoolean(context, arguments[0]));
1129
1130     return JSValueMakeUndefined(context);
1131 }
1132
1133 static JSValueRef setPersistentUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1134 {
1135     // Has mac implementation
1136     if (argumentCount < 1)
1137         return JSValueMakeUndefined(context);
1138
1139     auto path = adopt(JSValueToStringCopy(context, arguments[0], exception));
1140     ASSERT(!*exception);
1141
1142     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1143     controller->setPersistentUserStyleSheetLocation(path.get());
1144
1145     return JSValueMakeUndefined(context);
1146 }
1147
1148 static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1149 {
1150     // Has mac & windows implementation
1151     if (argumentCount < 1)
1152         return JSValueMakeUndefined(context);
1153
1154     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1155     controller->setPrivateBrowsingEnabled(JSValueToBoolean(context, arguments[0]));
1156
1157     return JSValueMakeUndefined(context);
1158 }
1159
1160 static JSValueRef setJavaScriptCanAccessClipboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1161 {
1162     // Has mac & windows implementation
1163     if (argumentCount < 1)
1164         return JSValueMakeUndefined(context);
1165
1166     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1167     controller->setJavaScriptCanAccessClipboard(JSValueToBoolean(context, arguments[0]));
1168
1169     return JSValueMakeUndefined(context);
1170 }
1171
1172 static JSValueRef setXSSAuditorEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1173 {
1174     // Has mac & windows implementation
1175     if (argumentCount < 1)
1176         return JSValueMakeUndefined(context);
1177
1178     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1179     controller->setXSSAuditorEnabled(JSValueToBoolean(context, arguments[0]));
1180
1181     return JSValueMakeUndefined(context);
1182 }
1183
1184 static JSValueRef setSpatialNavigationEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1185 {
1186     // Has mac & windows implementation.
1187     if (argumentCount < 1)
1188         return JSValueMakeUndefined(context);
1189
1190     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1191     controller->setSpatialNavigationEnabled(JSValueToBoolean(context, arguments[0]));
1192
1193     return JSValueMakeUndefined(context);
1194 }
1195
1196 static JSValueRef setPrintingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1197 {
1198     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1199     controller->setIsPrinting(true);
1200     return JSValueMakeUndefined(context);
1201 }
1202
1203 static JSValueRef setAllowsAnySSLCertificateCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1204 {
1205     bool allowAnyCertificate = false;
1206     if (argumentCount == 1)
1207         allowAnyCertificate = JSValueToBoolean(context, arguments[0]);
1208     
1209     TestRunner::setAllowsAnySSLCertificate(allowAnyCertificate);
1210     return JSValueMakeUndefined(context);
1211 }
1212
1213 static JSValueRef setAllowUniversalAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1214 {
1215     // Has mac & windows implementation
1216     if (argumentCount < 1)
1217         return JSValueMakeUndefined(context);
1218
1219     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1220     controller->setAllowUniversalAccessFromFileURLs(JSValueToBoolean(context, arguments[0]));
1221
1222     return JSValueMakeUndefined(context);
1223 }
1224
1225 static JSValueRef setAllowFileAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1226 {
1227     // Has mac & windows implementation
1228     if (argumentCount < 1)
1229         return JSValueMakeUndefined(context);
1230
1231     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1232     controller->setAllowFileAccessFromFileURLs(JSValueToBoolean(context, arguments[0]));
1233
1234     return JSValueMakeUndefined(context);
1235 }
1236
1237 static JSValueRef setNeedsStorageAccessFromFileURLsQuirkCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1238 {
1239     // Has mac & windows implementation
1240     if (argumentCount < 1)
1241         return JSValueMakeUndefined(context);
1242     
1243     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1244     controller->setNeedsStorageAccessFromFileURLsQuirk(JSValueToBoolean(context, arguments[0]));
1245     
1246     return JSValueMakeUndefined(context);
1247 }
1248
1249 static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1250 {
1251     // Has mac & windows implementation
1252     if (argumentCount < 1)
1253         return JSValueMakeUndefined(context);
1254
1255     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1256     controller->setTabKeyCyclesThroughElements(JSValueToBoolean(context, arguments[0]));
1257
1258     return JSValueMakeUndefined(context);
1259 }
1260
1261 #if PLATFORM(IOS)
1262 static JSValueRef setTelephoneNumberParsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1263 {
1264     if (argumentCount < 1)
1265         return JSValueMakeUndefined(context);
1266
1267     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1268     controller->setTelephoneNumberParsingEnabled(JSValueToBoolean(context, arguments[0]));
1269
1270     return JSValueMakeUndefined(context);
1271 }
1272
1273 static JSValueRef setPagePausedCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1274 {
1275     if (argumentCount < 1)
1276         return JSValueMakeUndefined(context);
1277
1278     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1279     controller->setPagePaused(JSValueToBoolean(context, arguments[0]));
1280
1281     return JSValueMakeUndefined(context);
1282 }
1283 #endif
1284
1285 static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1286 {
1287     // Has mac implementation
1288     if (argumentCount < 1)
1289         return JSValueMakeUndefined(context);
1290
1291     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1292     controller->setUseDashboardCompatibilityMode(JSValueToBoolean(context, arguments[0]));
1293
1294     return JSValueMakeUndefined(context);
1295 }
1296
1297 static JSValueRef setUserStyleSheetEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1298 {
1299     // Has mac implementation
1300     if (argumentCount < 1)
1301         return JSValueMakeUndefined(context);
1302
1303     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1304     controller->setUserStyleSheetEnabled(JSValueToBoolean(context, arguments[0]));
1305
1306     return JSValueMakeUndefined(context);
1307 }
1308
1309 static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1310 {
1311     // Has mac implementation
1312     if (argumentCount < 1)
1313         return JSValueMakeUndefined(context);
1314
1315     auto path = adopt(JSValueToStringCopy(context, arguments[0], exception));
1316     ASSERT(!*exception);
1317
1318     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1319     controller->setUserStyleSheetLocation(path.get());
1320
1321     return JSValueMakeUndefined(context);
1322 }
1323
1324 static JSValueRef setValueForUserCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1325 {
1326     // Has mac implementation
1327     if (argumentCount != 2)
1328         return JSValueMakeUndefined(context);
1329
1330     auto value = adopt(JSValueToStringCopy(context, arguments[1], exception));
1331     ASSERT(!*exception);
1332
1333     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1334     controller->setValueForUser(context, arguments[0], value.get());
1335
1336     return JSValueMakeUndefined(context);
1337 }
1338
1339 static JSValueRef setWillSendRequestClearHeaderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1340 {
1341     // Has mac & windows implementation
1342     if (argumentCount < 1)
1343         return JSValueMakeUndefined(context);
1344
1345     auto header = adopt(JSValueToStringCopy(context, arguments[0], exception));
1346     ASSERT(!*exception);
1347
1348     size_t maxLength = JSStringGetMaximumUTF8CStringSize(header.get());
1349     auto headerBuffer = std::make_unique<char[]>(maxLength + 1);
1350     JSStringGetUTF8CString(header.get(), headerBuffer.get(), maxLength + 1);
1351
1352     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1353     controller->setWillSendRequestClearHeader(headerBuffer.get());
1354
1355     return JSValueMakeUndefined(context);
1356 }
1357
1358 static JSValueRef setWillSendRequestReturnsNullCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1359 {
1360     // Has cross-platform implementation
1361     if (argumentCount < 1)
1362         return JSValueMakeUndefined(context);
1363
1364     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1365     controller->setWillSendRequestReturnsNull(JSValueToBoolean(context, arguments[0]));
1366
1367     return JSValueMakeUndefined(context);
1368 }
1369
1370 static JSValueRef setWillSendRequestReturnsNullOnRedirectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1371 {
1372     // Has cross-platform implementation
1373     if (argumentCount < 1)
1374         return JSValueMakeUndefined(context);
1375
1376     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1377     controller->setWillSendRequestReturnsNullOnRedirect(JSValueToBoolean(context, arguments[0]));
1378
1379     return JSValueMakeUndefined(context);
1380 }
1381
1382 static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1383 {
1384     // Has mac implementation
1385     if (argumentCount < 1)
1386         return JSValueMakeUndefined(context);
1387
1388     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1389     controller->setWindowIsKey(JSValueToBoolean(context, arguments[0]));
1390
1391     return JSValueMakeUndefined(context);
1392 }
1393
1394 static JSValueRef setViewSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1395 {
1396     if (argumentCount < 2)
1397         return JSValueMakeUndefined(context);
1398
1399     double width = JSValueToNumber(context, arguments[0], exception);
1400     ASSERT(!*exception);
1401     double height = JSValueToNumber(context, arguments[1], exception);
1402     ASSERT(!*exception);
1403
1404     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1405     controller->setViewSize(width, height);
1406
1407     return JSValueMakeUndefined(context);
1408 }
1409
1410 static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1411 {
1412     // Has mac & windows implementation
1413     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1414     controller->setWaitToDump(true);
1415
1416     return JSValueMakeUndefined(context);
1417 }
1418
1419 static JSValueRef windowCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1420 {
1421     // Has mac implementation
1422     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1423     int windows = controller->windowCount();
1424     return JSValueMakeNumber(context, windows);
1425 }
1426
1427 static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1428 {
1429     // Has mac & windows implementation
1430     if (argumentCount < 1)
1431         return JSValueMakeUndefined(context);
1432
1433     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1434     controller->setPopupBlockingEnabled(JSValueToBoolean(context, arguments[0]));
1435
1436     return JSValueMakeUndefined(context);
1437 }
1438
1439 static JSValueRef setPluginsEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1440 {
1441     // Has mac & windows implementation
1442     if (argumentCount < 1)
1443         return JSValueMakeUndefined(context);
1444     
1445     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1446     controller->setPluginsEnabled(JSValueToBoolean(context, arguments[0]));
1447     
1448     return JSValueMakeUndefined(context);
1449 }    
1450
1451 static JSValueRef setPageVisibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1452 {
1453     // Has mac & windows implementation
1454     if (argumentCount < 1)
1455         return JSValueMakeUndefined(context);
1456
1457     auto visibility = adopt(JSValueToStringCopy(context, arguments[0], exception));
1458     ASSERT(!*exception);
1459
1460     size_t maxLength = JSStringGetMaximumUTF8CStringSize(visibility.get());
1461     char* visibilityBuffer = new char[maxLength + 1];
1462     JSStringGetUTF8CString(visibility.get(), visibilityBuffer, maxLength + 1);
1463     
1464     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1465     controller->setPageVisibility(visibilityBuffer);
1466     delete[] visibilityBuffer;
1467     
1468     return JSValueMakeUndefined(context);
1469 }    
1470
1471 static JSValueRef resetPageVisibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1472 {
1473     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1474     controller->resetPageVisibility();
1475     return JSValueMakeUndefined(context);
1476 }    
1477
1478 static JSValueRef setAutomaticLinkDetectionEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1479 {
1480     if (argumentCount < 1)
1481         return JSValueMakeUndefined(context);
1482
1483     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1484     controller->setAutomaticLinkDetectionEnabled(JSValueToBoolean(context, arguments[0]));
1485     return JSValueMakeUndefined(context);
1486 }
1487
1488 static JSValueRef setStopProvisionalFrameLoadsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1489 {
1490     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1491     controller->setStopProvisionalFrameLoads(true);
1492     return JSValueMakeUndefined(context);
1493 }
1494
1495 static JSValueRef showWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1496 {
1497     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1498     controller->showWebInspector();
1499     return JSValueMakeUndefined(context);
1500 }
1501
1502 static JSValueRef closeWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1503 {
1504     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1505     controller->closeWebInspector();
1506     return JSValueMakeUndefined(context);
1507 }
1508
1509 static JSValueRef evaluateInWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1510 {
1511     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1512     auto script = adopt(JSValueToStringCopy(context, arguments[0], exception));
1513     ASSERT(!*exception);
1514
1515     controller->evaluateInWebInspector(script.get());
1516     return JSValueMakeUndefined(context);
1517 }
1518
1519 static JSValueRef evaluateScriptInIsolatedWorldCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1520 {
1521     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1522     double worldID = JSValueToNumber(context, arguments[0], exception);
1523     ASSERT(!*exception);
1524     auto script = adopt(JSValueToStringCopy(context, arguments[1], exception));
1525     ASSERT(!*exception);
1526
1527     controller->evaluateScriptInIsolatedWorld(static_cast<unsigned>(worldID), JSContextGetGlobalObject(context), script.get());
1528     return JSValueMakeUndefined(context);
1529 }
1530
1531 static JSValueRef evaluateScriptInIsolatedWorldAndReturnValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1532 {
1533     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1534     double worldID = JSValueToNumber(context, arguments[0], exception);
1535     ASSERT(!*exception);
1536     auto script = adopt(JSValueToStringCopy(context, arguments[1], exception));
1537     ASSERT(!*exception);
1538
1539     controller->evaluateScriptInIsolatedWorldAndReturnValue(static_cast<unsigned>(worldID), JSContextGetGlobalObject(context), script.get());
1540     return JSValueMakeUndefined(context);
1541 }
1542
1543 static JSValueRef waitForPolicyDelegateCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*)
1544 {
1545     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1546     controller->waitForPolicyDelegate();
1547     return JSValueMakeUndefined(context);
1548 }
1549
1550 static JSValueRef addOriginAccessWhitelistEntryCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1551 {
1552     if (argumentCount != 4)
1553         return JSValueMakeUndefined(context);
1554
1555     auto sourceOrigin = adopt(JSValueToStringCopy(context, arguments[0], exception));
1556     ASSERT(!*exception);
1557     auto destinationProtocol = adopt(JSValueToStringCopy(context, arguments[1], exception));
1558     ASSERT(!*exception);
1559     auto destinationHost = adopt(JSValueToStringCopy(context, arguments[2], exception));
1560     ASSERT(!*exception);
1561     bool allowDestinationSubdomains = JSValueToBoolean(context, arguments[3]);
1562
1563     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1564     controller->addOriginAccessWhitelistEntry(sourceOrigin.get(), destinationProtocol.get(), destinationHost.get(), allowDestinationSubdomains);
1565     return JSValueMakeUndefined(context);
1566 }
1567
1568 static JSValueRef removeOriginAccessWhitelistEntryCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1569 {
1570     if (argumentCount != 4)
1571         return JSValueMakeUndefined(context);
1572
1573     auto sourceOrigin = adopt(JSValueToStringCopy(context, arguments[0], exception));
1574     ASSERT(!*exception);
1575     auto destinationProtocol = adopt(JSValueToStringCopy(context, arguments[1], exception));
1576     ASSERT(!*exception);
1577     auto destinationHost = adopt(JSValueToStringCopy(context, arguments[2], exception));
1578     ASSERT(!*exception);
1579     bool allowDestinationSubdomains = JSValueToBoolean(context, arguments[3]);
1580
1581     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1582     controller->removeOriginAccessWhitelistEntry(sourceOrigin.get(), destinationProtocol.get(), destinationHost.get(), allowDestinationSubdomains);
1583     return JSValueMakeUndefined(context);
1584 }
1585
1586 static JSValueRef setScrollbarPolicyCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1587 {
1588     if (argumentCount != 2)
1589         return JSValueMakeUndefined(context);
1590
1591     auto orientation = adopt(JSValueToStringCopy(context, arguments[0], exception));
1592     ASSERT(!*exception);
1593     auto policy = adopt(JSValueToStringCopy(context, arguments[1], exception));
1594     ASSERT(!*exception);
1595
1596     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1597     controller->setScrollbarPolicy(orientation.get(), policy.get());
1598     return JSValueMakeUndefined(context);
1599 }
1600
1601 static JSValueRef addUserScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1602 {
1603     if (argumentCount != 3)
1604         return JSValueMakeUndefined(context);
1605     
1606     auto source = adopt(JSValueToStringCopy(context, arguments[0], exception));
1607     ASSERT(!*exception);
1608     bool runAtStart = JSValueToBoolean(context, arguments[1]);
1609     bool allFrames = JSValueToBoolean(context, arguments[2]);
1610     
1611     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1612     controller->addUserScript(source.get(), runAtStart, allFrames);
1613     return JSValueMakeUndefined(context);
1614 }
1615  
1616 static JSValueRef addUserStyleSheetCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1617 {
1618     if (argumentCount != 2)
1619         return JSValueMakeUndefined(context);
1620     
1621     auto source = adopt(JSValueToStringCopy(context, arguments[0], exception));
1622     ASSERT(!*exception);
1623     bool allFrames = JSValueToBoolean(context, arguments[1]);
1624    
1625     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1626     controller->addUserStyleSheet(source.get(), allFrames);
1627     return JSValueMakeUndefined(context);
1628 }
1629
1630 static JSValueRef setShouldPaintBrokenImageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1631 {
1632     // Has Mac implementation
1633     if (argumentCount < 1)
1634         return JSValueMakeUndefined(context);
1635
1636     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1637     controller->setShouldPaintBrokenImage(JSValueToBoolean(context, arguments[0]));
1638
1639     return JSValueMakeUndefined(context);
1640 }
1641
1642 static JSValueRef apiTestNewWindowDataLoadBaseURLCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1643 {
1644     if (argumentCount != 2)
1645         return JSValueMakeUndefined(context);
1646
1647     auto utf8Data = adopt(JSValueToStringCopy(context, arguments[0], exception));
1648     ASSERT(!*exception);
1649
1650     auto baseURL = adopt(JSValueToStringCopy(context, arguments[1], exception));
1651     ASSERT(!*exception);
1652         
1653     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1654     controller->apiTestNewWindowDataLoadBaseURL(utf8Data.get(), baseURL.get());
1655     return JSValueMakeUndefined(context);
1656 }
1657
1658 static JSValueRef apiTestGoToCurrentBackForwardItemCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1659 {
1660     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1661     controller->apiTestGoToCurrentBackForwardItem();
1662     return JSValueMakeUndefined(context);
1663 }
1664
1665 static JSValueRef setWebViewEditableCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1666 {
1667     // Has Mac implementation
1668     if (argumentCount < 1)
1669         return JSValueMakeUndefined(context);
1670
1671     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1672     controller->setWebViewEditable(JSValueToBoolean(context, arguments[0]));
1673
1674     return JSValueMakeUndefined(context);
1675 }
1676
1677 static JSValueRef abortModalCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1678 {
1679     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1680     controller->abortModal();
1681     return JSValueMakeUndefined(context);
1682 }
1683
1684 static JSValueRef authenticateSessionCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1685 {
1686     // authenticateSession(url, username, password)
1687     if (argumentCount != 3)
1688         return JSValueMakeUndefined(context);
1689
1690     auto url = adopt(JSValueToStringCopy(context, arguments[0], exception));
1691     ASSERT(!*exception);
1692     auto username = adopt(JSValueToStringCopy(context, arguments[1], exception));
1693     ASSERT(!*exception);
1694     auto password = adopt(JSValueToStringCopy(context, arguments[2], exception));
1695     ASSERT(!*exception);
1696
1697     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1698     controller->authenticateSession(url.get(), username.get(), password.get());
1699     return JSValueMakeUndefined(context);
1700 }
1701
1702 static JSValueRef setSerializeHTTPLoadsCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1703 {
1704     bool serialize = true;
1705     if (argumentCount == 1)
1706         serialize = JSValueToBoolean(context, arguments[0]);
1707
1708     TestRunner::setSerializeHTTPLoads(serialize);
1709     return JSValueMakeUndefined(context);
1710 }
1711
1712 static JSValueRef setShouldStayOnPageAfterHandlingBeforeUnloadCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1713 {
1714     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1715     
1716     if (argumentCount == 1)
1717         controller->setShouldStayOnPageAfterHandlingBeforeUnload(JSValueToBoolean(context, arguments[0]));
1718
1719     return JSValueMakeUndefined(context);
1720 }
1721
1722 static JSValueRef addChromeInputFieldCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1723 {
1724     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1725     controller->addChromeInputField();
1726     // the first argument is a callback that is called once the input field has been added
1727     if (argumentCount == 1)
1728         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1729     return JSValueMakeUndefined(context);
1730 }
1731
1732 static JSValueRef removeChromeInputFieldCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1733 {
1734     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1735     controller->removeChromeInputField();
1736     // the first argument is a callback that is called once the input field has been added
1737     if (argumentCount == 1)
1738         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1739     return JSValueMakeUndefined(context);
1740 }
1741
1742 static JSValueRef focusWebViewCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1743 {
1744     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1745     controller->focusWebView();
1746     // the first argument is a callback that is called once the input field has been added
1747     if (argumentCount == 1)
1748         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1749     return JSValueMakeUndefined(context);
1750 }
1751
1752 static JSValueRef setBackingScaleFactorCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1753 {
1754     if (argumentCount != 2)
1755         return JSValueMakeUndefined(context);
1756
1757     double backingScaleFactor = JSValueToNumber(context, arguments[0], exception);
1758     ASSERT(!*exception);
1759
1760     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1761     controller->setBackingScaleFactor(backingScaleFactor);
1762
1763     // The second argument is a callback that is called once the backing scale factor has been set.
1764     JSObjectCallAsFunction(context, JSValueToObject(context, arguments[1], 0), thisObject, 0, 0, 0);
1765     return JSValueMakeUndefined(context);
1766 }
1767
1768 static JSValueRef preciseTimeCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1769 {
1770     return JSValueMakeNumber(context, WallTime::now().secondsSinceEpoch().seconds());
1771 }
1772
1773 static JSValueRef imageCountInGeneralPasteboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1774 {
1775     // Has mac & windows implementation
1776     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1777     
1778     return JSValueMakeNumber(context, controller->imageCountInGeneralPasteboard());
1779 }
1780
1781 static JSValueRef setSpellCheckerLoggingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1782 {
1783     if (argumentCount < 1)
1784         return JSValueMakeUndefined(context);
1785     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1786     controller->setSpellCheckerLoggingEnabled(JSValueToBoolean(context, arguments[0]));
1787     return JSValueMakeUndefined(context);
1788 }
1789
1790 static JSValueRef setSpellCheckerResultsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1791 {
1792     if (argumentCount < 1)
1793         return JSValueMakeUndefined(context);
1794
1795     auto* runner = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1796     runner->setSpellCheckerResults(context, JSValueToObject(context, arguments[0], nullptr));
1797     return JSValueMakeUndefined(context);
1798 }
1799
1800 static JSValueRef setOpenPanelFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1801 {
1802     if (argumentCount == 1)
1803         static_cast<TestRunner*>(JSObjectGetPrivate(thisObject))->setOpenPanelFiles(context, arguments[0]);
1804     return JSValueMakeUndefined(context);
1805 }
1806
1807 // Static Values
1808
1809 static JSValueRef getTimeoutCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1810 {
1811     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1812     return JSValueMakeNumber(context, controller->timeout());
1813 }
1814
1815 static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1816 {
1817     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1818     return JSValueMakeBoolean(context, controller->globalFlag());
1819 }
1820
1821 static JSValueRef getDidCancelClientRedirect(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1822 {
1823     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1824     return JSValueMakeBoolean(context, controller->didCancelClientRedirect());
1825 }
1826
1827 static JSValueRef getDatabaseDefaultQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1828 {
1829     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1830     return JSValueMakeNumber(context, controller->databaseDefaultQuota());
1831 }
1832
1833 static JSValueRef getDatabaseMaxQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1834 {
1835     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1836     return JSValueMakeNumber(context, controller->databaseMaxQuota());
1837 }
1838
1839 static JSValueRef getWebHistoryItemCountCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1840 {
1841     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1842     return JSValueMakeNumber(context, controller->webHistoryItemCount());
1843 }
1844
1845 static JSValueRef getSecureEventInputIsEnabledCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1846 {
1847 #if PLATFORM(MAC) && !PLATFORM(IOS)
1848     return JSValueMakeBoolean(context, IsSecureEventInputEnabled());
1849 #else
1850     return JSValueMakeBoolean(context, false);
1851 #endif
1852 }
1853
1854 static JSValueRef getTitleTextDirectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1855 {
1856     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1857     auto titleDirection = adopt(JSStringCreateWithUTF8CString(controller->titleTextDirection().c_str()));
1858     return JSValueMakeString(context, titleDirection.get());
1859 }
1860
1861 static JSValueRef getInspectorTestStubURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1862 {
1863     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1864     auto url = controller->inspectorTestStubURL();
1865     return JSValueMakeString(context, url.get());
1866 }
1867
1868 static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1869 {
1870     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1871     controller->setGlobalFlag(JSValueToBoolean(context, value));
1872     return true;
1873 }
1874
1875 static bool setDatabaseDefaultQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1876 {
1877     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1878     controller->setDatabaseDefaultQuota(JSValueToNumber(context, value, exception));
1879     ASSERT(!*exception);
1880     return true;
1881 }
1882
1883 static bool setDatabaseMaxQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1884 {
1885     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1886     controller->setDatabaseMaxQuota(JSValueToNumber(context, value, exception));
1887     ASSERT(!*exception);
1888     return true;
1889 }
1890
1891 static JSValueRef ignoreLegacyWebNotificationPermissionRequestsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1892 {
1893     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1894     controller->ignoreLegacyWebNotificationPermissionRequests();
1895     return JSValueMakeUndefined(context);
1896 }
1897
1898 static JSValueRef simulateLegacyWebNotificationClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1899 {
1900     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); 
1901     auto title = adopt(JSValueToStringCopy(context, arguments[0], exception));
1902     controller->simulateLegacyWebNotificationClick(title.get());
1903     return JSValueMakeUndefined(context);
1904 }
1905
1906 static JSValueRef setTextDirectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1907 {
1908     if (argumentCount == 1) {
1909         auto direction = adopt(JSValueToStringCopy(context, arguments[0], exception));
1910         TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1911         controller->setTextDirection(direction.get());
1912     }
1913
1914     return JSValueMakeUndefined(context);
1915
1916 }
1917
1918 static JSValueRef setHasCustomFullScreenBehaviorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1919 {
1920     if (argumentCount == 1) {
1921         bool hasCustomBehavior = JSValueToBoolean(context, arguments[0]);
1922         TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1923         controller->setHasCustomFullScreenBehavior(hasCustomBehavior);
1924     }
1925
1926     return JSValueMakeUndefined(context);
1927 }
1928
1929 static JSValueRef setStorageDatabaseIdleIntervalCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1930 {
1931     if (argumentCount != 1)
1932         return JSValueMakeUndefined(context);
1933
1934     double interval = JSValueToNumber(context, arguments[0], exception);
1935     ASSERT(!*exception);
1936
1937     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1938     controller->setStorageDatabaseIdleInterval(interval);
1939
1940     return JSValueMakeUndefined(context);
1941 }
1942
1943 static JSValueRef closeIdleLocalStorageDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1944 {
1945     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1946     controller->closeIdleLocalStorageDatabases();
1947
1948     return JSValueMakeUndefined(context);
1949 }
1950
1951 static JSValueRef grantWebNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1952 {
1953     if (argumentCount < 1)
1954         return JSValueMakeUndefined(context);
1955
1956     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1957
1958     auto origin = adopt(JSValueToStringCopy(context, arguments[0], exception));
1959     ASSERT(!*exception);
1960     controller->grantWebNotificationPermission(origin.get());
1961
1962     return JSValueMakeUndefined(context);
1963 }
1964
1965
1966 static JSValueRef denyWebNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1967 {
1968     if (argumentCount < 1)
1969         return JSValueMakeUndefined(context);
1970
1971     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1972
1973     auto origin = adopt(JSValueToStringCopy(context, arguments[0], exception));
1974     ASSERT(!*exception);
1975     controller->denyWebNotificationPermission(origin.get());
1976
1977     return JSValueMakeUndefined(context);
1978 }
1979
1980
1981 static JSValueRef removeAllWebNotificationPermissionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1982 {
1983     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1984
1985     controller->removeAllWebNotificationPermissions();
1986
1987     return JSValueMakeUndefined(context);
1988 }
1989
1990
1991 static JSValueRef simulateWebNotificationClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1992 {
1993     // Has Windows implementation
1994     if (argumentCount < 1)
1995         return JSValueMakeUndefined(context);
1996
1997     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1998
1999     controller->simulateWebNotificationClick(arguments[0]);
2000
2001     return JSValueMakeUndefined(context);
2002 }
2003
2004 static JSValueRef forceImmediateCompletionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2005 {
2006     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
2007     controller->forceImmediateCompletion();
2008     return JSValueMakeUndefined(context);
2009 }
2010
2011 static JSValueRef failNextNewCodeBlock(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2012 {
2013     if (argumentCount < 1)
2014         return JSValueMakeUndefined(context);
2015     
2016     return JSC::failNextNewCodeBlock(context);
2017 }
2018
2019 static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2020 {
2021     return JSC::numberOfDFGCompiles(context, arguments[0]);
2022 }
2023
2024 static JSValueRef neverInlineFunction(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2025 {
2026     if (argumentCount < 1)
2027         return JSValueMakeUndefined(context);
2028     
2029     return JSC::setNeverInline(context, arguments[0]);
2030 }
2031
2032 static JSValueRef accummulateLogsForChannel(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2033 {
2034     if (argumentCount < 1)
2035         return JSValueMakeUndefined(context);
2036
2037     auto channel = adopt(JSValueToStringCopy(context, arguments[0], exception));
2038     ASSERT(!*exception);
2039
2040     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
2041     controller->setAccummulateLogsForChannel(channel.get());
2042
2043     return JSValueMakeUndefined(context);
2044 }
2045
2046 static JSValueRef runUIScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2047 {
2048     if (argumentCount < 1)
2049         return JSValueMakeUndefined(context);
2050
2051     auto script = argumentCount > 0 ? adopt(JSValueToStringCopy(context, arguments[0], 0)) : JSRetainPtr<JSStringRef>();
2052     JSValueRef callback = argumentCount > 1 ? arguments[1] : JSValueMakeUndefined(context);
2053
2054     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
2055     controller->runUIScript(context, script.get(), callback);
2056
2057     return JSValueMakeUndefined(context);
2058 }
2059
2060 static void testRunnerObjectFinalize(JSObjectRef object)
2061 {
2062     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(object));
2063     controller->deref();
2064 }
2065
2066 // Object Creation
2067
2068 void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
2069 {
2070     auto testRunnerStr = adopt(JSStringCreateWithUTF8CString("testRunner"));
2071     ref();
2072
2073     JSClassRef classRef = getJSClass();
2074     JSValueRef layoutTestContollerObject = JSObjectMake(context, classRef, this);
2075     JSClassRelease(classRef);
2076
2077     JSObjectSetProperty(context, windowObject, testRunnerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
2078 }
2079
2080 JSClassRef TestRunner::getJSClass()
2081 {
2082     static JSStaticValue* staticValues = TestRunner::staticValues();
2083     static JSStaticFunction* staticFunctions = TestRunner::staticFunctions();
2084     static JSClassDefinition classDefinition = {
2085         0, kJSClassAttributeNone, "TestRunner", 0, staticValues, staticFunctions,
2086         0, testRunnerObjectFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
2087     };
2088
2089     return JSClassCreate(&classDefinition);
2090 }
2091
2092 JSStaticValue* TestRunner::staticValues()
2093 {
2094     static JSStaticValue staticValues[] = {
2095         { "didCancelClientRedirect", getDidCancelClientRedirect, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2096         { "timeout", getTimeoutCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2097         { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone },
2098         { "webHistoryItemCount", getWebHistoryItemCountCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2099         { "secureEventInputIsEnabled", getSecureEventInputIsEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2100         { "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2101         { "databaseDefaultQuota", getDatabaseDefaultQuotaCallback, setDatabaseDefaultQuotaCallback, kJSPropertyAttributeNone },
2102         { "databaseMaxQuota", getDatabaseMaxQuotaCallback, setDatabaseMaxQuotaCallback, kJSPropertyAttributeNone },
2103         { "inspectorTestStubURL", getInspectorTestStubURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2104         { 0, 0, 0, 0 }
2105     };
2106     return staticValues;
2107 }
2108
2109 JSStaticFunction* TestRunner::staticFunctions()
2110 {
2111     static JSStaticFunction staticFunctions[] = {
2112         { "abortModal", abortModalCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2113         { "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2114         { "addURLToRedirect", addURLToRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2115         { "addUserScript", addUserScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2116         { "addUserStyleSheet", addUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2117         { "apiTestNewWindowDataLoadBaseURL", apiTestNewWindowDataLoadBaseURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2118         { "apiTestGoToCurrentBackForwardItem", apiTestGoToCurrentBackForwardItemCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2119         { "applicationCacheDiskUsageForOrigin", applicationCacheDiskUsageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2120         { "callShouldCloseOnWebView", callShouldCloseOnWebViewCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2121         { "clearAllApplicationCaches", clearAllApplicationCachesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2122         { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2123         { "clearApplicationCacheForOrigin", clearApplicationCacheForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2124         { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2125         { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2126         { "closeWebInspector", closeWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2127         { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2128         { "disallowIncreaseForApplicationCacheQuota", disallowIncreaseForApplicationCacheQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2129         { "dispatchPendingLoadRequests", dispatchPendingLoadRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2130         { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2131         { "displayAndTrackRepaints", displayAndTrackRepaintsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2132         { "dumpApplicationCacheDelegateCallbacks", dumpApplicationCacheDelegateCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2133         { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2134         { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2135         { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2136         { "dumpChildFramesAsText", dumpChildFramesAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2137         { "dumpDOMAsWebArchive", dumpDOMAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2138         { "dumpDatabaseCallbacks", dumpDatabaseCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2139         { "dumpEditingCallbacks", dumpEditingCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2140         { "dumpFrameLoadCallbacks", dumpFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2141         { "dumpProgressFinishedCallback", dumpProgressFinishedCallbackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2142         { "dumpUserGestureInFrameLoadCallbacks", dumpUserGestureInFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },        
2143         { "dumpResourceLoadCallbacks", dumpResourceLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2144         { "dumpResourceResponseMIMETypes", dumpResourceResponseMIMETypesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2145         { "dumpSelectionRect", dumpSelectionRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2146         { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2147         { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2148         { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2149         { "dumpWillCacheResponse", dumpWillCacheResponseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2150         { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2151         { "evaluateInWebInspector", evaluateInWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2152         { "evaluateScriptInIsolatedWorldAndReturnValue", evaluateScriptInIsolatedWorldAndReturnValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2153         { "evaluateScriptInIsolatedWorld", evaluateScriptInIsolatedWorldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2154         { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2155         { "findString", findStringCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2156         { "originsWithApplicationCache", originsWithApplicationCacheCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2157         { "goBack", goBackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
2158         { "ignoreLegacyWebNotificationPermissionRequests", ignoreLegacyWebNotificationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2159         { "isGeolocationProviderActive", isGeolocationProviderActiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2160         { "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2161         { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2162         { "numberOfPendingGeolocationPermissionRequests", numberOfPendingGeolocationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2163         { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2164         { "overridePreference", overridePreferenceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2165         { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2166         { "printToPDF", dumpAsPDFCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2167         { "queueBackNavigation", queueBackNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2168         { "queueForwardNavigation", queueForwardNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2169         { "queueLoad", queueLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2170         { "queueLoadHTMLString", queueLoadHTMLStringCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2171         { "queueLoadingScript", queueLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2172         { "queueNonLoadingScript", queueNonLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2173         { "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2174         { "removeAllVisitedLinks", removeAllVisitedLinksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2175         { "removeOriginAccessWhitelistEntry", removeOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2176         { "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2177         { "resetPageVisibility", resetPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2178         { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2179         { "setAllowUniversalAccessFromFileURLs", setAllowUniversalAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2180         { "setAllowFileAccessFromFileURLs", setAllowFileAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2181         { "setNeedsStorageAccessFromFileURLsQuirk", setNeedsStorageAccessFromFileURLsQuirkCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2182         { "setAllowsAnySSLCertificate", setAllowsAnySSLCertificateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2183         { "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2184         { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2185         { "setAudioResult", setAudioResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2186         { "setAuthenticationPassword", setAuthenticationPasswordCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2187         { "setAuthenticationUsername", setAuthenticationUsernameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2188         { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2189         { "setCacheModel", setCacheModelCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2190         { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2191         { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2192         { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2193         { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2194         { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
2195         { "setDefersLoading", setDefersLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2196         { "setUseDeferredFrameLoading", setUseDeferredFrameLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2197         { "setDomainRelaxationForbiddenForURLScheme", setDomainRelaxationForbiddenForURLSchemeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2198         { "setGeolocationPermission", setGeolocationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2199         { "setRejectsProtectionSpaceAndContinueForAuthenticationChallenges", setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2200         { "setHandlesAuthenticationChallenges", setHandlesAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2201         { "setIconDatabaseEnabled", setIconDatabaseEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2202         { "setAutomaticLinkDetectionEnabled", setAutomaticLinkDetectionEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2203         { "setMainFrameIsFirstResponder", setMainFrameIsFirstResponderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2204         { "setMockDeviceOrientation", setMockDeviceOrientationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2205         { "setMockGeolocationPositionUnavailableError", setMockGeolocationPositionUnavailableErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2206         { "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2207         { "setNewWindowsCopyBackForwardList", setNewWindowsCopyBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2208         { "setPageVisibility", setPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2209         { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2210         { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2211         { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2212         { "setPluginsEnabled", setPluginsEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2213         { "setPrinting", setPrintingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2214         { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2215         { "setSerializeHTTPLoads", setSerializeHTTPLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2216         { "setSpatialNavigationEnabled", setSpatialNavigationEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2217         { "setStopProvisionalFrameLoads", setStopProvisionalFrameLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2218         { "setTabKeyCyclesThroughElements", setTabKeyCyclesThroughElementsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2219 #if PLATFORM(IOS)
2220         { "setTelephoneNumberParsingEnabled", setTelephoneNumberParsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2221         { "setPagePaused", setPagePausedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2222 #endif
2223         { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2224         { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2225         { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2226         { "setValueForUser", setValueForUserCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2227         { "setWebViewEditable", setWebViewEditableCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2228         { "setWillSendRequestClearHeader", setWillSendRequestClearHeaderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2229         { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2230         { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2231         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2232         { "setViewSize", setViewSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2233         { "setJavaScriptCanAccessClipboard", setJavaScriptCanAccessClipboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2234         { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2235         { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2236         { "simulateLegacyWebNotificationClick", simulateLegacyWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2237         { "testOnscreen", testOnscreenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2238         { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2239         { "waitForPolicyDelegate", waitForPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2240         { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2241         { "windowCount", windowCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2242         { "addOriginAccessWhitelistEntry", addOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2243         { "setScrollbarPolicy", setScrollbarPolicyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2244         { "authenticateSession", authenticateSessionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2245         { "setShouldPaintBrokenImage", setShouldPaintBrokenImageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2246         { "setTextDirection", setTextDirectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2247         { "setShouldStayOnPageAfterHandlingBeforeUnload", setShouldStayOnPageAfterHandlingBeforeUnloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2248         { "addChromeInputField", addChromeInputFieldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2249         { "removeChromeInputField", removeChromeInputFieldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2250         { "focusWebView", focusWebViewCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2251         { "setBackingScaleFactor", setBackingScaleFactorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2252         { "preciseTime", preciseTimeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2253         { "setHasCustomFullScreenBehavior", setHasCustomFullScreenBehaviorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2254         { "setStorageDatabaseIdleInterval", setStorageDatabaseIdleIntervalCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2255         { "closeIdleLocalStorageDatabases", closeIdleLocalStorageDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2256         { "grantWebNotificationPermission", grantWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2257         { "denyWebNotificationPermission", denyWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2258         { "removeAllWebNotificationPermissions", removeAllWebNotificationPermissionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2259         { "simulateWebNotificationClick", simulateWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2260         { "failNextNewCodeBlock", failNextNewCodeBlock, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2261         { "numberOfDFGCompiles", numberOfDFGCompiles, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2262         { "neverInlineFunction", neverInlineFunction, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2263         { "accummulateLogsForChannel", accummulateLogsForChannel, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2264         { "runUIScript", runUIScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2265         { "imageCountInGeneralPasteboard", imageCountInGeneralPasteboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2266         { "setSpellCheckerLoggingEnabled", setSpellCheckerLoggingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2267         { "setSpellCheckerResults", setSpellCheckerResultsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2268         { "setOpenPanelFiles", setOpenPanelFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2269         { "forceImmediateCompletion", forceImmediateCompletionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2270         { 0, 0, 0 }
2271     };
2272
2273     return staticFunctions;
2274 }
2275
2276 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL)
2277 {
2278     WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL));
2279 }
2280
2281 void TestRunner::queueLoadAlternateHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
2282 {
2283     WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL, unreachableURL));
2284 }
2285
2286 void TestRunner::queueBackNavigation(int howFarBack)
2287 {
2288     WorkQueue::singleton().queue(new BackItem(howFarBack));
2289 }
2290
2291 void TestRunner::queueForwardNavigation(int howFarForward)
2292 {
2293     WorkQueue::singleton().queue(new ForwardItem(howFarForward));
2294 }
2295
2296 void TestRunner::queueLoadingScript(JSStringRef script)
2297 {
2298     WorkQueue::singleton().queue(new LoadingScriptItem(script));
2299 }
2300
2301 void TestRunner::queueNonLoadingScript(JSStringRef script)
2302 {
2303     WorkQueue::singleton().queue(new NonLoadingScriptItem(script));
2304 }
2305
2306 void TestRunner::queueReload()
2307 {
2308     WorkQueue::singleton().queue(new ReloadItem);
2309 }
2310
2311 void TestRunner::ignoreLegacyWebNotificationPermissionRequests()
2312 {
2313     m_areLegacyWebNotificationPermissionRequestsIgnored = false;
2314 }
2315
2316 void TestRunner::waitToDumpWatchdogTimerFired()
2317 {
2318     const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
2319     fprintf(testResult, "%s", message);
2320
2321     auto accumulatedLogs = getAndResetAccumulatedLogs();
2322     if (!accumulatedLogs.isEmpty()) {
2323         const char* message = "Logs accumulated during test run:\n";
2324         fprintf(testResult, "%s%s\n", message, accumulatedLogs.utf8().data());
2325     }
2326
2327     notifyDone();
2328 }
2329
2330 void TestRunner::setGeolocationPermissionCommon(bool allow)
2331 {
2332     m_isGeolocationPermissionSet = true;
2333     m_geolocationPermission = allow;
2334 }
2335
2336 void TestRunner::setPOSIXLocale(JSStringRef locale)
2337 {
2338     char localeBuf[32];
2339     JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
2340     setlocale(LC_ALL, localeBuf);
2341 }
2342
2343 void TestRunner::addURLToRedirect(std::string origin, std::string destination)
2344 {
2345     m_URLsToRedirect[origin] = destination;
2346 }
2347
2348 const char* TestRunner::redirectionDestinationForURL(const char* origin)
2349 {
2350     if (!origin)
2351         return nullptr;
2352
2353     auto iterator = m_URLsToRedirect.find(origin);
2354     if (iterator == m_URLsToRedirect.end())
2355         return nullptr;
2356
2357     return iterator->second.data();
2358 }
2359
2360 void TestRunner::setShouldPaintBrokenImage(bool shouldPaintBrokenImage)
2361 {
2362     m_shouldPaintBrokenImage = shouldPaintBrokenImage;
2363 }
2364
2365 void TestRunner::setAccummulateLogsForChannel(JSStringRef channel)
2366 {
2367     size_t maxLength = JSStringGetMaximumUTF8CStringSize(channel);
2368     auto buffer = std::make_unique<char[]>(maxLength + 1);
2369     JSStringGetUTF8CString(channel, buffer.get(), maxLength + 1);
2370
2371     WebCoreTestSupport::setLogChannelToAccumulate({ buffer.get() });
2372 }
2373
2374 typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
2375 static CallbackMap& callbackMap()
2376 {
2377     static CallbackMap& map = *new CallbackMap;
2378     return map;
2379 }
2380
2381 void TestRunner::cacheTestRunnerCallback(unsigned index, JSValueRef callback)
2382 {
2383     if (!callback)
2384         return;
2385
2386     if (callbackMap().contains(index)) {
2387         fprintf(stderr, "FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n", index);
2388         return;
2389     }
2390
2391     JSContextRef context = mainFrameJSContext();
2392     JSValueProtect(context, callback);
2393     callbackMap().add(index, callback);
2394 }
2395
2396 void TestRunner::callTestRunnerCallback(unsigned index, size_t argumentCount, const JSValueRef arguments[])
2397 {
2398     if (!callbackMap().contains(index))
2399         return;
2400
2401     JSContextRef context = mainFrameJSContext();
2402     if (JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0)) {
2403         JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
2404         JSValueUnprotect(context, callback);
2405     }
2406 }
2407
2408 void TestRunner::clearTestRunnerCallbacks()
2409 {
2410     JSContextRef context = mainFrameJSContext();
2411
2412     for (auto& iter : callbackMap()) {
2413         if (JSObjectRef callback = JSValueToObject(context, iter.value, 0))
2414             JSValueUnprotect(context, callback);
2415     }
2416
2417     callbackMap().clear();
2418 }
2419
2420 enum {
2421     FirstUIScriptCallbackID = 100
2422 };
2423
2424 static unsigned nextUIScriptCallbackID()
2425 {
2426     static unsigned callbackID = FirstUIScriptCallbackID;
2427     return callbackID++;
2428 }
2429
2430 void TestRunner::runUIScript(JSContextRef context, JSStringRef script, JSValueRef callback)
2431 {
2432     m_pendingUIScriptInvocationData = nullptr;
2433
2434     unsigned callbackID = nextUIScriptCallbackID();
2435     cacheTestRunnerCallback(callbackID, callback);
2436
2437     if (!m_UIScriptContext)
2438         m_UIScriptContext = std::make_unique<WTR::UIScriptContext>(*this);
2439
2440     String scriptString(JSStringGetCharactersPtr(script), JSStringGetLength(script));
2441     m_UIScriptContext->runUIScript(scriptString, callbackID);
2442 }
2443
2444 void TestRunner::callUIScriptCallback(unsigned callbackID, JSStringRef result)
2445 {
2446     JSRetainPtr<JSStringRef> protectedResult(result);
2447 #if !PLATFORM(IOS)
2448     RunLoop::main().dispatch([protectedThis = makeRef(*this), callbackID, protectedResult]() mutable {
2449         JSContextRef context = protectedThis->mainFrameJSContext();
2450         JSValueRef resultValue = JSValueMakeString(context, protectedResult.get());
2451         protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue);
2452     });
2453 #else
2454     WebThreadRun(
2455         BlockPtr<void()>::fromCallable([protectedThis = makeRef(*this), callbackID, protectedResult] {
2456             JSContextRef context = protectedThis->mainFrameJSContext();
2457             JSValueRef resultValue = JSValueMakeString(context, protectedResult.get());
2458             protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue);
2459         }).get()
2460     );
2461 #endif
2462 }
2463
2464 void TestRunner::uiScriptDidComplete(const String& result, unsigned callbackID)
2465 {
2466     auto stringRef = adopt(JSStringCreateWithUTF8CString(result.utf8().data()));
2467     callUIScriptCallback(callbackID, stringRef.get());
2468 }
2469
2470 void TestRunner::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate)
2471 {
2472     WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate);
2473 }
2474
2475 void TestRunner::setOpenPanelFiles(JSContextRef context, JSValueRef filesValue)
2476 {
2477     if (!JSValueIsArray(context, filesValue))
2478         return;
2479
2480     JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
2481     static auto lengthProperty = adopt(JSStringCreateWithUTF8CString("length"));
2482     JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
2483     if (!JSValueIsNumber(context, filesLengthValue))
2484         return;
2485
2486     m_openPanelFiles.clear();
2487     auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
2488     for (size_t i = 0; i < filesLength; ++i) {
2489         JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
2490         if (!JSValueIsString(context, fileValue))
2491             continue;
2492
2493         auto file = adopt(JSValueToStringCopy(context, fileValue, nullptr));
2494         size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
2495         auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
2496         JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
2497
2498         m_openPanelFiles.push_back(fileBuffer.get());
2499     }
2500 }
2501
2502 void TestRunner::cleanup()
2503 {
2504     clearTestRunnerCallbacks();
2505 }