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