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