8a2b6841c1f657eccdbfda83b9217b81a9be5c42
[WebKit-https.git] / WebKitTools / DumpRenderTree / LayoutTestController.cpp
1 /*
2  * Copyright (C) 2007 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 "DumpRenderTree.h"
30 #include "LayoutTestController.h"
31
32 #include <JavaScriptCore/JSObjectRef.h>
33 #include <JavaScriptCore/JSRetainPtr.h>
34 #include <wtf/Assertions.h>
35 #include <wtf/MathExtras.h>
36
37 LayoutTestController::LayoutTestController(bool testRepaintDefault, bool testRepaintSweepHorizontallyDefault)
38     : m_dumpAsText(false)
39     , m_dumpAsPDF(false)
40     , m_dumpBackForwardList(false)
41     , m_dumpChildFrameScrollPositions(false)
42     , m_dumpChildFramesAsText(false)
43     , m_dumpDatabaseCallbacks(false)
44     , m_dumpDOMAsWebArchive(false)
45     , m_dumpSelectionRect(false)
46     , m_dumpSourceAsWebArchive(false)
47     , m_dumpStatusCallbacks(false)
48     , m_dumpTitleChanges(false)
49     , m_dumpEditingCallbacks(false)
50     , m_dumpResourceLoadCallbacks(false)
51     , m_dumpFrameLoadCallbacks(false)
52     , m_addFileToPasteboardOnDrag(false)
53     , m_callCloseOnWebViews(true)
54     , m_canOpenWindows(false)
55     , m_closeRemainingWindowsWhenComplete(true)
56     , m_stopProvisionalFrameLoads(false)
57     , m_testRepaint(testRepaintDefault)
58     , m_testRepaintSweepHorizontally(testRepaintSweepHorizontallyDefault)
59     , m_waitToDump(false)
60     , m_windowIsKey(true)
61     , m_globalFlag(false)
62 {
63 }
64
65 // Static Functions
66
67 static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
68 {
69     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
70     controller->setDumpAsText(true);
71     return JSValueMakeUndefined(context);
72 }
73
74 static JSValueRef dumpAsPDFCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
75 {
76     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
77     controller->setDumpAsPDF(true);
78     return JSValueMakeUndefined(context);
79 }
80
81 static JSValueRef dumpBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
82 {
83     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
84     controller->setDumpBackForwardList(true);
85     return JSValueMakeUndefined(context);
86 }
87
88 static JSValueRef dumpChildFramesAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
89 {
90     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
91     controller->setDumpChildFramesAsText(true);
92     return JSValueMakeUndefined(context);
93 }
94
95 static JSValueRef dumpChildFrameScrollPositionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
96 {
97     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
98     controller->setDumpChildFrameScrollPositions(true);
99     return JSValueMakeUndefined(context);
100 }
101
102 static JSValueRef dumpDatabaseCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
103 {
104     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
105     controller->setDumpDatabaseCallbacks(true);
106     return JSValueMakeUndefined(context);
107 }
108
109 static JSValueRef dumpDOMAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
110 {
111     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
112     controller->setDumpDOMAsWebArchive(true);
113     return JSValueMakeUndefined(context);
114 }
115
116 static JSValueRef dumpEditingCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
117 {
118     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
119     controller->setDumpEditingCallbacks(true);
120     return JSValueMakeUndefined(context);
121 }
122
123 static JSValueRef dumpResourceLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
124 {
125     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
126     controller->setDumpResourceLoadCallbacks(true);
127     return JSValueMakeUndefined(context);
128 }
129
130 static JSValueRef dumpSelectionRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
131 {
132     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
133     controller->setDumpSelectionRect(true);
134     return JSValueMakeUndefined(context);
135 }
136
137 static JSValueRef dumpSourceAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
138 {
139     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
140     controller->setDumpSourceAsWebArchive(true);
141     return JSValueMakeUndefined(context);
142 }
143
144 static JSValueRef dumpStatusCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
145 {
146     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
147     controller->setDumpStatusCallbacks(true);
148     return JSValueMakeUndefined(context);
149 }
150
151 static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
152 {
153     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
154     controller->setDumpTitleChanges(true);
155     return JSValueMakeUndefined(context);
156 }
157
158 static JSValueRef pathToLocalResourceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
159 {
160     if (argumentCount < 1)
161         return JSValueMakeUndefined(context);
162
163     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
164     JSRetainPtr<JSStringRef> localPath(Adopt, JSValueToStringCopy(context, arguments[0], exception));
165     ASSERT(!*exception);
166
167     JSRetainPtr<JSStringRef> convertedPath(Adopt, controller->pathToLocalResource(context, localPath.get()));
168     if (!convertedPath)
169         return JSValueMakeUndefined(context);
170
171     return JSValueMakeString(context, convertedPath.get());
172 }
173
174 static JSValueRef repaintSweepHorizontallyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
175 {
176     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
177     controller->setTestRepaintSweepHorizontally(true);
178     return JSValueMakeUndefined(context);
179 }
180
181 static JSValueRef setCallCloseOnWebViewsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
182 {
183     if (argumentCount < 1)
184         return JSValueMakeUndefined(context);
185
186     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
187     controller->setCallCloseOnWebViews(JSValueToBoolean(context, arguments[0]));
188     return JSValueMakeUndefined(context);
189 }
190
191 static JSValueRef setCanOpenWindowsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
192 {
193     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
194     controller->setCanOpenWindows(true);
195     return JSValueMakeUndefined(context);
196 }
197
198 static JSValueRef setCloseRemainingWindowsWhenCompleteCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
199 {
200     if (argumentCount < 1)
201         return JSValueMakeUndefined(context);
202
203     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
204     controller->setCloseRemainingWindowsWhenComplete(JSValueToBoolean(context, arguments[0]));
205     return JSValueMakeUndefined(context);
206 }
207
208 static JSValueRef testRepaintCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
209 {
210     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
211     controller->setTestRepaint(true);
212     return JSValueMakeUndefined(context);
213 }
214
215 static JSValueRef addFileToPasteboardOnDragCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
216 {
217     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
218     controller->setAddFileToPasteboardOnDrag(true);
219     return JSValueMakeUndefined(context);
220 }
221
222 static JSValueRef addDisallowedURLCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
223 {
224     // Has mac implementation
225     if (argumentCount < 1)
226         return JSValueMakeUndefined(context);
227
228     JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
229     ASSERT(!*exception);
230
231     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
232     controller->addDisallowedURL(url.get());
233
234     return JSValueMakeUndefined(context);
235 }
236
237 static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
238 {
239     // Has mac & windows implementation
240     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
241     controller->clearAllDatabases();
242
243     return JSValueMakeUndefined(context);
244 }
245
246 static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
247 {
248     // Has mac & windows implementation
249     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
250     controller->clearBackForwardList();
251
252     return JSValueMakeUndefined(context);
253 }
254
255 static JSValueRef clearPersistentUserStyleSheetCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
256 {
257     // Has mac & windows implementation
258     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
259     controller->clearPersistentUserStyleSheet();
260
261     return JSValueMakeUndefined(context);
262 }
263
264 static JSValueRef decodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
265 {
266     // Has mac implementation
267     if (argumentCount < 1)
268         return JSValueMakeUndefined(context);
269
270     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
271     ASSERT(!*exception);
272
273     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
274     JSRetainPtr<JSStringRef> decodedHostName(Adopt, controller->copyDecodedHostName(name.get()));
275     return JSValueMakeString(context, decodedHostName.get());
276 }
277
278 static JSValueRef displayCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
279 {
280     // Has mac & windows implementation
281     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
282     controller->display();
283
284     return JSValueMakeUndefined(context);
285 }
286
287 static JSValueRef encodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
288 {
289     // Has mac implementation
290     if (argumentCount < 1)
291         return JSValueMakeUndefined(context);
292
293     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
294     ASSERT(!*exception);
295
296     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
297     JSRetainPtr<JSStringRef> encodedHostName(Adopt, controller->copyEncodedHostName(name.get()));
298     return JSValueMakeString(context, encodedHostName.get());
299 }
300
301 static JSValueRef execCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
302 {
303     // Has Mac & Windows implementations.
304     if (argumentCount < 1)
305         return JSValueMakeUndefined(context);
306
307     JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception));
308     ASSERT(!*exception);
309
310     // Ignoring the second parameter (userInterface), as this command emulates a manual action.
311
312     JSRetainPtr<JSStringRef> value;
313     if (argumentCount >= 3) {
314         value.adopt(JSValueToStringCopy(context, arguments[2], exception));
315         ASSERT(!*exception);
316     } else
317         value.adopt(JSStringCreateWithUTF8CString(""));
318
319
320     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
321     controller->execCommand(name.get(), value.get());
322
323     return JSValueMakeUndefined(context);
324 }
325
326 static JSValueRef keepWebHistoryCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
327 {
328     // Has mac implementation
329     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
330     controller->keepWebHistory();
331
332     return JSValueMakeUndefined(context);
333 }
334
335 static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
336 {
337     // Has mac & windows implementation
338     // May be able to be made platform independant by using shared WorkQueue
339     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
340     controller->notifyDone();
341
342     return JSValueMakeUndefined(context);
343 }
344
345 static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
346 {
347     // Has mac & windows implementation
348     // May be able to be made platform independant by using shared WorkQueue
349     if (argumentCount < 1)
350         return JSValueMakeUndefined(context);
351
352     double howFarBackDouble = JSValueToNumber(context, arguments[0], exception);
353     ASSERT(!*exception);
354
355     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
356     controller->queueBackNavigation(static_cast<int>(howFarBackDouble));
357
358     return JSValueMakeUndefined(context);
359 }
360
361 static JSValueRef queueForwardNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
362 {
363     // Has mac & windows implementation
364     // May be able to be made platform independant by using shared WorkQueue
365     if (argumentCount < 1)
366         return JSValueMakeUndefined(context);
367
368     double howFarForwardDouble = JSValueToNumber(context, arguments[0], exception);
369     ASSERT(!*exception);
370
371     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
372     controller->queueForwardNavigation(static_cast<int>(howFarForwardDouble));
373
374     return JSValueMakeUndefined(context);
375 }
376
377 static JSValueRef queueLoadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
378 {
379     // Has mac & windows implementation
380     // May be able to be made platform independant by using shared WorkQueue
381     if (argumentCount < 1)
382         return JSValueMakeUndefined(context);
383
384     JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
385     ASSERT(!*exception);
386
387     JSRetainPtr<JSStringRef> target;
388     if (argumentCount >= 2) {
389         target.adopt(JSValueToStringCopy(context, arguments[1], exception));
390         ASSERT(!*exception);
391     } else
392         target.adopt(JSStringCreateWithUTF8CString(""));
393
394     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
395     controller->queueLoad(url.get(), target.get());
396
397     return JSValueMakeUndefined(context);
398 }
399
400 static JSValueRef queueReloadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
401 {
402     // Has mac & windows implementation
403     // May be able to be made platform independant by using shared WorkQueue
404
405     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
406     controller->queueReload();
407
408     return JSValueMakeUndefined(context);
409 }
410
411 static JSValueRef queueScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
412 {
413     // Has mac & windows implementation
414     // May be able to be made platform independant by using shared WorkQueue
415     if (argumentCount < 1)
416         return JSValueMakeUndefined(context);
417
418     JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
419     ASSERT(!*exception);
420
421     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
422     controller->queueScript(script.get());
423
424     return JSValueMakeUndefined(context);
425 }
426
427 static JSValueRef setAcceptsEditingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
428 {
429     // Has mac & windows implementation
430     if (argumentCount < 1)
431         return JSValueMakeUndefined(context);
432
433     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
434     controller->setAcceptsEditing(JSValueToBoolean(context, arguments[0]));
435
436     return JSValueMakeUndefined(context);
437 }
438
439 static JSValueRef setAuthorAndUserStylesEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
440 {
441     // Has mac & windows implementation
442     if (argumentCount < 1)
443         return JSValueMakeUndefined(context);
444
445     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
446     controller->setAuthorAndUserStylesEnabled(JSValueToBoolean(context, arguments[0]));
447
448     return JSValueMakeUndefined(context);
449 }
450
451 static JSValueRef setCustomPolicyDelegateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
452 {
453     // Has mac implementation
454     if (argumentCount < 1)
455         return JSValueMakeUndefined(context);
456
457     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
458     controller->setCustomPolicyDelegate(JSValueToBoolean(context, arguments[0]));
459
460     return JSValueMakeUndefined(context);
461 }
462
463 static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
464 {
465     // Has mac implementation
466     if (argumentCount < 1)
467         return JSValueMakeUndefined(context);
468
469     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
470
471     double quota = JSValueToNumber(context, arguments[0], NULL);
472     if (!isnan(quota))
473         controller->setDatabaseQuota(static_cast<unsigned long long>(quota));
474         
475     return JSValueMakeUndefined(context);
476
477 }
478
479 static JSValueRef setMainFrameIsFirstResponderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
480 {
481     // Has mac implementation
482     if (argumentCount < 1)
483         return JSValueMakeUndefined(context);
484
485     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
486     controller->setMainFrameIsFirstResponder(JSValueToBoolean(context, arguments[0]));
487
488     return JSValueMakeUndefined(context);
489 }
490
491 static JSValueRef setPersistentUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
492 {
493     // Has mac implementation
494     if (argumentCount < 1)
495         return JSValueMakeUndefined(context);
496
497     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
498     ASSERT(!*exception);
499
500     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
501     controller->setPersistentUserStyleSheetLocation(path.get());
502
503     return JSValueMakeUndefined(context);
504 }
505
506 static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
507 {
508     // Has mac & windows implementation
509     if (argumentCount < 1)
510         return JSValueMakeUndefined(context);
511
512     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
513     controller->setPrivateBrowsingEnabled(JSValueToBoolean(context, arguments[0]));
514
515     return JSValueMakeUndefined(context);
516 }
517
518 static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
519 {
520     // Has mac & windows implementation
521     if (argumentCount < 1)
522         return JSValueMakeUndefined(context);
523
524     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
525     controller->setTabKeyCyclesThroughElements(JSValueToBoolean(context, arguments[0]));
526
527     return JSValueMakeUndefined(context);
528 }
529
530 static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
531 {
532     // Has mac implementation
533     if (argumentCount < 1)
534         return JSValueMakeUndefined(context);
535
536     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
537     controller->setUseDashboardCompatibilityMode(JSValueToBoolean(context, arguments[0]));
538
539     return JSValueMakeUndefined(context);
540 }
541
542 static JSValueRef setUserStyleSheetEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
543 {
544     // Has mac implementation
545     if (argumentCount < 1)
546         return JSValueMakeUndefined(context);
547
548     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
549     controller->setUserStyleSheetEnabled(JSValueToBoolean(context, arguments[0]));
550
551     return JSValueMakeUndefined(context);
552 }
553
554 static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
555 {
556     // Has mac implementation
557     if (argumentCount < 1)
558         return JSValueMakeUndefined(context);
559
560     JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception));
561     ASSERT(!*exception);
562
563     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
564     controller->setUserStyleSheetLocation(path.get());
565
566     return JSValueMakeUndefined(context);
567 }
568
569 static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
570 {
571     // Has mac implementation
572     if (argumentCount < 1)
573         return JSValueMakeUndefined(context);
574
575     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
576     controller->setWindowIsKey(JSValueToBoolean(context, arguments[0]));
577
578     return JSValueMakeUndefined(context);
579 }
580
581 static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
582 {
583     // Has mac & windows implementation
584     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
585     controller->setWaitToDump(true);
586
587     return JSValueMakeUndefined(context);
588 }
589
590 static JSValueRef windowCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
591 {
592     // Has mac implementation
593     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
594     int windows = controller->windowCount();
595     return JSValueMakeNumber(context, windows);
596 }
597
598 static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
599 {
600     // Has mac & windows implementation
601     if (argumentCount < 1)
602         return JSValueMakeUndefined(context);
603
604     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
605     controller->setPopupBlockingEnabled(JSValueToBoolean(context, arguments[0]));
606
607     return JSValueMakeUndefined(context);
608 }
609
610 static JSValueRef setStopProvisionalFrameLoadsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
611 {
612     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
613     controller->setStopProvisionalFrameLoads(true);
614     return JSValueMakeUndefined(context);
615 }
616
617 static JSValueRef elementDoesAutoCompleteForElementWithIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
618 {
619     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
620     JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[0], exception));
621     ASSERT(!*exception);
622
623     bool autoCompletes = controller->elementDoesAutoCompleteForElementWithId(elementId.get());
624
625     return JSValueMakeBoolean(context, autoCompletes);
626 }
627
628 // Static Values
629
630 static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
631 {
632     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
633     return JSValueMakeBoolean(context, controller->globalFlag());
634 }
635
636 static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
637 {
638     LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
639     controller->setGlobalFlag(JSValueToBoolean(context, value));
640     return true;
641 }
642
643 // Object Creation
644
645 void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
646 {
647     JSRetainPtr<JSStringRef> layoutTestContollerStr(Adopt, JSStringCreateWithUTF8CString("layoutTestController"));
648     JSValueRef layoutTestContollerObject = JSObjectMake(context, getJSClass(), this);
649     JSObjectSetProperty(context, windowObject, layoutTestContollerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
650 }
651
652 JSClassRef LayoutTestController::getJSClass()
653 {
654     static JSClassRef layoutTestControllerClass;
655
656     if (!layoutTestControllerClass) {
657         JSStaticValue* staticValues = LayoutTestController::staticValues();
658         JSStaticFunction* staticFunctions = LayoutTestController::staticFunctions();
659         JSClassDefinition classDefinition = {
660             0, kJSClassAttributeNone, "LayoutTestController", 0, staticValues, staticFunctions,
661             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
662         };
663
664         layoutTestControllerClass = JSClassCreate(&classDefinition);
665     }
666
667     return layoutTestControllerClass;
668 }
669
670 JSStaticValue* LayoutTestController::staticValues()
671 {
672     static JSStaticValue staticValues[] = {
673         { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone },
674         { 0, 0, 0, 0 }
675     };
676     return staticValues;
677
678 }
679
680 JSStaticFunction* LayoutTestController::staticFunctions()
681 {
682     static JSStaticFunction staticFunctions[] = {
683         { "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
684         { "addFileToPasteboardOnDrag", addFileToPasteboardOnDragCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
685         { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
686         { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
687         { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
688         { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
689         { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
690         { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
691         { "printToPDF", dumpAsPDFCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
692         { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
693         { "dumpChildFramesAsText", dumpChildFramesAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
694         { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
695         { "dumpDatabaseCallbacks", dumpDatabaseCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
696         { "dumpDOMAsWebArchive", dumpDOMAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
697         { "dumpEditingCallbacks", dumpEditingCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
698         { "dumpResourceLoadCallbacks", dumpResourceLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
699         { "dumpSelectionRect", dumpSelectionRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
700         { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
701         { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
702         { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
703         { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
704         { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
705         { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
706         { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
707         { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
708         { "queueBackNavigation", queueBackNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
709         { "queueForwardNavigation", queueForwardNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
710         { "queueLoad", queueLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
711         { "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
712         { "queueScript", queueScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
713         { "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
714         { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
715         { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
716         { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
717         { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
718         { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
719         { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
720         { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
721         { "setMainFrameIsFirstResponder", setMainFrameIsFirstResponderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
722         { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
723         { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
724         { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
725         { "setStopProvisionalFrameLoads", setStopProvisionalFrameLoadsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
726         { "setTabKeyCyclesThroughElements", setTabKeyCyclesThroughElementsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
727         { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
728         { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
729         { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
730         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
731         { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
732         { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
733         { "windowCount", windowCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
734         { "elementDoesAutoCompleteForElementWithId", elementDoesAutoCompleteForElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
735         { 0, 0, 0 }
736     };
737
738     return staticFunctions;
739 }
740
741