6be67ab24dea89a8b2e3166fbbffdb5a69e8e6dc
[WebKit-https.git] / WebKitTools / DumpRenderTree / LayoutTestController.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "LayoutTestController.h"
31
32 #include "WorkQueue.h"
33 #include "WorkQueueItem.h"
34 #include <JavaScriptCore/JSObjectRef.h>
35 #include <JavaScriptCore/JSRetainPtr.h>
36 #include <stdio.h>
37 #include <wtf/Assertions.h>
38 #include <wtf/MathExtras.h>
39 #include <wtf/RefPtr.h>
40
41 LayoutTestController::LayoutTestController(const std::string& testPathOrURL, const std::string& expectedPixelHash)
42     : m_dumpAsText(false)
43     , m_dumpAsPDF(false)
44     , m_dumpBackForwardList(false)
45     , m_dumpChildFrameScrollPositions(false)
46     , m_dumpChildFramesAsText(false)
47     , m_dumpDatabaseCallbacks(false)
48     , m_dumpDOMAsWebArchive(false)
49     , m_dumpSelectionRect(false)
50     , m_dumpSourceAsWebArchive(false)
51     , m_dumpStatusCallbacks(false)
52     , m_dumpTitleChanges(false)
53     , m_dumpEditingCallbacks(false)
54     , m_dumpResourceLoadCallbacks(false)
55     , m_dumpResourceResponseMIMETypes(false)
56     , m_dumpWillCacheResponse(false)
57     , m_dumpFrameLoadCallbacks(false)
58     , m_callCloseOnWebViews(true)
59     , m_canOpenWindows(false)
60     , m_closeRemainingWindowsWhenComplete(true)
61     , m_stopProvisionalFrameLoads(false)
62     , m_testOnscreen(false)
63     , m_testRepaint(false)
64     , m_testRepaintSweepHorizontally(false)
65     , m_waitToDump(false)
66     , m_willSendRequestReturnsNullOnRedirect(false)
67     , m_windowIsKey(true)
68     , m_alwaysAcceptCookies(false)
69     , m_globalFlag(false)
70     , m_isGeolocationPermissionSet(false)
71     , m_geolocationPermission(false)
72     , m_testPathOrURL(testPathOrURL)
73     , m_expectedPixelHash(expectedPixelHash)
74 {
75 }
76
77 // Static Functions
78
79 static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
80 {
81     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
82     controller->setDumpAsText(true);
83     return JSValueMakeUndefined(context);
84 }
85
86 static JSValueRef dumpAsPDFCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
87 {
88     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
89     controller->setDumpAsPDF(true);
90     return JSValueMakeUndefined(context);
91 }
92
93 static JSValueRef dumpBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
94 {
95     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
96     controller->setDumpBackForwardList(true);
97     return JSValueMakeUndefined(context);
98 }
99
100 static JSValueRef dumpChildFramesAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
101 {
102     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
103     controller->setDumpChildFramesAsText(true);
104     return JSValueMakeUndefined(context);
105 }
106
107 static JSValueRef dumpChildFrameScrollPositionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
108 {
109     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
110     controller->setDumpChildFrameScrollPositions(true);
111     return JSValueMakeUndefined(context);
112 }
113
114 static JSValueRef dumpDatabaseCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
115 {
116     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
117     controller->setDumpDatabaseCallbacks(true);
118     return JSValueMakeUndefined(context);
119 }
120
121 static JSValueRef dumpDOMAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
122 {
123     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
124     controller->setDumpDOMAsWebArchive(true);
125     return JSValueMakeUndefined(context);
126 }
127
128 static JSValueRef dumpEditingCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
129 {
130     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
131     controller->setDumpEditingCallbacks(true);
132     return JSValueMakeUndefined(context);
133 }
134
135 static JSValueRef dumpResourceLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
136 {
137     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
138     controller->setDumpResourceLoadCallbacks(true);
139     return JSValueMakeUndefined(context);
140 }
141
142 static JSValueRef dumpFrameLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
143 {
144     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
145     controller->setDumpFrameLoadCallbacks(true);
146     return JSValueMakeUndefined(context);
147 }
148
149 static JSValueRef dumpResourceResponseMIMETypesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
150 {
151     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
152     controller->setDumpResourceResponseMIMETypes(true);
153     return JSValueMakeUndefined(context);
154 }
155
156 static JSValueRef dumpSelectionRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
157 {
158     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
159     controller->setDumpSelectionRect(true);
160     return JSValueMakeUndefined(context);
161 }
162
163 static JSValueRef dumpSourceAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
164 {
165     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
166     controller->setDumpSourceAsWebArchive(true);
167     return JSValueMakeUndefined(context);
168 }
169
170 static JSValueRef dumpStatusCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
171 {
172     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
173     controller->setDumpStatusCallbacks(true);
174     return JSValueMakeUndefined(context);
175 }
176
177 static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
178 {
179     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
180     controller->setDumpTitleChanges(true);
181     return JSValueMakeUndefined(context);
182 }
183
184 static JSValueRef dumpWillCacheResponseCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
185 {
186     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
187     controller->setDumpWillCacheResponse(true);
188     return JSValueMakeUndefined(context);
189 }
190
191 static JSValueRef pathToLocalResourceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
192 {
193     if (argumentCount < 1)
194         return JSValueMakeUndefined(context);
195
196     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
197     JSRetainPtr<JSStringRef> localPath(Adopt, JSValueToStringCopy(context, arguments[0], exception));
198     ASSERT(!*exception);
199
200     JSRetainPtr<JSStringRef> convertedPath(Adopt, controller->pathToLocalResource(context, localPath.get()));
201     if (!convertedPath)
202         return JSValueMakeUndefined(context);
203
204     return JSValueMakeString(context, convertedPath.get());
205 }
206
207 static JSValueRef repaintSweepHorizontallyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
208 {
209     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
210     controller->setTestRepaintSweepHorizontally(true);
211     return JSValueMakeUndefined(context);
212 }
213
214 static JSValueRef setCallCloseOnWebViewsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
215 {
216     if (argumentCount < 1)
217         return JSValueMakeUndefined(context);
218
219     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
220     controller->setCallCloseOnWebViews(JSValueToBoolean(context, arguments[0]));
221     return JSValueMakeUndefined(context);
222 }
223
224 static JSValueRef setCanOpenWindowsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
225 {
226     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
227     controller->setCanOpenWindows(true);
228     return JSValueMakeUndefined(context);
229 }
230
231 static JSValueRef setCloseRemainingWindowsWhenCompleteCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
232 {
233     if (argumentCount < 1)
234         return JSValueMakeUndefined(context);
235
236     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
237     controller->setCloseRemainingWindowsWhenComplete(JSValueToBoolean(context, arguments[0]));
238     return JSValueMakeUndefined(context);
239 }
240
241 static JSValueRef testOnscreenCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
242 {
243     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
244     controller->setTestOnscreen(true);
245     return JSValueMakeUndefined(context);
246 }
247
248 static JSValueRef testRepaintCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
249 {
250     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
251     controller->setTestRepaint(true);
252     return JSValueMakeUndefined(context);
253 }
254
255 static JSValueRef addDisallowedURLCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
256 {
257     // Has mac implementation
258     if (argumentCount < 1)
259         return JSValueMakeUndefined(context);
260
261     JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
262     ASSERT(!*exception);
263
264     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
265     controller->addDisallowedURL(url.get());
266
267     return JSValueMakeUndefined(context);
268 }
269
270 static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
271 {
272     // Has mac & windows implementation
273     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
274     controller->clearAllDatabases();
275
276     return JSValueMakeUndefined(context);
277 }
278
279 static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
280 {
281     // Has mac & windows implementation
282     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
283     controller->clearBackForwardList();
284
285     return JSValueMakeUndefined(context);
286 }
287
288 static JSValueRef clearPersistentUserStyleSheetCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
289 {
290     // Has mac & windows implementation
291     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
292     controller->clearPersistentUserStyleSheet();
293
294     return JSValueMakeUndefined(context);
295 }
296
297 static JSValueRef decodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
298 {
299     // Has mac implementation
300     if (argumentCount < 1)
301         return JSValueMakeUndefined(context);
302
303     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
304     ASSERT(!*exception);
305
306     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
307     JSRetainPtr<JSStringRef> decodedHostName(Adopt, controller->copyDecodedHostName(name.get()));
308     return JSValueMakeString(context, decodedHostName.get());
309 }
310
311 static JSValueRef disableImageLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
312 {
313     // Has mac implementation, needs windows implementation
314     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
315     controller->disableImageLoading();
316     
317     return JSValueMakeUndefined(context);
318 }
319
320 static JSValueRef dispatchPendingLoadRequestsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
321 {
322     // Has mac implementation, needs windows implementation
323     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
324     controller->dispatchPendingLoadRequests();
325     
326     return JSValueMakeUndefined(context);
327 }
328
329 static JSValueRef displayCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
330 {
331     // Has mac & windows implementation
332     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
333     controller->display();
334
335     return JSValueMakeUndefined(context);
336 }
337
338 static JSValueRef encodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
339 {
340     // Has mac implementation
341     if (argumentCount < 1)
342         return JSValueMakeUndefined(context);
343
344     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
345     ASSERT(!*exception);
346
347     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
348     JSRetainPtr<JSStringRef> encodedHostName(Adopt, controller->copyEncodedHostName(name.get()));
349     return JSValueMakeString(context, encodedHostName.get());
350 }
351
352 static JSValueRef execCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
353 {
354     // Has Mac & Windows implementations.
355     if (argumentCount < 1)
356         return JSValueMakeUndefined(context);
357
358     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
359     ASSERT(!*exception);
360
361     // Ignoring the second parameter (userInterface), as this command emulates a manual action.
362
363     JSRetainPtr<JSStringRef> value;
364     if (argumentCount >= 3) {
365         value.adopt(JSValueToStringCopy(context, arguments[2], exception));
366         ASSERT(!*exception);
367     } else
368         value.adopt(JSStringCreateWithUTF8CString(""));
369
370
371     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
372     controller->execCommand(name.get(), value.get());
373
374     return JSValueMakeUndefined(context);
375 }
376
377 static JSValueRef grantDesktopNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
378 {
379     // Has Windows implementation
380     if (argumentCount < 1)
381         return JSValueMakeUndefined(context);
382
383     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
384
385     controller->grantDesktopNotificationPermission(JSValueToStringCopy(context, arguments[0], NULL));
386         
387     return JSValueMakeUndefined(context);
388 }
389
390 static JSValueRef isCommandEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
391 {
392     // Has Mac implementation.
393
394     if (argumentCount < 1)
395         return JSValueMakeUndefined(context);
396
397     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
398     ASSERT(!*exception);
399
400     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
401
402     return JSValueMakeBoolean(context, controller->isCommandEnabled(name.get()));
403 }
404
405 static JSValueRef overridePreferenceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
406 {
407     if (argumentCount < 2)
408         return JSValueMakeUndefined(context);
409
410     JSRetainPtr<JSStringRef> key(Adopt, JSValueToStringCopy(context, arguments[0], exception));
411     ASSERT(!*exception);
412     JSRetainPtr<JSStringRef> value(Adopt, JSValueToStringCopy(context, arguments[1], exception));
413     ASSERT(!*exception);
414
415     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
416     controller->overridePreference(key.get(), value.get());
417
418     return JSValueMakeUndefined(context);
419 }
420
421 static JSValueRef keepWebHistoryCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
422 {
423     // Has mac implementation
424     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
425     controller->keepWebHistory();
426
427     return JSValueMakeUndefined(context);
428 }
429
430 static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
431 {
432     // Has mac & windows implementation
433     // May be able to be made platform independant by using shared WorkQueue
434     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
435     controller->notifyDone();
436     return JSValueMakeUndefined(context);
437 }
438
439 static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
440 {
441     // Has mac & windows implementation
442     // May be able to be made platform independant by using shared WorkQueue
443     if (argumentCount < 1)
444         return JSValueMakeUndefined(context);
445
446     double howFarBackDouble = JSValueToNumber(context, arguments[0], exception);
447     ASSERT(!*exception);
448
449     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
450     controller->queueBackNavigation(static_cast<int>(howFarBackDouble));
451
452     return JSValueMakeUndefined(context);
453 }
454
455 static JSValueRef queueForwardNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
456 {
457     // Has mac & windows implementation
458     // May be able to be made platform independant by using shared WorkQueue
459     if (argumentCount < 1)
460         return JSValueMakeUndefined(context);
461
462     double howFarForwardDouble = JSValueToNumber(context, arguments[0], exception);
463     ASSERT(!*exception);
464
465     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
466     controller->queueForwardNavigation(static_cast<int>(howFarForwardDouble));
467
468     return JSValueMakeUndefined(context);
469 }
470
471 static JSValueRef queueLoadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
472 {
473     // Has mac & windows implementation
474     // May be able to be made platform independant by using shared WorkQueue
475     if (argumentCount < 1)
476         return JSValueMakeUndefined(context);
477
478     JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
479     ASSERT(!*exception);
480
481     JSRetainPtr<JSStringRef> target;
482     if (argumentCount >= 2) {
483         target.adopt(JSValueToStringCopy(context, arguments[1], exception));
484         ASSERT(!*exception);
485     } else
486         target.adopt(JSStringCreateWithUTF8CString(""));
487
488     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
489     controller->queueLoad(url.get(), target.get());
490
491     return JSValueMakeUndefined(context);
492 }
493
494 static JSValueRef queueReloadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
495 {
496     // Has mac & windows implementation
497     // May be able to be made platform independant by using shared WorkQueue
498
499     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
500     controller->queueReload();
501
502     return JSValueMakeUndefined(context);
503 }
504
505 static JSValueRef queueLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
506 {
507     // Has mac & windows implementation
508     // May be able to be made platform independant by using shared WorkQueue
509     if (argumentCount < 1)
510         return JSValueMakeUndefined(context);
511
512     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
513     ASSERT(!*exception);
514
515     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
516     controller->queueLoadingScript(script.get());
517
518     return JSValueMakeUndefined(context);
519 }
520
521 static JSValueRef queueNonLoadingScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
522 {
523     // Has mac & windows implementation
524     // May be able to be made platform independant by using shared WorkQueue
525     if (argumentCount < 1)
526         return JSValueMakeUndefined(context);
527
528     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
529     ASSERT(!*exception);
530
531     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
532     controller->queueNonLoadingScript(script.get());
533
534     return JSValueMakeUndefined(context);
535 }
536
537 static JSValueRef setAcceptsEditingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
538 {
539     // Has mac & windows implementation
540     if (argumentCount < 1)
541         return JSValueMakeUndefined(context);
542
543     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
544     controller->setAcceptsEditing(JSValueToBoolean(context, arguments[0]));
545
546     return JSValueMakeUndefined(context);
547 }
548
549 static JSValueRef setAlwaysAcceptCookiesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
550 {
551     // Has mac & windows implementation
552     if (argumentCount < 1)
553         return JSValueMakeUndefined(context);
554
555     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
556     controller->setAlwaysAcceptCookies(JSValueToBoolean(context, arguments[0]));
557
558     return JSValueMakeUndefined(context);
559 }
560
561 static JSValueRef setAppCacheMaximumSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
562 {
563     // Has mac implementation
564     if (argumentCount < 1)
565         return JSValueMakeUndefined(context);
566
567     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
568
569     double size = JSValueToNumber(context, arguments[0], NULL);
570     if (!isnan(size))
571         controller->setAppCacheMaximumSize(static_cast<unsigned long long>(size));
572         
573     return JSValueMakeUndefined(context);
574
575 }
576
577 static JSValueRef setAuthorAndUserStylesEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
578 {
579     // Has mac & windows implementation
580     if (argumentCount < 1)
581         return JSValueMakeUndefined(context);
582
583     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
584     controller->setAuthorAndUserStylesEnabled(JSValueToBoolean(context, arguments[0]));
585
586     return JSValueMakeUndefined(context);
587 }
588
589 static JSValueRef setCacheModelCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
590 {
591     // Has Mac implementation.
592     if (argumentCount < 1)
593         return JSValueMakeUndefined(context);
594
595     int cacheModel = JSValueToNumber(context, arguments[0], exception);
596     ASSERT(!*exception);
597
598     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
599     controller->setCacheModel(cacheModel);
600
601     return JSValueMakeUndefined(context);
602 }
603
604 static JSValueRef setCustomPolicyDelegateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
605 {
606     // Has mac implementation
607     if (argumentCount < 1)
608         return JSValueMakeUndefined(context);
609     
610     bool permissive = false;
611     if (argumentCount >= 2)
612         permissive = JSValueToBoolean(context, arguments[1]);
613
614     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
615     controller->setCustomPolicyDelegate(JSValueToBoolean(context, arguments[0]), permissive);
616
617     return JSValueMakeUndefined(context);
618 }
619
620 static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
621 {
622     // Has mac implementation
623     if (argumentCount < 1)
624         return JSValueMakeUndefined(context);
625
626     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
627
628     double quota = JSValueToNumber(context, arguments[0], NULL);
629     if (!isnan(quota))
630         controller->setDatabaseQuota(static_cast<unsigned long long>(quota));
631         
632     return JSValueMakeUndefined(context);
633 }
634
635 static JSValueRef setMockGeolocationPositionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
636 {
637     if (argumentCount < 3)
638         return JSValueMakeUndefined(context);
639
640     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
641     controller->setMockGeolocationPosition(JSValueToNumber(context, arguments[0], NULL),  // latitude
642                                            JSValueToNumber(context, arguments[1], NULL),  // longitude
643                                            JSValueToNumber(context, arguments[2], NULL));  // accuracy
644
645     return JSValueMakeUndefined(context);
646 }
647
648 static JSValueRef setMockGeolocationErrorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
649 {
650     if (argumentCount < 2)
651         return JSValueMakeUndefined(context);
652
653     int code = JSValueToNumber(context, arguments[0], NULL);
654     JSRetainPtr<JSStringRef> message(Adopt, JSValueToStringCopy(context, arguments[1], exception));
655     ASSERT(!*exception);
656
657     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
658     controller->setMockGeolocationError(code, message.get());
659
660     return JSValueMakeUndefined(context);
661 }
662
663 static JSValueRef setGeolocationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
664 {
665     // Has mac implementation
666     if (argumentCount < 1)
667         return JSValueMakeUndefined(context);
668
669     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
670     controller->setGeolocationPermission(JSValueToBoolean(context, arguments[0]));
671
672     return JSValueMakeUndefined(context);
673 }
674
675 static JSValueRef setIconDatabaseEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
676 {
677     // Has mac & windows implementation
678     if (argumentCount < 1)
679         return JSValueMakeUndefined(context);
680
681     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
682     controller->setIconDatabaseEnabled(JSValueToBoolean(context, arguments[0]));
683
684     return JSValueMakeUndefined(context);
685 }
686
687 static JSValueRef setJavaScriptProfilingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
688 {
689     if (argumentCount < 1)
690         return JSValueMakeUndefined(context);
691
692     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
693     controller->setJavaScriptProfilingEnabled(JSValueToBoolean(context, arguments[0]));
694
695     return JSValueMakeUndefined(context);
696 }
697
698 static JSValueRef setMainFrameIsFirstResponderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
699 {
700     // Has mac implementation
701     if (argumentCount < 1)
702         return JSValueMakeUndefined(context);
703
704     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
705     controller->setMainFrameIsFirstResponder(JSValueToBoolean(context, arguments[0]));
706
707     return JSValueMakeUndefined(context);
708 }
709
710 static JSValueRef setPersistentUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
711 {
712     // Has mac implementation
713     if (argumentCount < 1)
714         return JSValueMakeUndefined(context);
715
716     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
717     ASSERT(!*exception);
718
719     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
720     controller->setPersistentUserStyleSheetLocation(path.get());
721
722     return JSValueMakeUndefined(context);
723 }
724
725 static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
726 {
727     // Has mac & windows implementation
728     if (argumentCount < 1)
729         return JSValueMakeUndefined(context);
730
731     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
732     controller->setPrivateBrowsingEnabled(JSValueToBoolean(context, arguments[0]));
733
734     return JSValueMakeUndefined(context);
735 }
736
737 static JSValueRef setXSSAuditorEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
738 {
739     // Has mac & windows implementation
740     if (argumentCount < 1)
741         return JSValueMakeUndefined(context);
742
743     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
744     controller->setXSSAuditorEnabled(JSValueToBoolean(context, arguments[0]));
745
746     return JSValueMakeUndefined(context);
747 }
748
749 static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
750 {
751     // Has mac & windows implementation
752     if (argumentCount < 1)
753         return JSValueMakeUndefined(context);
754
755     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
756     controller->setTabKeyCyclesThroughElements(JSValueToBoolean(context, arguments[0]));
757
758     return JSValueMakeUndefined(context);
759 }
760
761 static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
762 {
763     // Has mac implementation
764     if (argumentCount < 1)
765         return JSValueMakeUndefined(context);
766
767     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
768     controller->setUseDashboardCompatibilityMode(JSValueToBoolean(context, arguments[0]));
769
770     return JSValueMakeUndefined(context);
771 }
772
773 static JSValueRef setUserStyleSheetEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
774 {
775     // Has mac implementation
776     if (argumentCount < 1)
777         return JSValueMakeUndefined(context);
778
779     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
780     controller->setUserStyleSheetEnabled(JSValueToBoolean(context, arguments[0]));
781
782     return JSValueMakeUndefined(context);
783 }
784
785 static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
786 {
787     // Has mac implementation
788     if (argumentCount < 1)
789         return JSValueMakeUndefined(context);
790
791     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
792     ASSERT(!*exception);
793
794     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
795     controller->setUserStyleSheetLocation(path.get());
796
797     return JSValueMakeUndefined(context);
798 }
799
800 static JSValueRef setWillSendRequestReturnsNullOnRedirectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
801 {
802     // Has cross-platform implementation
803     if (argumentCount < 1)
804         return JSValueMakeUndefined(context);
805
806     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
807     controller->setWillSendRequestReturnsNullOnRedirect(JSValueToBoolean(context, arguments[0]));
808
809     return JSValueMakeUndefined(context);
810 }
811
812 static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
813 {
814     // Has mac implementation
815     if (argumentCount < 1)
816         return JSValueMakeUndefined(context);
817
818     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
819     controller->setWindowIsKey(JSValueToBoolean(context, arguments[0]));
820
821     return JSValueMakeUndefined(context);
822 }
823
824 static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
825 {
826     // Has mac & windows implementation
827     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
828     controller->setWaitToDump(true);
829
830     return JSValueMakeUndefined(context);
831 }
832
833 static JSValueRef windowCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
834 {
835     // Has mac implementation
836     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
837     int windows = controller->windowCount();
838     return JSValueMakeNumber(context, windows);
839 }
840
841 static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
842 {
843     // Has mac & windows implementation
844     if (argumentCount < 1)
845         return JSValueMakeUndefined(context);
846
847     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
848     controller->setPopupBlockingEnabled(JSValueToBoolean(context, arguments[0]));
849
850     return JSValueMakeUndefined(context);
851 }
852
853 static JSValueRef setSmartInsertDeleteEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
854 {
855     if (argumentCount < 1)
856         return JSValueMakeUndefined(context);
857
858     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
859     controller->setSmartInsertDeleteEnabled(JSValueToBoolean(context, arguments[0]));
860     return JSValueMakeUndefined(context);
861 }
862
863 static JSValueRef setSelectTrailingWhitespaceEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
864 {
865     if (argumentCount < 1)
866         return JSValueMakeUndefined(context);
867
868     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
869     controller->setSelectTrailingWhitespaceEnabled(JSValueToBoolean(context, arguments[0]));
870     return JSValueMakeUndefined(context);
871 }
872
873 static JSValueRef setStopProvisionalFrameLoadsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
874 {
875     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
876     controller->setStopProvisionalFrameLoads(true);
877     return JSValueMakeUndefined(context);
878 }
879
880 static JSValueRef elementDoesAutoCompleteForElementWithIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
881 {
882     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
883     JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[0], exception));
884     ASSERT(!*exception);
885
886     bool autoCompletes = controller->elementDoesAutoCompleteForElementWithId(elementId.get());
887
888     return JSValueMakeBoolean(context, autoCompletes);
889 }
890
891 static JSValueRef pauseAnimationAtTimeOnElementWithIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
892 {
893     if (argumentCount != 3)
894         return JSValueMakeUndefined(context);
895
896     JSRetainPtr<JSStringRef> animationName(Adopt, JSValueToStringCopy(context, arguments[0], exception));
897     ASSERT(!*exception);
898     double time = JSValueToNumber(context, arguments[1], exception);
899     ASSERT(!*exception);
900     JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[2], exception));
901     ASSERT(!*exception);
902
903     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
904     return JSValueMakeBoolean(context, controller->pauseAnimationAtTimeOnElementWithId(animationName.get(), time, elementId.get()));
905 }
906
907 static JSValueRef pauseTransitionAtTimeOnElementWithIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
908 {
909     if (argumentCount != 3)
910         return JSValueMakeUndefined(context);
911
912     JSRetainPtr<JSStringRef> propertyName(Adopt, JSValueToStringCopy(context, arguments[0], exception));
913     ASSERT(!*exception);
914     double time = JSValueToNumber(context, arguments[1], exception);
915     ASSERT(!*exception);
916     JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[2], exception));
917     ASSERT(!*exception);
918
919     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
920     return JSValueMakeBoolean(context, controller->pauseTransitionAtTimeOnElementWithId(propertyName.get(), time, elementId.get()));
921 }
922
923 static JSValueRef numberOfActiveAnimationsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
924 {
925     if (argumentCount != 0)
926         return JSValueMakeUndefined(context);
927
928     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
929     return JSValueMakeNumber(context, controller->numberOfActiveAnimations());
930 }
931
932 static JSValueRef waitForPolicyDelegateCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*)
933 {
934     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
935     controller->waitForPolicyDelegate();
936     return JSValueMakeUndefined(context);
937 }
938
939 static JSValueRef whiteListAccessFromOriginCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
940 {
941     if (argumentCount != 4)
942         return JSValueMakeUndefined(context);
943
944     JSRetainPtr<JSStringRef> sourceOrigin(Adopt, JSValueToStringCopy(context, arguments[0], exception));
945     ASSERT(!*exception);
946     JSRetainPtr<JSStringRef> destinationProtocol(Adopt, JSValueToStringCopy(context, arguments[1], exception));
947     ASSERT(!*exception);
948     JSRetainPtr<JSStringRef> destinationHost(Adopt, JSValueToStringCopy(context, arguments[2], exception));
949     ASSERT(!*exception);
950     bool allowDestinationSubdomains = JSValueToBoolean(context, arguments[3]);
951
952     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
953     controller->whiteListAccessFromOrigin(sourceOrigin.get(), destinationProtocol.get(), destinationHost.get(), allowDestinationSubdomains);
954     return JSValueMakeUndefined(context);
955 }
956
957 static JSValueRef addUserScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
958 {
959     if (argumentCount != 2)
960         return JSValueMakeUndefined(context);
961     
962     JSRetainPtr<JSStringRef> source(Adopt, JSValueToStringCopy(context, arguments[0], exception));
963     ASSERT(!*exception);
964     bool runAtStart = JSValueToBoolean(context, arguments[1]);
965     
966     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
967     controller->addUserScript(source.get(), runAtStart);
968     return JSValueMakeUndefined(context);
969 }
970  
971 static JSValueRef addUserStyleSheetCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
972 {
973     if (argumentCount != 1)
974         return JSValueMakeUndefined(context);
975     
976     JSRetainPtr<JSStringRef> source(Adopt, JSValueToStringCopy(context, arguments[0], exception));
977     ASSERT(!*exception);
978    
979     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
980     controller->addUserStyleSheet(source.get());
981     return JSValueMakeUndefined(context);
982 }
983
984 // Static Values
985
986 static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
987 {
988     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
989     return JSValueMakeBoolean(context, controller->globalFlag());
990 }
991
992 static JSValueRef getWebHistoryItemCountCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
993 {
994     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
995     return JSValueMakeNumber(context, controller->webHistoryItemCount());
996 }
997
998 static JSValueRef getWorkerThreadCountCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
999 {
1000     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
1001     return JSValueMakeNumber(context, controller->workerThreadCount());
1002 }
1003
1004 static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
1005 {
1006     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
1007     controller->setGlobalFlag(JSValueToBoolean(context, value));
1008     return true;
1009 }
1010
1011 static void layoutTestControllerObjectFinalize(JSObjectRef object)
1012 {
1013     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(object));
1014     controller->deref();
1015 }
1016
1017 // Object Creation
1018
1019 void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
1020 {
1021     JSRetainPtr<JSStringRef> layoutTestContollerStr(Adopt, JSStringCreateWithUTF8CString("layoutTestController"));
1022     ref();
1023     JSValueRef layoutTestContollerObject = JSObjectMake(context, getJSClass(), this);
1024     JSObjectSetProperty(context, windowObject, layoutTestContollerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
1025 }
1026
1027 JSClassRef LayoutTestController::getJSClass()
1028 {
1029     static JSClassRef layoutTestControllerClass;
1030
1031     if (!layoutTestControllerClass) {
1032         JSStaticValue* staticValues = LayoutTestController::staticValues();
1033         JSStaticFunction* staticFunctions = LayoutTestController::staticFunctions();
1034         JSClassDefinition classDefinition = {
1035             0, kJSClassAttributeNone, "LayoutTestController", 0, staticValues, staticFunctions,
1036             0, layoutTestControllerObjectFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
1037         };
1038
1039         layoutTestControllerClass = JSClassCreate(&classDefinition);
1040     }
1041
1042     return layoutTestControllerClass;
1043 }
1044
1045 JSStaticValue* LayoutTestController::staticValues()
1046 {
1047     static JSStaticValue staticValues[] = {
1048         { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone },
1049         { "webHistoryItemCount", getWebHistoryItemCountCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1050         { "workerThreadCount", getWorkerThreadCountCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1051         { 0, 0, 0, 0 }
1052     };
1053     return staticValues;
1054 }
1055
1056 JSStaticFunction* LayoutTestController::staticFunctions()
1057 {
1058     static JSStaticFunction staticFunctions[] = {
1059         { "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1060         { "addUserScript", addUserScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1061         { "addUserStyleSheet", addUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1062         { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1063         { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1064         { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1065         { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1066         { "disableImageLoading", disableImageLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1067         { "dispatchPendingLoadRequests", dispatchPendingLoadRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1068         { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1069         { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1070         { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1071         { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1072         { "dumpChildFramesAsText", dumpChildFramesAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1073         { "dumpDOMAsWebArchive", dumpDOMAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1074         { "dumpDatabaseCallbacks", dumpDatabaseCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1075         { "dumpEditingCallbacks", dumpEditingCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1076         { "dumpResourceLoadCallbacks", dumpResourceLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1077         { "dumpFrameLoadCallbacks", dumpFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1078         { "dumpResourceResponseMIMETypes", dumpResourceResponseMIMETypesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1079         { "dumpSelectionRect", dumpSelectionRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1080         { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1081         { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1082         { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1083         { "dumpWillCacheResponse", dumpWillCacheResponseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1084         { "elementDoesAutoCompleteForElementWithId", elementDoesAutoCompleteForElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1085         { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1086         { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1087         { "grantDesktopNotificationPermission", grantDesktopNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
1088         { "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1089         { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1090         { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1091         { "numberOfActiveAnimations", numberOfActiveAnimationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1092         { "overridePreference", overridePreferenceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1093         { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1094         { "pauseAnimationAtTimeOnElementWithId", pauseAnimationAtTimeOnElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1095         { "pauseTransitionAtTimeOnElementWithId", pauseTransitionAtTimeOnElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1096         { "printToPDF", dumpAsPDFCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1097         { "queueBackNavigation", queueBackNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1098         { "queueForwardNavigation", queueForwardNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1099         { "queueLoad", queueLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1100         { "queueLoadingScript", queueLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1101         { "queueNonLoadingScript", queueNonLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1102         { "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1103         { "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1104         { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1105         { "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1106         { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1107         { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
1108         { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1109         { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1110         { "setCacheModel", setCacheModelCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1111         { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1112         { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1113         { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
1114         { "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1115         { "setMockGeolocationError", setMockGeolocationErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1116         { "setGeolocationPermission", setGeolocationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1117         { "setIconDatabaseEnabled", setIconDatabaseEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1118         { "setJavaScriptProfilingEnabled", setJavaScriptProfilingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1119         { "setMainFrameIsFirstResponder", setMainFrameIsFirstResponderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1120         { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1121         { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1122         { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1123         { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1124         { "setSelectTrailingWhitespaceEnabled", setSelectTrailingWhitespaceEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1125         { "setSmartInsertDeleteEnabled", setSmartInsertDeleteEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1126         { "setStopProvisionalFrameLoads", setStopProvisionalFrameLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1127         { "setTabKeyCyclesThroughElements", setTabKeyCyclesThroughElementsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1128         { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1129         { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1130         { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1131         { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1132         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1133         { "testOnscreen", testOnscreenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1134         { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1135         { "waitForPolicyDelegate", waitForPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1136         { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1137         { "windowCount", windowCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1138         { "whiteListAccessFromOrigin", whiteListAccessFromOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1139         { 0, 0, 0 }
1140     };
1141
1142     return staticFunctions;
1143 }
1144
1145 void LayoutTestController::queueBackNavigation(int howFarBack)
1146 {
1147     WorkQueue::shared()->queue(new BackItem(howFarBack));
1148 }
1149
1150 void LayoutTestController::queueForwardNavigation(int howFarForward)
1151 {
1152     WorkQueue::shared()->queue(new ForwardItem(howFarForward));
1153 }
1154
1155 void LayoutTestController::queueLoadingScript(JSStringRef script)
1156 {
1157     WorkQueue::shared()->queue(new LoadingScriptItem(script));
1158 }
1159
1160 void LayoutTestController::queueNonLoadingScript(JSStringRef script)
1161 {
1162     WorkQueue::shared()->queue(new NonLoadingScriptItem(script));
1163 }
1164
1165 void LayoutTestController::queueReload()
1166 {
1167     WorkQueue::shared()->queue(new ReloadItem);
1168 }
1169
1170 void LayoutTestController::grantDesktopNotificationPermission(JSStringRef origin)
1171 {
1172     m_desktopNotificationAllowedOrigins.push_back(JSStringRetain(origin));
1173 }
1174
1175 bool LayoutTestController::checkDesktopNotificationPermission(JSStringRef origin)
1176 {
1177     std::vector<JSStringRef>::iterator i;
1178     for (i = m_desktopNotificationAllowedOrigins.begin();
1179          i != m_desktopNotificationAllowedOrigins.end();
1180          ++i) {
1181         if (JSStringIsEqual(*i, origin))
1182             return true;
1183     }
1184     return false;
1185 }
1186
1187 void LayoutTestController::waitToDumpWatchdogTimerFired()
1188 {
1189     const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
1190     fprintf(stderr, "%s", message);
1191     fprintf(stdout, "%s", message);
1192     notifyDone();
1193 }
1194
1195 void LayoutTestController::setGeolocationPermission(bool allow)
1196 {
1197     m_isGeolocationPermissionSet = true;
1198     m_geolocationPermission = allow;
1199 }