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