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