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