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