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