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