Test gardening for GTK.
[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     JSRetainPtr<JSStringRef> localPath(Adopt, JSValueToStringCopy(context, arguments[0], exception));
293     ASSERT(!*exception);
294
295     JSRetainPtr<JSStringRef> convertedPath(Adopt, 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> origin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
401     ASSERT(!*exception);
402
403     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
504     ASSERT(!*exception);
505
506     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
507     JSRetainPtr<JSStringRef> decodedHostName(Adopt, 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     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
545     ASSERT(!*exception);
546
547     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
548     JSRetainPtr<JSStringRef> encodedHostName(Adopt, 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> key(Adopt, JSValueToStringCopy(context, arguments[0], exception));
622     ASSERT(!*exception);
623     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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     JSRetainPtr<JSStringRef> 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         JSRetainPtr<JSStringRef> unreachableURL;
737         unreachableURL.adopt(JSValueToStringCopy(context, arguments[2], exception));
738         ASSERT(!*exception);
739         controller->queueLoadAlternateHTMLString(content.get(), baseURL.get(), unreachableURL.get());
740         return JSValueMakeUndefined(context);
741     }
742
743     controller->queueLoadHTMLString(content.get(), baseURL.get());
744     return JSValueMakeUndefined(context);
745 }
746
747 static JSValueRef queueReloadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
748 {
749     // Has mac & windows implementation
750     // May be able to be made platform independant by using shared WorkQueue
751
752     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
753     controller->queueReload();
754
755     return JSValueMakeUndefined(context);
756 }
757
758 static JSValueRef queueLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
759 {
760     // Has mac & windows implementation
761     // May be able to be made platform independant by using shared WorkQueue
762     if (argumentCount < 1)
763         return JSValueMakeUndefined(context);
764
765     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
766     ASSERT(!*exception);
767
768     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
769     controller->queueLoadingScript(script.get());
770
771     return JSValueMakeUndefined(context);
772 }
773
774 static JSValueRef queueNonLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
775 {
776     // Has mac & windows implementation
777     // May be able to be made platform independant by using shared WorkQueue
778     if (argumentCount < 1)
779         return JSValueMakeUndefined(context);
780
781     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
782     ASSERT(!*exception);
783
784     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
785     controller->queueNonLoadingScript(script.get());
786
787     return JSValueMakeUndefined(context);
788 }
789
790 static JSValueRef setAcceptsEditingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
791 {
792     // Has mac & windows implementation
793     if (argumentCount < 1)
794         return JSValueMakeUndefined(context);
795
796     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
797     controller->setAcceptsEditing(JSValueToBoolean(context, arguments[0]));
798
799     return JSValueMakeUndefined(context);
800 }
801
802 static JSValueRef setAlwaysAcceptCookiesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
803 {
804     // Has mac & windows implementation
805     if (argumentCount < 1)
806         return JSValueMakeUndefined(context);
807
808     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
809     controller->setAlwaysAcceptCookies(JSValueToBoolean(context, arguments[0]));
810
811     return JSValueMakeUndefined(context);
812 }
813
814 static JSValueRef setAppCacheMaximumSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
815 {
816     // Has mac implementation
817     if (argumentCount < 1)
818         return JSValueMakeUndefined(context);
819
820     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
821
822     double size = JSValueToNumber(context, arguments[0], NULL);
823     if (!std::isnan(size))
824         controller->setAppCacheMaximumSize(static_cast<unsigned long long>(size));
825         
826     return JSValueMakeUndefined(context);
827 }
828
829 static JSValueRef setAuthenticationPasswordCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
830 {
831     // Has mac & windows implementation
832     if (argumentCount < 1)
833         return JSValueMakeUndefined(context);
834
835     JSRetainPtr<JSStringRef> password(Adopt, JSValueToStringCopy(context, arguments[0], exception));
836     ASSERT(!*exception);
837
838     size_t maxLength = JSStringGetMaximumUTF8CStringSize(password.get());
839     char* passwordBuffer = new char[maxLength + 1];
840     JSStringGetUTF8CString(password.get(), passwordBuffer, maxLength + 1);
841     
842     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
843     controller->setAuthenticationPassword(passwordBuffer);
844     delete[] passwordBuffer;
845
846     return JSValueMakeUndefined(context);
847 }
848
849 static JSValueRef setAuthenticationUsernameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
850 {
851     // Has mac & windows implementation
852     if (argumentCount < 1)
853         return JSValueMakeUndefined(context);
854
855     JSRetainPtr<JSStringRef> username(Adopt, JSValueToStringCopy(context, arguments[0], exception));
856     ASSERT(!*exception);
857
858     size_t maxLength = JSStringGetMaximumUTF8CStringSize(username.get());
859     char* usernameBuffer = new char[maxLength + 1];
860     JSStringGetUTF8CString(username.get(), usernameBuffer, maxLength + 1);
861     
862     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
863     controller->setAuthenticationUsername(usernameBuffer);
864     delete[] usernameBuffer;
865
866     return JSValueMakeUndefined(context);
867 }
868
869 static JSValueRef setAuthorAndUserStylesEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
870 {
871     // Has mac & windows implementation
872     if (argumentCount < 1)
873         return JSValueMakeUndefined(context);
874
875     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
876     controller->setAuthorAndUserStylesEnabled(JSValueToBoolean(context, arguments[0]));
877
878     return JSValueMakeUndefined(context);
879 }
880
881 static JSValueRef setCacheModelCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
882 {
883     // Has Mac implementation.
884     if (argumentCount < 1)
885         return JSValueMakeUndefined(context);
886
887     int cacheModel = JSValueToNumber(context, arguments[0], exception);
888     ASSERT(!*exception);
889
890     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
891     controller->setCacheModel(cacheModel);
892
893     return JSValueMakeUndefined(context);
894 }
895
896 static JSValueRef setCustomPolicyDelegateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
897 {
898     // Has mac implementation
899     if (argumentCount < 1)
900         return JSValueMakeUndefined(context);
901     
902     bool permissive = false;
903     if (argumentCount >= 2)
904         permissive = JSValueToBoolean(context, arguments[1]);
905
906     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
907     controller->setCustomPolicyDelegate(JSValueToBoolean(context, arguments[0]), permissive);
908
909     return JSValueMakeUndefined(context);
910 }
911
912 static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
913 {
914     // Has mac implementation
915     if (argumentCount < 1)
916         return JSValueMakeUndefined(context);
917
918     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
919
920     double quota = JSValueToNumber(context, arguments[0], NULL);
921     if (!std::isnan(quota))
922         controller->setDatabaseQuota(static_cast<unsigned long long>(quota));
923         
924     return JSValueMakeUndefined(context);
925 }
926
927 static JSValueRef setDefersLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
928 {
929     if (argumentCount < 1)
930         return JSValueMakeUndefined(context);
931
932     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
933     controller->setDefersLoading(JSValueToBoolean(context, arguments[0]));
934
935     return JSValueMakeUndefined(context);
936 }
937
938 static JSValueRef setUseDeferredFrameLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
939 {
940     if (argumentCount < 1)
941         return JSValueMakeUndefined(context);
942
943     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
944     controller->setUseDeferredFrameLoading(JSValueToBoolean(context, arguments[0]));
945
946     return JSValueMakeUndefined(context);
947 }
948
949 static JSValueRef setDomainRelaxationForbiddenForURLSchemeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
950 {
951     // Has Mac and Windows implementation
952     if (argumentCount < 2)
953         return JSValueMakeUndefined(context);
954
955     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
956
957     bool forbidden = JSValueToBoolean(context, arguments[0]);
958     JSRetainPtr<JSStringRef> scheme(Adopt, JSValueToStringCopy(context, arguments[1], 0));
959     controller->setDomainRelaxationForbiddenForURLScheme(forbidden, scheme.get());
960
961     return JSValueMakeUndefined(context);
962 }
963
964 static JSValueRef setMockDeviceOrientationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
965 {
966     if (argumentCount < 6)
967         return JSValueMakeUndefined(context);
968
969     bool canProvideAlpha = JSValueToBoolean(context, arguments[0]);
970     double alpha = JSValueToNumber(context, arguments[1], exception);
971     ASSERT(!*exception);
972     bool canProvideBeta = JSValueToBoolean(context, arguments[2]);
973     double beta = JSValueToNumber(context, arguments[3], exception);
974     ASSERT(!*exception);
975     bool canProvideGamma = JSValueToBoolean(context, arguments[4]);
976     double gamma = JSValueToNumber(context, arguments[5], exception);
977     ASSERT(!*exception);
978
979     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
980     controller->setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
981
982     return JSValueMakeUndefined(context);
983 }
984
985 static JSValueRef setMockGeolocationPositionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
986 {
987     if (argumentCount < 3)
988         return JSValueMakeUndefined(context);
989
990     double latitude = JSValueToNumber(context, arguments[0], 0);
991     double longitude = JSValueToNumber(context, arguments[1], 0);
992     double accuracy = JSValueToNumber(context, arguments[2], 0);
993
994     bool canProvideAltitude = false;
995     double altitude = 0.;
996     if (argumentCount > 3 && !JSValueIsUndefined(context, arguments[3])) {
997         canProvideAltitude = true;
998         altitude = JSValueToNumber(context, arguments[3], 0);
999     }
1000
1001     bool canProvideAltitudeAccuracy = false;
1002     double altitudeAccuracy = 0.;
1003     if (argumentCount > 4 && !JSValueIsUndefined(context, arguments[4])) {
1004         canProvideAltitudeAccuracy = true;
1005         altitudeAccuracy = JSValueToNumber(context, arguments[4], 0);
1006     }
1007
1008     bool canProvideHeading = false;
1009     double heading = 0.;
1010     if (argumentCount > 5 && !JSValueIsUndefined(context, arguments[5])) {
1011         canProvideHeading = true;
1012         heading = JSValueToNumber(context, arguments[5], 0);
1013     }
1014
1015     bool canProvideSpeed = false;
1016     double speed = 0.;
1017     if (argumentCount > 6 && !JSValueIsUndefined(context, arguments[6])) {
1018         canProvideSpeed = true;
1019         speed = JSValueToNumber(context, arguments[6], 0);
1020     }
1021
1022     bool canProvideFloorLevel = false;
1023     double floorLevel = 0.;
1024     if (argumentCount > 7 && !JSValueIsUndefined(context, arguments[7])) {
1025         canProvideFloorLevel = true;
1026         floorLevel = JSValueToNumber(context, arguments[7], 0);
1027     }
1028
1029     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1030     controller->setMockGeolocationPosition(latitude, longitude, accuracy, canProvideAltitude, altitude, canProvideAltitudeAccuracy, altitudeAccuracy, canProvideHeading, heading, canProvideSpeed, speed, canProvideFloorLevel, floorLevel);
1031
1032     return JSValueMakeUndefined(context);
1033 }
1034
1035 static JSValueRef setMockGeolocationPositionUnavailableErrorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1036 {
1037     if (argumentCount != 1)
1038         return JSValueMakeUndefined(context);
1039
1040     JSRetainPtr<JSStringRef> message(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1041     ASSERT(!*exception);
1042
1043     TestRunner* controller = reinterpret_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1044     controller->setMockGeolocationPositionUnavailableError(message.get());
1045
1046     return JSValueMakeUndefined(context);
1047 }
1048
1049 static JSValueRef setNewWindowsCopyBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1050 {
1051     // Has mac implementation
1052     if (argumentCount < 1)
1053         return JSValueMakeUndefined(context);
1054     
1055     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1056     controller->setNewWindowsCopyBackForwardList(JSValueToBoolean(context, arguments[0]));
1057
1058     return JSValueMakeUndefined(context);
1059 }
1060
1061 static JSValueRef setGeolocationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1062 {
1063     // Has mac implementation
1064     if (argumentCount < 1)
1065         return JSValueMakeUndefined(context);
1066
1067     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1068     controller->setGeolocationPermission(JSValueToBoolean(context, arguments[0]));
1069
1070     return JSValueMakeUndefined(context);
1071 }
1072
1073 static JSValueRef setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1074 {
1075     // Has mac & windows implementation
1076     if (argumentCount < 1)
1077         return JSValueMakeUndefined(context);
1078     
1079     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1080     controller->setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(JSValueToBoolean(context, arguments[0]));
1081     
1082     return JSValueMakeUndefined(context);
1083 }
1084
1085 static JSValueRef setHandlesAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1086 {
1087     // Has mac & windows implementation
1088     if (argumentCount < 1)
1089         return JSValueMakeUndefined(context);
1090
1091     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1092     controller->setHandlesAuthenticationChallenges(JSValueToBoolean(context, arguments[0]));
1093
1094     return JSValueMakeUndefined(context);
1095 }
1096
1097 static JSValueRef setPOSIXLocaleCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1098 {
1099     if (argumentCount < 1)
1100         return JSValueMakeUndefined(context);
1101
1102     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1103     JSRetainPtr<JSStringRef> locale(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1104     ASSERT(!*exception);
1105     controller->setPOSIXLocale(locale.get());
1106
1107     return JSValueMakeUndefined(context);
1108 }
1109
1110 static JSValueRef setIconDatabaseEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1111 {
1112     // Has mac & windows implementation
1113     if (argumentCount < 1)
1114         return JSValueMakeUndefined(context);
1115
1116     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1117     controller->setIconDatabaseEnabled(JSValueToBoolean(context, arguments[0]));
1118
1119     return JSValueMakeUndefined(context);
1120 }
1121
1122 static JSValueRef setMainFrameIsFirstResponderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1123 {
1124     // Has mac implementation
1125     if (argumentCount < 1)
1126         return JSValueMakeUndefined(context);
1127
1128     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1129     controller->setMainFrameIsFirstResponder(JSValueToBoolean(context, arguments[0]));
1130
1131     return JSValueMakeUndefined(context);
1132 }
1133
1134 static JSValueRef setPersistentUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1135 {
1136     // Has mac implementation
1137     if (argumentCount < 1)
1138         return JSValueMakeUndefined(context);
1139
1140     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1141     ASSERT(!*exception);
1142
1143     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1144     controller->setPersistentUserStyleSheetLocation(path.get());
1145
1146     return JSValueMakeUndefined(context);
1147 }
1148
1149 static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1150 {
1151     // Has mac & windows implementation
1152     if (argumentCount < 1)
1153         return JSValueMakeUndefined(context);
1154
1155     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1156     controller->setPrivateBrowsingEnabled(JSValueToBoolean(context, arguments[0]));
1157
1158     return JSValueMakeUndefined(context);
1159 }
1160
1161 static JSValueRef setJavaScriptCanAccessClipboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1162 {
1163     // Has mac & windows implementation
1164     if (argumentCount < 1)
1165         return JSValueMakeUndefined(context);
1166
1167     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1168     controller->setJavaScriptCanAccessClipboard(JSValueToBoolean(context, arguments[0]));
1169
1170     return JSValueMakeUndefined(context);
1171 }
1172
1173 static JSValueRef setXSSAuditorEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1174 {
1175     // Has mac & windows implementation
1176     if (argumentCount < 1)
1177         return JSValueMakeUndefined(context);
1178
1179     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1180     controller->setXSSAuditorEnabled(JSValueToBoolean(context, arguments[0]));
1181
1182     return JSValueMakeUndefined(context);
1183 }
1184
1185 static JSValueRef setSpatialNavigationEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1186 {
1187     // Has mac & windows implementation.
1188     if (argumentCount < 1)
1189         return JSValueMakeUndefined(context);
1190
1191     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1192     controller->setSpatialNavigationEnabled(JSValueToBoolean(context, arguments[0]));
1193
1194     return JSValueMakeUndefined(context);
1195 }
1196
1197 static JSValueRef setPrintingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1198 {
1199     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1200     controller->setIsPrinting(true);
1201     return JSValueMakeUndefined(context);
1202 }
1203
1204 static JSValueRef setAllowsAnySSLCertificateCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1205 {
1206     bool allowAnyCertificate = false;
1207     if (argumentCount == 1)
1208         allowAnyCertificate = JSValueToBoolean(context, arguments[0]);
1209     
1210     TestRunner::setAllowsAnySSLCertificate(allowAnyCertificate);
1211     return JSValueMakeUndefined(context);
1212 }
1213
1214 static JSValueRef setAllowUniversalAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1215 {
1216     // Has mac & windows implementation
1217     if (argumentCount < 1)
1218         return JSValueMakeUndefined(context);
1219
1220     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1221     controller->setAllowUniversalAccessFromFileURLs(JSValueToBoolean(context, arguments[0]));
1222
1223     return JSValueMakeUndefined(context);
1224 }
1225
1226 static JSValueRef setAllowFileAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1227 {
1228     // Has mac & windows implementation
1229     if (argumentCount < 1)
1230         return JSValueMakeUndefined(context);
1231
1232     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1233     controller->setAllowFileAccessFromFileURLs(JSValueToBoolean(context, arguments[0]));
1234
1235     return JSValueMakeUndefined(context);
1236 }
1237
1238 static JSValueRef setNeedsStorageAccessFromFileURLsQuirkCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1239 {
1240     // Has mac & windows implementation
1241     if (argumentCount < 1)
1242         return JSValueMakeUndefined(context);
1243     
1244     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1245     controller->setNeedsStorageAccessFromFileURLsQuirk(JSValueToBoolean(context, arguments[0]));
1246     
1247     return JSValueMakeUndefined(context);
1248 }
1249
1250 static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1251 {
1252     // Has mac & windows implementation
1253     if (argumentCount < 1)
1254         return JSValueMakeUndefined(context);
1255
1256     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1257     controller->setTabKeyCyclesThroughElements(JSValueToBoolean(context, arguments[0]));
1258
1259     return JSValueMakeUndefined(context);
1260 }
1261
1262 #if PLATFORM(IOS)
1263 static JSValueRef setTelephoneNumberParsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1264 {
1265     if (argumentCount < 1)
1266         return JSValueMakeUndefined(context);
1267
1268     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1269     controller->setTelephoneNumberParsingEnabled(JSValueToBoolean(context, arguments[0]));
1270
1271     return JSValueMakeUndefined(context);
1272 }
1273
1274 static JSValueRef setPagePausedCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1275 {
1276     if (argumentCount < 1)
1277         return JSValueMakeUndefined(context);
1278
1279     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1280     controller->setPagePaused(JSValueToBoolean(context, arguments[0]));
1281
1282     return JSValueMakeUndefined(context);
1283 }
1284 #endif
1285
1286 static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1287 {
1288     // Has mac implementation
1289     if (argumentCount < 1)
1290         return JSValueMakeUndefined(context);
1291
1292     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1293     controller->setUseDashboardCompatibilityMode(JSValueToBoolean(context, arguments[0]));
1294
1295     return JSValueMakeUndefined(context);
1296 }
1297
1298 static JSValueRef setUserStyleSheetEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1299 {
1300     // Has mac implementation
1301     if (argumentCount < 1)
1302         return JSValueMakeUndefined(context);
1303
1304     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1305     controller->setUserStyleSheetEnabled(JSValueToBoolean(context, arguments[0]));
1306
1307     return JSValueMakeUndefined(context);
1308 }
1309
1310 static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1311 {
1312     // Has mac implementation
1313     if (argumentCount < 1)
1314         return JSValueMakeUndefined(context);
1315
1316     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1317     ASSERT(!*exception);
1318
1319     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1320     controller->setUserStyleSheetLocation(path.get());
1321
1322     return JSValueMakeUndefined(context);
1323 }
1324
1325 static JSValueRef setValueForUserCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1326 {
1327     // Has mac implementation
1328     if (argumentCount != 2)
1329         return JSValueMakeUndefined(context);
1330
1331     JSRetainPtr<JSStringRef> value(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1332     ASSERT(!*exception);
1333
1334     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1335     controller->setValueForUser(context, arguments[0], value.get());
1336
1337     return JSValueMakeUndefined(context);
1338 }
1339
1340 static JSValueRef setWillSendRequestClearHeaderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1341 {
1342     // Has mac & windows implementation
1343     if (argumentCount < 1)
1344         return JSValueMakeUndefined(context);
1345
1346     JSRetainPtr<JSStringRef> header(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1347     ASSERT(!*exception);
1348
1349     size_t maxLength = JSStringGetMaximumUTF8CStringSize(header.get());
1350     auto headerBuffer = std::make_unique<char[]>(maxLength + 1);
1351     JSStringGetUTF8CString(header.get(), headerBuffer.get(), maxLength + 1);
1352
1353     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1354     controller->setWillSendRequestClearHeader(headerBuffer.get());
1355
1356     return JSValueMakeUndefined(context);
1357 }
1358
1359 static JSValueRef setWillSendRequestReturnsNullCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1360 {
1361     // Has cross-platform implementation
1362     if (argumentCount < 1)
1363         return JSValueMakeUndefined(context);
1364
1365     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1366     controller->setWillSendRequestReturnsNull(JSValueToBoolean(context, arguments[0]));
1367
1368     return JSValueMakeUndefined(context);
1369 }
1370
1371 static JSValueRef setWillSendRequestReturnsNullOnRedirectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1372 {
1373     // Has cross-platform implementation
1374     if (argumentCount < 1)
1375         return JSValueMakeUndefined(context);
1376
1377     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1378     controller->setWillSendRequestReturnsNullOnRedirect(JSValueToBoolean(context, arguments[0]));
1379
1380     return JSValueMakeUndefined(context);
1381 }
1382
1383 static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1384 {
1385     // Has mac implementation
1386     if (argumentCount < 1)
1387         return JSValueMakeUndefined(context);
1388
1389     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1390     controller->setWindowIsKey(JSValueToBoolean(context, arguments[0]));
1391
1392     return JSValueMakeUndefined(context);
1393 }
1394
1395 static JSValueRef setViewSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1396 {
1397     if (argumentCount < 2)
1398         return JSValueMakeUndefined(context);
1399
1400     double width = JSValueToNumber(context, arguments[0], exception);
1401     ASSERT(!*exception);
1402     double height = JSValueToNumber(context, arguments[1], exception);
1403     ASSERT(!*exception);
1404
1405     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1406     controller->setViewSize(width, height);
1407
1408     return JSValueMakeUndefined(context);
1409 }
1410
1411 static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1412 {
1413     // Has mac & windows implementation
1414     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1415     controller->setWaitToDump(true);
1416
1417     return JSValueMakeUndefined(context);
1418 }
1419
1420 static JSValueRef windowCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1421 {
1422     // Has mac implementation
1423     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1424     int windows = controller->windowCount();
1425     return JSValueMakeNumber(context, windows);
1426 }
1427
1428 static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1429 {
1430     // Has mac & windows implementation
1431     if (argumentCount < 1)
1432         return JSValueMakeUndefined(context);
1433
1434     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1435     controller->setPopupBlockingEnabled(JSValueToBoolean(context, arguments[0]));
1436
1437     return JSValueMakeUndefined(context);
1438 }
1439
1440 static JSValueRef setPluginsEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1441 {
1442     // Has mac & windows implementation
1443     if (argumentCount < 1)
1444         return JSValueMakeUndefined(context);
1445     
1446     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1447     controller->setPluginsEnabled(JSValueToBoolean(context, arguments[0]));
1448     
1449     return JSValueMakeUndefined(context);
1450 }    
1451
1452 static JSValueRef setPageVisibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1453 {
1454     // Has mac & windows implementation
1455     if (argumentCount < 1)
1456         return JSValueMakeUndefined(context);
1457
1458     JSRetainPtr<JSStringRef> visibility(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1459     ASSERT(!*exception);
1460
1461     size_t maxLength = JSStringGetMaximumUTF8CStringSize(visibility.get());
1462     char* visibilityBuffer = new char[maxLength + 1];
1463     JSStringGetUTF8CString(visibility.get(), visibilityBuffer, maxLength + 1);
1464     
1465     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1466     controller->setPageVisibility(visibilityBuffer);
1467     delete[] visibilityBuffer;
1468     
1469     return JSValueMakeUndefined(context);
1470 }    
1471
1472 static JSValueRef resetPageVisibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1473 {
1474     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1475     controller->resetPageVisibility();
1476     return JSValueMakeUndefined(context);
1477 }    
1478
1479 static JSValueRef setAutomaticLinkDetectionEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1480 {
1481     if (argumentCount < 1)
1482         return JSValueMakeUndefined(context);
1483
1484     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1485     controller->setAutomaticLinkDetectionEnabled(JSValueToBoolean(context, arguments[0]));
1486     return JSValueMakeUndefined(context);
1487 }
1488
1489 static JSValueRef setStopProvisionalFrameLoadsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1490 {
1491     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1492     controller->setStopProvisionalFrameLoads(true);
1493     return JSValueMakeUndefined(context);
1494 }
1495
1496 static JSValueRef showWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1497 {
1498     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1499     controller->showWebInspector();
1500     return JSValueMakeUndefined(context);
1501 }
1502
1503 static JSValueRef closeWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1504 {
1505     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1506     controller->closeWebInspector();
1507     return JSValueMakeUndefined(context);
1508 }
1509
1510 static JSValueRef evaluateInWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1511 {
1512     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1513     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1514     ASSERT(!*exception);
1515
1516     controller->evaluateInWebInspector(script.get());
1517     return JSValueMakeUndefined(context);
1518 }
1519
1520 static JSValueRef evaluateScriptInIsolatedWorldCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1521 {
1522     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1523     double worldID = JSValueToNumber(context, arguments[0], exception);
1524     ASSERT(!*exception);
1525     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1526     ASSERT(!*exception);
1527
1528     controller->evaluateScriptInIsolatedWorld(static_cast<unsigned>(worldID), JSContextGetGlobalObject(context), script.get());
1529     return JSValueMakeUndefined(context);
1530 }
1531
1532 static JSValueRef evaluateScriptInIsolatedWorldAndReturnValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1533 {
1534     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1535     double worldID = JSValueToNumber(context, arguments[0], exception);
1536     ASSERT(!*exception);
1537     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1538     ASSERT(!*exception);
1539
1540     controller->evaluateScriptInIsolatedWorldAndReturnValue(static_cast<unsigned>(worldID), JSContextGetGlobalObject(context), script.get());
1541     return JSValueMakeUndefined(context);
1542 }
1543
1544 static JSValueRef waitForPolicyDelegateCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*)
1545 {
1546     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1547     controller->waitForPolicyDelegate();
1548     return JSValueMakeUndefined(context);
1549 }
1550
1551 static JSValueRef addOriginAccessWhitelistEntryCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1552 {
1553     if (argumentCount != 4)
1554         return JSValueMakeUndefined(context);
1555
1556     JSRetainPtr<JSStringRef> sourceOrigin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1557     ASSERT(!*exception);
1558     JSRetainPtr<JSStringRef> destinationProtocol(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1559     ASSERT(!*exception);
1560     JSRetainPtr<JSStringRef> destinationHost(Adopt, JSValueToStringCopy(context, arguments[2], exception));
1561     ASSERT(!*exception);
1562     bool allowDestinationSubdomains = JSValueToBoolean(context, arguments[3]);
1563
1564     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1565     controller->addOriginAccessWhitelistEntry(sourceOrigin.get(), destinationProtocol.get(), destinationHost.get(), allowDestinationSubdomains);
1566     return JSValueMakeUndefined(context);
1567 }
1568
1569 static JSValueRef removeOriginAccessWhitelistEntryCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1570 {
1571     if (argumentCount != 4)
1572         return JSValueMakeUndefined(context);
1573
1574     JSRetainPtr<JSStringRef> sourceOrigin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1575     ASSERT(!*exception);
1576     JSRetainPtr<JSStringRef> destinationProtocol(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1577     ASSERT(!*exception);
1578     JSRetainPtr<JSStringRef> destinationHost(Adopt, JSValueToStringCopy(context, arguments[2], exception));
1579     ASSERT(!*exception);
1580     bool allowDestinationSubdomains = JSValueToBoolean(context, arguments[3]);
1581
1582     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1583     controller->removeOriginAccessWhitelistEntry(sourceOrigin.get(), destinationProtocol.get(), destinationHost.get(), allowDestinationSubdomains);
1584     return JSValueMakeUndefined(context);
1585 }
1586
1587 static JSValueRef setScrollbarPolicyCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1588 {
1589     if (argumentCount != 2)
1590         return JSValueMakeUndefined(context);
1591
1592     JSRetainPtr<JSStringRef> orientation(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1593     ASSERT(!*exception);
1594     JSRetainPtr<JSStringRef> policy(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1595     ASSERT(!*exception);
1596
1597     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1598     controller->setScrollbarPolicy(orientation.get(), policy.get());
1599     return JSValueMakeUndefined(context);
1600 }
1601
1602 static JSValueRef addUserScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1603 {
1604     if (argumentCount != 3)
1605         return JSValueMakeUndefined(context);
1606     
1607     JSRetainPtr<JSStringRef> source(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1608     ASSERT(!*exception);
1609     bool runAtStart = JSValueToBoolean(context, arguments[1]);
1610     bool allFrames = JSValueToBoolean(context, arguments[2]);
1611     
1612     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1613     controller->addUserScript(source.get(), runAtStart, allFrames);
1614     return JSValueMakeUndefined(context);
1615 }
1616  
1617 static JSValueRef addUserStyleSheetCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1618 {
1619     if (argumentCount != 2)
1620         return JSValueMakeUndefined(context);
1621     
1622     JSRetainPtr<JSStringRef> source(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1623     ASSERT(!*exception);
1624     bool allFrames = JSValueToBoolean(context, arguments[1]);
1625    
1626     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1627     controller->addUserStyleSheet(source.get(), allFrames);
1628     return JSValueMakeUndefined(context);
1629 }
1630
1631 static JSValueRef setShouldPaintBrokenImageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1632 {
1633     // Has Mac implementation
1634     if (argumentCount < 1)
1635         return JSValueMakeUndefined(context);
1636
1637     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1638     controller->setShouldPaintBrokenImage(JSValueToBoolean(context, arguments[0]));
1639
1640     return JSValueMakeUndefined(context);
1641 }
1642
1643 static JSValueRef apiTestNewWindowDataLoadBaseURLCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1644 {
1645     if (argumentCount != 2)
1646         return JSValueMakeUndefined(context);
1647
1648     JSRetainPtr<JSStringRef> utf8Data(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1649     ASSERT(!*exception);
1650
1651     JSRetainPtr<JSStringRef> baseURL(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1652     ASSERT(!*exception);
1653         
1654     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1655     controller->apiTestNewWindowDataLoadBaseURL(utf8Data.get(), baseURL.get());
1656     return JSValueMakeUndefined(context);
1657 }
1658
1659 static JSValueRef apiTestGoToCurrentBackForwardItemCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1660 {
1661     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1662     controller->apiTestGoToCurrentBackForwardItem();
1663     return JSValueMakeUndefined(context);
1664 }
1665
1666 static JSValueRef setWebViewEditableCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1667 {
1668     // Has Mac implementation
1669     if (argumentCount < 1)
1670         return JSValueMakeUndefined(context);
1671
1672     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1673     controller->setWebViewEditable(JSValueToBoolean(context, arguments[0]));
1674
1675     return JSValueMakeUndefined(context);
1676 }
1677
1678 static JSValueRef abortModalCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1679 {
1680     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1681     controller->abortModal();
1682     return JSValueMakeUndefined(context);
1683 }
1684
1685 static JSValueRef authenticateSessionCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1686 {
1687     // authenticateSession(url, username, password)
1688     if (argumentCount != 3)
1689         return JSValueMakeUndefined(context);
1690
1691     JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1692     ASSERT(!*exception);
1693     JSRetainPtr<JSStringRef> username(Adopt, JSValueToStringCopy(context, arguments[1], exception));
1694     ASSERT(!*exception);
1695     JSRetainPtr<JSStringRef> password(Adopt, JSValueToStringCopy(context, arguments[2], exception));
1696     ASSERT(!*exception);
1697
1698     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1699     controller->authenticateSession(url.get(), username.get(), password.get());
1700     return JSValueMakeUndefined(context);
1701 }
1702
1703 static JSValueRef setSerializeHTTPLoadsCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1704 {
1705     bool serialize = true;
1706     if (argumentCount == 1)
1707         serialize = JSValueToBoolean(context, arguments[0]);
1708
1709     TestRunner::setSerializeHTTPLoads(serialize);
1710     return JSValueMakeUndefined(context);
1711 }
1712
1713 static JSValueRef setShouldStayOnPageAfterHandlingBeforeUnloadCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1714 {
1715     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1716     
1717     if (argumentCount == 1)
1718         controller->setShouldStayOnPageAfterHandlingBeforeUnload(JSValueToBoolean(context, arguments[0]));
1719
1720     return JSValueMakeUndefined(context);
1721 }
1722
1723 static JSValueRef addChromeInputFieldCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1724 {
1725     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1726     controller->addChromeInputField();
1727     // the first argument is a callback that is called once the input field has been added
1728     if (argumentCount == 1)
1729         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1730     return JSValueMakeUndefined(context);
1731 }
1732
1733 static JSValueRef removeChromeInputFieldCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1734 {
1735     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1736     controller->removeChromeInputField();
1737     // the first argument is a callback that is called once the input field has been added
1738     if (argumentCount == 1)
1739         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1740     return JSValueMakeUndefined(context);
1741 }
1742
1743 static JSValueRef focusWebViewCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1744 {
1745     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1746     controller->focusWebView();
1747     // the first argument is a callback that is called once the input field has been added
1748     if (argumentCount == 1)
1749         JSObjectCallAsFunction(context, JSValueToObject(context, arguments[0], 0), thisObject, 0, 0, 0);
1750     return JSValueMakeUndefined(context);
1751 }
1752
1753 static JSValueRef setBackingScaleFactorCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1754 {
1755     if (argumentCount != 2)
1756         return JSValueMakeUndefined(context);
1757
1758     double backingScaleFactor = JSValueToNumber(context, arguments[0], exception);
1759     ASSERT(!*exception);
1760
1761     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1762     controller->setBackingScaleFactor(backingScaleFactor);
1763
1764     // The second argument is a callback that is called once the backing scale factor has been set.
1765     JSObjectCallAsFunction(context, JSValueToObject(context, arguments[1], 0), thisObject, 0, 0, 0);
1766     return JSValueMakeUndefined(context);
1767 }
1768
1769 static JSValueRef preciseTimeCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1770 {
1771     return JSValueMakeNumber(context, WallTime::now().secondsSinceEpoch().seconds());
1772 }
1773
1774 static JSValueRef imageCountInGeneralPasteboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1775 {
1776     // Has mac & windows implementation
1777     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1778     
1779     return JSValueMakeNumber(context, controller->imageCountInGeneralPasteboard());
1780 }
1781
1782 static JSValueRef setSpellCheckerLoggingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1783 {
1784     if (argumentCount < 1)
1785         return JSValueMakeUndefined(context);
1786     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1787     controller->setSpellCheckerLoggingEnabled(JSValueToBoolean(context, arguments[0]));
1788     return JSValueMakeUndefined(context);
1789 }
1790
1791 static JSValueRef setOpenPanelFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1792 {
1793     if (argumentCount == 1)
1794         static_cast<TestRunner*>(JSObjectGetPrivate(thisObject))->setOpenPanelFiles(context, arguments[0]);
1795     return JSValueMakeUndefined(context);
1796 }
1797
1798 // Static Values
1799
1800 static JSValueRef getTimeoutCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1801 {
1802     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1803     return JSValueMakeNumber(context, controller->timeout());
1804 }
1805
1806 static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1807 {
1808     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1809     return JSValueMakeBoolean(context, controller->globalFlag());
1810 }
1811
1812 static JSValueRef getDidCancelClientRedirect(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1813 {
1814     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1815     return JSValueMakeBoolean(context, controller->didCancelClientRedirect());
1816 }
1817
1818 static JSValueRef getDatabaseDefaultQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1819 {
1820     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1821     return JSValueMakeNumber(context, controller->databaseDefaultQuota());
1822 }
1823
1824 static JSValueRef getDatabaseMaxQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1825 {
1826     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1827     return JSValueMakeNumber(context, controller->databaseMaxQuota());
1828 }
1829
1830 static JSValueRef getWebHistoryItemCountCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1831 {
1832     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1833     return JSValueMakeNumber(context, controller->webHistoryItemCount());
1834 }
1835
1836 static JSValueRef getSecureEventInputIsEnabledCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1837 {
1838 #if PLATFORM(MAC) && !PLATFORM(IOS)
1839     return JSValueMakeBoolean(context, IsSecureEventInputEnabled());
1840 #else
1841     return JSValueMakeBoolean(context, false);
1842 #endif
1843 }
1844
1845 static JSValueRef getTitleTextDirectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1846 {
1847     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1848     JSRetainPtr<JSStringRef> titleDirection(Adopt, JSStringCreateWithUTF8CString(controller->titleTextDirection().c_str()));
1849     return JSValueMakeString(context, titleDirection.get());
1850 }
1851
1852 static JSValueRef getInspectorTestStubURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
1853 {
1854     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1855     JSRetainPtr<JSStringRef> url(Adopt, controller->inspectorTestStubURL());
1856     return JSValueMakeString(context, url.get());
1857 }
1858
1859 static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1860 {
1861     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1862     controller->setGlobalFlag(JSValueToBoolean(context, value));
1863     return true;
1864 }
1865
1866 static bool setDatabaseDefaultQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1867 {
1868     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1869     controller->setDatabaseDefaultQuota(JSValueToNumber(context, value, exception));
1870     ASSERT(!*exception);
1871     return true;
1872 }
1873
1874 static bool setDatabaseMaxQuotaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1875 {
1876     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1877     controller->setDatabaseMaxQuota(JSValueToNumber(context, value, exception));
1878     ASSERT(!*exception);
1879     return true;
1880 }
1881
1882 static JSValueRef ignoreLegacyWebNotificationPermissionRequestsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1883 {
1884     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1885     controller->ignoreLegacyWebNotificationPermissionRequests();
1886     return JSValueMakeUndefined(context);
1887 }
1888
1889 static JSValueRef simulateLegacyWebNotificationClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1890 {
1891     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); 
1892     JSRetainPtr<JSStringRef> title(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1893     controller->simulateLegacyWebNotificationClick(title.get());
1894     return JSValueMakeUndefined(context);
1895 }
1896
1897 static JSValueRef setTextDirectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1898 {
1899     if (argumentCount == 1) {
1900         JSRetainPtr<JSStringRef> direction(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1901         TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1902         controller->setTextDirection(direction.get());
1903     }
1904
1905     return JSValueMakeUndefined(context);
1906
1907 }
1908
1909 static JSValueRef setHasCustomFullScreenBehaviorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1910 {
1911     if (argumentCount == 1) {
1912         bool hasCustomBehavior = JSValueToBoolean(context, arguments[0]);
1913         TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1914         controller->setHasCustomFullScreenBehavior(hasCustomBehavior);
1915     }
1916
1917     return JSValueMakeUndefined(context);
1918 }
1919
1920 static JSValueRef setStorageDatabaseIdleIntervalCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1921 {
1922     if (argumentCount != 1)
1923         return JSValueMakeUndefined(context);
1924
1925     double interval = JSValueToNumber(context, arguments[0], exception);
1926     ASSERT(!*exception);
1927
1928     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1929     controller->setStorageDatabaseIdleInterval(interval);
1930
1931     return JSValueMakeUndefined(context);
1932 }
1933
1934 static JSValueRef closeIdleLocalStorageDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1935 {
1936     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1937     controller->closeIdleLocalStorageDatabases();
1938
1939     return JSValueMakeUndefined(context);
1940 }
1941
1942 static JSValueRef grantWebNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1943 {
1944     if (argumentCount < 1)
1945         return JSValueMakeUndefined(context);
1946
1947     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1948
1949     JSRetainPtr<JSStringRef> origin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1950     ASSERT(!*exception);
1951     controller->grantWebNotificationPermission(origin.get());
1952
1953     return JSValueMakeUndefined(context);
1954 }
1955
1956
1957 static JSValueRef denyWebNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1958 {
1959     if (argumentCount < 1)
1960         return JSValueMakeUndefined(context);
1961
1962     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1963
1964     JSRetainPtr<JSStringRef> origin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
1965     ASSERT(!*exception);
1966     controller->denyWebNotificationPermission(origin.get());
1967
1968     return JSValueMakeUndefined(context);
1969 }
1970
1971
1972 static JSValueRef removeAllWebNotificationPermissionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1973 {
1974     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1975
1976     controller->removeAllWebNotificationPermissions();
1977
1978     return JSValueMakeUndefined(context);
1979 }
1980
1981
1982 static JSValueRef simulateWebNotificationClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1983 {
1984     // Has Windows implementation
1985     if (argumentCount < 1)
1986         return JSValueMakeUndefined(context);
1987
1988     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1989
1990     controller->simulateWebNotificationClick(arguments[0]);
1991
1992     return JSValueMakeUndefined(context);
1993 }
1994
1995 static JSValueRef forceImmediateCompletionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1996 {
1997     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
1998     controller->forceImmediateCompletion();
1999     return JSValueMakeUndefined(context);
2000 }
2001
2002 static JSValueRef failNextNewCodeBlock(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2003 {
2004     if (argumentCount < 1)
2005         return JSValueMakeUndefined(context);
2006     
2007     return JSC::failNextNewCodeBlock(context);
2008 }
2009
2010 static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2011 {
2012     return JSC::numberOfDFGCompiles(context, arguments[0]);
2013 }
2014
2015 static JSValueRef neverInlineFunction(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2016 {
2017     if (argumentCount < 1)
2018         return JSValueMakeUndefined(context);
2019     
2020     return JSC::setNeverInline(context, arguments[0]);
2021 }
2022
2023 static JSValueRef accummulateLogsForChannel(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2024 {
2025     if (argumentCount < 1)
2026         return JSValueMakeUndefined(context);
2027
2028     JSRetainPtr<JSStringRef> channel(Adopt, JSValueToStringCopy(context, arguments[0], exception));
2029     ASSERT(!*exception);
2030
2031     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
2032     controller->setAccummulateLogsForChannel(channel.get());
2033
2034     return JSValueMakeUndefined(context);
2035 }
2036
2037 static JSValueRef runUIScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
2038 {
2039     if (argumentCount < 1)
2040         return JSValueMakeUndefined(context);
2041
2042     JSRetainPtr<JSStringRef> script = argumentCount > 0 ? JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, arguments[0], 0)) : JSRetainPtr<JSStringRef>();
2043     JSValueRef callback = argumentCount > 1 ? arguments[1] : JSValueMakeUndefined(context);
2044
2045     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
2046     controller->runUIScript(context, script.get(), callback);
2047
2048     return JSValueMakeUndefined(context);
2049 }
2050
2051 static void testRunnerObjectFinalize(JSObjectRef object)
2052 {
2053     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(object));
2054     controller->deref();
2055 }
2056
2057 // Object Creation
2058
2059 void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
2060 {
2061     JSRetainPtr<JSStringRef> testRunnerStr(Adopt, JSStringCreateWithUTF8CString("testRunner"));
2062     ref();
2063
2064     JSClassRef classRef = getJSClass();
2065     JSValueRef layoutTestContollerObject = JSObjectMake(context, classRef, this);
2066     JSClassRelease(classRef);
2067
2068     JSObjectSetProperty(context, windowObject, testRunnerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
2069 }
2070
2071 JSClassRef TestRunner::getJSClass()
2072 {
2073     static JSStaticValue* staticValues = TestRunner::staticValues();
2074     static JSStaticFunction* staticFunctions = TestRunner::staticFunctions();
2075     static JSClassDefinition classDefinition = {
2076         0, kJSClassAttributeNone, "TestRunner", 0, staticValues, staticFunctions,
2077         0, testRunnerObjectFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
2078     };
2079
2080     return JSClassCreate(&classDefinition);
2081 }
2082
2083 JSStaticValue* TestRunner::staticValues()
2084 {
2085     static JSStaticValue staticValues[] = {
2086         { "didCancelClientRedirect", getDidCancelClientRedirect, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2087         { "timeout", getTimeoutCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2088         { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone },
2089         { "webHistoryItemCount", getWebHistoryItemCountCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2090         { "secureEventInputIsEnabled", getSecureEventInputIsEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2091         { "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2092         { "databaseDefaultQuota", getDatabaseDefaultQuotaCallback, setDatabaseDefaultQuotaCallback, kJSPropertyAttributeNone },
2093         { "databaseMaxQuota", getDatabaseMaxQuotaCallback, setDatabaseMaxQuotaCallback, kJSPropertyAttributeNone },
2094         { "inspectorTestStubURL", getInspectorTestStubURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2095         { 0, 0, 0, 0 }
2096     };
2097     return staticValues;
2098 }
2099
2100 JSStaticFunction* TestRunner::staticFunctions()
2101 {
2102     static JSStaticFunction staticFunctions[] = {
2103         { "abortModal", abortModalCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2104         { "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2105         { "addURLToRedirect", addURLToRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2106         { "addUserScript", addUserScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2107         { "addUserStyleSheet", addUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2108         { "apiTestNewWindowDataLoadBaseURL", apiTestNewWindowDataLoadBaseURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2109         { "apiTestGoToCurrentBackForwardItem", apiTestGoToCurrentBackForwardItemCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2110         { "applicationCacheDiskUsageForOrigin", applicationCacheDiskUsageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2111         { "callShouldCloseOnWebView", callShouldCloseOnWebViewCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2112         { "clearAllApplicationCaches", clearAllApplicationCachesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2113         { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2114         { "clearApplicationCacheForOrigin", clearApplicationCacheForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2115         { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2116         { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2117         { "closeWebInspector", closeWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2118         { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2119         { "disallowIncreaseForApplicationCacheQuota", disallowIncreaseForApplicationCacheQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2120         { "dispatchPendingLoadRequests", dispatchPendingLoadRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2121         { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2122         { "displayAndTrackRepaints", displayAndTrackRepaintsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2123         { "dumpApplicationCacheDelegateCallbacks", dumpApplicationCacheDelegateCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2124         { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2125         { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2126         { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2127         { "dumpChildFramesAsText", dumpChildFramesAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2128         { "dumpDOMAsWebArchive", dumpDOMAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2129         { "dumpDatabaseCallbacks", dumpDatabaseCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2130         { "dumpEditingCallbacks", dumpEditingCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2131         { "dumpFrameLoadCallbacks", dumpFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2132         { "dumpProgressFinishedCallback", dumpProgressFinishedCallbackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2133         { "dumpUserGestureInFrameLoadCallbacks", dumpUserGestureInFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },        
2134         { "dumpResourceLoadCallbacks", dumpResourceLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2135         { "dumpResourceResponseMIMETypes", dumpResourceResponseMIMETypesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2136         { "dumpSelectionRect", dumpSelectionRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2137         { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2138         { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2139         { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2140         { "dumpWillCacheResponse", dumpWillCacheResponseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2141         { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2142         { "evaluateInWebInspector", evaluateInWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2143         { "evaluateScriptInIsolatedWorldAndReturnValue", evaluateScriptInIsolatedWorldAndReturnValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2144         { "evaluateScriptInIsolatedWorld", evaluateScriptInIsolatedWorldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2145         { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2146         { "findString", findStringCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2147         { "originsWithApplicationCache", originsWithApplicationCacheCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2148         { "goBack", goBackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
2149         { "ignoreLegacyWebNotificationPermissionRequests", ignoreLegacyWebNotificationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2150         { "isGeolocationProviderActive", isGeolocationProviderActiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2151         { "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2152         { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2153         { "numberOfPendingGeolocationPermissionRequests", numberOfPendingGeolocationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2154         { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2155         { "overridePreference", overridePreferenceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2156         { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2157         { "printToPDF", dumpAsPDFCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2158         { "queueBackNavigation", queueBackNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2159         { "queueForwardNavigation", queueForwardNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2160         { "queueLoad", queueLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2161         { "queueLoadHTMLString", queueLoadHTMLStringCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2162         { "queueLoadingScript", queueLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2163         { "queueNonLoadingScript", queueNonLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2164         { "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2165         { "removeAllVisitedLinks", removeAllVisitedLinksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2166         { "removeOriginAccessWhitelistEntry", removeOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2167         { "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2168         { "resetPageVisibility", resetPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2169         { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2170         { "setAllowUniversalAccessFromFileURLs", setAllowUniversalAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2171         { "setAllowFileAccessFromFileURLs", setAllowFileAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2172         { "setNeedsStorageAccessFromFileURLsQuirk", setNeedsStorageAccessFromFileURLsQuirkCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2173         { "setAllowsAnySSLCertificate", setAllowsAnySSLCertificateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2174         { "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2175         { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2176         { "setAudioResult", setAudioResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2177         { "setAuthenticationPassword", setAuthenticationPasswordCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2178         { "setAuthenticationUsername", setAuthenticationUsernameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2179         { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2180         { "setCacheModel", setCacheModelCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2181         { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2182         { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2183         { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2184         { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2185         { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
2186         { "setDefersLoading", setDefersLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2187         { "setUseDeferredFrameLoading", setUseDeferredFrameLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2188         { "setDomainRelaxationForbiddenForURLScheme", setDomainRelaxationForbiddenForURLSchemeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2189         { "setGeolocationPermission", setGeolocationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2190         { "setRejectsProtectionSpaceAndContinueForAuthenticationChallenges", setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2191         { "setHandlesAuthenticationChallenges", setHandlesAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2192         { "setIconDatabaseEnabled", setIconDatabaseEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2193         { "setAutomaticLinkDetectionEnabled", setAutomaticLinkDetectionEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2194         { "setMainFrameIsFirstResponder", setMainFrameIsFirstResponderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2195         { "setMockDeviceOrientation", setMockDeviceOrientationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2196         { "setMockGeolocationPositionUnavailableError", setMockGeolocationPositionUnavailableErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2197         { "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2198         { "setNewWindowsCopyBackForwardList", setNewWindowsCopyBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2199         { "setPageVisibility", setPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2200         { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2201         { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2202         { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2203         { "setPluginsEnabled", setPluginsEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2204         { "setPrinting", setPrintingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2205         { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2206         { "setSerializeHTTPLoads", setSerializeHTTPLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2207         { "setSpatialNavigationEnabled", setSpatialNavigationEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2208         { "setStopProvisionalFrameLoads", setStopProvisionalFrameLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2209         { "setTabKeyCyclesThroughElements", setTabKeyCyclesThroughElementsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2210 #if PLATFORM(IOS)
2211         { "setTelephoneNumberParsingEnabled", setTelephoneNumberParsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2212         { "setPagePaused", setPagePausedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2213 #endif
2214         { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2215         { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2216         { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2217         { "setValueForUser", setValueForUserCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2218         { "setWebViewEditable", setWebViewEditableCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2219         { "setWillSendRequestClearHeader", setWillSendRequestClearHeaderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2220         { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2221         { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2222         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2223         { "setViewSize", setViewSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2224         { "setJavaScriptCanAccessClipboard", setJavaScriptCanAccessClipboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2225         { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2226         { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2227         { "simulateLegacyWebNotificationClick", simulateLegacyWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2228         { "testOnscreen", testOnscreenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2229         { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2230         { "waitForPolicyDelegate", waitForPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2231         { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2232         { "windowCount", windowCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2233         { "addOriginAccessWhitelistEntry", addOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2234         { "setScrollbarPolicy", setScrollbarPolicyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2235         { "authenticateSession", authenticateSessionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2236         { "setShouldPaintBrokenImage", setShouldPaintBrokenImageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2237         { "setTextDirection", setTextDirectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2238         { "setShouldStayOnPageAfterHandlingBeforeUnload", setShouldStayOnPageAfterHandlingBeforeUnloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2239         { "addChromeInputField", addChromeInputFieldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2240         { "removeChromeInputField", removeChromeInputFieldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2241         { "focusWebView", focusWebViewCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2242         { "setBackingScaleFactor", setBackingScaleFactorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2243         { "preciseTime", preciseTimeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2244         { "setHasCustomFullScreenBehavior", setHasCustomFullScreenBehaviorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2245         { "setStorageDatabaseIdleInterval", setStorageDatabaseIdleIntervalCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2246         { "closeIdleLocalStorageDatabases", closeIdleLocalStorageDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2247         { "grantWebNotificationPermission", grantWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2248         { "denyWebNotificationPermission", denyWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2249         { "removeAllWebNotificationPermissions", removeAllWebNotificationPermissionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2250         { "simulateWebNotificationClick", simulateWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2251         { "failNextNewCodeBlock", failNextNewCodeBlock, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2252         { "numberOfDFGCompiles", numberOfDFGCompiles, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2253         { "neverInlineFunction", neverInlineFunction, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2254         { "accummulateLogsForChannel", accummulateLogsForChannel, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2255         { "runUIScript", runUIScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2256         { "imageCountInGeneralPasteboard", imageCountInGeneralPasteboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2257         { "setSpellCheckerLoggingEnabled", setSpellCheckerLoggingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2258         { "setOpenPanelFiles", setOpenPanelFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2259         { "forceImmediateCompletion", forceImmediateCompletionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
2260         { 0, 0, 0 }
2261     };
2262
2263     return staticFunctions;
2264 }
2265
2266 void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL)
2267 {
2268     WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL));
2269 }
2270
2271 void TestRunner::queueLoadAlternateHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
2272 {
2273     WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL, unreachableURL));
2274 }
2275
2276 void TestRunner::queueBackNavigation(int howFarBack)
2277 {
2278     WorkQueue::singleton().queue(new BackItem(howFarBack));
2279 }
2280
2281 void TestRunner::queueForwardNavigation(int howFarForward)
2282 {
2283     WorkQueue::singleton().queue(new ForwardItem(howFarForward));
2284 }
2285
2286 void TestRunner::queueLoadingScript(JSStringRef script)
2287 {
2288     WorkQueue::singleton().queue(new LoadingScriptItem(script));
2289 }
2290
2291 void TestRunner::queueNonLoadingScript(JSStringRef script)
2292 {
2293     WorkQueue::singleton().queue(new NonLoadingScriptItem(script));
2294 }
2295
2296 void TestRunner::queueReload()
2297 {
2298     WorkQueue::singleton().queue(new ReloadItem);
2299 }
2300
2301 void TestRunner::ignoreLegacyWebNotificationPermissionRequests()
2302 {
2303     m_areLegacyWebNotificationPermissionRequestsIgnored = false;
2304 }
2305
2306 void TestRunner::waitToDumpWatchdogTimerFired()
2307 {
2308     const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
2309     fprintf(testResult, "%s", message);
2310
2311     auto accumulatedLogs = getAndResetAccumulatedLogs();
2312     if (!accumulatedLogs.isEmpty()) {
2313         const char* message = "Logs accumulated during test run:\n";
2314         fprintf(testResult, "%s%s\n", message, accumulatedLogs.utf8().data());
2315     }
2316
2317     notifyDone();
2318 }
2319
2320 void TestRunner::setGeolocationPermissionCommon(bool allow)
2321 {
2322     m_isGeolocationPermissionSet = true;
2323     m_geolocationPermission = allow;
2324 }
2325
2326 void TestRunner::setPOSIXLocale(JSStringRef locale)
2327 {
2328     char localeBuf[32];
2329     JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
2330     setlocale(LC_ALL, localeBuf);
2331 }
2332
2333 void TestRunner::addURLToRedirect(std::string origin, std::string destination)
2334 {
2335     m_URLsToRedirect[origin] = destination;
2336 }
2337
2338 const std::string& TestRunner::redirectionDestinationForURL(std::string origin)
2339 {
2340     return m_URLsToRedirect[origin];
2341 }
2342
2343 void TestRunner::setShouldPaintBrokenImage(bool shouldPaintBrokenImage)
2344 {
2345     m_shouldPaintBrokenImage = shouldPaintBrokenImage;
2346 }
2347
2348 void TestRunner::setAccummulateLogsForChannel(JSStringRef channel)
2349 {
2350     size_t maxLength = JSStringGetMaximumUTF8CStringSize(channel);
2351     auto buffer = std::make_unique<char[]>(maxLength + 1);
2352     JSStringGetUTF8CString(channel, buffer.get(), maxLength + 1);
2353
2354     WebCoreTestSupport::setLogChannelToAccumulate({ buffer.get() });
2355 }
2356
2357 typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap;
2358 static CallbackMap& callbackMap()
2359 {
2360     static CallbackMap& map = *new CallbackMap;
2361     return map;
2362 }
2363
2364 void TestRunner::cacheTestRunnerCallback(unsigned index, JSValueRef callback)
2365 {
2366     if (!callback)
2367         return;
2368
2369     if (callbackMap().contains(index)) {
2370         fprintf(stderr, "FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n", index);
2371         return;
2372     }
2373
2374     JSContextRef context = mainFrameJSContext();
2375     JSValueProtect(context, callback);
2376     callbackMap().add(index, callback);
2377 }
2378
2379 void TestRunner::callTestRunnerCallback(unsigned index, size_t argumentCount, const JSValueRef arguments[])
2380 {
2381     if (!callbackMap().contains(index))
2382         return;
2383
2384     JSContextRef context = mainFrameJSContext();
2385     if (JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0)) {
2386         JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0);
2387         JSValueUnprotect(context, callback);
2388     }
2389 }
2390
2391 void TestRunner::clearTestRunnerCallbacks()
2392 {
2393     JSContextRef context = mainFrameJSContext();
2394
2395     for (auto& iter : callbackMap()) {
2396         if (JSObjectRef callback = JSValueToObject(context, iter.value, 0))
2397             JSValueUnprotect(context, callback);
2398     }
2399
2400     callbackMap().clear();
2401 }
2402
2403 enum {
2404     FirstUIScriptCallbackID = 100
2405 };
2406
2407 static unsigned nextUIScriptCallbackID()
2408 {
2409     static unsigned callbackID = FirstUIScriptCallbackID;
2410     return callbackID++;
2411 }
2412
2413 void TestRunner::runUIScript(JSContextRef context, JSStringRef script, JSValueRef callback)
2414 {
2415     m_pendingUIScriptInvocationData = nullptr;
2416
2417     unsigned callbackID = nextUIScriptCallbackID();
2418     cacheTestRunnerCallback(callbackID, callback);
2419
2420     if (!m_UIScriptContext)
2421         m_UIScriptContext = std::make_unique<WTR::UIScriptContext>(*this);
2422
2423     String scriptString(JSStringGetCharactersPtr(script), JSStringGetLength(script));
2424     m_UIScriptContext->runUIScript(scriptString, callbackID);
2425 }
2426
2427 void TestRunner::callUIScriptCallback(unsigned callbackID, JSStringRef result)
2428 {
2429     JSRetainPtr<JSStringRef> protectedResult(result);
2430 #if !PLATFORM(IOS)
2431     RunLoop::main().dispatch([protectedThis = makeRef(*this), callbackID, protectedResult]() mutable {
2432         JSContextRef context = protectedThis->mainFrameJSContext();
2433         JSValueRef resultValue = JSValueMakeString(context, protectedResult.get());
2434         protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue);
2435     });
2436 #else
2437     WebThreadRun(
2438         BlockPtr<void()>::fromCallable([protectedThis = makeRef(*this), callbackID, protectedResult] {
2439             JSContextRef context = protectedThis->mainFrameJSContext();
2440             JSValueRef resultValue = JSValueMakeString(context, protectedResult.get());
2441             protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue);
2442         }).get()
2443     );
2444 #endif
2445 }
2446
2447 void TestRunner::uiScriptDidComplete(const String& result, unsigned callbackID)
2448 {
2449     JSRetainPtr<JSStringRef> stringRef(Adopt, JSStringCreateWithUTF8CString(result.utf8().data()));
2450     callUIScriptCallback(callbackID, stringRef.get());
2451 }
2452
2453 void TestRunner::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate)
2454 {
2455     WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate);
2456 }
2457
2458 void TestRunner::setOpenPanelFiles(JSContextRef context, JSValueRef filesValue)
2459 {
2460     if (!JSValueIsArray(context, filesValue))
2461         return;
2462
2463     JSObjectRef files = JSValueToObject(context, filesValue, nullptr);
2464     static auto lengthProperty = JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("length"));
2465     JSValueRef filesLengthValue = JSObjectGetProperty(context, files, lengthProperty.get(), nullptr);
2466     if (!JSValueIsNumber(context, filesLengthValue))
2467         return;
2468
2469     m_openPanelFiles.clear();
2470     auto filesLength = static_cast<size_t>(JSValueToNumber(context, filesLengthValue, nullptr));
2471     for (size_t i = 0; i < filesLength; ++i) {
2472         JSValueRef fileValue = JSObjectGetPropertyAtIndex(context, files, i, nullptr);
2473         if (!JSValueIsString(context, fileValue))
2474             continue;
2475
2476         auto file = JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, fileValue, nullptr));
2477         size_t fileBufferSize = JSStringGetMaximumUTF8CStringSize(file.get()) + 1;
2478         auto fileBuffer = std::make_unique<char[]>(fileBufferSize);
2479         JSStringGetUTF8CString(file.get(), fileBuffer.get(), fileBufferSize);
2480
2481         m_openPanelFiles.push_back(fileBuffer.get());
2482     }
2483 }
2484
2485 void TestRunner::cleanup()
2486 {
2487     clearTestRunnerCallbacks();
2488 }