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