Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  * Copyright (C) 2010 Pawel Hajdan (phajdan.jr (at) 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("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 
    220 LayoutTestController::~LayoutTestController()
    221 {
    222 }
    223 
    224 LayoutTestController::WorkQueue::~WorkQueue()
    225 {
    226     reset();
    227 }
    228 
    229 void 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 
    241 void 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 
    256 void LayoutTestController::WorkQueue::reset()
    257 {
    258     m_frozen = false;
    259     while (!m_queue.isEmpty()) {
    260         delete m_queue.takeFirst();
    261     }
    262 }
    263 
    264 void LayoutTestController::WorkQueue::addWork(WorkItem* work)
    265 {
    266     if (m_frozen) {
    267         delete work;
    268         return;
    269     }
    270     m_queue.append(work);
    271 }
    272 
    273 void 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 
    285 void LayoutTestController::dumpDatabaseCallbacks(const CppArgumentList&, CppVariant* result)
    286 {
    287     // Do nothing; we don't use this flag anywhere for now
    288     result->setNull();
    289 }
    290 
    291 void LayoutTestController::dumpEditingCallbacks(const CppArgumentList&, CppVariant* result)
    292 {
    293     m_dumpEditingCallbacks = true;
    294     result->setNull();
    295 }
    296 
    297 void LayoutTestController::dumpBackForwardList(const CppArgumentList&, CppVariant* result)
    298 {
    299     m_dumpBackForwardList = true;
    300     result->setNull();
    301 }
    302 
    303 void LayoutTestController::dumpFrameLoadCallbacks(const CppArgumentList&, CppVariant* result)
    304 {
    305     m_dumpFrameLoadCallbacks = true;
    306     result->setNull();
    307 }
    308 
    309 void LayoutTestController::dumpUserGestureInFrameLoadCallbacks(const CppArgumentList&, CppVariant* result)
    310 {
    311     m_dumpUserGestureInFrameLoadCallbacks = true;
    312     result->setNull();
    313 }
    314 
    315 void LayoutTestController::dumpResourceLoadCallbacks(const CppArgumentList&, CppVariant* result)
    316 {
    317     m_dumpResourceLoadCallbacks = true;
    318     result->setNull();
    319 }
    320 
    321 void LayoutTestController::dumpResourceResponseMIMETypes(const CppArgumentList&, CppVariant* result)
    322 {
    323     m_dumpResourceResponseMIMETypes = true;
    324     result->setNull();
    325 }
    326 
    327 void LayoutTestController::dumpChildFrameScrollPositions(const CppArgumentList&, CppVariant* result)
    328 {
    329     m_dumpChildFrameScrollPositions = true;
    330     result->setNull();
    331 }
    332 
    333 void LayoutTestController::dumpChildFramesAsText(const CppArgumentList&, CppVariant* result)
    334 {
    335     m_dumpChildFramesAsText = true;
    336     result->setNull();
    337 }
    338 
    339 void LayoutTestController::dumpWindowStatusChanges(const CppArgumentList&, CppVariant* result)
    340 {
    341     m_dumpWindowStatusChanges = true;
    342     result->setNull();
    343 }
    344 
    345 void LayoutTestController::dumpTitleChanges(const CppArgumentList&, CppVariant* result)
    346 {
    347     m_dumpTitleChanges = true;
    348     result->setNull();
    349 }
    350 
    351 void 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 
    358 void 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 
    366 void 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 
    375 void 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 
    386 class WorkItemBackForward : public LayoutTestController::WorkItem {
    387 public:
    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     }
    394 private:
    395     int m_distance;
    396 };
    397 
    398 void 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 
    405 void 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 
    412 class WorkItemReload : public LayoutTestController::WorkItem {
    413 public:
    414     bool run(TestShell* shell)
    415     {
    416         shell->reload();
    417         return true;
    418     }
    419 };
    420 
    421 void LayoutTestController::queueReload(const CppArgumentList&, CppVariant* result)
    422 {
    423     m_workQueue.addWork(new WorkItemReload);
    424     result->setNull();
    425 }
    426 
    427 class WorkItemLoadingScript : public LayoutTestController::WorkItem {
    428 public:
    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     }
    435 private:
    436     string m_script;
    437 };
    438 
    439 class WorkItemNonLoadingScript : public LayoutTestController::WorkItem {
    440 public:
    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     }
    447 private:
    448     string m_script;
    449 };
    450 
    451 void 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 
    458 void 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 
    465 class WorkItemLoad : public LayoutTestController::WorkItem {
    466 public:
    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     }
    475 private:
    476     WebURL m_url;
    477     WebString m_target;
    478 };
    479 
    480 void 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 
    496 class WorkItemLoadHTMLString : public LayoutTestController::WorkItem  {
    497 public:
    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     }
    511 private:
    512     std::string m_html;
    513     WebURL m_baseURL;
    514     WebURL m_unreachableURL;
    515 };
    516 
    517 void 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 
    532 void 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 
    542 void 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 
    596 void 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 
    607 void LayoutTestController::policyDelegateDone()
    608 {
    609     ASSERT(m_waitUntilDone);
    610     m_shell->testFinished();
    611     m_waitUntilDone = false;
    612 }
    613 
    614 void LayoutTestController::setCanOpenWindows(const CppArgumentList&, CppVariant* result)
    615 {
    616     m_canOpenWindows = true;
    617     result->setNull();
    618 }
    619 
    620 void 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 
    627 void LayoutTestController::windowCount(const CppArgumentList&, CppVariant* result)
    628 {
    629     result->set(static_cast<int>(m_shell->windowCount()));
    630 }
    631 
    632 void 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 
    639 void 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 
    646 void 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 
    653 void 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 
    675 void LayoutTestController::showWebInspector(const CppArgumentList&, CppVariant* result)
    676 {
    677     m_shell->showDevTools();
    678     result->setNull();
    679 }
    680 
    681 void LayoutTestController::closeWebInspector(const CppArgumentList& args, CppVariant* result)
    682 {
    683     m_shell->closeDevTools();
    684     result->setNull();
    685 }
    686 
    687 void 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 
    694 void 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 
    703 void 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 
    714 void 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 
    723 void 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 
    740 void 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 
    752 void 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 
    762 void LayoutTestController::setUseDashboardCompatibilityMode(const CppArgumentList&, CppVariant* result)
    763 {
    764     // We have no need to support Dashboard Compatibility Mode (mac-only)
    765     result->setNull();
    766 }
    767 
    768 void LayoutTestController::clearAllApplicationCaches(const CppArgumentList&, CppVariant* result)
    769 {
    770     // FIXME: Implement to support application cache quotas.
    771     result->setNull();
    772 }
    773 
    774 void LayoutTestController::clearApplicationCacheForOrigin(const CppArgumentList&, CppVariant* result)
    775 {
    776     // FIXME: Implement to support deleting all application cache for an origin.
    777     result->setNull();
    778 }
    779 
    780 void LayoutTestController::setApplicationCacheOriginQuota(const CppArgumentList&, CppVariant* result)
    781 {
    782     // FIXME: Implement to support application cache quotas.
    783     result->setNull();
    784 }
    785 
    786 void LayoutTestController::originsWithApplicationCache(const CppArgumentList&, CppVariant* result)
    787 {
    788     // FIXME: Implement to support getting origins that have application caches.
    789     result->setNull();
    790 }
    791 
    792 void 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 
    799 void 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 
    811 void LayoutTestController::waitForPolicyDelegate(const CppArgumentList&, CppVariant* result)
    812 {
    813     m_shell->webViewHost()->waitForPolicyDelegate();
    814     m_waitUntilDone = true;
    815     result->setNull();
    816 }
    817 
    818 void 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 
    828 void 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 
    835 void 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 
    842 void 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 
    880 void LayoutTestController::addFileToPasteboardOnDrag(const CppArgumentList&, CppVariant* result)
    881 {
    882     result->setNull();
    883     m_shouldAddFileToPasteboard = true;
    884 }
    885 
    886 void LayoutTestController::setStopProvisionalFrameLoads(const CppArgumentList&, CppVariant* result)
    887 {
    888     result->setNull();
    889     m_stopProvisionalFrameLoads = true;
    890 }
    891 
    892 void 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 
    899 void 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 
    906 bool 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 
    922 bool 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 
    938 bool 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 
    952 int 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 
    965 void 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 
    978 void 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 
    991 void 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 
   1002 void 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 
   1013 void 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 
   1023 void LayoutTestController::numberOfActiveAnimations(const CppArgumentList&, CppVariant* result)
   1024 {
   1025     result->set(numberOfActiveAnimations());
   1026 }
   1027 
   1028 void LayoutTestController::suspendAnimations(const CppArgumentList&, CppVariant* result)
   1029 {
   1030     suspendAnimations();
   1031     result->setNull();
   1032 }
   1033 
   1034 void LayoutTestController::resumeAnimations(const CppArgumentList&, CppVariant* result)
   1035 {
   1036     resumeAnimations();
   1037     result->setNull();
   1038 }
   1039 
   1040 void 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 
   1053 void LayoutTestController::disableImageLoading(const CppArgumentList&, CppVariant* result)
   1054 {
   1055     m_shell->preferences()->loadsImagesAutomatically = false;
   1056     m_shell->applyPreferences();
   1057     result->setNull();
   1058 }
   1059 
   1060 void LayoutTestController::setIconDatabaseEnabled(const CppArgumentList&, CppVariant* result)
   1061 {
   1062     // We don't use the WebKit icon database.
   1063     result->setNull();
   1064 }
   1065 
   1066 void LayoutTestController::callShouldCloseOnWebView(const CppArgumentList&, CppVariant* result)
   1067 {
   1068     result->set(m_shell->webView()->dispatchBeforeUnloadEvent());
   1069 }
   1070 
   1071 void 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 
   1081 void 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 
   1093 void 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 
   1100 void 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 
   1110 void LayoutTestController::dumpAsWebArchive(const CppArgumentList& arguments, CppVariant* result)
   1111 {
   1112     result->setNull();
   1113 }
   1114 
   1115 void LayoutTestController::setMainFrameIsFirstResponder(const CppArgumentList& arguments, CppVariant* result)
   1116 {
   1117     result->setNull();
   1118 }
   1119 
   1120 void LayoutTestController::dumpSelectionRect(const CppArgumentList& arguments, CppVariant* result)
   1121 {
   1122     m_dumpSelectionRect = true;
   1123     result->setNull();
   1124 }
   1125 
   1126 void 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 
   1137 void 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 
   1145 void LayoutTestController::testRepaint(const CppArgumentList&, CppVariant* result)
   1146 {
   1147     m_testRepaint = true;
   1148     result->setNull();
   1149 }
   1150 
   1151 void LayoutTestController::repaintSweepHorizontally(const CppArgumentList&, CppVariant* result)
   1152 {
   1153     m_sweepHorizontally = true;
   1154     result->setNull();
   1155 }
   1156 
   1157 void LayoutTestController::clearBackForwardList(const CppArgumentList& arguments, CppVariant* result)
   1158 {
   1159     result->setNull();
   1160 }
   1161 
   1162 void LayoutTestController::keepWebHistory(const CppArgumentList& arguments,  CppVariant* result)
   1163 {
   1164     result->setNull();
   1165 }
   1166 
   1167 void LayoutTestController::storeWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
   1168 {
   1169     result->setNull();
   1170 }
   1171 
   1172 void LayoutTestController::accessStoredWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
   1173 {
   1174     result->setNull();
   1175 }
   1176 
   1177 void LayoutTestController::objCClassNameOf(const CppArgumentList& arguments, CppVariant* result)
   1178 {
   1179     result->setNull();
   1180 }
   1181 
   1182 void LayoutTestController::addDisallowedURL(const CppArgumentList& arguments, CppVariant* result)
   1183 {
   1184     result->setNull();
   1185 }
   1186 
   1187 void LayoutTestController::setCallCloseOnWebViews(const CppArgumentList& arguments, CppVariant* result)
   1188 {
   1189     result->setNull();
   1190 }
   1191 
   1192 void LayoutTestController::setPrivateBrowsingEnabled(const CppArgumentList& arguments, CppVariant* result)
   1193 {
   1194     result->setNull();
   1195 }
   1196 
   1197 void 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 
   1206 void 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 
   1215 void 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 
   1226 void 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 
   1235 void 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.
   1246 bool 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 
   1263 int32_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 
   1279 WebString 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 
   1288 void 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 
   1365 void LayoutTestController::fallbackMethod(const CppArgumentList&, CppVariant* result)
   1366 {
   1367     printf("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on LayoutTestController\n");
   1368     result->setNull();
   1369 }
   1370 
   1371 void 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 
   1390 void 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 
   1409 void LayoutTestController::clearAllDatabases(const CppArgumentList& arguments, CppVariant* result)
   1410 {
   1411     result->setNull();
   1412     webkit_support::ClearAllDatabases();
   1413 }
   1414 
   1415 void 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 
   1422 void 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 
   1429 void 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 
   1443 static 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 
   1468 void 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 
   1486 void 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 
   1503 void 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 
   1513 void LayoutTestController::logErrorToConsole(const std::string& text)
   1514 {
   1515     m_shell->webViewHost()->didAddMessageToConsole(
   1516         WebConsoleMessage(WebConsoleMessage::LevelError, WebString::fromUTF8(text)),
   1517         WebString(), 0);
   1518 }
   1519 
   1520 void 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 
   1528 void 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 
   1536 void 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 
   1547 void 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 
   1560 void 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 
   1576 void 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
   1591 void 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 
   1601 void 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 
   1611 void 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 
   1621 void LayoutTestController::abortModal(const CppArgumentList& arguments, CppVariant* result)
   1622 {
   1623     result->setNull();
   1624 }
   1625 
   1626 void 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 
   1635 void LayoutTestController::layerTreeAsText(const CppArgumentList& args, CppVariant* result)
   1636 {
   1637     result->set(m_shell->webView()->mainFrame()->layerTreeAsText(m_showDebugLayerTree).utf8());
   1638 }
   1639 
   1640 void 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 
   1649 void 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 
   1656 void 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 
   1664 void 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 
   1681 void 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 
   1698 void LayoutTestController::deleteAllLocalStorage(const CppArgumentList& arguments, CppVariant*)
   1699 {
   1700     // Not Implemented
   1701 }
   1702 
   1703 void LayoutTestController::originsWithLocalStorage(const CppArgumentList& arguments, CppVariant*)
   1704 {
   1705     // Not Implemented
   1706 }
   1707 
   1708 void LayoutTestController::deleteLocalStorageForOrigin(const CppArgumentList& arguments, CppVariant*)
   1709 {
   1710     // Not Implemented
   1711 }
   1712 
   1713 void LayoutTestController::observeStorageTrackerNotifications(const CppArgumentList&, CppVariant*)
   1714 {
   1715     // Not Implemented
   1716 }
   1717 
   1718 void LayoutTestController::syncLocalStorage(const CppArgumentList&, CppVariant*)
   1719 {
   1720     // Not Implemented
   1721 }
   1722 
   1723 void 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