2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "LayoutTestController.h"
32 #include "DumpRenderTree.h"
33 #include "EditingDelegate.h"
34 #include "PolicyDelegate.h"
35 #include "WorkQueue.h"
36 #include "WorkQueueItem.h"
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <JavaScriptCore/Assertions.h>
39 #include <JavaScriptCore/JSRetainPtr.h>
40 #include <JavaScriptCore/JSStringRefBSTR.h>
41 #include <JavaScriptCore/JavaScriptCore.h>
42 #include <WebCore/COMPtr.h>
43 #include <WebKit/WebKit.h>
44 #include <WebKit/WebKitCOMAPI.h>
50 #include <wtf/Platform.h>
51 #include <wtf/RetainPtr.h>
52 #include <wtf/Vector.h>
57 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath);
59 LayoutTestController::~LayoutTestController()
61 COMPtr<IWebView> webView;
62 if (FAILED(frame->webView(&webView)))
65 // reset webview-related states back to default values in preparation for next test
67 COMPtr<IWebViewPrivate> viewPrivate;
68 if (SUCCEEDED(webView->QueryInterface(&viewPrivate)))
69 viewPrivate->setTabKeyCyclesThroughElements(TRUE);
71 COMPtr<IWebViewEditing> viewEditing;
72 if (FAILED(webView->QueryInterface(&viewEditing)))
74 COMPtr<IWebEditingDelegate> delegate;
75 if (FAILED(viewEditing->editingDelegate(&delegate)))
77 COMPtr<EditingDelegate> editingDelegate(Query, viewEditing.get());
79 editingDelegate->setAcceptsEditing(TRUE);
82 void LayoutTestController::addDisallowedURL(JSStringRef url)
87 void LayoutTestController::clearBackForwardList()
89 COMPtr<IWebView> webView;
90 if (FAILED(frame->webView(&webView)))
93 COMPtr<IWebBackForwardList> backForwardList;
94 if (FAILED(webView->backForwardList(&backForwardList)))
97 COMPtr<IWebHistoryItem> item;
98 if (FAILED(backForwardList->currentItem(&item)))
101 // We clear the history by setting the back/forward list's capacity to 0
102 // then restoring it back and adding back the current item.
104 if (FAILED(backForwardList->capacity(&capacity)))
107 backForwardList->setCapacity(0);
108 backForwardList->setCapacity(capacity);
109 backForwardList->addItem(item.get());
110 backForwardList->goToItem(item.get());
113 bool LayoutTestController::callShouldCloseOnWebView()
115 COMPtr<IWebView> webView;
116 if (FAILED(frame->webView(&webView)))
119 COMPtr<IWebViewPrivate> viewPrivate;
120 if (FAILED(webView->QueryInterface(&viewPrivate)))
124 viewPrivate->shouldClose(&result);
128 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
134 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
140 void LayoutTestController::disableImageLoading()
142 COMPtr<IWebView> webView;
143 if (FAILED(frame->webView(&webView)))
146 COMPtr<IWebPreferences> preferences;
147 if (FAILED(webView->preferences(&preferences)))
150 preferences->setLoadsImagesAutomatically(FALSE);
153 void LayoutTestController::dispatchPendingLoadRequests()
155 // FIXME: Implement for testing fix for 6727495
158 void LayoutTestController::display()
163 void LayoutTestController::keepWebHistory()
165 COMPtr<IWebHistory> history;
166 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
169 COMPtr<IWebHistory> sharedHistory;
170 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(sharedHistory), reinterpret_cast<void**>(&sharedHistory))))
173 history->setOptionalSharedHistory(sharedHistory.get());
176 JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
178 // FIXME: Implement this.
179 return JSValueMakeUndefined(context);
182 JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
184 // FIXME: Implement this.
185 return JSValueMakeUndefined(context);
188 JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
190 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
195 HRESULT hr = framePrivate->layerTreeAsText(&textBSTR);
197 wstring text(textBSTR, SysStringLen(textBSTR));
198 SysFreeString(textBSTR);
199 JSRetainPtr<JSStringRef> textValueJS(Adopt, JSStringCreateWithCharacters(text.data(), text.length()));
203 JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const
205 COMPtr<IWebView> webView;
206 if (FAILED(frame->webView(&webView)))
209 COMPtr<IWebViewPrivate> webViewPrivate(Query, webView);
213 COMPtr<IDOMElement> element;
214 if (FAILED(webViewPrivate->elementFromJS(context, nodeObject, &element)))
217 COMPtr<IDOMElementPrivate> elementPrivate(Query, element);
222 if (FAILED(elementPrivate->markerTextForListItem(&textBSTR)))
225 JSRetainPtr<JSStringRef> markerText(Adopt, JSStringCreateWithBSTR(textBSTR));
226 SysFreeString(textBSTR);
230 void LayoutTestController::waitForPolicyDelegate()
232 COMPtr<IWebView> webView;
233 if (FAILED(frame->webView(&webView)))
237 policyDelegate->setControllerToNotifyDone(this);
238 webView->setPolicyDelegate(policyDelegate);
241 size_t LayoutTestController::webHistoryItemCount()
243 COMPtr<IWebHistory> history;
244 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
247 COMPtr<IWebHistory> sharedHistory;
248 if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
251 COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
252 if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
256 if (FAILED(sharedHistoryPrivate->allItems(&count, 0)))
262 unsigned LayoutTestController::workerThreadCount() const
264 COMPtr<IWebWorkersPrivate> workers;
265 if (FAILED(WebKitCreateInstance(CLSID_WebWorkersPrivate, 0, __uuidof(workers), reinterpret_cast<void**>(&workers))))
268 if (FAILED(workers->workerThreadCount(&count)))
273 JSRetainPtr<JSStringRef> LayoutTestController::platformName() const
275 JSRetainPtr<JSStringRef> platformName(Adopt, JSStringCreateWithUTF8CString("win"));
279 void LayoutTestController::notifyDone()
281 // Same as on mac. This can be shared.
282 if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
284 m_waitToDump = false;
287 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
289 wstring input(JSStringGetCharactersPtr(url), JSStringGetLength(url));
292 if (!resolveCygwinPath(input, localPath)) {
293 printf("ERROR: Failed to resolve Cygwin path %S\n", input.c_str());
297 return JSStringCreateWithCharacters(localPath.c_str(), localPath.length());
300 static wstring jsStringRefToWString(JSStringRef jsStr)
302 size_t length = JSStringGetLength(jsStr);
303 Vector<WCHAR> buffer(length + 1);
304 memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR));
305 buffer[length] = '\0';
307 return buffer.data();
310 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
312 COMPtr<IWebDataSource> dataSource;
313 if (FAILED(frame->dataSource(&dataSource)))
316 COMPtr<IWebURLResponse> response;
317 if (FAILED(dataSource->response(&response)) || !response)
320 BSTR responseURLBSTR;
321 if (FAILED(response->URL(&responseURLBSTR)))
323 wstring responseURL(responseURLBSTR, SysStringLen(responseURLBSTR));
324 SysFreeString(responseURLBSTR);
326 // FIXME: We should do real relative URL resolution here.
327 int lastSlash = responseURL.rfind('/');
329 responseURL = responseURL.substr(0, lastSlash);
331 wstring wURL = jsStringRefToWString(url);
332 wstring wAbsoluteURL = responseURL + TEXT("/") + wURL;
333 JSRetainPtr<JSStringRef> jsAbsoluteURL(Adopt, JSStringCreateWithCharacters(wAbsoluteURL.data(), wAbsoluteURL.length()));
335 WorkQueue::shared()->queue(new LoadItem(jsAbsoluteURL.get(), target));
338 void LayoutTestController::setAcceptsEditing(bool acceptsEditing)
340 COMPtr<IWebView> webView;
341 if (FAILED(frame->webView(&webView)))
344 COMPtr<IWebViewEditing> viewEditing;
345 if (FAILED(webView->QueryInterface(&viewEditing)))
348 COMPtr<IWebEditingDelegate> delegate;
349 if (FAILED(viewEditing->editingDelegate(&delegate)))
352 EditingDelegate* editingDelegate = (EditingDelegate*)(IWebEditingDelegate*)delegate.get();
353 editingDelegate->setAcceptsEditing(acceptsEditing);
356 void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
358 if (alwaysAcceptCookies == m_alwaysAcceptCookies)
361 if (!::setAlwaysAcceptCookies(alwaysAcceptCookies))
363 m_alwaysAcceptCookies = alwaysAcceptCookies;
366 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
368 COMPtr<IWebView> webView;
369 if (FAILED(frame->webView(&webView)))
372 COMPtr<IWebPreferences> preferences;
373 if (FAILED(webView->preferences(&preferences)))
376 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
380 prefsPrivate->setAuthorAndUserStylesEnabled(flag);
383 void LayoutTestController::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
385 COMPtr<IWebView> webView;
386 if (FAILED(frame->webView(&webView)))
389 COMPtr<IWebViewPrivate> webViewPrivate(Query, webView);
393 COMPtr<IDOMElement> element;
394 if (FAILED(webViewPrivate->elementFromJS(context, nodeObject, &element)))
397 COMPtr<IFormsAutoFillTransition> autofillElement(Query, element);
398 if (!autofillElement)
401 autofillElement->setAutofilled(autofilled);
404 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
406 COMPtr<IWebView> webView;
407 if (FAILED(frame->webView(&webView)))
411 policyDelegate->setPermissive(permissive);
412 webView->setPolicyDelegate(policyDelegate);
414 webView->setPolicyDelegate(0);
417 void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
419 // FIXME: Implement for DeviceOrientation layout tests.
420 // See https://bugs.webkit.org/show_bug.cgi?id=30335.
423 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
425 // FIXME: Implement for Geolocation layout tests.
426 // See https://bugs.webkit.org/show_bug.cgi?id=28264.
429 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
431 // FIXME: Implement for Geolocation layout tests.
432 // See https://bugs.webkit.org/show_bug.cgi?id=28264.
435 void LayoutTestController::setGeolocationPermission(bool allow)
437 // FIXME: Implement for Geolocation layout tests.
438 setGeolocationPermissionCommon(allow);
441 int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
443 // FIXME: Implement for Geolocation layout tests.
447 void LayoutTestController::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
449 // FIXME: Implement for speech input layout tests.
450 // See https://bugs.webkit.org/show_bug.cgi?id=39485.
453 void LayoutTestController::startSpeechInput(JSContextRef inputElement)
455 // FIXME: Implement for speech input layout tests.
456 // See https://bugs.webkit.org/show_bug.cgi?id=39485.
459 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
461 // See also <rdar://problem/6480108>
462 COMPtr<IWebIconDatabase> iconDatabase;
463 COMPtr<IWebIconDatabase> tmpIconDatabase;
464 if (FAILED(WebKitCreateInstance(CLSID_WebIconDatabase, 0, IID_IWebIconDatabase, (void**)&tmpIconDatabase)))
466 if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase)))
469 iconDatabase->setEnabled(iconDatabaseEnabled);
472 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
477 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
479 COMPtr<IWebView> webView;
480 if (FAILED(frame->webView(&webView)))
483 COMPtr<IWebPreferences> preferences;
484 if (FAILED(webView->preferences(&preferences)))
487 preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
490 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
492 COMPtr<IWebView> webView;
493 if (FAILED(frame->webView(&webView)))
496 COMPtr<IWebPreferences> preferences;
497 if (FAILED(webView->preferences(&preferences)))
500 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
504 prefsPrivate->setXSSAuditorEnabled(enabled);
507 void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
509 COMPtr<IWebView> webView;
510 if (FAILED(frame->webView(&webView)))
513 COMPtr<IWebPreferences> preferences;
514 if (FAILED(webView->preferences(&preferences)))
517 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
521 prefsPrivate->setFrameFlatteningEnabled(enabled);
524 void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
526 // FIXME: Implement for SpatialNavigation layout tests.
529 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
531 COMPtr<IWebView> webView;
532 if (FAILED(frame->webView(&webView)))
535 COMPtr<IWebPreferences> preferences;
536 if (FAILED(webView->preferences(&preferences)))
539 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
543 prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
546 void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
548 COMPtr<IWebView> webView;
549 if (FAILED(frame->webView(&webView)))
552 COMPtr<IWebPreferences> preferences;
553 if (FAILED(webView->preferences(&preferences)))
556 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
560 prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
563 void LayoutTestController::setPopupBlockingEnabled(bool enabled)
565 COMPtr<IWebView> webView;
566 if (FAILED(frame->webView(&webView)))
569 COMPtr<IWebPreferences> preferences;
570 if (FAILED(webView->preferences(&preferences)))
573 preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled);
576 void LayoutTestController::setPluginsEnabled(bool flag)
581 void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
583 COMPtr<IWebView> webView;
584 if (FAILED(frame->webView(&webView)))
587 COMPtr<IWebPreferences> preferences;
588 if (FAILED(webView->preferences(&preferences)))
591 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
595 prefsPrivate->setJavaScriptCanAccessClipboard(enabled);
598 void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle)
600 COMPtr<IWebView> webView;
601 if (FAILED(frame->webView(&webView)))
604 COMPtr<IWebViewPrivate> viewPrivate;
605 if (FAILED(webView->QueryInterface(&viewPrivate)))
608 viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE);
611 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
616 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
618 COMPtr<IWebView> webView;
619 if (FAILED(frame->webView(&webView)))
622 COMPtr<IWebPreferences> preferences;
623 if (FAILED(webView->preferences(&preferences)))
626 preferences->setUserStyleSheetEnabled(flag);
629 bool appendComponentToPath(wstring& path, const wstring& component)
631 WCHAR buffer[MAX_PATH];
633 if (path.size() + 1 > MAX_PATH)
636 memcpy(buffer, path.data(), path.size() * sizeof(WCHAR));
637 buffer[path.size()] = '\0';
639 if (!PathAppendW(buffer, component.c_str()))
642 path = wstring(buffer);
646 static bool followShortcuts(wstring& path)
648 if (PathFileExists(path.c_str()))
651 // Do we have a shortcut?
652 wstring linkPath = path;
653 linkPath.append(TEXT(".lnk"));
654 if (!PathFileExists(linkPath.c_str()))
657 // We have a shortcut, find its target.
658 COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink);
661 COMPtr<IPersistFile> persistFile(Query, shortcut);
664 if (FAILED(persistFile->Load(linkPath.c_str(), STGM_READ)))
666 if (FAILED(shortcut->Resolve(0, 0)))
668 WCHAR targetPath[MAX_PATH];
669 DWORD targetPathLen = _countof(targetPath);
670 if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0)))
672 if (!PathFileExists(targetPath))
674 // Use the target path as the result path instead.
675 path = wstring(targetPath);
680 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath)
682 wstring fileProtocol = L"file://";
683 bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos;
684 if (cygwinPath[isFileProtocol ? 7 : 0] != '/') // ensure path is absolute
687 // Get the Root path.
688 WCHAR rootPath[MAX_PATH];
689 DWORD rootPathSize = _countof(rootPath);
691 DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize);
693 if (result != ERROR_SUCCESS || keyType != REG_SZ) {
694 // Cygwin 1.7 doesn't store Cygwin's root as a mount point anymore, because mount points are now stored in /etc/fstab.
695 // However, /etc/fstab doesn't contain any information about where / is located as a Windows path, so we need to use Cygwin's
696 // new registry key that has the root.
697 result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygwin\\setup"), TEXT("rootdir"), &keyType, &rootPath, &rootPathSize);
698 if (result != ERROR_SUCCESS || keyType != REG_SZ)
702 windowsPath = wstring(rootPath, rootPathSize);
704 int oldPos = isFileProtocol ? 8 : 1;
706 int newPos = cygwinPath.find('/', oldPos);
709 wstring pathComponent = cygwinPath.substr(oldPos);
711 if (!appendComponentToPath(windowsPath, pathComponent))
714 if (!followShortcuts(windowsPath))
720 wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos);
721 if (!appendComponentToPath(windowsPath, pathComponent))
724 if (!followShortcuts(windowsPath))
731 windowsPath = fileProtocol + windowsPath;
736 void LayoutTestController::setUserStyleSheetLocation(JSStringRef jsURL)
738 COMPtr<IWebView> webView;
739 if (FAILED(frame->webView(&webView)))
742 COMPtr<IWebPreferences> preferences;
743 if (FAILED(webView->preferences(&preferences)))
746 RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
747 RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, urlString.get(), 0));
751 // Now copy the file system path, POSIX style.
752 RetainPtr<CFStringRef> pathCF(AdoptCF, CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle));
756 wstring path = cfStringRefToWString(pathCF.get());
759 if (!resolveCygwinPath(path, resultPath))
762 // The path has been resolved, now convert it back to a CFURL.
763 int result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, 0, 0, 0, 0);
764 Vector<char> utf8Vector(result);
765 result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, 0, 0);
769 url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false);
773 resultPath = cfStringRefToWString(CFURLGetString(url.get()));
775 BSTR resultPathBSTR = SysAllocStringLen(resultPath.data(), resultPath.size());
776 preferences->setUserStyleSheetLocation(resultPathBSTR);
777 SysFreeString(resultPathBSTR);
780 void LayoutTestController::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
785 void LayoutTestController::setViewModeMediaFeature(JSStringRef mode)
790 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
792 RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
793 ::setPersistentUserStyleSheetLocation(urlString.get());
796 void LayoutTestController::clearPersistentUserStyleSheet()
798 ::setPersistentUserStyleSheetLocation(0);
801 void LayoutTestController::setWindowIsKey(bool flag)
803 COMPtr<IWebView> webView;
804 if (FAILED(frame->webView(&webView)))
807 COMPtr<IWebViewPrivate> viewPrivate;
808 if (FAILED(webView->QueryInterface(&viewPrivate)))
812 if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow)))
815 ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0);
818 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
820 COMPtr<IWebView> webView;
821 if (FAILED(frame->webView(&webView)))
824 COMPtr<IWebViewEditing> viewEditing;
825 if (FAILED(webView->QueryInterface(&viewEditing)))
828 viewEditing->setSmartInsertDeleteEnabled(flag ? TRUE : FALSE);
831 void LayoutTestController::setJavaScriptProfilingEnabled(bool flag)
833 COMPtr<IWebView> webView;
834 if (FAILED(frame->webView(&webView)))
837 COMPtr<IWebViewPrivate> viewPrivate;
838 if (FAILED(webView->QueryInterface(&viewPrivate)))
841 COMPtr<IWebInspector> inspector;
842 if (FAILED(viewPrivate->inspector(&inspector)))
845 setDeveloperExtrasEnabled(flag);
846 inspector->setJavaScriptProfilingEnabled(flag);
849 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
851 COMPtr<IWebView> webView;
852 if (FAILED(frame->webView(&webView)))
855 COMPtr<IWebViewEditing> viewEditing;
856 if (FAILED(webView->QueryInterface(&viewEditing)))
859 viewEditing->setSelectTrailingWhitespaceEnabled(flag ? TRUE : FALSE);
862 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
864 static void CALLBACK waitUntilDoneWatchdogFired(HWND, UINT, UINT_PTR, DWORD)
866 gLayoutTestController->waitToDumpWatchdogTimerFired();
869 void LayoutTestController::setWaitToDump(bool waitUntilDone)
871 m_waitToDump = waitUntilDone;
872 if (m_waitToDump && !waitToDumpWatchdog)
873 waitToDumpWatchdog = SetTimer(0, 0, waitToDumpWatchdogInterval * 1000, waitUntilDoneWatchdogFired);
876 int LayoutTestController::windowCount()
878 return openWindows().size();
881 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
883 COMPtr<IDOMDocument> document;
884 if (FAILED(frame->DOMDocument(&document)))
887 wstring idWstring = jsStringRefToWString(id);
888 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
889 COMPtr<IDOMElement> element;
890 HRESULT result = document->getElementById(idBSTR, &element);
891 SysFreeString(idBSTR);
896 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
901 if (FAILED(framePrivate->elementDoesAutoComplete(element.get(), &autoCompletes)))
904 return autoCompletes;
907 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
909 wstring wName = jsStringRefToWString(name);
910 wstring wValue = jsStringRefToWString(value);
912 COMPtr<IWebView> webView;
913 if (FAILED(frame->webView(&webView)))
916 COMPtr<IWebViewPrivate> viewPrivate;
917 if (FAILED(webView->QueryInterface(&viewPrivate)))
920 BSTR nameBSTR = SysAllocStringLen((OLECHAR*)wName.c_str(), wName.length());
921 BSTR valueBSTR = SysAllocStringLen((OLECHAR*)wValue.c_str(), wValue.length());
922 viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR);
924 SysFreeString(nameBSTR);
925 SysFreeString(valueBSTR);
928 bool LayoutTestController::findString(JSContextRef /* context */, JSStringRef /* target */, JSObjectRef /* optionsArray */)
934 void LayoutTestController::setCacheModel(int)
939 bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/)
941 printf("ERROR: LayoutTestController::isCommandEnabled() not implemented\n");
945 void LayoutTestController::clearAllApplicationCaches()
947 // FIXME: Implement to support application cache quotas.
950 void LayoutTestController::clearApplicationCacheForOrigin(JSStringRef origin)
952 // FIXME: Implement to support deleting all application cache for an origin.
955 void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
957 // FIXME: Implement to support application cache quotas.
960 JSValueRef LayoutTestController::originsWithApplicationCache(JSContextRef context)
962 // FIXME: Implement to get origins that have application caches.
963 return JSValueMakeUndefined(context);
966 long long LayoutTestController::applicationCacheDiskUsageForOrigin(JSStringRef name)
968 // FIXME: Implement to get disk usage by all application caches for an origin.
972 void LayoutTestController::clearAllDatabases()
974 COMPtr<IWebDatabaseManager> databaseManager;
975 COMPtr<IWebDatabaseManager> tmpDatabaseManager;
976 if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
978 if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
981 databaseManager->deleteAllDatabases();
984 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
986 COMPtr<IWebView> webView;
987 if (FAILED(frame->webView(&webView)))
990 COMPtr<IWebPreferences> preferences;
991 if (FAILED(webView->preferences(&preferences)))
994 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
998 BSTR keyBSTR = JSStringCopyBSTR(key);
999 BSTR valueBSTR = JSStringCopyBSTR(value);
1000 prefsPrivate->setPreferenceForTest(keyBSTR, valueBSTR);
1001 SysFreeString(keyBSTR);
1002 SysFreeString(valueBSTR);
1005 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
1007 COMPtr<IWebDatabaseManager> databaseManager;
1008 COMPtr<IWebDatabaseManager> tmpDatabaseManager;
1010 if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
1012 if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
1015 databaseManager->setQuota(TEXT("file:///"), quota);
1018 void LayoutTestController::goBack()
1020 // FIXME: implement to enable loader/navigation-while-deferring-loads.html
1023 void LayoutTestController::setDefersLoading(bool)
1025 // FIXME: implement to enable loader/navigation-while-deferring-loads.html
1028 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
1030 COMPtr<IWebViewPrivate> webView;
1031 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1034 BSTR schemeBSTR = JSStringCopyBSTR(scheme);
1035 webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR);
1036 SysFreeString(schemeBSTR);
1039 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
1041 printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n");
1044 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
1046 COMPtr<IDOMDocument> document;
1047 if (FAILED(frame->DOMDocument(&document)))
1050 BSTR idBSTR = JSStringCopyBSTR(elementId);
1051 COMPtr<IDOMElement> element;
1052 HRESULT hr = document->getElementById(idBSTR, &element);
1053 SysFreeString(idBSTR);
1057 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1061 BSTR nameBSTR = JSStringCopyBSTR(animationName);
1062 BOOL wasRunning = FALSE;
1063 hr = framePrivate->pauseAnimation(nameBSTR, element.get(), time, &wasRunning);
1064 SysFreeString(nameBSTR);
1066 return SUCCEEDED(hr) && wasRunning;
1069 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
1071 COMPtr<IDOMDocument> document;
1072 if (FAILED(frame->DOMDocument(&document)))
1075 BSTR idBSTR = JSStringCopyBSTR(elementId);
1076 COMPtr<IDOMElement> element;
1077 HRESULT hr = document->getElementById(idBSTR, &element);
1078 SysFreeString(idBSTR);
1082 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1086 BSTR nameBSTR = JSStringCopyBSTR(propertyName);
1087 BOOL wasRunning = FALSE;
1088 hr = framePrivate->pauseTransition(nameBSTR, element.get(), time, &wasRunning);
1089 SysFreeString(nameBSTR);
1091 return SUCCEEDED(hr) && wasRunning;
1094 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
1096 COMPtr<IDOMDocument> document;
1097 if (FAILED(frame->DOMDocument(&document)))
1100 BSTR idBSTR = JSStringCopyBSTR(animationId);
1101 COMPtr<IDOMElement> element;
1102 HRESULT hr = document->getElementById(idBSTR, &element);
1103 SysFreeString(idBSTR);
1107 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1111 BSTR elementIdBSTR = JSStringCopyBSTR(elementId);
1112 BOOL wasRunning = FALSE;
1113 hr = framePrivate->pauseSVGAnimation(elementIdBSTR, element.get(), time, &wasRunning);
1114 SysFreeString(elementIdBSTR);
1116 return SUCCEEDED(hr) && wasRunning;
1119 unsigned LayoutTestController::numberOfActiveAnimations() const
1121 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1126 if (FAILED(framePrivate->numberOfActiveAnimations(&number)))
1132 void LayoutTestController::suspendAnimations() const
1134 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1138 framePrivate->suspendAnimations();
1141 void LayoutTestController::resumeAnimations() const
1143 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1147 framePrivate->resumeAnimations();
1150 static _bstr_t bstrT(JSStringRef jsString)
1152 // The false parameter tells the _bstr_t constructor to adopt the BSTR we pass it.
1153 return _bstr_t(JSStringCopyBSTR(jsString), false);
1156 void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1158 COMPtr<IWebViewPrivate> webView;
1159 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1162 webView->addOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1165 void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1167 COMPtr<IWebViewPrivate> webView;
1168 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1171 webView->removeOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1174 void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
1179 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1181 COMPtr<IWebViewPrivate> webView;
1182 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1185 COMPtr<IWebScriptWorld> world;
1186 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1189 webView->addUserScriptToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0, runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd);
1193 void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1195 COMPtr<IWebViewPrivate> webView;
1196 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1199 COMPtr<IWebScriptWorld> world;
1200 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1203 webView->addUserStyleSheetToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0);
1206 void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
1208 COMPtr<IWebView> webView;
1209 if (FAILED(frame->webView(&webView)))
1212 COMPtr<IWebPreferences> preferences;
1213 if (FAILED(webView->preferences(&preferences)))
1216 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
1220 prefsPrivate->setDeveloperExtrasEnabled(enabled);
1223 void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
1225 // FIXME: Implement this.
1228 void LayoutTestController::showWebInspector()
1230 COMPtr<IWebView> webView;
1231 if (FAILED(frame->webView(&webView)))
1234 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1238 COMPtr<IWebInspector> inspector;
1239 if (SUCCEEDED(viewPrivate->inspector(&inspector)))
1243 void LayoutTestController::closeWebInspector()
1245 COMPtr<IWebView> webView;
1246 if (FAILED(frame->webView(&webView)))
1249 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1253 COMPtr<IWebInspector> inspector;
1254 if (FAILED(viewPrivate->inspector(&inspector)))
1260 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
1262 COMPtr<IWebView> webView;
1263 if (FAILED(frame->webView(&webView)))
1266 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1270 COMPtr<IWebInspector> inspector;
1271 if (FAILED(viewPrivate->inspector(&inspector)))
1274 COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
1275 if (!inspectorPrivate)
1278 inspectorPrivate->evaluateInFrontend(callId, bstrT(script).GetBSTR());
1281 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
1282 static WorldMap& worldMap()
1284 static WorldMap& map = *new WorldMap;
1288 unsigned worldIDForWorld(IWebScriptWorld* world)
1290 WorldMap::const_iterator end = worldMap().end();
1291 for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
1292 if (it->second == world)
1299 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1301 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1305 // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
1306 // that is created once and cached forever.
1307 COMPtr<IWebScriptWorld> world;
1309 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1312 COMPtr<IWebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
1313 if (!worldSlot && FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(worldSlot), reinterpret_cast<void**>(&worldSlot))))
1319 if (FAILED(framePrivate->stringByEvaluatingJavaScriptInScriptWorld(world.get(), globalObject, bstrT(script).GetBSTR(), &result)))
1321 SysFreeString(result);
1324 void LayoutTestController::removeAllVisitedLinks()
1326 COMPtr<IWebHistory> history;
1327 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
1330 COMPtr<IWebHistory> sharedHistory;
1331 if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
1334 COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
1335 if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
1338 sharedHistoryPrivate->removeAllVisitedLinks();
1341 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
1343 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1347 wstring idWstring = jsStringRefToWString(id);
1348 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1349 BSTR counterValueBSTR;
1350 if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR)))
1353 wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR));
1354 SysFreeString(idBSTR);
1355 SysFreeString(counterValueBSTR);
1356 JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length()));
1357 return counterValueJS;
1360 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
1362 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1366 wstring idWstring = jsStringRefToWString(id);
1367 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1368 int pageNumber = -1;
1369 if (FAILED(framePrivate->pageNumberForElementById(idBSTR, pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1371 SysFreeString(idBSTR);
1375 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
1377 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1381 int pageNumber = -1;
1382 if (FAILED(framePrivate->numberOfPages(pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1387 JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
1389 // FIXME: Implement this.
1390 return JSRetainPtr<JSStringRef>();
1393 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
1398 bool LayoutTestController::isPageBoxVisible(int pageNumber) const
1404 JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
1407 return JSRetainPtr<JSStringRef>();
1410 void LayoutTestController::apiTestGoToCurrentBackForwardItem()
1412 COMPtr<IWebView> webView;
1413 if (FAILED(frame->webView(&webView)))
1416 COMPtr<IWebBackForwardList> backForwardList;
1417 if (FAILED(webView->backForwardList(&backForwardList)))
1420 COMPtr<IWebHistoryItem> item;
1421 if (FAILED(backForwardList->currentItem(&item)))
1425 webView->goToBackForwardItem(item.get(), &success);
1428 void LayoutTestController::setWebViewEditable(bool)
1432 void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
1436 void LayoutTestController::setEditingBehavior(const char* editingBehavior)
1438 COMPtr<IWebView> webView;
1439 if (FAILED(frame->webView(&webView)))
1442 COMPtr<IWebPreferences> preferences;
1443 if (FAILED(webView->preferences(&preferences)))
1446 string behaviorString(editingBehavior);
1447 if (behaviorString == "mac")
1448 preferences->setEditingBehavior(WebKitEditingMacBehavior);
1449 else if (behaviorString == "win")
1450 preferences->setEditingBehavior(WebKitEditingWinBehavior);
1451 else if (behaviorString == "unix")
1452 preferences->setEditingBehavior(WebKitEditingUnixBehavior);
1455 void LayoutTestController::abortModal()
1459 bool LayoutTestController::hasSpellingMarker(int from, int length)
1461 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1465 if (FAILED(framePrivate->hasSpellingMarker(from, length, &ret)))
1470 bool LayoutTestController::hasGrammarMarker(int from, int length)
1472 // FIXME: Implement this.
1476 void LayoutTestController::dumpConfigurationForViewport(int /*deviceDPI*/, int /*deviceWidth*/, int /*deviceHeight*/, int /*availableWidth*/, int /*availableHeight*/)
1478 // FIXME: Implement this.
1481 void LayoutTestController::setSerializeHTTPLoads(bool)
1483 // FIXME: Implement.
1486 void LayoutTestController::syncLocalStorage()
1488 // FIXME: Implement.
1491 void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
1493 // FIXME: Implement.
1496 void LayoutTestController::deleteAllLocalStorage()
1498 // FIXME: Implement.
1501 JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
1503 // FIXME: Implement.
1504 return JSValueMakeUndefined(context);
1507 long long LayoutTestController::localStorageDiskUsageForOrigin(JSStringRef originIdentifier)
1509 // FIXME: Implement to support getting local storage disk usage for an origin.
1513 void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
1515 // FIXME: Implement.
1518 void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
1520 COMPtr<IWebView> webView;
1521 if (FAILED(frame->webView(&webView)))
1524 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1528 viewPrivate->setMinimumTimerInterval(minimumTimerInterval);
1531 void LayoutTestController::setTextDirection(JSStringRef direction)
1533 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1537 framePrivate->setTextDirection(bstrT(direction).GetBSTR());
1540 void LayoutTestController::allowRoundingHacks()