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