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