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