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