834d2e8c923aaebae84be9f41c2dcefe721b5978
[WebKit-https.git] / Tools / DumpRenderTree / chromium / LayoutTestController.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2010 Pawel Hajdan (phajdan.jr@chromium.org)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "LayoutTestController.h"
34
35 #include "DRTDevToolsAgent.h"
36 #include "TestShell.h"
37 #include "WebAnimationController.h"
38 #include "WebBindings.h"
39 #include "WebConsoleMessage.h"
40 #include "WebData.h"
41 #include "WebDeviceOrientation.h"
42 #include "WebDeviceOrientationClientMock.h"
43 #include "WebDocument.h"
44 #include "WebElement.h"
45 #include "WebFrame.h"
46 #include "WebGeolocationClientMock.h"
47 #include "WebIDBFactory.h"
48 #include "WebInputElement.h"
49 #include "WebKit.h"
50 #include "WebNotificationPresenter.h"
51 #include "WebPermissions.h"
52 #include "WebScriptSource.h"
53 #include "WebSecurityPolicy.h"
54 #include "WebSettings.h"
55 #include "WebSize.h"
56 #include "WebSpeechInputControllerMock.h"
57 #include "WebURL.h"
58 #include "WebView.h"
59 #include "WebViewHost.h"
60 #include "webkit/support/webkit_support.h"
61 #include <algorithm>
62 #include <cstdlib>
63 #include <limits>
64 #include <wtf/text/WTFString.h>
65
66 #if OS(WINDOWS)
67 #include <wtf/OwnArrayPtr.h>
68 #endif
69
70 using namespace WebCore;
71 using namespace WebKit;
72 using namespace std;
73
74 LayoutTestController::LayoutTestController(TestShell* shell)
75     : m_shell(shell)
76     , m_closeRemainingWindows(false)
77     , m_deferMainResourceDataLoad(false)
78     , m_showDebugLayerTree(false)
79     , m_workQueue(this)
80     , m_shouldStayOnPageAfterHandlingBeforeUnload(false)
81 {
82
83     // Initialize the map that associates methods of this class with the names
84     // they will use when called by JavaScript. The actual binding of those
85     // names to their methods will be done by calling bindToJavaScript() (defined
86     // by CppBoundClass, the parent to LayoutTestController).
87     bindMethod("addFileToPasteboardOnDrag", &LayoutTestController::addFileToPasteboardOnDrag);
88     bindMethod("addMockSpeechInputResult", &LayoutTestController::addMockSpeechInputResult);
89     bindMethod("addOriginAccessWhitelistEntry", &LayoutTestController::addOriginAccessWhitelistEntry);
90     bindMethod("addUserScript", &LayoutTestController::addUserScript);
91     bindMethod("addUserStyleSheet", &LayoutTestController::addUserStyleSheet);
92     bindMethod("clearAllDatabases", &LayoutTestController::clearAllDatabases);
93     bindMethod("closeWebInspector", &LayoutTestController::closeWebInspector);
94     bindMethod("counterValueForElementById", &LayoutTestController::counterValueForElementById);
95     bindMethod("disableImageLoading", &LayoutTestController::disableImageLoading);
96     bindMethod("display", &LayoutTestController::display);
97     bindMethod("displayInvalidatedRegion", &LayoutTestController::displayInvalidatedRegion);
98     bindMethod("dumpAsText", &LayoutTestController::dumpAsText);
99     bindMethod("dumpBackForwardList", &LayoutTestController::dumpBackForwardList);
100     bindMethod("dumpChildFramesAsText", &LayoutTestController::dumpChildFramesAsText);
101     bindMethod("dumpChildFrameScrollPositions", &LayoutTestController::dumpChildFrameScrollPositions);
102     bindMethod("dumpDatabaseCallbacks", &LayoutTestController::dumpDatabaseCallbacks);
103     bindMethod("dumpEditingCallbacks", &LayoutTestController::dumpEditingCallbacks);
104     bindMethod("dumpFrameLoadCallbacks", &LayoutTestController::dumpFrameLoadCallbacks);
105     bindMethod("dumpProgressFinishedCallback", &LayoutTestController::dumpProgressFinishedCallback);
106     bindMethod("dumpUserGestureInFrameLoadCallbacks", &LayoutTestController::dumpUserGestureInFrameLoadCallbacks);
107     bindMethod("dumpResourceLoadCallbacks", &LayoutTestController::dumpResourceLoadCallbacks);
108     bindMethod("dumpResourceResponseMIMETypes", &LayoutTestController::dumpResourceResponseMIMETypes);
109     bindMethod("dumpSelectionRect", &LayoutTestController::dumpSelectionRect);
110     bindMethod("dumpStatusCallbacks", &LayoutTestController::dumpWindowStatusChanges);
111     bindMethod("dumpTitleChanges", &LayoutTestController::dumpTitleChanges);
112     bindMethod("elementDoesAutoCompleteForElementWithId", &LayoutTestController::elementDoesAutoCompleteForElementWithId);
113     bindMethod("evaluateInWebInspector", &LayoutTestController::evaluateInWebInspector);
114     bindMethod("evaluateScriptInIsolatedWorld", &LayoutTestController::evaluateScriptInIsolatedWorld);
115     bindMethod("setIsolatedWorldSecurityOrigin", &LayoutTestController::setIsolatedWorldSecurityOrigin);
116     bindMethod("execCommand", &LayoutTestController::execCommand);
117     bindMethod("forceRedSelectionColors", &LayoutTestController::forceRedSelectionColors);
118     bindMethod("grantDesktopNotificationPermission", &LayoutTestController::grantDesktopNotificationPermission);
119     bindMethod("hasSpellingMarker", &LayoutTestController::hasSpellingMarker);
120     bindMethod("isCommandEnabled", &LayoutTestController::isCommandEnabled);
121     bindMethod("layerTreeAsText", &LayoutTestController::layerTreeAsText);
122     bindMethod("loseCompositorContext", &LayoutTestController::loseCompositorContext);
123     bindMethod("markerTextForListItem", &LayoutTestController::markerTextForListItem);
124     bindMethod("notifyDone", &LayoutTestController::notifyDone);
125     bindMethod("numberOfActiveAnimations", &LayoutTestController::numberOfActiveAnimations);
126     bindMethod("numberOfPages", &LayoutTestController::numberOfPages);
127     bindMethod("numberOfPendingGeolocationPermissionRequests", &LayoutTestController:: numberOfPendingGeolocationPermissionRequests);
128     bindMethod("objCIdentityIsEqual", &LayoutTestController::objCIdentityIsEqual);
129     bindMethod("overridePreference", &LayoutTestController::overridePreference);
130     bindMethod("pageNumberForElementById", &LayoutTestController::pageNumberForElementById);
131     bindMethod("pathToLocalResource", &LayoutTestController::pathToLocalResource);
132     bindMethod("pauseAnimationAtTimeOnElementWithId", &LayoutTestController::pauseAnimationAtTimeOnElementWithId);
133     bindMethod("pauseTransitionAtTimeOnElementWithId", &LayoutTestController::pauseTransitionAtTimeOnElementWithId);
134     bindMethod("queueBackNavigation", &LayoutTestController::queueBackNavigation);
135     bindMethod("queueForwardNavigation", &LayoutTestController::queueForwardNavigation);
136     bindMethod("queueLoadingScript", &LayoutTestController::queueLoadingScript);
137     bindMethod("queueLoad", &LayoutTestController::queueLoad);
138     bindMethod("queueLoadHTMLString", &LayoutTestController::queueLoadHTMLString);
139     bindMethod("queueNonLoadingScript", &LayoutTestController::queueNonLoadingScript);
140     bindMethod("queueReload", &LayoutTestController::queueReload);
141     bindMethod("removeOriginAccessWhitelistEntry", &LayoutTestController::removeOriginAccessWhitelistEntry);
142     bindMethod("repaintSweepHorizontally", &LayoutTestController::repaintSweepHorizontally);
143     bindMethod("resetPageVisibility", &LayoutTestController::resetPageVisibility);
144     bindMethod("resumeAnimations", &LayoutTestController::resumeAnimations);
145     bindMethod("sampleSVGAnimationForElementAtTime", &LayoutTestController::sampleSVGAnimationForElementAtTime);
146     bindMethod("setAcceptsEditing", &LayoutTestController::setAcceptsEditing);
147     bindMethod("setAllowDisplayOfInsecureContent", &LayoutTestController::setAllowDisplayOfInsecureContent);
148     bindMethod("setAllowFileAccessFromFileURLs", &LayoutTestController::setAllowFileAccessFromFileURLs);
149     bindMethod("setAllowRunningOfInsecureContent", &LayoutTestController::setAllowRunningOfInsecureContent);
150     bindMethod("setAllowUniversalAccessFromFileURLs", &LayoutTestController::setAllowUniversalAccessFromFileURLs);
151     bindMethod("setAlwaysAcceptCookies", &LayoutTestController::setAlwaysAcceptCookies);
152     bindMethod("setAuthorAndUserStylesEnabled", &LayoutTestController::setAuthorAndUserStylesEnabled);
153     bindMethod("setAutofilled", &LayoutTestController::setAutofilled);
154     bindMethod("setCanOpenWindows", &LayoutTestController::setCanOpenWindows);
155     bindMethod("setCloseRemainingWindowsWhenComplete", &LayoutTestController::setCloseRemainingWindowsWhenComplete);
156     bindMethod("setCustomPolicyDelegate", &LayoutTestController::setCustomPolicyDelegate);
157     bindMethod("setDatabaseQuota", &LayoutTestController::setDatabaseQuota);
158     bindMethod("setDeferMainResourceDataLoad", &LayoutTestController::setDeferMainResourceDataLoad);
159     bindMethod("setDomainRelaxationForbiddenForURLScheme", &LayoutTestController::setDomainRelaxationForbiddenForURLScheme);
160     bindMethod("setEditingBehavior", &LayoutTestController::setEditingBehavior);
161     bindMethod("setAudioData", &LayoutTestController::setAudioData);
162     bindMethod("setGeolocationPermission", &LayoutTestController::setGeolocationPermission);
163     bindMethod("setIconDatabaseEnabled", &LayoutTestController::setIconDatabaseEnabled);
164     bindMethod("setJavaScriptCanAccessClipboard", &LayoutTestController::setJavaScriptCanAccessClipboard);
165     bindMethod("setJavaScriptProfilingEnabled", &LayoutTestController::setJavaScriptProfilingEnabled);
166     bindMethod("setMinimumTimerInterval", &LayoutTestController::setMinimumTimerInterval);
167     bindMethod("setMockDeviceOrientation", &LayoutTestController::setMockDeviceOrientation);
168     bindMethod("setMockGeolocationError", &LayoutTestController::setMockGeolocationError);
169     bindMethod("setMockGeolocationPosition", &LayoutTestController::setMockGeolocationPosition);
170     bindMethod("setOverrideIndexedDBBackingStore", &LayoutTestController::setOverrideIndexedDBBackingStore);
171     bindMethod("setPageVisibility", &LayoutTestController::setPageVisibility);
172     bindMethod("setPluginsEnabled", &LayoutTestController::setPluginsEnabled);
173     bindMethod("setPopupBlockingEnabled", &LayoutTestController::setPopupBlockingEnabled);
174     bindMethod("setPOSIXLocale", &LayoutTestController::setPOSIXLocale);
175     bindMethod("setScrollbarPolicy", &LayoutTestController::setScrollbarPolicy);
176     bindMethod("setSelectTrailingWhitespaceEnabled", &LayoutTestController::setSelectTrailingWhitespaceEnabled);
177     bindMethod("setSmartInsertDeleteEnabled", &LayoutTestController::setSmartInsertDeleteEnabled);
178     bindMethod("setStopProvisionalFrameLoads", &LayoutTestController::setStopProvisionalFrameLoads);
179     bindMethod("setTabKeyCyclesThroughElements", &LayoutTestController::setTabKeyCyclesThroughElements);
180     bindMethod("setUserStyleSheetEnabled", &LayoutTestController::setUserStyleSheetEnabled);
181     bindMethod("setUserStyleSheetLocation", &LayoutTestController::setUserStyleSheetLocation);
182     bindMethod("setValueForUser", &LayoutTestController::setValueForUser);
183     bindMethod("setWillSendRequestClearHeader", &LayoutTestController::setWillSendRequestClearHeader);
184     bindMethod("setWillSendRequestReturnsNull", &LayoutTestController::setWillSendRequestReturnsNull);
185     bindMethod("setWillSendRequestReturnsNullOnRedirect", &LayoutTestController::setWillSendRequestReturnsNullOnRedirect);
186     bindMethod("setWindowIsKey", &LayoutTestController::setWindowIsKey);
187     bindMethod("setXSSAuditorEnabled", &LayoutTestController::setXSSAuditorEnabled);
188     bindMethod("setAsynchronousSpellCheckingEnabled", &LayoutTestController::setAsynchronousSpellCheckingEnabled);
189     bindMethod("showWebInspector", &LayoutTestController::showWebInspector);
190     bindMethod("simulateDesktopNotificationClick", &LayoutTestController::simulateDesktopNotificationClick);
191     bindMethod("startSpeechInput", &LayoutTestController::startSpeechInput);
192     bindMethod("suspendAnimations", &LayoutTestController::suspendAnimations);
193     bindMethod("testRepaint", &LayoutTestController::testRepaint);
194     bindMethod("waitForPolicyDelegate", &LayoutTestController::waitForPolicyDelegate);
195     bindMethod("waitUntilDone", &LayoutTestController::waitUntilDone);
196     bindMethod("windowCount", &LayoutTestController::windowCount);
197     bindMethod("setTextDirection", &LayoutTestController::setTextDirection);
198     bindMethod("setImagesAllowed", &LayoutTestController::setImagesAllowed);
199     bindMethod("setStorageAllowed", &LayoutTestController::setStorageAllowed);
200     bindMethod("setPluginsAllowed", &LayoutTestController::setPluginsAllowed);
201
202     // The following are stubs.
203     bindMethod("abortModal", &LayoutTestController::abortModal);
204     bindMethod("accessStoredWebScriptObject", &LayoutTestController::accessStoredWebScriptObject);
205     bindMethod("addDisallowedURL", &LayoutTestController::addDisallowedURL);
206     bindMethod("applicationCacheDiskUsageForOrigin", &LayoutTestController::applicationCacheDiskUsageForOrigin);
207     bindMethod("callShouldCloseOnWebView", &LayoutTestController::callShouldCloseOnWebView);
208     bindMethod("clearAllApplicationCaches", &LayoutTestController::clearAllApplicationCaches);
209     bindMethod("clearApplicationCacheForOrigin", &LayoutTestController::clearApplicationCacheForOrigin);
210     bindMethod("clearBackForwardList", &LayoutTestController::clearBackForwardList);
211     bindMethod("dumpAsWebArchive", &LayoutTestController::dumpAsWebArchive);
212     bindMethod("keepWebHistory", &LayoutTestController::keepWebHistory);
213     bindMethod("objCClassNameOf", &LayoutTestController::objCClassNameOf);
214     bindMethod("setApplicationCacheOriginQuota", &LayoutTestController::setApplicationCacheOriginQuota);
215     bindMethod("setCallCloseOnWebViews", &LayoutTestController::setCallCloseOnWebViews);
216     bindMethod("setMainFrameIsFirstResponder", &LayoutTestController::setMainFrameIsFirstResponder);
217     bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled);
218     bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode);
219     bindMethod("storeWebScriptObject", &LayoutTestController::storeWebScriptObject);
220     bindMethod("deleteAllLocalStorage", &LayoutTestController::deleteAllLocalStorage);
221     bindMethod("localStorageDiskUsageForOrigin", &LayoutTestController::localStorageDiskUsageForOrigin);
222     bindMethod("originsWithLocalStorage", &LayoutTestController::originsWithLocalStorage);
223     bindMethod("deleteLocalStorageForOrigin", &LayoutTestController::deleteLocalStorageForOrigin);
224     bindMethod("observeStorageTrackerNotifications", &LayoutTestController::observeStorageTrackerNotifications);
225     bindMethod("syncLocalStorage", &LayoutTestController::syncLocalStorage);
226     bindMethod("setShouldStayOnPageAfterHandlingBeforeUnload", &LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload);
227     bindMethod("enableFixedLayoutMode", &LayoutTestController::enableFixedLayoutMode);
228     bindMethod("setFixedLayoutSize", &LayoutTestController::setFixedLayoutSize);
229     
230     // The fallback method is called when an unknown method is invoked.
231     bindFallbackMethod(&LayoutTestController::fallbackMethod);
232
233     // Shared properties.
234     // globalFlag is used by a number of layout tests in
235     // LayoutTests\http\tests\security\dataURL.
236     bindProperty("globalFlag", &m_globalFlag);
237     // webHistoryItemCount is used by tests in LayoutTests\http\tests\history
238     bindProperty("webHistoryItemCount", &m_webHistoryItemCount);
239     bindProperty("titleTextDirection", &m_titleTextDirection);
240 }
241
242 LayoutTestController::~LayoutTestController()
243 {
244 }
245
246 LayoutTestController::WorkQueue::~WorkQueue()
247 {
248     reset();
249 }
250
251 void LayoutTestController::WorkQueue::processWorkSoon()
252 {
253     if (m_controller->m_shell->webViewHost()->topLoadingFrame())
254         return;
255
256     if (!m_queue.isEmpty()) {
257         // We delay processing queued work to avoid recursion problems.
258         postTask(new WorkQueueTask(this));
259     } else if (!m_controller->m_waitUntilDone)
260         m_controller->m_shell->testFinished();
261 }
262
263 void LayoutTestController::WorkQueue::processWork()
264 {
265     TestShell* shell = m_controller->m_shell;
266     // Quit doing work once a load is in progress.
267     while (!m_queue.isEmpty()) {
268         bool startedLoad = m_queue.first()->run(shell);
269         delete m_queue.takeFirst();
270         if (startedLoad)
271             return;
272     }
273
274     if (!m_controller->m_waitUntilDone && !shell->webViewHost()->topLoadingFrame())
275         shell->testFinished();
276 }
277
278 void LayoutTestController::WorkQueue::reset()
279 {
280     m_frozen = false;
281     while (!m_queue.isEmpty())
282         delete m_queue.takeFirst();
283 }
284
285 void LayoutTestController::WorkQueue::addWork(WorkItem* work)
286 {
287     if (m_frozen) {
288         delete work;
289         return;
290     }
291     m_queue.append(work);
292 }
293
294 void LayoutTestController::dumpAsText(const CppArgumentList& arguments, CppVariant* result)
295 {
296     m_dumpAsText = true;
297     m_generatePixelResults = false;
298
299     // Optional paramater, describing whether it's allowed to dump pixel results in dumpAsText mode.
300     if (arguments.size() > 0 && arguments[0].isBool())
301         m_generatePixelResults = arguments[0].value.boolValue;
302
303     result->setNull();
304 }
305
306 void LayoutTestController::dumpDatabaseCallbacks(const CppArgumentList&, CppVariant* result)
307 {
308     // Do nothing; we don't use this flag anywhere for now
309     result->setNull();
310 }
311
312 void LayoutTestController::dumpEditingCallbacks(const CppArgumentList&, CppVariant* result)
313 {
314     m_dumpEditingCallbacks = true;
315     result->setNull();
316 }
317
318 void LayoutTestController::dumpBackForwardList(const CppArgumentList&, CppVariant* result)
319 {
320     m_dumpBackForwardList = true;
321     result->setNull();
322 }
323
324 void LayoutTestController::dumpFrameLoadCallbacks(const CppArgumentList&, CppVariant* result)
325 {
326     m_dumpFrameLoadCallbacks = true;
327     result->setNull();
328 }
329
330 void LayoutTestController::dumpProgressFinishedCallback(const CppArgumentList&, CppVariant* result)
331 {
332     m_dumpProgressFinishedCallback = true;
333     result->setNull();
334 }
335
336 void LayoutTestController::dumpUserGestureInFrameLoadCallbacks(const CppArgumentList&, CppVariant* result)
337 {
338     m_dumpUserGestureInFrameLoadCallbacks = true;
339     result->setNull();
340 }
341
342 void LayoutTestController::dumpResourceLoadCallbacks(const CppArgumentList&, CppVariant* result)
343 {
344     m_dumpResourceLoadCallbacks = true;
345     result->setNull();
346 }
347
348 void LayoutTestController::dumpResourceResponseMIMETypes(const CppArgumentList&, CppVariant* result)
349 {
350     m_dumpResourceResponseMIMETypes = true;
351     result->setNull();
352 }
353
354 void LayoutTestController::dumpChildFrameScrollPositions(const CppArgumentList&, CppVariant* result)
355 {
356     m_dumpChildFrameScrollPositions = true;
357     result->setNull();
358 }
359
360 void LayoutTestController::dumpChildFramesAsText(const CppArgumentList&, CppVariant* result)
361 {
362     m_dumpChildFramesAsText = true;
363     result->setNull();
364 }
365
366 void LayoutTestController::dumpWindowStatusChanges(const CppArgumentList&, CppVariant* result)
367 {
368     m_dumpWindowStatusChanges = true;
369     result->setNull();
370 }
371
372 void LayoutTestController::dumpTitleChanges(const CppArgumentList&, CppVariant* result)
373 {
374     m_dumpTitleChanges = true;
375     result->setNull();
376 }
377
378 void LayoutTestController::setAcceptsEditing(const CppArgumentList& arguments, CppVariant* result)
379 {
380     if (arguments.size() > 0 && arguments[0].isBool())
381         m_acceptsEditing = arguments[0].value.boolValue;
382     result->setNull();
383 }
384
385 void LayoutTestController::waitUntilDone(const CppArgumentList&, CppVariant* result)
386 {
387     if (!webkit_support::BeingDebugged())
388         postDelayedTask(new NotifyDoneTimedOutTask(this), m_shell->layoutTestTimeout());
389     m_waitUntilDone = true;
390     result->setNull();
391 }
392
393 void LayoutTestController::notifyDone(const CppArgumentList&, CppVariant* result)
394 {
395     // Test didn't timeout. Kill the timeout timer.
396     m_taskList.revokeAll();
397
398     completeNotifyDone(false);
399     result->setNull();
400 }
401
402 void LayoutTestController::completeNotifyDone(bool isTimeout)
403 {
404     if (m_waitUntilDone && !m_shell->webViewHost()->topLoadingFrame() && m_workQueue.isEmpty()) {
405         if (isTimeout)
406             m_shell->testTimedOut();
407         else
408             m_shell->testFinished();
409     }
410     m_waitUntilDone = false;
411 }
412
413 class WorkItemBackForward : public LayoutTestController::WorkItem {
414 public:
415     WorkItemBackForward(int distance) : m_distance(distance) { }
416     bool run(TestShell* shell)
417     {
418         shell->goToOffset(m_distance);
419         return true; // FIXME: Did it really start a navigation?
420     }
421
422 private:
423     int m_distance;
424 };
425
426 void LayoutTestController::queueBackNavigation(const CppArgumentList& arguments, CppVariant* result)
427 {
428     if (arguments.size() > 0 && arguments[0].isNumber())
429         m_workQueue.addWork(new WorkItemBackForward(-arguments[0].toInt32()));
430     result->setNull();
431 }
432
433 void LayoutTestController::queueForwardNavigation(const CppArgumentList& arguments, CppVariant* result)
434 {
435     if (arguments.size() > 0 && arguments[0].isNumber())
436         m_workQueue.addWork(new WorkItemBackForward(arguments[0].toInt32()));
437     result->setNull();
438 }
439
440 class WorkItemReload : public LayoutTestController::WorkItem {
441 public:
442     bool run(TestShell* shell)
443     {
444         shell->reload();
445         return true;
446     }
447 };
448
449 void LayoutTestController::queueReload(const CppArgumentList&, CppVariant* result)
450 {
451     m_workQueue.addWork(new WorkItemReload);
452     result->setNull();
453 }
454
455 class WorkItemLoadingScript : public LayoutTestController::WorkItem {
456 public:
457     WorkItemLoadingScript(const string& script) : m_script(script) { }
458     bool run(TestShell* shell)
459     {
460         shell->webView()->mainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(m_script)));
461         return true; // FIXME: Did it really start a navigation?
462     }
463
464 private:
465     string m_script;
466 };
467
468 class WorkItemNonLoadingScript : public LayoutTestController::WorkItem {
469 public:
470     WorkItemNonLoadingScript(const string& script) : m_script(script) { }
471     bool run(TestShell* shell)
472     {
473         shell->webView()->mainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(m_script)));
474         return false;
475     }
476
477 private:
478     string m_script;
479 };
480
481 void LayoutTestController::queueLoadingScript(const CppArgumentList& arguments, CppVariant* result)
482 {
483     if (arguments.size() > 0 && arguments[0].isString())
484         m_workQueue.addWork(new WorkItemLoadingScript(arguments[0].toString()));
485     result->setNull();
486 }
487
488 void LayoutTestController::queueNonLoadingScript(const CppArgumentList& arguments, CppVariant* result)
489 {
490     if (arguments.size() > 0 && arguments[0].isString())
491         m_workQueue.addWork(new WorkItemNonLoadingScript(arguments[0].toString()));
492     result->setNull();
493 }
494
495 class WorkItemLoad : public LayoutTestController::WorkItem {
496 public:
497     WorkItemLoad(const WebURL& url, const WebString& target)
498         : m_url(url)
499         , m_target(target) { }
500     bool run(TestShell* shell)
501     {
502         shell->webViewHost()->loadURLForFrame(m_url, m_target);
503         return true; // FIXME: Did it really start a navigation?
504     }
505
506 private:
507     WebURL m_url;
508     WebString m_target;
509 };
510
511 void LayoutTestController::queueLoad(const CppArgumentList& arguments, CppVariant* result)
512 {
513     if (arguments.size() > 0 && arguments[0].isString()) {
514         // FIXME: Implement WebURL::resolve() and avoid GURL.
515         GURL currentURL = m_shell->webView()->mainFrame()->document().url();
516         GURL fullURL = currentURL.Resolve(arguments[0].toString());
517
518         string target = "";
519         if (arguments.size() > 1 && arguments[1].isString())
520             target = arguments[1].toString();
521
522         m_workQueue.addWork(new WorkItemLoad(fullURL, WebString::fromUTF8(target)));
523     }
524     result->setNull();
525 }
526
527 class WorkItemLoadHTMLString : public LayoutTestController::WorkItem  {
528 public:
529     WorkItemLoadHTMLString(const std::string& html, const WebURL& baseURL)
530         : m_html(html)
531         , m_baseURL(baseURL) { }
532     WorkItemLoadHTMLString(const std::string& html, const WebURL& baseURL, const WebURL& unreachableURL)
533         : m_html(html)
534         , m_baseURL(baseURL)
535         , m_unreachableURL(unreachableURL) { }
536     bool run(TestShell* shell)
537     {
538         shell->webView()->mainFrame()->loadHTMLString(
539             WebKit::WebData(m_html.data(), m_html.length()), m_baseURL, m_unreachableURL);
540         return true;
541     }
542
543 private:
544     std::string m_html;
545     WebURL m_baseURL;
546     WebURL m_unreachableURL;
547 };
548
549 void LayoutTestController::queueLoadHTMLString(const CppArgumentList& arguments, CppVariant* result)
550 {
551     if (arguments.size() > 0 && arguments[0].isString()) {
552         string html = arguments[0].toString();
553         WebURL baseURL;
554         if (arguments.size() > 1 && arguments[1].isString())
555             baseURL = WebURL(GURL(arguments[1].toString()));
556         if (arguments.size() > 2 && arguments[2].isString())
557             m_workQueue.addWork(new WorkItemLoadHTMLString(html, baseURL, WebURL(GURL(arguments[2].toString()))));
558         else
559             m_workQueue.addWork(new WorkItemLoadHTMLString(html, baseURL));
560     }
561     result->setNull();
562 }
563
564 void LayoutTestController::objCIdentityIsEqual(const CppArgumentList& arguments, CppVariant* result)
565 {
566     if (arguments.size() < 2) {
567         // This is the best we can do to return an error.
568         result->setNull();
569         return;
570     }
571     result->set(arguments[0].isEqual(arguments[1]));
572 }
573
574 void LayoutTestController::reset()
575 {
576     if (m_shell) {
577         m_shell->webView()->setZoomLevel(false, 0);
578         m_shell->webView()->setTabKeyCyclesThroughElements(true);
579 #if !OS(DARWIN) && !OS(WINDOWS) // Actually, TOOLKIT_GTK
580         // (Constants copied because we can't depend on the header that defined
581         // them from this file.)
582         m_shell->webView()->setSelectionColors(0xff1e90ff, 0xff000000, 0xffc8c8c8, 0xff323232);
583 #endif
584         m_shell->webView()->removeAllUserContent();
585     }
586     m_dumpAsText = false;
587     m_dumpAsAudio = false;
588     m_dumpEditingCallbacks = false;
589     m_dumpFrameLoadCallbacks = false;
590     m_dumpProgressFinishedCallback = false;
591     m_dumpUserGestureInFrameLoadCallbacks = false;
592     m_dumpResourceLoadCallbacks = false;
593     m_dumpResourceResponseMIMETypes = false;
594     m_dumpBackForwardList = false;
595     m_dumpChildFrameScrollPositions = false;
596     m_dumpChildFramesAsText = false;
597     m_dumpWindowStatusChanges = false;
598     m_dumpSelectionRect = false;
599     m_dumpTitleChanges = false;
600     m_generatePixelResults = true;
601     m_acceptsEditing = true;
602     m_waitUntilDone = false;
603     m_canOpenWindows = false;
604     m_testRepaint = false;
605     m_sweepHorizontally = false;
606     m_shouldAddFileToPasteboard = false;
607     m_stopProvisionalFrameLoads = false;
608     m_deferMainResourceDataLoad = true;
609     m_globalFlag.set(false);
610     m_webHistoryItemCount.set(0);
611     m_titleTextDirection.set("ltr");
612     m_userStyleSheetLocation = WebURL();
613
614     webkit_support::SetAcceptAllCookies(false);
615     WebSecurityPolicy::resetOriginAccessWhitelists();
616
617     // Reset the default quota for each origin to 5MB
618     webkit_support::SetDatabaseQuota(5 * 1024 * 1024);
619
620     setlocale(LC_ALL, "");
621
622     if (m_closeRemainingWindows)
623         m_shell->closeRemainingWindows();
624     else
625         m_closeRemainingWindows = true;
626     m_workQueue.reset();
627     m_taskList.revokeAll();
628     m_shouldStayOnPageAfterHandlingBeforeUnload = false;
629 }
630
631 void LayoutTestController::locationChangeDone()
632 {
633     m_webHistoryItemCount.set(m_shell->navigationEntryCount());
634
635     // No more new work after the first complete load.
636     m_workQueue.setFrozen(true);
637
638     if (!m_waitUntilDone)
639         m_workQueue.processWorkSoon();
640 }
641
642 void LayoutTestController::policyDelegateDone()
643 {
644     ASSERT(m_waitUntilDone);
645     m_shell->testFinished();
646     m_waitUntilDone = false;
647 }
648
649 void LayoutTestController::setCanOpenWindows(const CppArgumentList&, CppVariant* result)
650 {
651     m_canOpenWindows = true;
652     result->setNull();
653 }
654
655 void LayoutTestController::setTabKeyCyclesThroughElements(const CppArgumentList& arguments, CppVariant* result)
656 {
657     if (arguments.size() > 0 && arguments[0].isBool())
658         m_shell->webView()->setTabKeyCyclesThroughElements(arguments[0].toBoolean());
659     result->setNull();
660 }
661
662 void LayoutTestController::windowCount(const CppArgumentList&, CppVariant* result)
663 {
664     result->set(static_cast<int>(m_shell->windowCount()));
665 }
666
667 void LayoutTestController::setCloseRemainingWindowsWhenComplete(const CppArgumentList& arguments, CppVariant* result)
668 {
669     if (arguments.size() > 0 && arguments[0].isBool())
670         m_closeRemainingWindows = arguments[0].value.boolValue;
671     result->setNull();
672 }
673
674 void LayoutTestController::setAlwaysAcceptCookies(const CppArgumentList& arguments, CppVariant* result)
675 {
676     if (arguments.size() > 0)
677         webkit_support::SetAcceptAllCookies(cppVariantToBool(arguments[0]));
678     result->setNull();
679 }
680
681 void LayoutTestController::setAsynchronousSpellCheckingEnabled(const CppArgumentList& arguments, CppVariant* result)
682 {
683     if (arguments.size() > 0 && arguments[0].isBool())
684         m_shell->webView()->settings()->setAsynchronousSpellCheckingEnabled(cppVariantToBool(arguments[0]));
685     result->setNull();
686 }
687
688 void LayoutTestController::showWebInspector(const CppArgumentList&, CppVariant* result)
689 {
690     m_shell->showDevTools();
691     result->setNull();
692 }
693
694 void LayoutTestController::closeWebInspector(const CppArgumentList& args, CppVariant* result)
695 {
696     m_shell->closeDevTools();
697     result->setNull();
698 }
699
700 void LayoutTestController::setWindowIsKey(const CppArgumentList& arguments, CppVariant* result)
701 {
702     if (arguments.size() > 0 && arguments[0].isBool())
703         m_shell->setFocus(m_shell->webView(), arguments[0].value.boolValue);
704     result->setNull();
705 }
706
707 void LayoutTestController::setUserStyleSheetEnabled(const CppArgumentList& arguments, CppVariant* result)
708 {
709     if (arguments.size() > 0 && arguments[0].isBool()) {
710         m_shell->preferences()->userStyleSheetLocation = arguments[0].value.boolValue ? m_userStyleSheetLocation : WebURL();
711         m_shell->applyPreferences();
712     }
713     result->setNull();
714 }
715
716 void LayoutTestController::setUserStyleSheetLocation(const CppArgumentList& arguments, CppVariant* result)
717 {
718     if (arguments.size() > 0 && arguments[0].isString()) {
719         m_userStyleSheetLocation = webkit_support::LocalFileToDataURL(
720             webkit_support::RewriteLayoutTestsURL(arguments[0].toString()));
721         m_shell->preferences()->userStyleSheetLocation = m_userStyleSheetLocation;
722         m_shell->applyPreferences();
723     }
724     result->setNull();
725 }
726
727 void LayoutTestController::setAuthorAndUserStylesEnabled(const CppArgumentList& arguments, CppVariant* result)
728 {
729     if (arguments.size() > 0 && arguments[0].isBool()) {
730         m_shell->preferences()->authorAndUserStylesEnabled = arguments[0].value.boolValue;
731         m_shell->applyPreferences();
732     }
733     result->setNull();
734 }
735
736 void LayoutTestController::execCommand(const CppArgumentList& arguments, CppVariant* result)
737 {
738     result->setNull();
739     if (arguments.size() <= 0 || !arguments[0].isString())
740         return;
741
742     std::string command = arguments[0].toString();
743     std::string value("");
744     // Ignore the second parameter (which is userInterface)
745     // since this command emulates a manual action.
746     if (arguments.size() >= 3 && arguments[2].isString())
747         value = arguments[2].toString();
748
749     // Note: webkit's version does not return the boolean, so neither do we.
750     m_shell->webView()->focusedFrame()->executeCommand(WebString::fromUTF8(command), WebString::fromUTF8(value));
751 }
752
753 void LayoutTestController::isCommandEnabled(const CppArgumentList& arguments, CppVariant* result)
754 {
755     if (arguments.size() <= 0 || !arguments[0].isString()) {
756         result->setNull();
757         return;
758     }
759
760     std::string command = arguments[0].toString();
761     bool rv = m_shell->webView()->focusedFrame()->isCommandEnabled(WebString::fromUTF8(command));
762     result->set(rv);
763 }
764
765 void LayoutTestController::setPopupBlockingEnabled(const CppArgumentList& arguments, CppVariant* result)
766 {
767     if (arguments.size() > 0 && arguments[0].isBool()) {
768         bool blockPopups = arguments[0].toBoolean();
769         m_shell->preferences()->javaScriptCanOpenWindowsAutomatically = !blockPopups;
770         m_shell->applyPreferences();
771     }
772     result->setNull();
773 }
774
775 void LayoutTestController::setImagesAllowed(const CppArgumentList& arguments, CppVariant* result)
776 {
777     if (arguments.size() > 0 && arguments[0].isBool())
778         m_shell->webPermissions()->setImagesAllowed(arguments[0].toBoolean());
779     result->setNull();
780 }
781
782 void LayoutTestController::setStorageAllowed(const CppArgumentList& arguments, CppVariant* result)
783 {
784     if (arguments.size() > 0 && arguments[0].isBool())
785         m_shell->webPermissions()->setStorageAllowed(arguments[0].toBoolean());
786     result->setNull();
787 }
788
789 void LayoutTestController::setPluginsAllowed(const CppArgumentList& arguments, CppVariant* result)
790 {
791     if (arguments.size() > 0 && arguments[0].isBool())
792         m_shell->webPermissions()->setPluginsAllowed(arguments[0].toBoolean());
793     result->setNull();
794 }
795
796 void LayoutTestController::setUseDashboardCompatibilityMode(const CppArgumentList&, CppVariant* result)
797 {
798     // We have no need to support Dashboard Compatibility Mode (mac-only)
799     result->setNull();
800 }
801
802 void LayoutTestController::clearAllApplicationCaches(const CppArgumentList&, CppVariant* result)
803 {
804     // FIXME: Implement to support application cache quotas.
805     result->setNull();
806 }
807
808 void LayoutTestController::clearApplicationCacheForOrigin(const CppArgumentList&, CppVariant* result)
809 {
810     // FIXME: Implement to support deleting all application cache for an origin.
811     result->setNull();
812 }
813
814 void LayoutTestController::setApplicationCacheOriginQuota(const CppArgumentList&, CppVariant* result)
815 {
816     // FIXME: Implement to support application cache quotas.
817     result->setNull();
818 }
819
820 void LayoutTestController::originsWithApplicationCache(const CppArgumentList&, CppVariant* result)
821 {
822     // FIXME: Implement to support getting origins that have application caches.
823     result->setNull();
824 }
825
826 void LayoutTestController::applicationCacheDiskUsageForOrigin(const CppArgumentList&, CppVariant* result)
827 {
828     // FIXME: Implement to support getting disk usage by all application cache for an origin.
829     result->setNull();
830 }
831
832 void LayoutTestController::setScrollbarPolicy(const CppArgumentList&, CppVariant* result)
833 {
834     // FIXME: implement.
835     // Currently only has a non-null implementation on QT.
836     result->setNull();
837 }
838
839 void LayoutTestController::setCustomPolicyDelegate(const CppArgumentList& arguments, CppVariant* result)
840 {
841     if (arguments.size() > 0 && arguments[0].isBool()) {
842         bool enable = arguments[0].value.boolValue;
843         bool permissive = false;
844         if (arguments.size() > 1 && arguments[1].isBool())
845             permissive = arguments[1].value.boolValue;
846         m_shell->webViewHost()->setCustomPolicyDelegate(enable, permissive);
847     }
848     result->setNull();
849 }
850
851 void LayoutTestController::waitForPolicyDelegate(const CppArgumentList&, CppVariant* result)
852 {
853     m_shell->webViewHost()->waitForPolicyDelegate();
854     m_waitUntilDone = true;
855     result->setNull();
856 }
857
858 void LayoutTestController::setWillSendRequestClearHeader(const CppArgumentList& arguments, CppVariant* result)
859 {
860     if (arguments.size() > 0 && arguments[0].isString()) {
861         string header = arguments[0].toString();
862         if (!header.empty())
863             m_shell->webViewHost()->addClearHeader(String::fromUTF8(header.c_str()));
864     }
865     result->setNull();
866 }
867
868 void LayoutTestController::setWillSendRequestReturnsNullOnRedirect(const CppArgumentList& arguments, CppVariant* result)
869 {
870     if (arguments.size() > 0 && arguments[0].isBool())
871         m_shell->webViewHost()->setBlockRedirects(arguments[0].value.boolValue);
872     result->setNull();
873 }
874
875 void LayoutTestController::setWillSendRequestReturnsNull(const CppArgumentList& arguments, CppVariant* result)
876 {
877     if (arguments.size() > 0 && arguments[0].isBool())
878         m_shell->webViewHost()->setRequestReturnNull(arguments[0].value.boolValue);
879     result->setNull();
880 }
881
882 void LayoutTestController::pathToLocalResource(const CppArgumentList& arguments, CppVariant* result)
883 {
884     result->setNull();
885     if (arguments.size() <= 0 || !arguments[0].isString())
886         return;
887
888     string url = arguments[0].toString();
889 #if OS(WINDOWS)
890     if (!url.find("/tmp/")) {
891         // We want a temp file.
892         const unsigned tempPrefixLength = 5;
893         size_t bufferSize = MAX_PATH;
894         OwnArrayPtr<WCHAR> tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
895         DWORD tempLength = ::GetTempPathW(bufferSize, tempPath.get());
896         if (tempLength + url.length() - tempPrefixLength + 1 > bufferSize) {
897             bufferSize = tempLength + url.length() - tempPrefixLength + 1;
898             tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
899             tempLength = GetTempPathW(bufferSize, tempPath.get());
900             ASSERT(tempLength < bufferSize);
901         }
902         string resultPath(WebString(tempPath.get(), tempLength).utf8());
903         resultPath.append(url.substr(tempPrefixLength));
904         result->set(resultPath);
905         return;
906     }
907 #endif
908
909     // Some layout tests use file://// which we resolve as a UNC path. Normalize
910     // them to just file:///.
911     string lowerUrl = url;
912     transform(lowerUrl.begin(), lowerUrl.end(), lowerUrl.begin(), ::tolower);
913     while (!lowerUrl.find("file:////")) {
914         url = url.substr(0, 8) + url.substr(9);
915         lowerUrl = lowerUrl.substr(0, 8) + lowerUrl.substr(9);
916     }
917     result->set(webkit_support::RewriteLayoutTestsURL(url).spec());
918 }
919
920 void LayoutTestController::addFileToPasteboardOnDrag(const CppArgumentList&, CppVariant* result)
921 {
922     result->setNull();
923     m_shouldAddFileToPasteboard = true;
924 }
925
926 void LayoutTestController::setStopProvisionalFrameLoads(const CppArgumentList&, CppVariant* result)
927 {
928     result->setNull();
929     m_stopProvisionalFrameLoads = true;
930 }
931
932 void LayoutTestController::setSmartInsertDeleteEnabled(const CppArgumentList& arguments, CppVariant* result)
933 {
934     if (arguments.size() > 0 && arguments[0].isBool())
935         m_shell->webViewHost()->setSmartInsertDeleteEnabled(arguments[0].value.boolValue);
936     result->setNull();
937 }
938
939 void LayoutTestController::setSelectTrailingWhitespaceEnabled(const CppArgumentList& arguments, CppVariant* result)
940 {
941     if (arguments.size() > 0 && arguments[0].isBool())
942         m_shell->webViewHost()->setSelectTrailingWhitespaceEnabled(arguments[0].value.boolValue);
943     result->setNull();
944 }
945
946 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const WebString& animationName, double time, const WebString& elementId)
947 {
948     WebFrame* webFrame = m_shell->webView()->mainFrame();
949     if (!webFrame)
950         return false;
951
952     WebAnimationController* controller = webFrame->animationController();
953     if (!controller)
954         return false;
955
956     WebElement element = webFrame->document().getElementById(elementId);
957     if (element.isNull())
958         return false;
959     return controller->pauseAnimationAtTime(element, animationName, time);
960 }
961
962 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(const WebString& propertyName, double time, const WebString& elementId)
963 {
964     WebFrame* webFrame = m_shell->webView()->mainFrame();
965     if (!webFrame)
966         return false;
967
968     WebAnimationController* controller = webFrame->animationController();
969     if (!controller)
970         return false;
971
972     WebElement element = webFrame->document().getElementById(elementId);
973     if (element.isNull())
974         return false;
975     return controller->pauseTransitionAtTime(element, propertyName, time);
976 }
977
978 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(const WebString& elementId)
979 {
980     WebFrame* webFrame = m_shell->webView()->mainFrame();
981     if (!webFrame)
982         return false;
983
984     WebElement element = webFrame->document().getElementById(elementId);
985     if (element.isNull() || !element.hasTagName("input"))
986         return false;
987
988     WebInputElement inputElement = element.to<WebInputElement>();
989     return inputElement.autoComplete();
990 }
991
992 int LayoutTestController::numberOfActiveAnimations()
993 {
994     WebFrame* webFrame = m_shell->webView()->mainFrame();
995     if (!webFrame)
996         return -1;
997
998     WebAnimationController* controller = webFrame->animationController();
999     if (!controller)
1000         return -1;
1001
1002     return controller->numberOfActiveAnimations();
1003 }
1004
1005 void LayoutTestController::suspendAnimations()
1006 {
1007     WebFrame* webFrame = m_shell->webView()->mainFrame();
1008     if (!webFrame)
1009         return;
1010
1011     WebAnimationController* controller = webFrame->animationController();
1012     if (!controller)
1013         return;
1014
1015     controller->suspendAnimations();
1016 }
1017
1018 void LayoutTestController::resumeAnimations()
1019 {
1020     WebFrame* webFrame = m_shell->webView()->mainFrame();
1021     if (!webFrame)
1022         return;
1023
1024     WebAnimationController* controller = webFrame->animationController();
1025     if (!controller)
1026         return;
1027
1028     controller->resumeAnimations();
1029 }
1030
1031 void LayoutTestController::pauseAnimationAtTimeOnElementWithId(const CppArgumentList& arguments, CppVariant* result)
1032 {
1033     result->set(false);
1034     if (arguments.size() > 2 && arguments[0].isString() && arguments[1].isNumber() && arguments[2].isString()) {
1035         WebString animationName = cppVariantToWebString(arguments[0]);
1036         double time = arguments[1].toDouble();
1037         WebString elementId = cppVariantToWebString(arguments[2]);
1038         result->set(pauseAnimationAtTimeOnElementWithId(animationName, time, elementId));
1039     }
1040 }
1041
1042 void LayoutTestController::pauseTransitionAtTimeOnElementWithId(const CppArgumentList& arguments, CppVariant* result)
1043 {
1044     result->set(false);
1045     if (arguments.size() > 2 && arguments[0].isString() && arguments[1].isNumber() && arguments[2].isString()) {
1046         WebString propertyName = cppVariantToWebString(arguments[0]);
1047         double time = arguments[1].toDouble();
1048         WebString elementId = cppVariantToWebString(arguments[2]);
1049         result->set(pauseTransitionAtTimeOnElementWithId(propertyName, time, elementId));
1050     }
1051 }
1052
1053 void LayoutTestController::elementDoesAutoCompleteForElementWithId(const CppArgumentList& arguments, CppVariant* result)
1054 {
1055     if (arguments.size() != 1 || !arguments[0].isString()) {
1056         result->set(false);
1057         return;
1058     }
1059     WebString elementId = cppVariantToWebString(arguments[0]);
1060     result->set(elementDoesAutoCompleteForElementWithId(elementId));
1061 }
1062
1063 void LayoutTestController::numberOfActiveAnimations(const CppArgumentList&, CppVariant* result)
1064 {
1065     result->set(numberOfActiveAnimations());
1066 }
1067
1068 void LayoutTestController::suspendAnimations(const CppArgumentList&, CppVariant* result)
1069 {
1070     suspendAnimations();
1071     result->setNull();
1072 }
1073
1074 void LayoutTestController::resumeAnimations(const CppArgumentList&, CppVariant* result)
1075 {
1076     resumeAnimations();
1077     result->setNull();
1078 }
1079
1080 void LayoutTestController::sampleSVGAnimationForElementAtTime(const CppArgumentList& arguments, CppVariant* result)
1081 {
1082     if (arguments.size() != 3) {
1083         result->setNull();
1084         return;
1085     }
1086     WebString animationId = cppVariantToWebString(arguments[0]);
1087     double time = arguments[1].toDouble();
1088     WebString elementId = cppVariantToWebString(arguments[2]);
1089     bool success = m_shell->webView()->mainFrame()->pauseSVGAnimation(animationId, time, elementId);
1090     result->set(success);
1091 }
1092
1093 void LayoutTestController::disableImageLoading(const CppArgumentList&, CppVariant* result)
1094 {
1095     m_shell->preferences()->loadsImagesAutomatically = false;
1096     m_shell->applyPreferences();
1097     result->setNull();
1098 }
1099
1100 void LayoutTestController::setIconDatabaseEnabled(const CppArgumentList&, CppVariant* result)
1101 {
1102     // We don't use the WebKit icon database.
1103     result->setNull();
1104 }
1105
1106 void LayoutTestController::setOverrideIndexedDBBackingStore(const CppArgumentList& arguments, CppVariant* result)
1107 {
1108     result->setNull();
1109 #if ENABLE(INDEXED_DATABASE)
1110     if (arguments.size() < 1 || !arguments[0].isString())
1111         return;
1112     string name = arguments[0].toString();
1113     if (name == "default")
1114         WebIDBFactory::setOverrideBackingStoreType(WebIDBFactory::DefaultBackingStore);
1115     else if (name == "sqlite")
1116         WebIDBFactory::setOverrideBackingStoreType(WebIDBFactory::SQLiteBackingStore);
1117     else if (name == "leveldb")
1118         WebIDBFactory::setOverrideBackingStoreType(WebIDBFactory::LevelDBBackingStore);
1119 #endif
1120 }
1121
1122 void LayoutTestController::callShouldCloseOnWebView(const CppArgumentList&, CppVariant* result)
1123 {
1124     result->set(m_shell->webView()->dispatchBeforeUnloadEvent());
1125 }
1126
1127 void LayoutTestController::grantDesktopNotificationPermission(const CppArgumentList& arguments, CppVariant* result)
1128 {
1129     if (arguments.size() != 1 || !arguments[0].isString()) {
1130         result->set(false);
1131         return;
1132     }
1133     m_shell->notificationPresenter()->grantPermission(cppVariantToWebString(arguments[0]));
1134     result->set(true);
1135 }
1136
1137 void LayoutTestController::simulateDesktopNotificationClick(const CppArgumentList& arguments, CppVariant* result)
1138 {
1139     if (arguments.size() != 1 || !arguments[0].isString()) {
1140         result->set(false);
1141         return;
1142     }
1143     if (m_shell->notificationPresenter()->simulateClick(cppVariantToWebString(arguments[0])))
1144         result->set(true);
1145     else
1146         result->set(false);
1147 }
1148
1149 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(const CppArgumentList& arguments, CppVariant* result)
1150 {
1151     if (arguments.size() != 2 || !arguments[0].isBool() || !arguments[1].isString())
1152         return;
1153     m_shell->webView()->setDomainRelaxationForbidden(cppVariantToBool(arguments[0]), cppVariantToWebString(arguments[1]));
1154 }
1155
1156 void LayoutTestController::setDeferMainResourceDataLoad(const CppArgumentList& arguments, CppVariant* result)
1157 {
1158     if (arguments.size() == 1)
1159         m_deferMainResourceDataLoad = cppVariantToBool(arguments[0]);
1160 }
1161
1162 //
1163 // Unimplemented stubs
1164 //
1165
1166 void LayoutTestController::dumpAsWebArchive(const CppArgumentList& arguments, CppVariant* result)
1167 {
1168     result->setNull();
1169 }
1170
1171 void LayoutTestController::setMainFrameIsFirstResponder(const CppArgumentList& arguments, CppVariant* result)
1172 {
1173     result->setNull();
1174 }
1175
1176 void LayoutTestController::dumpSelectionRect(const CppArgumentList& arguments, CppVariant* result)
1177 {
1178     m_dumpSelectionRect = true;
1179     result->setNull();
1180 }
1181
1182 void LayoutTestController::display(const CppArgumentList& arguments, CppVariant* result)
1183 {
1184     WebViewHost* host = m_shell->webViewHost();
1185     const WebKit::WebSize& size = m_shell->webView()->size();
1186     WebRect rect(0, 0, size.width, size.height);
1187     host->updatePaintRect(rect);
1188     host->paintInvalidatedRegion();
1189     host->displayRepaintMask();
1190     result->setNull();
1191 }
1192
1193 void LayoutTestController::displayInvalidatedRegion(const CppArgumentList& arguments, CppVariant* result)
1194 {
1195     WebViewHost* host = m_shell->webViewHost();
1196     host->paintInvalidatedRegion();
1197     host->displayRepaintMask();
1198     result->setNull();
1199 }
1200
1201 void LayoutTestController::testRepaint(const CppArgumentList&, CppVariant* result)
1202 {
1203     m_testRepaint = true;
1204     result->setNull();
1205 }
1206
1207 void LayoutTestController::repaintSweepHorizontally(const CppArgumentList&, CppVariant* result)
1208 {
1209     m_sweepHorizontally = true;
1210     result->setNull();
1211 }
1212
1213 void LayoutTestController::clearBackForwardList(const CppArgumentList& arguments, CppVariant* result)
1214 {
1215     result->setNull();
1216 }
1217
1218 void LayoutTestController::keepWebHistory(const CppArgumentList& arguments,  CppVariant* result)
1219 {
1220     result->setNull();
1221 }
1222
1223 void LayoutTestController::storeWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
1224 {
1225     result->setNull();
1226 }
1227
1228 void LayoutTestController::accessStoredWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
1229 {
1230     result->setNull();
1231 }
1232
1233 void LayoutTestController::objCClassNameOf(const CppArgumentList& arguments, CppVariant* result)
1234 {
1235     result->setNull();
1236 }
1237
1238 void LayoutTestController::addDisallowedURL(const CppArgumentList& arguments, CppVariant* result)
1239 {
1240     result->setNull();
1241 }
1242
1243 void LayoutTestController::setCallCloseOnWebViews(const CppArgumentList& arguments, CppVariant* result)
1244 {
1245     result->setNull();
1246 }
1247
1248 void LayoutTestController::setPrivateBrowsingEnabled(const CppArgumentList& arguments, CppVariant* result)
1249 {
1250     result->setNull();
1251 }
1252
1253 void LayoutTestController::setJavaScriptCanAccessClipboard(const CppArgumentList& arguments, CppVariant* result)
1254 {
1255     if (arguments.size() > 0 && arguments[0].isBool()) {
1256         m_shell->preferences()->javaScriptCanAccessClipboard = arguments[0].value.boolValue;
1257         m_shell->applyPreferences();
1258     }
1259     result->setNull();
1260 }
1261
1262 void LayoutTestController::setXSSAuditorEnabled(const CppArgumentList& arguments, CppVariant* result)
1263 {
1264     if (arguments.size() > 0 && arguments[0].isBool()) {
1265         m_shell->preferences()->XSSAuditorEnabled = arguments[0].value.boolValue;
1266         m_shell->applyPreferences();
1267     }
1268     result->setNull();
1269 }
1270
1271 void LayoutTestController::evaluateScriptInIsolatedWorld(const CppArgumentList& arguments, CppVariant* result)
1272 {
1273     if (arguments.size() >= 2 && arguments[0].isNumber() && arguments[1].isString()) {
1274         WebScriptSource source(cppVariantToWebString(arguments[1]));
1275         // This relies on the iframe focusing itself when it loads. This is a bit
1276         // sketchy, but it seems to be what other tests do.
1277         m_shell->webView()->focusedFrame()->executeScriptInIsolatedWorld(arguments[0].toInt32(), &source, 1, 1);
1278     }
1279     result->setNull();
1280 }
1281
1282 void LayoutTestController::setIsolatedWorldSecurityOrigin(const CppArgumentList& arguments, CppVariant* result)
1283 {
1284     result->setNull();
1285
1286     if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isString())
1287         return;
1288
1289     m_shell->webView()->focusedFrame()->setIsolatedWorldSecurityOrigin(
1290         arguments[0].toInt32(),
1291         WebSecurityOrigin::createFromString(cppVariantToWebString(arguments[1])));
1292 }
1293
1294 void LayoutTestController::setAllowUniversalAccessFromFileURLs(const CppArgumentList& arguments, CppVariant* result)
1295 {
1296     if (arguments.size() > 0 && arguments[0].isBool()) {
1297         m_shell->preferences()->allowUniversalAccessFromFileURLs = arguments[0].value.boolValue;
1298         m_shell->applyPreferences();
1299     }
1300     result->setNull();
1301 }
1302
1303 void LayoutTestController::setAllowDisplayOfInsecureContent(const CppArgumentList& arguments, CppVariant* result)
1304 {
1305     if (arguments.size() > 0 && arguments[0].isBool())
1306         m_shell->webPermissions()->setDisplayingInsecureContentAllowed(arguments[0].toBoolean());
1307
1308     result->setNull();
1309 }
1310
1311 void LayoutTestController::setAllowFileAccessFromFileURLs(const CppArgumentList& arguments, CppVariant* result)
1312 {
1313     if (arguments.size() > 0 && arguments[0].isBool()) {
1314         m_shell->preferences()->allowFileAccessFromFileURLs = arguments[0].value.boolValue;
1315         m_shell->applyPreferences();
1316     }
1317     result->setNull();
1318 }
1319
1320 void LayoutTestController::setAllowRunningOfInsecureContent(const CppArgumentList& arguments, CppVariant* result)
1321 {
1322     if (arguments.size() > 0 && arguments[0].isBool())
1323         m_shell->webPermissions()->setRunningInsecureContentAllowed(arguments[0].value.boolValue);
1324
1325     result->setNull();
1326 }
1327
1328 // Need these conversions because the format of the value for booleans
1329 // may vary - for example, on mac "1" and "0" are used for boolean.
1330 bool LayoutTestController::cppVariantToBool(const CppVariant& value)
1331 {
1332     if (value.isBool())
1333         return value.toBoolean();
1334     if (value.isNumber())
1335         return value.toInt32();
1336     if (value.isString()) {
1337         string valueString = value.toString();
1338         if (valueString == "true" || valueString == "1")
1339             return true;
1340         if (valueString == "false" || valueString == "0")
1341             return false;
1342     }
1343     logErrorToConsole("Invalid value. Expected boolean value.");
1344     return false;
1345 }
1346
1347 int32_t LayoutTestController::cppVariantToInt32(const CppVariant& value)
1348 {
1349     if (value.isNumber())
1350         return value.toInt32();
1351     if (value.isString()) {
1352         string stringSource = value.toString();
1353         const char* source = stringSource.data();
1354         char* end;
1355         long number = strtol(source, &end, 10);
1356         if (end == source + stringSource.length() && number >= numeric_limits<int32_t>::min() && number <= numeric_limits<int32_t>::max())
1357             return static_cast<int32_t>(number);
1358     }
1359     logErrorToConsole("Invalid value for preference. Expected integer value.");
1360     return 0;
1361 }
1362
1363 WebString LayoutTestController::cppVariantToWebString(const CppVariant& value)
1364 {
1365     if (!value.isString()) {
1366         logErrorToConsole("Invalid value for preference. Expected string value.");
1367         return WebString();
1368     }
1369     return WebString::fromUTF8(value.toString());
1370 }
1371
1372 void LayoutTestController::overridePreference(const CppArgumentList& arguments, CppVariant* result)
1373 {
1374     result->setNull();
1375     if (arguments.size() != 2 || !arguments[0].isString())
1376         return;
1377
1378     string key = arguments[0].toString();
1379     CppVariant value = arguments[1];
1380     WebPreferences* prefs = m_shell->preferences();
1381     if (key == "WebKitStandardFont")
1382         prefs->standardFontFamily = cppVariantToWebString(value);
1383     else if (key == "WebKitFixedFont")
1384         prefs->fixedFontFamily = cppVariantToWebString(value);
1385     else if (key == "WebKitSerifFont")
1386         prefs->serifFontFamily = cppVariantToWebString(value);
1387     else if (key == "WebKitSansSerifFont")
1388         prefs->sansSerifFontFamily = cppVariantToWebString(value);
1389     else if (key == "WebKitCursiveFont")
1390         prefs->cursiveFontFamily = cppVariantToWebString(value);
1391     else if (key == "WebKitFantasyFont")
1392         prefs->fantasyFontFamily = cppVariantToWebString(value);
1393     else if (key == "WebKitDefaultFontSize")
1394         prefs->defaultFontSize = cppVariantToInt32(value);
1395     else if (key == "WebKitDefaultFixedFontSize")
1396         prefs->defaultFixedFontSize = cppVariantToInt32(value);
1397     else if (key == "WebKitMinimumFontSize")
1398         prefs->minimumFontSize = cppVariantToInt32(value);
1399     else if (key == "WebKitMinimumLogicalFontSize")
1400         prefs->minimumLogicalFontSize = cppVariantToInt32(value);
1401     else if (key == "WebKitDefaultTextEncodingName")
1402         prefs->defaultTextEncodingName = cppVariantToWebString(value);
1403     else if (key == "WebKitJavaScriptEnabled")
1404         prefs->javaScriptEnabled = cppVariantToBool(value);
1405     else if (key == "WebKitWebSecurityEnabled")
1406         prefs->webSecurityEnabled = cppVariantToBool(value);
1407     else if (key == "WebKitJavaScriptCanOpenWindowsAutomatically")
1408         prefs->javaScriptCanOpenWindowsAutomatically = cppVariantToBool(value);
1409     else if (key == "WebKitDisplayImagesKey")
1410         prefs->loadsImagesAutomatically = cppVariantToBool(value);
1411     else if (key == "WebKitPluginsEnabled")
1412         prefs->pluginsEnabled = cppVariantToBool(value);
1413     else if (key == "WebKitDOMPasteAllowedPreferenceKey")
1414         prefs->DOMPasteAllowed = cppVariantToBool(value);
1415     else if (key == "WebKitDeveloperExtrasEnabledPreferenceKey")
1416         prefs->developerExtrasEnabled = cppVariantToBool(value);
1417     else if (key == "WebKitShrinksStandaloneImagesToFit")
1418         prefs->shrinksStandaloneImagesToFit = cppVariantToBool(value);
1419     else if (key == "WebKitTextAreasAreResizable")
1420         prefs->textAreasAreResizable = cppVariantToBool(value);
1421     else if (key == "WebKitJavaEnabled")
1422         prefs->javaEnabled = cppVariantToBool(value);
1423     else if (key == "WebKitUsesPageCachePreferenceKey")
1424         prefs->usesPageCache = cppVariantToBool(value);
1425     else if (key == "WebKitJavaScriptCanAccessClipboard")
1426         prefs->javaScriptCanAccessClipboard = cppVariantToBool(value);
1427     else if (key == "WebKitXSSAuditorEnabled")
1428         prefs->XSSAuditorEnabled = cppVariantToBool(value);
1429     else if (key == "WebKitLocalStorageEnabledPreferenceKey")
1430         prefs->localStorageEnabled = cppVariantToBool(value);
1431     else if (key == "WebKitOfflineWebApplicationCacheEnabled")
1432         prefs->offlineWebApplicationCacheEnabled = cppVariantToBool(value);
1433     else if (key == "WebKitTabToLinksPreferenceKey")
1434         prefs->tabsToLinks = cppVariantToBool(value);
1435     else if (key == "WebKitWebGLEnabled")
1436         prefs->experimentalWebGLEnabled = cppVariantToBool(value);
1437     else if (key == "WebKitHyperlinkAuditingEnabled")
1438         prefs->hyperlinkAuditingEnabled = cppVariantToBool(value);
1439     else if (key == "WebKitEnableCaretBrowsing")
1440         prefs->caretBrowsingEnabled = cppVariantToBool(value);
1441     else if (key == "WebKitAllowDisplayingInsecureContent")
1442         prefs->allowDisplayOfInsecureContent = cppVariantToBool(value);
1443     else if (key == "WebKitAllowRunningInsecureContent")
1444         prefs->allowRunningOfInsecureContent = cppVariantToBool(value);
1445     else if (key == "WebKitHixie76WebSocketProtocolEnabled")
1446         prefs->hixie76WebSocketProtocolEnabled = cppVariantToBool(value);
1447     else {
1448         string message("Invalid name for preference: ");
1449         message.append(key);
1450         logErrorToConsole(message);
1451     }
1452     m_shell->applyPreferences();
1453 }
1454
1455 void LayoutTestController::fallbackMethod(const CppArgumentList&, CppVariant* result)
1456 {
1457     printf("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on LayoutTestController\n");
1458     result->setNull();
1459 }
1460
1461 void LayoutTestController::addOriginAccessWhitelistEntry(const CppArgumentList& arguments, CppVariant* result)
1462 {
1463     result->setNull();
1464
1465     if (arguments.size() != 4 || !arguments[0].isString() || !arguments[1].isString()
1466         || !arguments[2].isString() || !arguments[3].isBool())
1467         return;
1468
1469     WebKit::WebURL url(GURL(arguments[0].toString()));
1470     if (!url.isValid())
1471         return;
1472
1473     WebSecurityPolicy::addOriginAccessWhitelistEntry(
1474         url,
1475         cppVariantToWebString(arguments[1]),
1476         cppVariantToWebString(arguments[2]),
1477         arguments[3].toBoolean());
1478 }
1479
1480 void LayoutTestController::removeOriginAccessWhitelistEntry(const CppArgumentList& arguments, CppVariant* result)
1481 {
1482     result->setNull();
1483
1484     if (arguments.size() != 4 || !arguments[0].isString() || !arguments[1].isString()
1485         || !arguments[2].isString() || !arguments[3].isBool())
1486         return;
1487
1488     WebKit::WebURL url(GURL(arguments[0].toString()));
1489     if (!url.isValid())
1490         return;
1491
1492     WebSecurityPolicy::removeOriginAccessWhitelistEntry(
1493         url,
1494         cppVariantToWebString(arguments[1]),
1495         cppVariantToWebString(arguments[2]),
1496         arguments[3].toBoolean());
1497 }
1498
1499 void LayoutTestController::clearAllDatabases(const CppArgumentList& arguments, CppVariant* result)
1500 {
1501     result->setNull();
1502     webkit_support::ClearAllDatabases();
1503 }
1504
1505 void LayoutTestController::setDatabaseQuota(const CppArgumentList& arguments, CppVariant* result)
1506 {
1507     result->setNull();
1508     if ((arguments.size() >= 1) && arguments[0].isNumber())
1509         webkit_support::SetDatabaseQuota(arguments[0].toInt32());
1510 }
1511
1512 void LayoutTestController::setPOSIXLocale(const CppArgumentList& arguments, CppVariant* result)
1513 {
1514     result->setNull();
1515     if (arguments.size() == 1 && arguments[0].isString())
1516         setlocale(LC_ALL, arguments[0].toString().c_str());
1517 }
1518
1519 void LayoutTestController::counterValueForElementById(const CppArgumentList& arguments, CppVariant* result)
1520 {
1521     result->setNull();
1522     if (arguments.size() < 1 || !arguments[0].isString())
1523         return;
1524     WebFrame* frame = m_shell->webView()->mainFrame();
1525     if (!frame)
1526         return;
1527     WebString counterValue = frame->counterValueForElementById(cppVariantToWebString(arguments[0]));
1528     if (counterValue.isNull())
1529         return;
1530     result->set(counterValue.utf8());
1531 }
1532
1533 static bool parsePageSizeParameters(const CppArgumentList& arguments,
1534                                     int argOffset,
1535                                     int* pageWidthInPixels,
1536                                     int* pageHeightInPixels)
1537 {
1538     // WebKit is using the window width/height of DumpRenderTree as the
1539     // default value of the page size.
1540     // FIXME: share these values with other ports.
1541     *pageWidthInPixels = 800;
1542     *pageHeightInPixels = 600;
1543     switch (arguments.size() - argOffset) {
1544     case 2:
1545         if (!arguments[argOffset].isNumber() || !arguments[1 + argOffset].isNumber())
1546             return false;
1547         *pageWidthInPixels = arguments[argOffset].toInt32();
1548         *pageHeightInPixels = arguments[1 + argOffset].toInt32();
1549         // fall through.
1550     case 0:
1551         break;
1552     default:
1553         return false;
1554     }
1555     return true;
1556 }
1557
1558 void LayoutTestController::pageNumberForElementById(const CppArgumentList& arguments, CppVariant* result)
1559 {
1560     result->setNull();
1561     int pageWidthInPixels = 0;
1562     int pageHeightInPixels = 0;
1563     if (!parsePageSizeParameters(arguments, 1,
1564                                  &pageWidthInPixels, &pageHeightInPixels))
1565         return;
1566     if (!arguments[0].isString())
1567         return;
1568     WebFrame* frame = m_shell->webView()->mainFrame();
1569     if (!frame)
1570         return;
1571     result->set(frame->pageNumberForElementById(cppVariantToWebString(arguments[0]),
1572                                                 static_cast<float>(pageWidthInPixels),
1573                                                 static_cast<float>(pageHeightInPixels)));
1574 }
1575
1576 void LayoutTestController::numberOfPages(const CppArgumentList& arguments, CppVariant* result)
1577 {
1578     result->setNull();
1579     int pageWidthInPixels = 0;
1580     int pageHeightInPixels = 0;
1581     if (!parsePageSizeParameters(arguments, 0, &pageWidthInPixels, &pageHeightInPixels))
1582         return;
1583
1584     WebFrame* frame = m_shell->webView()->mainFrame();
1585     if (!frame)
1586         return;
1587     WebSize size(pageWidthInPixels, pageHeightInPixels);
1588     int numberOfPages = frame->printBegin(size);
1589     frame->printEnd();
1590     result->set(numberOfPages);
1591 }
1592
1593 void LayoutTestController::numberOfPendingGeolocationPermissionRequests(const CppArgumentList& arguments, CppVariant* result)
1594 {
1595     result->setNull();
1596     Vector<WebViewHost*> windowList = m_shell->windowList();
1597     int numberOfRequests = 0;
1598     for (size_t i = 0; i < windowList.size(); i++)
1599         numberOfRequests += windowList[i]->geolocationClientMock()->numberOfPendingPermissionRequests();
1600     result->set(numberOfRequests);
1601 }
1602
1603 void LayoutTestController::logErrorToConsole(const std::string& text)
1604 {
1605     m_shell->webViewHost()->didAddMessageToConsole(
1606         WebConsoleMessage(WebConsoleMessage::LevelError, WebString::fromUTF8(text)),
1607         WebString(), 0);
1608 }
1609
1610 void LayoutTestController::setJavaScriptProfilingEnabled(const CppArgumentList& arguments, CppVariant* result)
1611 {
1612     result->setNull();
1613     if (arguments.size() < 1 || !arguments[0].isBool())
1614         return;
1615     m_shell->drtDevToolsAgent()->setJavaScriptProfilingEnabled(arguments[0].toBoolean());
1616 }
1617
1618 void LayoutTestController::evaluateInWebInspector(const CppArgumentList& arguments, CppVariant* result)
1619 {
1620     result->setNull();
1621     if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isString())
1622         return;
1623     m_shell->drtDevToolsAgent()->evaluateInWebInspector(arguments[0].toInt32(), arguments[1].toString());
1624 }
1625
1626 void LayoutTestController::forceRedSelectionColors(const CppArgumentList& arguments, CppVariant* result)
1627 {
1628     result->setNull();
1629     m_shell->webView()->setSelectionColors(0xffee0000, 0xff00ee00, 0xff000000, 0xffc0c0c0);
1630 }
1631
1632 void LayoutTestController::addUserScript(const CppArgumentList& arguments, CppVariant* result)
1633 {
1634     result->setNull();
1635     if (arguments.size() < 3 || !arguments[0].isString() || !arguments[1].isBool() || !arguments[2].isBool())
1636         return;
1637     WebView::addUserScript(
1638         cppVariantToWebString(arguments[0]), WebVector<WebString>(),
1639         arguments[1].toBoolean() ? WebView::UserScriptInjectAtDocumentStart : WebView::UserScriptInjectAtDocumentEnd,
1640         arguments[2].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly);
1641 }
1642
1643 void LayoutTestController::addUserStyleSheet(const CppArgumentList& arguments, CppVariant* result)
1644 {
1645     result->setNull();
1646     if (arguments.size() < 2 || !arguments[0].isString() || !arguments[1].isBool())
1647         return;
1648     WebView::addUserStyleSheet(
1649         cppVariantToWebString(arguments[0]), WebVector<WebString>(),
1650         arguments[1].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly,
1651         // Chromium defaults to InjectInSubsequentDocuments, but for compatibility
1652         // with the other ports' DRTs, we use UserStyleInjectInExistingDocuments.
1653         WebView::UserStyleInjectInExistingDocuments);
1654 }
1655
1656 void LayoutTestController::setEditingBehavior(const CppArgumentList& arguments, CppVariant* results)
1657 {
1658     string key = arguments[0].toString();
1659     if (key == "mac") {
1660         m_shell->preferences()->editingBehavior = WebSettings::EditingBehaviorMac;
1661         m_shell->applyPreferences();
1662     } else if (key == "win") {
1663         m_shell->preferences()->editingBehavior = WebSettings::EditingBehaviorWin;
1664         m_shell->applyPreferences();
1665     } else if (key == "unix") {
1666         m_shell->preferences()->editingBehavior = WebSettings::EditingBehaviorUnix;
1667         m_shell->applyPreferences();
1668     } else
1669         logErrorToConsole("Passed invalid editing behavior. Should be 'mac', 'win', or 'unix'.");
1670 }
1671
1672 void LayoutTestController::setMockDeviceOrientation(const CppArgumentList& arguments, CppVariant* result)
1673 {
1674     result->setNull();
1675     if (arguments.size() < 6 || !arguments[0].isBool() || !arguments[1].isNumber() || !arguments[2].isBool() || !arguments[3].isNumber() || !arguments[4].isBool() || !arguments[5].isNumber())
1676         return;
1677
1678     WebDeviceOrientation orientation(arguments[0].toBoolean(), arguments[1].toDouble(), arguments[2].toBoolean(), arguments[3].toDouble(), arguments[4].toBoolean(), arguments[5].toDouble());
1679     // Note that we only call setOrientation on the main page's mock since this is all that the
1680     // tests require. If necessary, we could get a list of WebViewHosts from the TestShell and
1681     // call setOrientation on each DeviceOrientationClientMock.
1682     m_shell->webViewHost()->deviceOrientationClientMock()->setOrientation(orientation);
1683 }
1684
1685 // FIXME: For greater test flexibility, we should be able to set each page's geolocation mock individually.
1686 // https://bugs.webkit.org/show_bug.cgi?id=52368
1687 void LayoutTestController::setGeolocationPermission(const CppArgumentList& arguments, CppVariant* result)
1688 {
1689     result->setNull();
1690     if (arguments.size() < 1 || !arguments[0].isBool())
1691         return;
1692     Vector<WebViewHost*> windowList = m_shell->windowList();
1693     for (size_t i = 0; i < windowList.size(); i++)
1694         windowList[i]->geolocationClientMock()->setPermission(arguments[0].toBoolean());
1695 }
1696
1697 void LayoutTestController::setMockGeolocationPosition(const CppArgumentList& arguments, CppVariant* result)
1698 {
1699     result->setNull();
1700     if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumber() || !arguments[2].isNumber())
1701         return;
1702     Vector<WebViewHost*> windowList = m_shell->windowList();
1703     for (size_t i = 0; i < windowList.size(); i++)
1704         windowList[i]->geolocationClientMock()->setPosition(arguments[0].toDouble(), arguments[1].toDouble(), arguments[2].toDouble());
1705 }
1706
1707 void LayoutTestController::setMockGeolocationError(const CppArgumentList& arguments, CppVariant* result)
1708 {
1709     result->setNull();
1710     if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isString())
1711         return;
1712     Vector<WebViewHost*> windowList = m_shell->windowList();
1713     for (size_t i = 0; i < windowList.size(); i++)
1714         windowList[i]->geolocationClientMock()->setError(arguments[0].toInt32(), cppVariantToWebString(arguments[1]));
1715 }
1716
1717 void LayoutTestController::abortModal(const CppArgumentList& arguments, CppVariant* result)
1718 {
1719     result->setNull();
1720 }
1721
1722 void LayoutTestController::addMockSpeechInputResult(const CppArgumentList& arguments, CppVariant* result)
1723 {
1724     result->setNull();
1725     if (arguments.size() < 3 || !arguments[0].isString() || !arguments[1].isNumber() || !arguments[2].isString())
1726         return;
1727
1728     m_shell->webViewHost()->speechInputControllerMock()->addMockRecognitionResult(cppVariantToWebString(arguments[0]), arguments[1].toDouble(), cppVariantToWebString(arguments[2]));
1729 }
1730
1731 void LayoutTestController::startSpeechInput(const CppArgumentList& arguments, CppVariant* result)
1732 {
1733     result->setNull();
1734     if (arguments.size() != 1)
1735         return;
1736
1737     WebElement element;
1738     if (!WebBindings::getElement(arguments[0].value.objectValue, &element))
1739         return;
1740
1741     WebInputElement* input = toWebInputElement(&element);
1742     if (!input)
1743         return;
1744
1745     if (!input->isSpeechInputEnabled())
1746         return;
1747
1748     input->startSpeechInput();
1749 }
1750
1751 void LayoutTestController::layerTreeAsText(const CppArgumentList& args, CppVariant* result)
1752 {
1753     result->set(m_shell->webView()->mainFrame()->layerTreeAsText(m_showDebugLayerTree).utf8());
1754 }
1755
1756 void LayoutTestController::loseCompositorContext(const CppArgumentList& args, CppVariant*)
1757 {
1758     int numTimes;
1759     if (args.size() == 1 || !args[0].isNumber())
1760         numTimes = 1;
1761     else
1762         numTimes = args[0].toInt32();
1763     m_shell->webView()->loseCompositorContext(numTimes);
1764 }
1765
1766 void LayoutTestController::markerTextForListItem(const CppArgumentList& args, CppVariant* result)
1767 {
1768     WebElement element;
1769     if (!WebBindings::getElement(args[0].value.objectValue, &element))
1770         result->setNull();
1771     else
1772         result->set(element.document().frame()->markerTextForListItem(element).utf8());
1773 }
1774
1775 void LayoutTestController::hasSpellingMarker(const CppArgumentList& arguments, CppVariant* result)
1776 {
1777     if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1778         return;
1779     result->set(m_shell->webView()->mainFrame()->selectionStartHasSpellingMarkerFor(arguments[0].toInt32(), arguments[1].toInt32()));
1780 }
1781
1782 void LayoutTestController::setMinimumTimerInterval(const CppArgumentList& arguments, CppVariant* result)
1783 {
1784     result->setNull();
1785     if (arguments.size() < 1 || !arguments[0].isNumber())
1786         return;
1787     m_shell->webView()->settings()->setMinimumTimerInterval(arguments[0].toDouble());
1788 }
1789
1790 void LayoutTestController::setAutofilled(const CppArgumentList& arguments, CppVariant* result)
1791 {
1792     result->setNull();
1793     if (arguments.size() != 2 || !arguments[1].isBool())
1794         return;
1795
1796     WebElement element;
1797     if (!WebBindings::getElement(arguments[0].value.objectValue, &element))
1798         return;
1799
1800     WebInputElement* input = toWebInputElement(&element);
1801     if (!input)
1802         return;
1803
1804     input->setAutofilled(arguments[1].value.boolValue);
1805 }
1806
1807 void LayoutTestController::setValueForUser(const CppArgumentList& arguments, CppVariant* result)
1808 {
1809     result->setNull();
1810     if (arguments.size() != 2)
1811         return;
1812
1813     WebElement element;
1814     if (!WebBindings::getElement(arguments[0].value.objectValue, &element))
1815         return;
1816
1817     WebInputElement* input = toWebInputElement(&element);
1818     if (!input)
1819         return;
1820
1821     input->setValue(cppVariantToWebString(arguments[1]), true);
1822 }
1823
1824 void LayoutTestController::deleteAllLocalStorage(const CppArgumentList& arguments, CppVariant*)
1825 {
1826     // Not Implemented
1827 }
1828
1829 void LayoutTestController::localStorageDiskUsageForOrigin(const CppArgumentList& arguments, CppVariant*)
1830 {
1831     // Not Implemented
1832 }
1833
1834 void LayoutTestController::originsWithLocalStorage(const CppArgumentList& arguments, CppVariant*)
1835 {
1836     // Not Implemented
1837 }
1838
1839 void LayoutTestController::deleteLocalStorageForOrigin(const CppArgumentList& arguments, CppVariant*)
1840 {
1841     // Not Implemented
1842 }
1843
1844 void LayoutTestController::observeStorageTrackerNotifications(const CppArgumentList&, CppVariant*)
1845 {
1846     // Not Implemented
1847 }
1848
1849 void LayoutTestController::syncLocalStorage(const CppArgumentList&, CppVariant*)
1850 {
1851     // Not Implemented
1852 }
1853
1854 void LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload(const CppArgumentList& arguments, CppVariant* result)
1855 {
1856     if (arguments.size() == 1 && arguments[0].isBool())
1857         m_shouldStayOnPageAfterHandlingBeforeUnload = arguments[0].toBoolean();
1858
1859     result->setNull();
1860 }
1861
1862 void LayoutTestController::enableFixedLayoutMode(const CppArgumentList& arguments, CppVariant* result)
1863 {
1864     if (arguments.size() <  1 || !arguments[0].isBool())
1865         return;
1866     bool enableFixedLayout = arguments[0].toBoolean();
1867     m_shell->webView()->enableFixedLayoutMode(enableFixedLayout);
1868     result->setNull();
1869 }
1870
1871 void LayoutTestController::setFixedLayoutSize(const CppArgumentList& arguments, CppVariant* result)
1872 {
1873     if (arguments.size() <  2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1874         return;
1875     int width = arguments[0].toInt32();
1876     int height = arguments[1].toInt32();
1877     m_shell->webView()->setFixedLayoutSize(WebSize(width, height));
1878     result->setNull();
1879 }
1880
1881 void LayoutTestController::setPluginsEnabled(const CppArgumentList& arguments, CppVariant* result)
1882 {
1883     if (arguments.size() > 0 && arguments[0].isBool()) {
1884         m_shell->preferences()->pluginsEnabled = arguments[0].toBoolean();
1885         m_shell->applyPreferences();
1886     }
1887     result->setNull();
1888 }
1889
1890 void LayoutTestController::resetPageVisibility(const CppArgumentList& arguments, CppVariant* result)
1891 {
1892     m_shell->webView()->setVisibilityState(WebPageVisibilityStateVisible, true);
1893 }
1894
1895 void LayoutTestController::setPageVisibility(const CppArgumentList& arguments, CppVariant* result)
1896 {
1897     if (arguments.size() > 0 && arguments[0].isString()) {
1898         string newVisibility = arguments[0].toString();
1899         if (newVisibility == "visible")
1900             m_shell->webView()->setVisibilityState(WebPageVisibilityStateVisible, false);
1901         else if (newVisibility == "hidden")
1902             m_shell->webView()->setVisibilityState(WebPageVisibilityStateHidden, false);
1903         else if (newVisibility == "prerender")
1904             m_shell->webView()->setVisibilityState(WebPageVisibilityStatePrerender, false);
1905     }
1906 }
1907
1908 void LayoutTestController::setTextDirection(const CppArgumentList& arguments, CppVariant* result)
1909 {
1910     result->setNull();
1911     if (arguments.size() != 1 || !arguments[0].isString())
1912         return;
1913
1914     // Map a direction name to a WebTextDirection value.
1915     std::string directionName = arguments[0].toString();
1916     WebKit::WebTextDirection direction;
1917     if (directionName == "auto")
1918         direction = WebKit::WebTextDirectionDefault;
1919     else if (directionName == "rtl")
1920         direction = WebKit::WebTextDirectionRightToLeft;
1921     else if (directionName == "ltr")
1922         direction = WebKit::WebTextDirectionLeftToRight;
1923     else
1924         return;
1925
1926     m_shell->webView()->setTextDirection(direction);
1927 }
1928
1929 void LayoutTestController::setAudioData(const CppArgumentList& arguments, CppVariant* result)
1930 {
1931     result->setNull();
1932
1933     if (arguments.size() < 1 || !arguments[0].isObject())
1934         return;
1935
1936     // Check that passed-in object is, in fact, an ArrayBufferView.
1937     NPObject* npobject = NPVARIANT_TO_OBJECT(arguments[0]);
1938     if (!npobject)
1939         return;
1940     if (!WebBindings::getArrayBufferView(npobject, &m_audioData))
1941         return;
1942
1943     setShouldDumpAsAudio(true);
1944 }