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