WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     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 "WebViewHost.h"
       
    38 #include "base/string_util.h"
       
    39 #include "public/WebAnimationController.h"
       
    40 #include "public/WebConsoleMessage.h"
       
    41 #include "public/WebDocument.h"
       
    42 #include "public/WebFrame.h"
       
    43 #include "public/WebGeolocationServiceMock.h"
       
    44 #include "public/WebInputElement.h"
       
    45 #include "public/WebKit.h"
       
    46 #include "public/WebNotificationPresenter.h"
       
    47 #include "public/WebScriptSource.h"
       
    48 #include "public/WebSecurityPolicy.h"
       
    49 #include "public/WebSettings.h"
       
    50 #include "public/WebSize.h"
       
    51 #include "public/WebURL.h"
       
    52 #include "public/WebView.h"
       
    53 #include "webkit/support/webkit_support.h"
       
    54 #include <wtf/text/WTFString.h>
       
    55 
       
    56 #if OS(WINDOWS)
       
    57 #include <wtf/OwnArrayPtr.h>
       
    58 #endif
       
    59 
       
    60 using namespace WebCore;
       
    61 using namespace WebKit;
       
    62 using namespace std;
       
    63 
       
    64 LayoutTestController::LayoutTestController(TestShell* shell)
       
    65     : m_timeoutFactory(this)
       
    66     , m_shell(shell)
       
    67     , m_workQueue(this)
       
    68 {
       
    69 
       
    70     // Initialize the map that associates methods of this class with the names
       
    71     // they will use when called by JavaScript.  The actual binding of those
       
    72     // names to their methods will be done by calling bindToJavaScript() (defined
       
    73     // by CppBoundClass, the parent to LayoutTestController).
       
    74     bindMethod("dumpAsText", &LayoutTestController::dumpAsText);
       
    75     bindMethod("dumpChildFrameScrollPositions", &LayoutTestController::dumpChildFrameScrollPositions);
       
    76     bindMethod("dumpChildFramesAsText", &LayoutTestController::dumpChildFramesAsText);
       
    77     bindMethod("dumpDatabaseCallbacks", &LayoutTestController::dumpDatabaseCallbacks);
       
    78     bindMethod("dumpEditingCallbacks", &LayoutTestController::dumpEditingCallbacks);
       
    79     bindMethod("dumpBackForwardList", &LayoutTestController::dumpBackForwardList);
       
    80     bindMethod("dumpFrameLoadCallbacks", &LayoutTestController::dumpFrameLoadCallbacks);
       
    81     bindMethod("dumpResourceLoadCallbacks", &LayoutTestController::dumpResourceLoadCallbacks);
       
    82     bindMethod("dumpStatusCallbacks", &LayoutTestController::dumpWindowStatusChanges);
       
    83     bindMethod("dumpTitleChanges", &LayoutTestController::dumpTitleChanges);
       
    84     bindMethod("setAcceptsEditing", &LayoutTestController::setAcceptsEditing);
       
    85     bindMethod("waitUntilDone", &LayoutTestController::waitUntilDone);
       
    86     bindMethod("notifyDone", &LayoutTestController::notifyDone);
       
    87     bindMethod("queueReload", &LayoutTestController::queueReload);
       
    88     bindMethod("queueLoadingScript", &LayoutTestController::queueLoadingScript);
       
    89     bindMethod("queueNonLoadingScript", &LayoutTestController::queueNonLoadingScript);
       
    90     bindMethod("queueLoad", &LayoutTestController::queueLoad);
       
    91     bindMethod("queueBackNavigation", &LayoutTestController::queueBackNavigation);
       
    92     bindMethod("queueForwardNavigation", &LayoutTestController::queueForwardNavigation);
       
    93     bindMethod("windowCount", &LayoutTestController::windowCount);
       
    94     bindMethod("setCanOpenWindows", &LayoutTestController::setCanOpenWindows);
       
    95     bindMethod("setCloseRemainingWindowsWhenComplete", &LayoutTestController::setCloseRemainingWindowsWhenComplete);
       
    96     bindMethod("objCIdentityIsEqual", &LayoutTestController::objCIdentityIsEqual);
       
    97     bindMethod("setAlwaysAcceptCookies", &LayoutTestController::setAlwaysAcceptCookies);
       
    98     bindMethod("showWebInspector", &LayoutTestController::showWebInspector);
       
    99     bindMethod("closeWebInspector", &LayoutTestController::closeWebInspector);
       
   100     bindMethod("setWindowIsKey", &LayoutTestController::setWindowIsKey);
       
   101     bindMethod("setTabKeyCyclesThroughElements", &LayoutTestController::setTabKeyCyclesThroughElements);
       
   102     bindMethod("setUserStyleSheetLocation", &LayoutTestController::setUserStyleSheetLocation);
       
   103     bindMethod("setUserStyleSheetEnabled", &LayoutTestController::setUserStyleSheetEnabled);
       
   104     bindMethod("setAuthorAndUserStylesEnabled", &LayoutTestController::setAuthorAndUserStylesEnabled);
       
   105     bindMethod("pathToLocalResource", &LayoutTestController::pathToLocalResource);
       
   106     bindMethod("addFileToPasteboardOnDrag", &LayoutTestController::addFileToPasteboardOnDrag);
       
   107     bindMethod("execCommand", &LayoutTestController::execCommand);
       
   108     bindMethod("isCommandEnabled", &LayoutTestController::isCommandEnabled);
       
   109     bindMethod("setPopupBlockingEnabled", &LayoutTestController::setPopupBlockingEnabled);
       
   110     bindMethod("setStopProvisionalFrameLoads", &LayoutTestController::setStopProvisionalFrameLoads);
       
   111     bindMethod("setSmartInsertDeleteEnabled", &LayoutTestController::setSmartInsertDeleteEnabled);
       
   112     bindMethod("setSelectTrailingWhitespaceEnabled", &LayoutTestController::setSelectTrailingWhitespaceEnabled);
       
   113     bindMethod("pauseAnimationAtTimeOnElementWithId", &LayoutTestController::pauseAnimationAtTimeOnElementWithId);
       
   114     bindMethod("pauseTransitionAtTimeOnElementWithId", &LayoutTestController::pauseTransitionAtTimeOnElementWithId);
       
   115     bindMethod("elementDoesAutoCompleteForElementWithId", &LayoutTestController::elementDoesAutoCompleteForElementWithId);
       
   116     bindMethod("numberOfActiveAnimations", &LayoutTestController::numberOfActiveAnimations);
       
   117     bindMethod("disableImageLoading", &LayoutTestController::disableImageLoading);
       
   118     bindMethod("setIconDatabaseEnabled", &LayoutTestController::setIconDatabaseEnabled);
       
   119     bindMethod("setCustomPolicyDelegate", &LayoutTestController::setCustomPolicyDelegate);
       
   120     bindMethod("setScrollbarPolicy", &LayoutTestController::setScrollbarPolicy);
       
   121     bindMethod("waitForPolicyDelegate", &LayoutTestController::waitForPolicyDelegate);
       
   122     bindMethod("setWillSendRequestClearHeader", &LayoutTestController::setWillSendRequestClearHeader);
       
   123     bindMethod("setWillSendRequestReturnsNullOnRedirect", &LayoutTestController::setWillSendRequestReturnsNullOnRedirect);
       
   124     bindMethod("setWillSendRequestReturnsNull", &LayoutTestController::setWillSendRequestReturnsNull);
       
   125     bindMethod("addOriginAccessWhitelistEntry", &LayoutTestController::addOriginAccessWhitelistEntry);
       
   126     bindMethod("removeOriginAccessWhitelistEntry", &LayoutTestController::removeOriginAccessWhitelistEntry);
       
   127     bindMethod("clearAllDatabases", &LayoutTestController::clearAllDatabases);
       
   128     bindMethod("setDatabaseQuota", &LayoutTestController::setDatabaseQuota);
       
   129     bindMethod("setPOSIXLocale", &LayoutTestController::setPOSIXLocale);
       
   130     bindMethod("counterValueForElementById", &LayoutTestController::counterValueForElementById);
       
   131     bindMethod("addUserScript", &LayoutTestController::addUserScript);
       
   132     bindMethod("addUserStyleSheet", &LayoutTestController::addUserStyleSheet);
       
   133     bindMethod("pageNumberForElementById", &LayoutTestController::pageNumberForElementById);
       
   134     bindMethod("numberOfPages", &LayoutTestController::numberOfPages);
       
   135     bindMethod("dumpSelectionRect", &LayoutTestController::dumpSelectionRect);
       
   136     bindMethod("grantDesktopNotificationPermission", &LayoutTestController::grantDesktopNotificationPermission);
       
   137 
       
   138     // The following are stubs.
       
   139     bindMethod("dumpAsWebArchive", &LayoutTestController::dumpAsWebArchive);
       
   140     bindMethod("setMainFrameIsFirstResponder", &LayoutTestController::setMainFrameIsFirstResponder);
       
   141     bindMethod("dumpSelectionRect", &LayoutTestController::dumpSelectionRect);
       
   142     bindMethod("display", &LayoutTestController::display);
       
   143     bindMethod("testRepaint", &LayoutTestController::testRepaint);
       
   144     bindMethod("repaintSweepHorizontally", &LayoutTestController::repaintSweepHorizontally);
       
   145     bindMethod("clearBackForwardList", &LayoutTestController::clearBackForwardList);
       
   146     bindMethod("keepWebHistory", &LayoutTestController::keepWebHistory);
       
   147     bindMethod("storeWebScriptObject", &LayoutTestController::storeWebScriptObject);
       
   148     bindMethod("accessStoredWebScriptObject", &LayoutTestController::accessStoredWebScriptObject);
       
   149     bindMethod("objCClassNameOf", &LayoutTestController::objCClassNameOf);
       
   150     bindMethod("addDisallowedURL", &LayoutTestController::addDisallowedURL);
       
   151     bindMethod("callShouldCloseOnWebView", &LayoutTestController::callShouldCloseOnWebView);
       
   152     bindMethod("setCallCloseOnWebViews", &LayoutTestController::setCallCloseOnWebViews);
       
   153     bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled);
       
   154     bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode);
       
   155 
       
   156     bindMethod("setJavaScriptCanAccessClipboard", &LayoutTestController::setJavaScriptCanAccessClipboard);
       
   157     bindMethod("setXSSAuditorEnabled", &LayoutTestController::setXSSAuditorEnabled);
       
   158     bindMethod("evaluateScriptInIsolatedWorld", &LayoutTestController::evaluateScriptInIsolatedWorld);
       
   159     bindMethod("overridePreference", &LayoutTestController::overridePreference);
       
   160     bindMethod("setAllowUniversalAccessFromFileURLs", &LayoutTestController::setAllowUniversalAccessFromFileURLs);
       
   161     bindMethod("setAllowFileAccessFromFileURLs", &LayoutTestController::setAllowFileAccessFromFileURLs);
       
   162     bindMethod("setTimelineProfilingEnabled", &LayoutTestController::setTimelineProfilingEnabled);
       
   163     bindMethod("evaluateInWebInspector", &LayoutTestController::evaluateInWebInspector);
       
   164     bindMethod("forceRedSelectionColors", &LayoutTestController::forceRedSelectionColors);
       
   165     bindMethod("setEditingBehavior", &LayoutTestController::setEditingBehavior);
       
   166 
       
   167     bindMethod("setGeolocationPermission", &LayoutTestController::setGeolocationPermission);
       
   168     bindMethod("setMockGeolocationPosition", &LayoutTestController::setMockGeolocationPosition);
       
   169     bindMethod("setMockGeolocationError", &LayoutTestController::setMockGeolocationError);
       
   170     bindMethod("abortModal", &LayoutTestController::abortModal);
       
   171 
       
   172     // The fallback method is called when an unknown method is invoked.
       
   173     bindFallbackMethod(&LayoutTestController::fallbackMethod);
       
   174 
       
   175     // Shared properties.
       
   176     // globalFlag is used by a number of layout tests in
       
   177     // LayoutTests\http\tests\security\dataURL.
       
   178     bindProperty("globalFlag", &m_globalFlag);
       
   179     // webHistoryItemCount is used by tests in LayoutTests\http\tests\history
       
   180     bindProperty("webHistoryItemCount", &m_webHistoryItemCount);
       
   181 }
       
   182 
       
   183 LayoutTestController::WorkQueue::~WorkQueue()
       
   184 {
       
   185     reset();
       
   186 }
       
   187 
       
   188 void LayoutTestController::WorkQueue::processWorkSoon()
       
   189 {
       
   190     if (m_controller->m_shell->webViewHost()->topLoadingFrame())
       
   191         return;
       
   192 
       
   193     if (!m_queue.isEmpty()) {
       
   194         // We delay processing queued work to avoid recursion problems.
       
   195         m_timer.Start(base::TimeDelta(), this, &WorkQueue::processWork);
       
   196     } else if (!m_controller->m_waitUntilDone) {
       
   197         m_controller->m_shell->testFinished();
       
   198     }
       
   199 }
       
   200 
       
   201 void LayoutTestController::WorkQueue::processWork()
       
   202 {
       
   203     TestShell* shell = m_controller->m_shell;
       
   204     // Quit doing work once a load is in progress.
       
   205     while (!m_queue.isEmpty()) {
       
   206         bool startedLoad = m_queue.first()->run(shell);
       
   207         delete m_queue.takeFirst();
       
   208         if (startedLoad)
       
   209             return;
       
   210     }
       
   211 
       
   212     if (!m_controller->m_waitUntilDone && !shell->webViewHost()->topLoadingFrame())
       
   213         shell->testFinished();
       
   214 }
       
   215 
       
   216 void LayoutTestController::WorkQueue::reset()
       
   217 {
       
   218     m_frozen = false;
       
   219     while (!m_queue.isEmpty()) {
       
   220         delete m_queue.takeFirst();
       
   221     }
       
   222 }
       
   223 
       
   224 void LayoutTestController::WorkQueue::addWork(WorkItem* work)
       
   225 {
       
   226     if (m_frozen) {
       
   227         delete work;
       
   228         return;
       
   229     }
       
   230     m_queue.append(work);
       
   231 }
       
   232 
       
   233 void LayoutTestController::dumpAsText(const CppArgumentList& arguments, CppVariant* result)
       
   234 {
       
   235     m_dumpAsText = true;
       
   236     m_generatePixelResults = false;
       
   237 
       
   238     // Optional paramater, describing whether it's allowed to dump pixel results in dumpAsText mode.
       
   239     if (arguments.size() > 0 && arguments[0].isBool())
       
   240         m_generatePixelResults = arguments[0].value.boolValue;
       
   241 
       
   242     result->setNull();
       
   243 }
       
   244 
       
   245 void LayoutTestController::dumpDatabaseCallbacks(const CppArgumentList&, CppVariant* result)
       
   246 {
       
   247     // Do nothing; we don't use this flag anywhere for now
       
   248     result->setNull();
       
   249 }
       
   250 
       
   251 void LayoutTestController::dumpEditingCallbacks(const CppArgumentList&, CppVariant* result)
       
   252 {
       
   253     m_dumpEditingCallbacks = true;
       
   254     result->setNull();
       
   255 }
       
   256 
       
   257 void LayoutTestController::dumpBackForwardList(const CppArgumentList&, CppVariant* result)
       
   258 {
       
   259     m_dumpBackForwardList = true;
       
   260     result->setNull();
       
   261 }
       
   262 
       
   263 void LayoutTestController::dumpFrameLoadCallbacks(const CppArgumentList&, CppVariant* result)
       
   264 {
       
   265     m_dumpFrameLoadCallbacks = true;
       
   266     result->setNull();
       
   267 }
       
   268 
       
   269 void LayoutTestController::dumpResourceLoadCallbacks(const CppArgumentList&, CppVariant* result)
       
   270 {
       
   271     m_dumpResourceLoadCallbacks = true;
       
   272     result->setNull();
       
   273 }
       
   274 
       
   275 void LayoutTestController::dumpChildFrameScrollPositions(const CppArgumentList&, CppVariant* result)
       
   276 {
       
   277     m_dumpChildFrameScrollPositions = true;
       
   278     result->setNull();
       
   279 }
       
   280 
       
   281 void LayoutTestController::dumpChildFramesAsText(const CppArgumentList&, CppVariant* result)
       
   282 {
       
   283     m_dumpChildFramesAsText = true;
       
   284     result->setNull();
       
   285 }
       
   286 
       
   287 void LayoutTestController::dumpWindowStatusChanges(const CppArgumentList&, CppVariant* result)
       
   288 {
       
   289     m_dumpWindowStatusChanges = true;
       
   290     result->setNull();
       
   291 }
       
   292 
       
   293 void LayoutTestController::dumpTitleChanges(const CppArgumentList&, CppVariant* result)
       
   294 {
       
   295     m_dumpTitleChanges = true;
       
   296     result->setNull();
       
   297 }
       
   298 
       
   299 void LayoutTestController::setAcceptsEditing(const CppArgumentList& arguments, CppVariant* result)
       
   300 {
       
   301     if (arguments.size() > 0 && arguments[0].isBool())
       
   302         m_acceptsEditing = arguments[0].value.boolValue;
       
   303     result->setNull();
       
   304 }
       
   305 
       
   306 void LayoutTestController::waitUntilDone(const CppArgumentList&, CppVariant* result)
       
   307 {
       
   308     if (!webkit_support::BeingDebugged()) {
       
   309         webkit_support::PostDelayedTaskFromHere(
       
   310             m_timeoutFactory.NewRunnableMethod(&LayoutTestController::notifyDoneTimedOut),
       
   311             m_shell->layoutTestTimeout());
       
   312     }
       
   313     m_waitUntilDone = true;
       
   314     result->setNull();
       
   315 }
       
   316 
       
   317 void LayoutTestController::notifyDone(const CppArgumentList&, CppVariant* result)
       
   318 {
       
   319     // Test didn't timeout. Kill the timeout timer.
       
   320     m_timeoutFactory.RevokeAll();
       
   321 
       
   322     completeNotifyDone(false);
       
   323     result->setNull();
       
   324 }
       
   325 
       
   326 void LayoutTestController::notifyDoneTimedOut()
       
   327 {
       
   328     completeNotifyDone(true);
       
   329 }
       
   330 
       
   331 void LayoutTestController::completeNotifyDone(bool isTimeout)
       
   332 {
       
   333     if (m_waitUntilDone && !m_shell->webViewHost()->topLoadingFrame() && m_workQueue.isEmpty()) {
       
   334         if (isTimeout)
       
   335             m_shell->testTimedOut();
       
   336         else
       
   337             m_shell->testFinished();
       
   338     }
       
   339     m_waitUntilDone = false;
       
   340 }
       
   341 
       
   342 class WorkItemBackForward : public LayoutTestController::WorkItem {
       
   343 public:
       
   344     WorkItemBackForward(int distance) : m_distance(distance) {}
       
   345     bool run(TestShell* shell)
       
   346     {
       
   347         shell->goToOffset(m_distance);
       
   348         return true; // FIXME: Did it really start a navigation?
       
   349     }
       
   350 private:
       
   351     int m_distance;
       
   352 };
       
   353 
       
   354 void LayoutTestController::queueBackNavigation(const CppArgumentList& arguments, CppVariant* result)
       
   355 {
       
   356     if (arguments.size() > 0 && arguments[0].isNumber())
       
   357         m_workQueue.addWork(new WorkItemBackForward(-arguments[0].toInt32()));
       
   358     result->setNull();
       
   359 }
       
   360 
       
   361 void LayoutTestController::queueForwardNavigation(const CppArgumentList& arguments, CppVariant* result)
       
   362 {
       
   363     if (arguments.size() > 0 && arguments[0].isNumber())
       
   364         m_workQueue.addWork(new WorkItemBackForward(arguments[0].toInt32()));
       
   365     result->setNull();
       
   366 }
       
   367 
       
   368 class WorkItemReload : public LayoutTestController::WorkItem {
       
   369 public:
       
   370     bool run(TestShell* shell)
       
   371     {
       
   372         shell->reload();
       
   373         return true;
       
   374     }
       
   375 };
       
   376 
       
   377 void LayoutTestController::queueReload(const CppArgumentList&, CppVariant* result)
       
   378 {
       
   379     m_workQueue.addWork(new WorkItemReload);
       
   380     result->setNull();
       
   381 }
       
   382 
       
   383 class WorkItemLoadingScript : public LayoutTestController::WorkItem {
       
   384 public:
       
   385     WorkItemLoadingScript(const string& script) : m_script(script) {}
       
   386     bool run(TestShell* shell)
       
   387     {
       
   388         shell->webView()->mainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(m_script)));
       
   389         return true; // FIXME: Did it really start a navigation?
       
   390     }
       
   391 private:
       
   392     string m_script;
       
   393 };
       
   394 
       
   395 class WorkItemNonLoadingScript : public LayoutTestController::WorkItem {
       
   396 public:
       
   397     WorkItemNonLoadingScript(const string& script) : m_script(script) {}
       
   398     bool run(TestShell* shell)
       
   399     {
       
   400         shell->webView()->mainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(m_script)));
       
   401         return false;
       
   402     }
       
   403 private:
       
   404     string m_script;
       
   405 };
       
   406 
       
   407 void LayoutTestController::queueLoadingScript(const CppArgumentList& arguments, CppVariant* result)
       
   408 {
       
   409     if (arguments.size() > 0 && arguments[0].isString())
       
   410         m_workQueue.addWork(new WorkItemLoadingScript(arguments[0].toString()));
       
   411     result->setNull();
       
   412 }
       
   413 
       
   414 void LayoutTestController::queueNonLoadingScript(const CppArgumentList& arguments, CppVariant* result)
       
   415 {
       
   416     if (arguments.size() > 0 && arguments[0].isString())
       
   417         m_workQueue.addWork(new WorkItemNonLoadingScript(arguments[0].toString()));
       
   418     result->setNull();
       
   419 }
       
   420 
       
   421 class WorkItemLoad : public LayoutTestController::WorkItem {
       
   422 public:
       
   423     WorkItemLoad(const WebURL& url, const WebString& target)
       
   424         : m_url(url)
       
   425         , m_target(target) {}
       
   426     bool run(TestShell* shell)
       
   427     {
       
   428         shell->webViewHost()->loadURLForFrame(m_url, m_target);
       
   429         return true; // FIXME: Did it really start a navigation?
       
   430     }
       
   431 private:
       
   432     WebURL m_url;
       
   433     WebString m_target;
       
   434 };
       
   435 
       
   436 void LayoutTestController::queueLoad(const CppArgumentList& arguments, CppVariant* result)
       
   437 {
       
   438     if (arguments.size() > 0 && arguments[0].isString()) {
       
   439         // FIXME: Implement WebURL::resolve() and avoid GURL.
       
   440         GURL currentURL = m_shell->webView()->mainFrame()->url();
       
   441         GURL fullURL = currentURL.Resolve(arguments[0].toString());
       
   442 
       
   443         string target = "";
       
   444         if (arguments.size() > 1 && arguments[1].isString())
       
   445             target = arguments[1].toString();
       
   446 
       
   447         m_workQueue.addWork(new WorkItemLoad(fullURL, WebString::fromUTF8(target)));
       
   448     }
       
   449     result->setNull();
       
   450 }
       
   451 
       
   452 void LayoutTestController::objCIdentityIsEqual(const CppArgumentList& arguments, CppVariant* result)
       
   453 {
       
   454     if (arguments.size() < 2) {
       
   455         // This is the best we can do to return an error.
       
   456         result->setNull();
       
   457         return;
       
   458     }
       
   459     result->set(arguments[0].isEqual(arguments[1]));
       
   460 }
       
   461 
       
   462 void LayoutTestController::reset()
       
   463 {
       
   464     if (m_shell) {
       
   465         m_shell->webView()->setZoomLevel(false, 0);
       
   466         m_shell->webView()->setTabKeyCyclesThroughElements(true);
       
   467 #if !OS(DARWIN) && !OS(WINDOWS) // Actually, TOOLKIT_GTK
       
   468         // (Constants copied because we can't depend on the header that defined
       
   469         // them from this file.)
       
   470         m_shell->webView()->setSelectionColors(0xff1e90ff, 0xff000000, 0xffc8c8c8, 0xff323232);
       
   471 #endif
       
   472         m_shell->webView()->removeAllUserContent();
       
   473     }
       
   474     m_dumpAsText = false;
       
   475     m_dumpEditingCallbacks = false;
       
   476     m_dumpFrameLoadCallbacks = false;
       
   477     m_dumpResourceLoadCallbacks = false;
       
   478     m_dumpBackForwardList = false;
       
   479     m_dumpChildFrameScrollPositions = false;
       
   480     m_dumpChildFramesAsText = false;
       
   481     m_dumpWindowStatusChanges = false;
       
   482     m_dumpSelectionRect = false;
       
   483     m_dumpTitleChanges = false;
       
   484     m_generatePixelResults = true;
       
   485     m_acceptsEditing = true;
       
   486     m_waitUntilDone = false;
       
   487     m_canOpenWindows = false;
       
   488     m_testRepaint = false;
       
   489     m_sweepHorizontally = false;
       
   490     m_shouldAddFileToPasteboard = false;
       
   491     m_stopProvisionalFrameLoads = false;
       
   492     m_globalFlag.set(false);
       
   493     m_webHistoryItemCount.set(0);
       
   494     m_userStyleSheetLocation = WebURL();
       
   495 
       
   496     webkit_support::SetAcceptAllCookies(false);
       
   497     WebSecurityPolicy::resetOriginAccessWhitelists();
       
   498 
       
   499     // Reset the default quota for each origin to 5MB
       
   500     webkit_support::SetDatabaseQuota(5 * 1024 * 1024);
       
   501 
       
   502     setlocale(LC_ALL, "");
       
   503 
       
   504     if (m_closeRemainingWindows)
       
   505         m_shell->closeRemainingWindows();
       
   506     else
       
   507         m_closeRemainingWindows = true;
       
   508     m_workQueue.reset();
       
   509 }
       
   510 
       
   511 void LayoutTestController::locationChangeDone()
       
   512 {
       
   513     m_webHistoryItemCount.set(m_shell->navigationEntryCount());
       
   514 
       
   515     // No more new work after the first complete load.
       
   516     m_workQueue.setFrozen(true);
       
   517 
       
   518     if (!m_waitUntilDone)
       
   519         m_workQueue.processWorkSoon();
       
   520 }
       
   521 
       
   522 void LayoutTestController::policyDelegateDone()
       
   523 {
       
   524     ASSERT(m_waitUntilDone);
       
   525     m_shell->testFinished();
       
   526     m_waitUntilDone = false;
       
   527 }
       
   528 
       
   529 void LayoutTestController::setCanOpenWindows(const CppArgumentList&, CppVariant* result)
       
   530 {
       
   531     m_canOpenWindows = true;
       
   532     result->setNull();
       
   533 }
       
   534 
       
   535 void LayoutTestController::setTabKeyCyclesThroughElements(const CppArgumentList& arguments, CppVariant* result)
       
   536 {
       
   537     if (arguments.size() > 0 && arguments[0].isBool())
       
   538         m_shell->webView()->setTabKeyCyclesThroughElements(arguments[0].toBoolean());
       
   539     result->setNull();
       
   540 }
       
   541 
       
   542 void LayoutTestController::windowCount(const CppArgumentList&, CppVariant* result)
       
   543 {
       
   544     result->set(static_cast<int>(m_shell->windowCount()));
       
   545 }
       
   546 
       
   547 void LayoutTestController::setCloseRemainingWindowsWhenComplete(const CppArgumentList& arguments, CppVariant* result)
       
   548 {
       
   549     if (arguments.size() > 0 && arguments[0].isBool())
       
   550         m_closeRemainingWindows = arguments[0].value.boolValue;
       
   551     result->setNull();
       
   552 }
       
   553 
       
   554 void LayoutTestController::setAlwaysAcceptCookies(const CppArgumentList& arguments, CppVariant* result)
       
   555 {
       
   556     if (arguments.size() > 0)
       
   557         webkit_support::SetAcceptAllCookies(cppVariantToBool(arguments[0]));
       
   558     result->setNull();
       
   559 }
       
   560 
       
   561 void LayoutTestController::showWebInspector(const CppArgumentList&, CppVariant* result)
       
   562 {
       
   563     m_shell->showDevTools();
       
   564     result->setNull();
       
   565 }
       
   566 
       
   567 void LayoutTestController::closeWebInspector(const CppArgumentList& args, CppVariant* result)
       
   568 {
       
   569     m_shell->closeDevTools();
       
   570     result->setNull();
       
   571 }
       
   572 
       
   573 void LayoutTestController::setWindowIsKey(const CppArgumentList& arguments, CppVariant* result)
       
   574 {
       
   575     if (arguments.size() > 0 && arguments[0].isBool())
       
   576         m_shell->setFocus(m_shell->webView(), arguments[0].value.boolValue);
       
   577     result->setNull();
       
   578 }
       
   579 
       
   580 void LayoutTestController::setUserStyleSheetEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   581 {
       
   582     if (arguments.size() > 0 && arguments[0].isBool())
       
   583         m_shell->webView()->settings()->setUserStyleSheetLocation(arguments[0].value.boolValue ? m_userStyleSheetLocation : WebURL());
       
   584     result->setNull();
       
   585 }
       
   586 
       
   587 void LayoutTestController::setUserStyleSheetLocation(const CppArgumentList& arguments, CppVariant* result)
       
   588 {
       
   589     if (arguments.size() > 0 && arguments[0].isString()) {
       
   590         m_userStyleSheetLocation = webkit_support::RewriteLayoutTestsURL(arguments[0].toString());
       
   591         m_shell->webView()->settings()->setUserStyleSheetLocation(m_userStyleSheetLocation);
       
   592     }
       
   593     result->setNull();
       
   594 }
       
   595 
       
   596 void LayoutTestController::setAuthorAndUserStylesEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   597 {
       
   598     if (arguments.size() > 0 && arguments[0].isBool())
       
   599         m_shell->webView()->settings()->setAuthorAndUserStylesEnabled(arguments[0].value.boolValue);
       
   600     result->setNull();
       
   601 }
       
   602 
       
   603 void LayoutTestController::execCommand(const CppArgumentList& arguments, CppVariant* result)
       
   604 {
       
   605     result->setNull();
       
   606     if (arguments.size() <= 0 || !arguments[0].isString())
       
   607         return;
       
   608 
       
   609     std::string command = arguments[0].toString();
       
   610     std::string value("");
       
   611     // Ignore the second parameter (which is userInterface)
       
   612     // since this command emulates a manual action.
       
   613     if (arguments.size() >= 3 && arguments[2].isString())
       
   614         value = arguments[2].toString();
       
   615 
       
   616     // Note: webkit's version does not return the boolean, so neither do we.
       
   617     m_shell->webView()->focusedFrame()->executeCommand(WebString::fromUTF8(command), WebString::fromUTF8(value));
       
   618 }
       
   619 
       
   620 void LayoutTestController::isCommandEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   621 {
       
   622     if (arguments.size() <= 0 || !arguments[0].isString()) {
       
   623         result->setNull();
       
   624         return;
       
   625     }
       
   626 
       
   627     std::string command = arguments[0].toString();
       
   628     bool rv = m_shell->webView()->focusedFrame()->isCommandEnabled(WebString::fromUTF8(command));
       
   629     result->set(rv);
       
   630 }
       
   631 
       
   632 void LayoutTestController::setPopupBlockingEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   633 {
       
   634     if (arguments.size() > 0 && arguments[0].isBool()) {
       
   635         bool blockPopups = arguments[0].toBoolean();
       
   636         m_shell->webView()->settings()->setJavaScriptCanOpenWindowsAutomatically(!blockPopups);
       
   637     }
       
   638     result->setNull();
       
   639 }
       
   640 
       
   641 void LayoutTestController::setUseDashboardCompatibilityMode(const CppArgumentList&, CppVariant* result)
       
   642 {
       
   643     // We have no need to support Dashboard Compatibility Mode (mac-only)
       
   644     result->setNull();
       
   645 }
       
   646 
       
   647 void LayoutTestController::setScrollbarPolicy(const CppArgumentList&, CppVariant* result)
       
   648 {
       
   649     // FIXME: implement.
       
   650     // Currently only has a non-null implementation on QT.
       
   651     result->setNull();
       
   652 }
       
   653 
       
   654 void LayoutTestController::setCustomPolicyDelegate(const CppArgumentList& arguments, CppVariant* result)
       
   655 {
       
   656     if (arguments.size() > 0 && arguments[0].isBool()) {
       
   657         bool enable = arguments[0].value.boolValue;
       
   658         bool permissive = false;
       
   659         if (arguments.size() > 1 && arguments[1].isBool())
       
   660             permissive = arguments[1].value.boolValue;
       
   661         m_shell->webViewHost()->setCustomPolicyDelegate(enable, permissive);
       
   662     }
       
   663     result->setNull();
       
   664 }
       
   665 
       
   666 void LayoutTestController::waitForPolicyDelegate(const CppArgumentList&, CppVariant* result)
       
   667 {
       
   668     m_shell->webViewHost()->waitForPolicyDelegate();
       
   669     m_waitUntilDone = true;
       
   670     result->setNull();
       
   671 }
       
   672 
       
   673 void LayoutTestController::setWillSendRequestClearHeader(const CppArgumentList& arguments, CppVariant* result)
       
   674 {
       
   675     if (arguments.size() > 0 && arguments[0].isString()) {
       
   676         string header = arguments[0].toString();
       
   677         if (!header.empty())
       
   678             m_shell->webViewHost()->addClearHeader(String::fromUTF8(header.c_str()));
       
   679     }
       
   680     result->setNull();
       
   681 }
       
   682 
       
   683 void LayoutTestController::setWillSendRequestReturnsNullOnRedirect(const CppArgumentList& arguments, CppVariant* result)
       
   684 {
       
   685     if (arguments.size() > 0 && arguments[0].isBool())
       
   686         m_shell->webViewHost()->setBlockRedirects(arguments[0].value.boolValue);
       
   687     result->setNull();
       
   688 }
       
   689 
       
   690 void LayoutTestController::setWillSendRequestReturnsNull(const CppArgumentList& arguments, CppVariant* result)
       
   691 {
       
   692     if (arguments.size() > 0 && arguments[0].isBool())
       
   693         m_shell->webViewHost()->setRequestReturnNull(arguments[0].value.boolValue);
       
   694     result->setNull();
       
   695 }
       
   696 
       
   697 void LayoutTestController::pathToLocalResource(const CppArgumentList& arguments, CppVariant* result)
       
   698 {
       
   699     result->setNull();
       
   700     if (arguments.size() <= 0 || !arguments[0].isString())
       
   701         return;
       
   702 
       
   703     string url = arguments[0].toString();
       
   704 #if OS(WINDOWS)
       
   705     if (StartsWithASCII(url, "/tmp/", true)) {
       
   706         // We want a temp file.
       
   707         const unsigned tempPrefixLength = 5;
       
   708         size_t bufferSize = MAX_PATH;
       
   709         OwnArrayPtr<WCHAR> tempPath(new WCHAR[bufferSize]);
       
   710         DWORD tempLength = ::GetTempPathW(bufferSize, tempPath.get());
       
   711         if (tempLength + url.length() - tempPrefixLength + 1 > bufferSize) {
       
   712             bufferSize = tempLength + url.length() - tempPrefixLength + 1;
       
   713             tempPath.set(new WCHAR[bufferSize]);
       
   714             tempLength = GetTempPathW(bufferSize, tempPath.get());
       
   715             ASSERT(tempLength < bufferSize);
       
   716         }
       
   717         std::string resultPath(WebString(tempPath.get(), tempLength).utf8());
       
   718         resultPath.append(url.substr(tempPrefixLength));
       
   719         result->set(resultPath);
       
   720         return;
       
   721     }
       
   722 #endif
       
   723 
       
   724     // Some layout tests use file://// which we resolve as a UNC path.  Normalize
       
   725     // them to just file:///.
       
   726     while (StartsWithASCII(url, "file:////", false))
       
   727         url = url.substr(0, 8) + url.substr(9);
       
   728     result->set(webkit_support::RewriteLayoutTestsURL(url).spec());
       
   729 }
       
   730 
       
   731 void LayoutTestController::addFileToPasteboardOnDrag(const CppArgumentList&, CppVariant* result)
       
   732 {
       
   733     result->setNull();
       
   734     m_shouldAddFileToPasteboard = true;
       
   735 }
       
   736 
       
   737 void LayoutTestController::setStopProvisionalFrameLoads(const CppArgumentList&, CppVariant* result)
       
   738 {
       
   739     result->setNull();
       
   740     m_stopProvisionalFrameLoads = true;
       
   741 }
       
   742 
       
   743 void LayoutTestController::setSmartInsertDeleteEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   744 {
       
   745     if (arguments.size() > 0 && arguments[0].isBool())
       
   746         m_shell->webViewHost()->setSmartInsertDeleteEnabled(arguments[0].value.boolValue);
       
   747     result->setNull();
       
   748 }
       
   749 
       
   750 void LayoutTestController::setSelectTrailingWhitespaceEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   751 {
       
   752     if (arguments.size() > 0 && arguments[0].isBool())
       
   753         m_shell->webViewHost()->setSelectTrailingWhitespaceEnabled(arguments[0].value.boolValue);
       
   754     result->setNull();
       
   755 }
       
   756 
       
   757 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const WebString& animationName, double time, const WebString& elementId)
       
   758 {
       
   759     WebFrame* webFrame = m_shell->webView()->mainFrame();
       
   760     if (!webFrame)
       
   761         return false;
       
   762 
       
   763     WebAnimationController* controller = webFrame->animationController();
       
   764     if (!controller)
       
   765         return false;
       
   766 
       
   767     WebElement element = webFrame->document().getElementById(elementId);
       
   768     if (element.isNull())
       
   769         return false;
       
   770     return controller->pauseAnimationAtTime(element, animationName, time);
       
   771 }
       
   772 
       
   773 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(const WebString& propertyName, double time, const WebString& elementId)
       
   774 {
       
   775     WebFrame* webFrame = m_shell->webView()->mainFrame();
       
   776     if (!webFrame)
       
   777         return false;
       
   778 
       
   779     WebAnimationController* controller = webFrame->animationController();
       
   780     if (!controller)
       
   781         return false;
       
   782 
       
   783     WebElement element = webFrame->document().getElementById(elementId);
       
   784     if (element.isNull())
       
   785         return false;
       
   786     return controller->pauseTransitionAtTime(element, propertyName, time);
       
   787 }
       
   788 
       
   789 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(const WebString& elementId)
       
   790 {
       
   791     WebFrame* webFrame = m_shell->webView()->mainFrame();
       
   792     if (!webFrame)
       
   793         return false;
       
   794 
       
   795     WebElement element = webFrame->document().getElementById(elementId);
       
   796     if (element.isNull() || !element.hasTagName("input"))
       
   797         return false;
       
   798 
       
   799     WebInputElement inputElement = element.to<WebInputElement>();
       
   800     return inputElement.autoComplete();
       
   801 }
       
   802 
       
   803 int LayoutTestController::numberOfActiveAnimations()
       
   804 {
       
   805     WebFrame* webFrame = m_shell->webView()->mainFrame();
       
   806     if (!webFrame)
       
   807         return -1;
       
   808 
       
   809     WebAnimationController* controller = webFrame->animationController();
       
   810     if (!controller)
       
   811         return -1;
       
   812 
       
   813     return controller->numberOfActiveAnimations();
       
   814 }
       
   815 
       
   816 void LayoutTestController::pauseAnimationAtTimeOnElementWithId(const CppArgumentList& arguments, CppVariant* result)
       
   817 {
       
   818     result->set(false);
       
   819     if (arguments.size() > 2 && arguments[0].isString() && arguments[1].isNumber() && arguments[2].isString()) {
       
   820         WebString animationName = cppVariantToWebString(arguments[0]);
       
   821         double time = arguments[1].toDouble();
       
   822         WebString elementId = cppVariantToWebString(arguments[2]);
       
   823         result->set(pauseAnimationAtTimeOnElementWithId(animationName, time, elementId));
       
   824     }
       
   825 }
       
   826 
       
   827 void LayoutTestController::pauseTransitionAtTimeOnElementWithId(const CppArgumentList& arguments, CppVariant* result)
       
   828 {
       
   829     result->set(false);
       
   830     if (arguments.size() > 2 && arguments[0].isString() && arguments[1].isNumber() && arguments[2].isString()) {
       
   831         WebString propertyName = cppVariantToWebString(arguments[0]);
       
   832         double time = arguments[1].toDouble();
       
   833         WebString elementId = cppVariantToWebString(arguments[2]);
       
   834         result->set(pauseTransitionAtTimeOnElementWithId(propertyName, time, elementId));
       
   835     }
       
   836 }
       
   837 
       
   838 void LayoutTestController::elementDoesAutoCompleteForElementWithId(const CppArgumentList& arguments, CppVariant* result)
       
   839 {
       
   840     if (arguments.size() != 1 || !arguments[0].isString()) {
       
   841         result->set(false);
       
   842         return;
       
   843     }
       
   844     WebString elementId = cppVariantToWebString(arguments[0]);
       
   845     result->set(elementDoesAutoCompleteForElementWithId(elementId));
       
   846 }
       
   847 
       
   848 void LayoutTestController::numberOfActiveAnimations(const CppArgumentList&, CppVariant* result)
       
   849 {
       
   850     result->set(numberOfActiveAnimations());
       
   851 }
       
   852 
       
   853 void LayoutTestController::disableImageLoading(const CppArgumentList&, CppVariant* result)
       
   854 {
       
   855     m_shell->webView()->settings()->setLoadsImagesAutomatically(false);
       
   856     result->setNull();
       
   857 }
       
   858 
       
   859 void LayoutTestController::setIconDatabaseEnabled(const CppArgumentList&, CppVariant* result)
       
   860 {
       
   861     // We don't use the WebKit icon database.
       
   862     result->setNull();
       
   863 }
       
   864 
       
   865 void LayoutTestController::callShouldCloseOnWebView(const CppArgumentList&, CppVariant* result)
       
   866 {
       
   867     result->set(m_shell->webView()->dispatchBeforeUnloadEvent());
       
   868 }
       
   869 
       
   870 void LayoutTestController::grantDesktopNotificationPermission(const CppArgumentList& arguments, CppVariant* result)
       
   871 {
       
   872     if (arguments.size() != 1 || !arguments[0].isString()) {
       
   873         result->set(false);
       
   874         return;
       
   875     }
       
   876     m_shell->notificationPresenter()->grantPermission(cppVariantToWebString(arguments[0]));
       
   877     result->set(true);
       
   878 }
       
   879 
       
   880 //
       
   881 // Unimplemented stubs
       
   882 //
       
   883 
       
   884 void LayoutTestController::dumpAsWebArchive(const CppArgumentList& arguments, CppVariant* result)
       
   885 {
       
   886     result->setNull();
       
   887 }
       
   888 
       
   889 void LayoutTestController::setMainFrameIsFirstResponder(const CppArgumentList& arguments, CppVariant* result)
       
   890 {
       
   891     result->setNull();
       
   892 }
       
   893 
       
   894 void LayoutTestController::dumpSelectionRect(const CppArgumentList& arguments, CppVariant* result)
       
   895 {
       
   896     m_dumpSelectionRect = true;
       
   897     result->setNull();
       
   898 }
       
   899 
       
   900 void LayoutTestController::display(const CppArgumentList& arguments, CppVariant* result)
       
   901 {
       
   902     WebViewHost* host = m_shell->webViewHost();
       
   903     const WebKit::WebSize& size = m_shell->webView()->size();
       
   904     WebRect rect(0, 0, size.width, size.height);
       
   905     host->updatePaintRect(rect);
       
   906     host->paintInvalidatedRegion();
       
   907     host->displayRepaintMask();
       
   908     result->setNull();
       
   909 }
       
   910 
       
   911 void LayoutTestController::testRepaint(const CppArgumentList&, CppVariant* result)
       
   912 {
       
   913     m_testRepaint = true;
       
   914     result->setNull();
       
   915 }
       
   916 
       
   917 void LayoutTestController::repaintSweepHorizontally(const CppArgumentList&, CppVariant* result)
       
   918 {
       
   919     m_sweepHorizontally = true;
       
   920     result->setNull();
       
   921 }
       
   922 
       
   923 void LayoutTestController::clearBackForwardList(const CppArgumentList& arguments, CppVariant* result)
       
   924 {
       
   925     result->setNull();
       
   926 }
       
   927 
       
   928 void LayoutTestController::keepWebHistory(const CppArgumentList& arguments,  CppVariant* result)
       
   929 {
       
   930     result->setNull();
       
   931 }
       
   932 
       
   933 void LayoutTestController::storeWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
       
   934 {
       
   935     result->setNull();
       
   936 }
       
   937 
       
   938 void LayoutTestController::accessStoredWebScriptObject(const CppArgumentList& arguments, CppVariant* result)
       
   939 {
       
   940     result->setNull();
       
   941 }
       
   942 
       
   943 void LayoutTestController::objCClassNameOf(const CppArgumentList& arguments, CppVariant* result)
       
   944 {
       
   945     result->setNull();
       
   946 }
       
   947 
       
   948 void LayoutTestController::addDisallowedURL(const CppArgumentList& arguments, CppVariant* result)
       
   949 {
       
   950     result->setNull();
       
   951 }
       
   952 void LayoutTestController::setCallCloseOnWebViews(const CppArgumentList& arguments, CppVariant* result)
       
   953 {
       
   954     result->setNull();
       
   955 }
       
   956 
       
   957 void LayoutTestController::setPrivateBrowsingEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   958 {
       
   959     result->setNull();
       
   960 }
       
   961 
       
   962 void LayoutTestController::setJavaScriptCanAccessClipboard(const CppArgumentList& arguments, CppVariant* result)
       
   963 {
       
   964     if (arguments.size() > 0 && arguments[0].isBool())
       
   965         m_shell->webView()->settings()->setJavaScriptCanAccessClipboard(arguments[0].value.boolValue);
       
   966     result->setNull();
       
   967 }
       
   968 
       
   969 void LayoutTestController::setXSSAuditorEnabled(const CppArgumentList& arguments, CppVariant* result)
       
   970 {
       
   971     if (arguments.size() > 0 && arguments[0].isBool())
       
   972         m_shell->webView()->settings()->setXSSAuditorEnabled(arguments[0].value.boolValue);
       
   973     result->setNull();
       
   974 }
       
   975 
       
   976 void LayoutTestController::evaluateScriptInIsolatedWorld(const CppArgumentList& arguments, CppVariant* result)
       
   977 {
       
   978     if (arguments.size() >= 2 && arguments[0].isNumber() && arguments[1].isString()) {
       
   979         WebScriptSource source(cppVariantToWebString(arguments[1]));
       
   980         // This relies on the iframe focusing itself when it loads. This is a bit
       
   981         // sketchy, but it seems to be what other tests do.
       
   982         m_shell->webView()->focusedFrame()->executeScriptInIsolatedWorld(arguments[0].toInt32(), &source, 1, 1);
       
   983     }
       
   984     result->setNull();
       
   985 }
       
   986 
       
   987 void LayoutTestController::setAllowUniversalAccessFromFileURLs(const CppArgumentList& arguments, CppVariant* result)
       
   988 {
       
   989     if (arguments.size() > 0 && arguments[0].isBool())
       
   990         m_shell->webView()->settings()->setAllowUniversalAccessFromFileURLs(arguments[0].value.boolValue);
       
   991     result->setNull();
       
   992 }
       
   993 
       
   994 void LayoutTestController::setAllowFileAccessFromFileURLs(const CppArgumentList& arguments, CppVariant* result)
       
   995 {
       
   996     if (arguments.size() > 0 && arguments[0].isBool())
       
   997         m_shell->webView()->settings()->setAllowFileAccessFromFileURLs(arguments[0].value.boolValue);
       
   998     result->setNull();
       
   999 }
       
  1000 
       
  1001 // Need these conversions because the format of the value for booleans
       
  1002 // may vary - for example, on mac "1" and "0" are used for boolean.
       
  1003 bool LayoutTestController::cppVariantToBool(const CppVariant& value)
       
  1004 {
       
  1005     if (value.isBool())
       
  1006         return value.toBoolean();
       
  1007     if (value.isInt32())
       
  1008         return value.toInt32();
       
  1009     if (value.isString()) {
       
  1010         string valueString = value.toString();
       
  1011         if (valueString == "true" || valueString == "1")
       
  1012             return true;
       
  1013         if (valueString == "false" || valueString == "0")
       
  1014             return false;
       
  1015     }
       
  1016     logErrorToConsole("Invalid value. Expected boolean value.");
       
  1017     return false;
       
  1018 }
       
  1019 
       
  1020 int32_t LayoutTestController::cppVariantToInt32(const CppVariant& value)
       
  1021 {
       
  1022     if (value.isInt32())
       
  1023         return value.toInt32();
       
  1024     if (value.isString()) {
       
  1025         int number;
       
  1026         if (StringToInt(value.toString(), &number))
       
  1027             return number;
       
  1028     }
       
  1029     logErrorToConsole("Invalid value for preference. Expected integer value.");
       
  1030     return 0;
       
  1031 }
       
  1032 
       
  1033 WebString LayoutTestController::cppVariantToWebString(const CppVariant& value)
       
  1034 {
       
  1035     if (!value.isString()) {
       
  1036         logErrorToConsole("Invalid value for preference. Expected string value.");
       
  1037         return WebString();
       
  1038     }
       
  1039     return WebString::fromUTF8(value.toString());
       
  1040 }
       
  1041 
       
  1042 void LayoutTestController::overridePreference(const CppArgumentList& arguments, CppVariant* result)
       
  1043 {
       
  1044     result->setNull();
       
  1045     if (arguments.size() != 2 || !arguments[0].isString())
       
  1046         return;
       
  1047 
       
  1048     string key = arguments[0].toString();
       
  1049     CppVariant value = arguments[1];
       
  1050     WebSettings* settings = m_shell->webView()->settings();
       
  1051     if (key == "WebKitStandardFont")
       
  1052         settings->setStandardFontFamily(cppVariantToWebString(value));
       
  1053     else if (key == "WebKitFixedFont")
       
  1054         settings->setFixedFontFamily(cppVariantToWebString(value));
       
  1055     else if (key == "WebKitSerifFont")
       
  1056         settings->setSerifFontFamily(cppVariantToWebString(value));
       
  1057     else if (key == "WebKitSansSerifFont")
       
  1058         settings->setSansSerifFontFamily(cppVariantToWebString(value));
       
  1059     else if (key == "WebKitCursiveFont")
       
  1060         settings->setCursiveFontFamily(cppVariantToWebString(value));
       
  1061     else if (key == "WebKitFantasyFont")
       
  1062         settings->setFantasyFontFamily(cppVariantToWebString(value));
       
  1063     else if (key == "WebKitDefaultFontSize")
       
  1064         settings->setDefaultFontSize(cppVariantToInt32(value));
       
  1065     else if (key == "WebKitDefaultFixedFontSize")
       
  1066         settings->setDefaultFixedFontSize(cppVariantToInt32(value));
       
  1067     else if (key == "WebKitMinimumFontSize")
       
  1068         settings->setMinimumFontSize(cppVariantToInt32(value));
       
  1069     else if (key == "WebKitMinimumLogicalFontSize")
       
  1070         settings->setMinimumLogicalFontSize(cppVariantToInt32(value));
       
  1071     else if (key == "WebKitDefaultTextEncodingName")
       
  1072         settings->setDefaultTextEncodingName(cppVariantToWebString(value));
       
  1073     else if (key == "WebKitJavaScriptEnabled")
       
  1074         settings->setJavaScriptEnabled(cppVariantToBool(value));
       
  1075     else if (key == "WebKitWebSecurityEnabled")
       
  1076         settings->setWebSecurityEnabled(cppVariantToBool(value));
       
  1077     else if (key == "WebKitJavaScriptCanOpenWindowsAutomatically")
       
  1078         settings->setJavaScriptCanOpenWindowsAutomatically(cppVariantToBool(value));
       
  1079     else if (key == "WebKitDisplayImagesKey")
       
  1080         settings->setLoadsImagesAutomatically(cppVariantToBool(value));
       
  1081     else if (key == "WebKitPluginsEnabled")
       
  1082         settings->setPluginsEnabled(cppVariantToBool(value));
       
  1083     else if (key == "WebKitDOMPasteAllowedPreferenceKey")
       
  1084         settings->setDOMPasteAllowed(cppVariantToBool(value));
       
  1085     else if (key == "WebKitDeveloperExtrasEnabledPreferenceKey")
       
  1086         settings->setDeveloperExtrasEnabled(cppVariantToBool(value));
       
  1087     else if (key == "WebKitShrinksStandaloneImagesToFit")
       
  1088         settings->setShrinksStandaloneImagesToFit(cppVariantToBool(value));
       
  1089     else if (key == "WebKitTextAreasAreResizable")
       
  1090         settings->setTextAreasAreResizable(cppVariantToBool(value));
       
  1091     else if (key == "WebKitJavaEnabled")
       
  1092         settings->setJavaEnabled(cppVariantToBool(value));
       
  1093     else if (key == "WebKitUsesPageCachePreferenceKey")
       
  1094         settings->setUsesPageCache(cppVariantToBool(value));
       
  1095     else if (key == "WebKitJavaScriptCanAccessClipboard")
       
  1096         settings->setJavaScriptCanAccessClipboard(cppVariantToBool(value));
       
  1097     else if (key == "WebKitXSSAuditorEnabled")
       
  1098         settings->setXSSAuditorEnabled(cppVariantToBool(value));
       
  1099     else if (key == "WebKitLocalStorageEnabledPreferenceKey")
       
  1100         settings->setLocalStorageEnabled(cppVariantToBool(value));
       
  1101     else if (key == "WebKitOfflineWebApplicationCacheEnabled")
       
  1102         settings->setOfflineWebApplicationCacheEnabled(cppVariantToBool(value));
       
  1103     else if (key == "WebKitTabToLinksPreferenceKey")
       
  1104         m_shell->webView()->setTabsToLinks(cppVariantToBool(value));
       
  1105     else if (key == "WebKitWebGLEnabled")
       
  1106         settings->setExperimentalWebGLEnabled(cppVariantToBool(value));
       
  1107     else {
       
  1108         string message("Invalid name for preference: ");
       
  1109         message.append(key);
       
  1110         logErrorToConsole(message);
       
  1111     }
       
  1112 }
       
  1113 
       
  1114 void LayoutTestController::fallbackMethod(const CppArgumentList&, CppVariant* result)
       
  1115 {
       
  1116     printf("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on LayoutTestController\n");
       
  1117     result->setNull();
       
  1118 }
       
  1119 
       
  1120 void LayoutTestController::addOriginAccessWhitelistEntry(const CppArgumentList& arguments, CppVariant* result)
       
  1121 {
       
  1122     result->setNull();
       
  1123 
       
  1124     if (arguments.size() != 4 || !arguments[0].isString() || !arguments[1].isString()
       
  1125         || !arguments[2].isString() || !arguments[3].isBool())
       
  1126         return;
       
  1127 
       
  1128     WebKit::WebURL url(GURL(arguments[0].toString()));
       
  1129     if (!url.isValid())
       
  1130         return;
       
  1131 
       
  1132     WebSecurityPolicy::addOriginAccessWhitelistEntry(
       
  1133         url,
       
  1134         cppVariantToWebString(arguments[1]),
       
  1135         cppVariantToWebString(arguments[2]),
       
  1136         arguments[3].toBoolean());
       
  1137 }
       
  1138 
       
  1139 void LayoutTestController::removeOriginAccessWhitelistEntry(const CppArgumentList& arguments, CppVariant* result)
       
  1140 {
       
  1141     result->setNull();
       
  1142 
       
  1143     if (arguments.size() != 4 || !arguments[0].isString() || !arguments[1].isString()
       
  1144         || !arguments[2].isString() || !arguments[3].isBool())
       
  1145         return;
       
  1146 
       
  1147     WebKit::WebURL url(GURL(arguments[0].toString()));
       
  1148     if (!url.isValid())
       
  1149         return;
       
  1150 
       
  1151     WebSecurityPolicy::removeOriginAccessWhitelistEntry(
       
  1152         url,
       
  1153         cppVariantToWebString(arguments[1]),
       
  1154         cppVariantToWebString(arguments[2]),
       
  1155         arguments[3].toBoolean());
       
  1156 }
       
  1157 
       
  1158 void LayoutTestController::clearAllDatabases(const CppArgumentList& arguments, CppVariant* result)
       
  1159 {
       
  1160     result->setNull();
       
  1161     webkit_support::ClearAllDatabases();
       
  1162 }
       
  1163 
       
  1164 void LayoutTestController::setDatabaseQuota(const CppArgumentList& arguments, CppVariant* result)
       
  1165 {
       
  1166     result->setNull();
       
  1167     if ((arguments.size() >= 1) && arguments[0].isInt32())
       
  1168         webkit_support::SetDatabaseQuota(arguments[0].toInt32());
       
  1169 }
       
  1170 
       
  1171 void LayoutTestController::setPOSIXLocale(const CppArgumentList& arguments, CppVariant* result)
       
  1172 {
       
  1173     result->setNull();
       
  1174     if (arguments.size() == 1 && arguments[0].isString())
       
  1175         setlocale(LC_ALL, arguments[0].toString().c_str());
       
  1176 }
       
  1177 
       
  1178 void LayoutTestController::counterValueForElementById(const CppArgumentList& arguments, CppVariant* result)
       
  1179 {
       
  1180     result->setNull();
       
  1181     if (arguments.size() < 1 || !arguments[0].isString())
       
  1182         return;
       
  1183     WebFrame* frame = m_shell->webView()->mainFrame();
       
  1184     if (!frame)
       
  1185         return;
       
  1186     WebString counterValue = frame->counterValueForElementById(cppVariantToWebString(arguments[0]));
       
  1187     if (counterValue.isNull())
       
  1188         return;
       
  1189     result->set(counterValue.utf8());
       
  1190 }
       
  1191 
       
  1192 static bool parsePageSizeParameters(const CppArgumentList& arguments,
       
  1193                                     int argOffset,
       
  1194                                     float* pageWidthInPixels,
       
  1195                                     float* pageHeightInPixels)
       
  1196 {
       
  1197     // WebKit is using the window width/height of DumpRenderTree as the
       
  1198     // default value of the page size.
       
  1199     // FIXME: share these values with other ports.
       
  1200     *pageWidthInPixels = 800;
       
  1201     *pageHeightInPixels = 600;
       
  1202     switch (arguments.size() - argOffset) {
       
  1203     case 2:
       
  1204         if (!arguments[argOffset].isNumber() || !arguments[1 + argOffset].isNumber())
       
  1205             return false;
       
  1206         *pageWidthInPixels = static_cast<float>(arguments[argOffset].toInt32());
       
  1207         *pageHeightInPixels = static_cast<float>(arguments[1 + argOffset].toInt32());
       
  1208         // fall through.
       
  1209     case 0:
       
  1210         break;
       
  1211     default:
       
  1212         return false;
       
  1213     }
       
  1214     return true;
       
  1215 }
       
  1216 
       
  1217 void LayoutTestController::pageNumberForElementById(const CppArgumentList& arguments, CppVariant* result)
       
  1218 {
       
  1219     result->setNull();
       
  1220     float pageWidthInPixels = 0;
       
  1221     float pageHeightInPixels = 0;
       
  1222     if (!parsePageSizeParameters(arguments, 1,
       
  1223                                  &pageWidthInPixels, &pageHeightInPixels))
       
  1224         return;
       
  1225     if (!arguments[0].isString())
       
  1226         return;
       
  1227     WebFrame* frame = m_shell->webView()->mainFrame();
       
  1228     if (!frame)
       
  1229         return;
       
  1230     result->set(frame->pageNumberForElementById(cppVariantToWebString(arguments[0]),
       
  1231                                                 pageWidthInPixels, pageHeightInPixels));
       
  1232 }
       
  1233 
       
  1234 void LayoutTestController::numberOfPages(const CppArgumentList& arguments, CppVariant* result)
       
  1235 {
       
  1236     result->setNull();
       
  1237     float pageWidthInPixels = 0;
       
  1238     float pageHeightInPixels = 0;
       
  1239     if (!parsePageSizeParameters(arguments, 0, &pageWidthInPixels, &pageHeightInPixels))
       
  1240         return;
       
  1241 
       
  1242     WebFrame* frame = m_shell->webView()->mainFrame();
       
  1243     if (!frame)
       
  1244         return;
       
  1245     WebSize size(pageWidthInPixels, pageHeightInPixels);
       
  1246     int numberOfPages = frame->printBegin(size);
       
  1247     frame->printEnd();
       
  1248     result->set(numberOfPages);
       
  1249 }
       
  1250 
       
  1251 void LayoutTestController::logErrorToConsole(const std::string& text)
       
  1252 {
       
  1253     m_shell->webViewHost()->didAddMessageToConsole(
       
  1254         WebConsoleMessage(WebConsoleMessage::LevelError, WebString::fromUTF8(text)),
       
  1255         WebString(), 0);
       
  1256 }
       
  1257 
       
  1258 void LayoutTestController::setTimelineProfilingEnabled(const CppArgumentList& arguments, CppVariant* result)
       
  1259 {
       
  1260     result->setNull();
       
  1261     if (arguments.size() < 1 || !arguments[0].isBool())
       
  1262         return;
       
  1263     m_shell->drtDevToolsAgent()->setTimelineProfilingEnabled(arguments[0].toBoolean());
       
  1264 }
       
  1265 
       
  1266 void LayoutTestController::evaluateInWebInspector(const CppArgumentList& arguments, CppVariant* result)
       
  1267 {
       
  1268     result->setNull();
       
  1269     if (arguments.size() < 2 || !arguments[0].isInt32() || !arguments[1].isString())
       
  1270         return;
       
  1271     m_shell->drtDevToolsAgent()->evaluateInWebInspector(arguments[0].toInt32(), arguments[1].toString());
       
  1272 }
       
  1273 
       
  1274 void LayoutTestController::forceRedSelectionColors(const CppArgumentList& arguments, CppVariant* result)
       
  1275 {
       
  1276     result->setNull();
       
  1277     m_shell->webView()->setSelectionColors(0xffee0000, 0xff00ee00, 0xff000000, 0xffc0c0c0);
       
  1278 }
       
  1279 
       
  1280 void LayoutTestController::addUserScript(const CppArgumentList& arguments, CppVariant* result)
       
  1281 {
       
  1282     result->setNull();
       
  1283     if (arguments.size() < 3 || !arguments[0].isString() || !arguments[1].isBool() || !arguments[2].isBool())
       
  1284         return;
       
  1285     WebView::addUserScript(
       
  1286         cppVariantToWebString(arguments[0]), WebVector<WebString>(),
       
  1287         arguments[1].toBoolean() ? WebView::UserScriptInjectAtDocumentStart : WebView::UserScriptInjectAtDocumentEnd,
       
  1288         arguments[2].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly);
       
  1289 }
       
  1290 
       
  1291 void LayoutTestController::addUserStyleSheet(const CppArgumentList& arguments, CppVariant* result)
       
  1292 {
       
  1293     result->setNull();
       
  1294     if (arguments.size() < 2 || !arguments[0].isString() || !arguments[1].isBool())
       
  1295         return;
       
  1296     WebView::addUserStyleSheet(
       
  1297         cppVariantToWebString(arguments[0]), WebVector<WebString>(),
       
  1298         arguments[2].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly);
       
  1299 }
       
  1300 
       
  1301 void LayoutTestController::setEditingBehavior(const CppArgumentList& arguments, CppVariant* results)
       
  1302 {
       
  1303     WebSettings* settings = m_shell->webView()->settings();
       
  1304     string key = arguments[0].toString();
       
  1305     if (key == "mac")
       
  1306         settings->setEditingBehavior(WebSettings::EditingBehaviorMac);
       
  1307     else if (key == "win")
       
  1308         settings->setEditingBehavior(WebSettings::EditingBehaviorWin);
       
  1309     else
       
  1310         logErrorToConsole("Passed invalid editing behavior. Should be 'mac' or 'win'.");
       
  1311 }
       
  1312 
       
  1313 void LayoutTestController::setGeolocationPermission(const CppArgumentList& arguments, CppVariant* result)
       
  1314 {
       
  1315     result->setNull();
       
  1316     if (arguments.size() < 1 || !arguments[0].isBool())
       
  1317         return;
       
  1318     WebGeolocationServiceMock::setMockGeolocationPermission(arguments[0].toBoolean());
       
  1319 }
       
  1320 
       
  1321 void LayoutTestController::setMockGeolocationPosition(const CppArgumentList& arguments, CppVariant* result)
       
  1322 {
       
  1323     result->setNull();
       
  1324     if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumber() || !arguments[2].isNumber())
       
  1325         return;
       
  1326     WebGeolocationServiceMock::setMockGeolocationPosition(arguments[0].toDouble(), arguments[1].toDouble(), arguments[2].toDouble());
       
  1327 }
       
  1328 
       
  1329 void LayoutTestController::setMockGeolocationError(const CppArgumentList& arguments, CppVariant* result)
       
  1330 {
       
  1331     result->setNull();
       
  1332     if (arguments.size() < 2 || !arguments[0].isInt32() || !arguments[1].isString())
       
  1333         return;
       
  1334     WebGeolocationServiceMock::setMockGeolocationError(arguments[0].toInt32(), cppVariantToWebString(arguments[1]));
       
  1335 }
       
  1336 
       
  1337 void LayoutTestController::abortModal(const CppArgumentList& arguments, CppVariant* result)
       
  1338 {
       
  1339     result->setNull();
       
  1340 }