Clean up ChunkedUpdateDrawingAreaProxy
[WebKit-https.git] / WebKitTools / DumpRenderTree / win / LayoutTestControllerWin.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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.
16  *
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.
27  */
28
29 #include "config.h"
30 #include "LayoutTestController.h"
31
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>
45 #include <comutil.h>
46 #include <shlwapi.h>
47 #include <shlguid.h>
48 #include <shobjidl.h>
49 #include <string>
50 #include <wtf/Platform.h>
51 #include <wtf/RetainPtr.h>
52 #include <wtf/Vector.h>
53
54 using std::string;
55 using std::wstring;
56
57 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath);
58
59 LayoutTestController::~LayoutTestController()
60 {
61     COMPtr<IWebView> webView;
62     if (FAILED(frame->webView(&webView)))
63         return;
64
65     // reset webview-related states back to default values in preparation for next test
66
67     COMPtr<IWebViewPrivate> viewPrivate;
68     if (SUCCEEDED(webView->QueryInterface(&viewPrivate)))
69         viewPrivate->setTabKeyCyclesThroughElements(TRUE);
70
71     COMPtr<IWebViewEditing> viewEditing;
72     if (FAILED(webView->QueryInterface(&viewEditing)))
73         return;
74     COMPtr<IWebEditingDelegate> delegate;
75     if (FAILED(viewEditing->editingDelegate(&delegate)))
76         return;
77     COMPtr<EditingDelegate> editingDelegate(Query, viewEditing.get());
78     if (editingDelegate)
79         editingDelegate->setAcceptsEditing(TRUE);
80 }
81
82 void LayoutTestController::addDisallowedURL(JSStringRef url)
83 {
84     // FIXME: Implement!
85 }
86
87 void LayoutTestController::clearBackForwardList()
88 {
89     COMPtr<IWebView> webView;
90     if (FAILED(frame->webView(&webView)))
91         return;
92
93     COMPtr<IWebBackForwardList> backForwardList;
94     if (FAILED(webView->backForwardList(&backForwardList)))
95         return;
96
97     COMPtr<IWebHistoryItem> item;
98     if (FAILED(backForwardList->currentItem(&item)))
99         return;
100
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.
103     int capacity;
104     if (FAILED(backForwardList->capacity(&capacity)))
105         return;
106
107     backForwardList->setCapacity(0);
108     backForwardList->setCapacity(capacity);
109     backForwardList->addItem(item.get());
110     backForwardList->goToItem(item.get());
111 }
112
113 bool LayoutTestController::callShouldCloseOnWebView()
114 {
115     COMPtr<IWebView> webView;
116     if (FAILED(frame->webView(&webView)))
117         return false;
118
119     COMPtr<IWebViewPrivate> viewPrivate;
120     if (FAILED(webView->QueryInterface(&viewPrivate)))
121         return false;
122
123     BOOL result;
124     viewPrivate->shouldClose(&result);
125     return result;
126 }
127
128 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
129 {
130     // FIXME: Implement!
131     return 0;
132 }
133
134 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
135 {
136     // FIXME: Implement!
137     return 0;
138 }
139
140 void LayoutTestController::disableImageLoading()
141 {
142     COMPtr<IWebView> webView;
143     if (FAILED(frame->webView(&webView)))
144         return;
145     
146     COMPtr<IWebPreferences> preferences;
147     if (FAILED(webView->preferences(&preferences)))
148         return;
149     
150     preferences->setLoadsImagesAutomatically(FALSE);
151 }
152
153 void LayoutTestController::dispatchPendingLoadRequests()
154 {
155     // FIXME: Implement for testing fix for 6727495
156 }
157
158 void LayoutTestController::display()
159 {
160     displayWebView();
161 }
162
163 void LayoutTestController::keepWebHistory()
164 {
165     COMPtr<IWebHistory> history;
166     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
167         return;
168
169     COMPtr<IWebHistory> sharedHistory;
170     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(sharedHistory), reinterpret_cast<void**>(&sharedHistory))))
171         return;
172
173     history->setOptionalSharedHistory(sharedHistory.get());
174 }
175
176 JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
177 {
178     // FIXME: Implement this.
179     return JSValueMakeUndefined(context);
180 }
181
182 JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
183 {
184     // FIXME: Implement this.
185     return JSValueMakeUndefined(context);
186 }
187
188 JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
189 {
190     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
191     if (!framePrivate)
192         return false;
193
194     BSTR textBSTR = 0;
195     HRESULT hr = framePrivate->layerTreeAsText(&textBSTR);
196
197     wstring text(textBSTR, SysStringLen(textBSTR));
198     SysFreeString(textBSTR);
199     JSRetainPtr<JSStringRef> textValueJS(Adopt, JSStringCreateWithCharacters(text.data(), text.length()));
200     return textValueJS;
201 }
202
203 JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const
204 {
205     COMPtr<IWebView> webView;
206     if (FAILED(frame->webView(&webView)))
207         return 0;
208
209     COMPtr<IWebViewPrivate> webViewPrivate(Query, webView);
210     if (!webViewPrivate)
211         return 0;
212
213     COMPtr<IDOMElement> element;
214     if (FAILED(webViewPrivate->elementFromJS(context, nodeObject, &element)))
215         return 0;
216
217     COMPtr<IDOMElementPrivate> elementPrivate(Query, element);
218     if (!elementPrivate)
219         return 0;
220
221     BSTR textBSTR = 0;
222     if (FAILED(elementPrivate->markerTextForListItem(&textBSTR)))
223         return 0;
224
225     JSRetainPtr<JSStringRef> markerText(Adopt, JSStringCreateWithBSTR(textBSTR));
226     SysFreeString(textBSTR);
227     return markerText;
228 }
229
230 void LayoutTestController::waitForPolicyDelegate()
231 {
232     COMPtr<IWebView> webView;
233     if (FAILED(frame->webView(&webView)))
234         return;
235
236     setWaitToDump(true);
237     policyDelegate->setControllerToNotifyDone(this);
238     webView->setPolicyDelegate(policyDelegate);
239 }
240
241 size_t LayoutTestController::webHistoryItemCount()
242 {
243     COMPtr<IWebHistory> history;
244     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
245         return 0;
246
247     COMPtr<IWebHistory> sharedHistory;
248     if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
249         return 0;
250
251     COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
252     if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
253         return 0;
254
255     int count;
256     if (FAILED(sharedHistoryPrivate->allItems(&count, 0)))
257         return 0;
258
259     return count;
260 }
261
262 unsigned LayoutTestController::workerThreadCount() const
263 {
264     COMPtr<IWebWorkersPrivate> workers;
265     if (FAILED(WebKitCreateInstance(CLSID_WebWorkersPrivate, 0, __uuidof(workers), reinterpret_cast<void**>(&workers))))
266         return 0;
267     unsigned count;
268     if (FAILED(workers->workerThreadCount(&count)))
269         return 0;
270     return count;
271 }
272
273 void LayoutTestController::notifyDone()
274 {
275     // Same as on mac.  This can be shared.
276     if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
277         dump();
278     m_waitToDump = false;
279 }
280
281 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
282 {
283     wstring input(JSStringGetCharactersPtr(url), JSStringGetLength(url));
284
285     wstring localPath;
286     if (!resolveCygwinPath(input, localPath)) {
287         printf("ERROR: Failed to resolve Cygwin path %S\n", input.c_str());
288         return 0;
289     }
290
291     return JSStringCreateWithCharacters(localPath.c_str(), localPath.length());
292 }
293
294 static wstring jsStringRefToWString(JSStringRef jsStr)
295 {
296     size_t length = JSStringGetLength(jsStr);
297     Vector<WCHAR> buffer(length + 1);
298     memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR));
299     buffer[length] = '\0';
300
301     return buffer.data();
302 }
303
304 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
305 {
306     COMPtr<IWebDataSource> dataSource;
307     if (FAILED(frame->dataSource(&dataSource)))
308         return;
309
310     COMPtr<IWebURLResponse> response;
311     if (FAILED(dataSource->response(&response)) || !response)
312         return;
313
314     BSTR responseURLBSTR;
315     if (FAILED(response->URL(&responseURLBSTR)))
316         return;
317     wstring responseURL(responseURLBSTR, SysStringLen(responseURLBSTR));
318     SysFreeString(responseURLBSTR);
319
320     // FIXME: We should do real relative URL resolution here.
321     int lastSlash = responseURL.rfind('/');
322     if (lastSlash != -1)
323         responseURL = responseURL.substr(0, lastSlash);
324
325     wstring wURL = jsStringRefToWString(url);
326     wstring wAbsoluteURL = responseURL + TEXT("/") + wURL;
327     JSRetainPtr<JSStringRef> jsAbsoluteURL(Adopt, JSStringCreateWithCharacters(wAbsoluteURL.data(), wAbsoluteURL.length()));
328
329     WorkQueue::shared()->queue(new LoadItem(jsAbsoluteURL.get(), target));
330 }
331
332 void LayoutTestController::setAcceptsEditing(bool acceptsEditing)
333 {
334     COMPtr<IWebView> webView;
335     if (FAILED(frame->webView(&webView)))
336         return;
337
338     COMPtr<IWebViewEditing> viewEditing;
339     if (FAILED(webView->QueryInterface(&viewEditing)))
340         return;
341
342     COMPtr<IWebEditingDelegate> delegate;
343     if (FAILED(viewEditing->editingDelegate(&delegate)))
344         return;
345
346     EditingDelegate* editingDelegate = (EditingDelegate*)(IWebEditingDelegate*)delegate.get();
347     editingDelegate->setAcceptsEditing(acceptsEditing);
348 }
349
350 void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
351 {
352     if (alwaysAcceptCookies == m_alwaysAcceptCookies)
353         return;
354
355     if (!::setAlwaysAcceptCookies(alwaysAcceptCookies))
356         return;
357     m_alwaysAcceptCookies = alwaysAcceptCookies;
358 }
359
360 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
361 {
362     COMPtr<IWebView> webView;
363     if (FAILED(frame->webView(&webView)))
364         return;
365
366     COMPtr<IWebPreferences> preferences;
367     if (FAILED(webView->preferences(&preferences)))
368         return;
369
370     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
371     if (!prefsPrivate)
372         return;
373
374     prefsPrivate->setAuthorAndUserStylesEnabled(flag);
375 }
376
377 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
378 {
379     COMPtr<IWebView> webView;
380     if (FAILED(frame->webView(&webView)))
381         return;
382
383     if (setDelegate) {
384         policyDelegate->setPermissive(permissive);
385         webView->setPolicyDelegate(policyDelegate);
386     } else
387         webView->setPolicyDelegate(0);
388 }
389
390 void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
391 {
392     // FIXME: Implement for DeviceOrientation layout tests.
393     // See https://bugs.webkit.org/show_bug.cgi?id=30335.
394 }
395
396 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
397 {
398     // FIXME: Implement for Geolocation layout tests.
399     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
400 }
401
402 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
403 {
404     // FIXME: Implement for Geolocation layout tests.
405     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
406 }
407
408 void LayoutTestController::setGeolocationPermission(bool allow)
409 {
410     // FIXME: Implement for Geolocation layout tests.
411     setGeolocationPermissionCommon(allow);
412 }
413
414 void LayoutTestController::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
415 {
416     // FIXME: Implement for speech input layout tests.
417     // See https://bugs.webkit.org/show_bug.cgi?id=39485.
418 }
419
420 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
421 {
422     // See also <rdar://problem/6480108>
423     COMPtr<IWebIconDatabase> iconDatabase;
424     COMPtr<IWebIconDatabase> tmpIconDatabase;
425     if (FAILED(WebKitCreateInstance(CLSID_WebIconDatabase, 0, IID_IWebIconDatabase, (void**)&tmpIconDatabase)))
426         return;
427     if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase)))
428         return;
429
430     iconDatabase->setEnabled(iconDatabaseEnabled);
431 }
432
433 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
434 {
435     // FIXME: Implement!
436 }
437
438 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
439 {
440     COMPtr<IWebView> webView;
441     if (FAILED(frame->webView(&webView)))
442         return;
443
444     COMPtr<IWebPreferences> preferences;
445     if (FAILED(webView->preferences(&preferences)))
446         return;
447
448     preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
449 }
450
451 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
452 {
453     COMPtr<IWebView> webView;
454     if (FAILED(frame->webView(&webView)))
455         return;
456
457     COMPtr<IWebPreferences> preferences;
458     if (FAILED(webView->preferences(&preferences)))
459         return;
460
461     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
462     if (!prefsPrivate)
463         return;
464
465     prefsPrivate->setXSSAuditorEnabled(enabled);
466 }
467
468 void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
469 {
470     COMPtr<IWebView> webView;
471     if (FAILED(frame->webView(&webView)))
472         return;
473
474     COMPtr<IWebPreferences> preferences;
475     if (FAILED(webView->preferences(&preferences)))
476         return;
477
478     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
479     if (!prefsPrivate)
480         return;
481
482     prefsPrivate->setFrameFlatteningEnabled(enabled);
483 }
484
485 void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
486 {
487     // FIXME: Implement for SpatialNavigation layout tests.
488 }
489
490 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
491 {
492     COMPtr<IWebView> webView;
493     if (FAILED(frame->webView(&webView)))
494         return;
495
496     COMPtr<IWebPreferences> preferences;
497     if (FAILED(webView->preferences(&preferences)))
498         return;
499
500     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
501     if (!prefsPrivate)
502         return;
503
504     prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
505 }
506
507 void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
508 {
509     COMPtr<IWebView> webView;
510     if (FAILED(frame->webView(&webView)))
511         return;
512
513     COMPtr<IWebPreferences> preferences;
514     if (FAILED(webView->preferences(&preferences)))
515         return;
516
517     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
518     if (!prefsPrivate)
519         return;
520
521     prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
522 }
523
524 void LayoutTestController::setPopupBlockingEnabled(bool enabled)
525 {
526     COMPtr<IWebView> webView;
527     if (FAILED(frame->webView(&webView)))
528         return;
529
530     COMPtr<IWebPreferences> preferences;
531     if (FAILED(webView->preferences(&preferences)))
532         return;
533
534     preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled);
535 }
536
537 void LayoutTestController::setPluginsEnabled(bool flag)
538 {
539     // FIXME: Implement
540 }
541
542 void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
543 {
544     COMPtr<IWebView> webView;
545     if (FAILED(frame->webView(&webView)))
546         return;
547
548     COMPtr<IWebPreferences> preferences;
549     if (FAILED(webView->preferences(&preferences)))
550         return;
551
552     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
553     if (!prefsPrivate)
554         return;
555
556     prefsPrivate->setJavaScriptCanAccessClipboard(enabled);
557 }
558
559 void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle)
560 {
561     COMPtr<IWebView> webView;
562     if (FAILED(frame->webView(&webView)))
563         return;
564
565     COMPtr<IWebViewPrivate> viewPrivate;
566     if (FAILED(webView->QueryInterface(&viewPrivate)))
567         return;
568
569     viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE);
570 }
571
572 void LayoutTestController::setTimelineProfilingEnabled(bool flag)
573 {
574     COMPtr<IWebView> webView;
575     if (FAILED(frame->webView(&webView)))
576         return;
577
578     COMPtr<IWebViewPrivate> viewPrivate;
579     if (FAILED(webView->QueryInterface(&viewPrivate)))
580         return;
581
582     COMPtr<IWebInspector> inspector;
583     if (FAILED(viewPrivate->inspector(&inspector)))
584         return;
585
586     inspector->setTimelineProfilingEnabled(flag);
587 }
588
589 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
590 {
591     // FIXME: Implement!
592 }
593
594 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
595 {
596     COMPtr<IWebView> webView;
597     if (FAILED(frame->webView(&webView)))
598         return;
599
600     COMPtr<IWebPreferences> preferences;
601     if (FAILED(webView->preferences(&preferences)))
602         return;
603
604    preferences->setUserStyleSheetEnabled(flag);
605 }
606
607 bool appendComponentToPath(wstring& path, const wstring& component)
608 {
609     WCHAR buffer[MAX_PATH];
610
611     if (path.size() + 1 > MAX_PATH)
612         return false;
613
614     memcpy(buffer, path.data(), path.size() * sizeof(WCHAR));
615     buffer[path.size()] = '\0';
616
617     if (!PathAppendW(buffer, component.c_str()))
618         return false;
619
620     path = wstring(buffer);
621     return true;
622 }
623
624 static bool followShortcuts(wstring& path)
625 {
626     if (PathFileExists(path.c_str()))
627         return true;
628
629     // Do we have a shortcut?
630     wstring linkPath = path;
631     linkPath.append(TEXT(".lnk"));
632     if (!PathFileExists(linkPath.c_str()))
633        return true;
634
635     // We have a shortcut, find its target.
636     COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink);
637     if (!shortcut)
638        return false;
639     COMPtr<IPersistFile> persistFile(Query, shortcut);
640     if (!shortcut)
641         return false;
642     if (FAILED(persistFile->Load(linkPath.c_str(), STGM_READ)))
643         return false;
644     if (FAILED(shortcut->Resolve(0, 0)))
645         return false;
646     WCHAR targetPath[MAX_PATH];
647     DWORD targetPathLen = _countof(targetPath);
648     if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0)))
649         return false;
650     if (!PathFileExists(targetPath))
651         return false;
652     // Use the target path as the result path instead.
653     path = wstring(targetPath);
654
655     return true;
656 }
657
658 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath)
659 {
660     wstring fileProtocol = L"file://";
661     bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos;
662     if (cygwinPath[isFileProtocol ? 7 : 0] != '/')  // ensure path is absolute
663         return false;
664
665     // Get the Root path.
666     WCHAR rootPath[MAX_PATH];
667     DWORD rootPathSize = _countof(rootPath);
668     DWORD keyType;
669     DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize);
670
671     if (result != ERROR_SUCCESS || keyType != REG_SZ) {
672         // Cygwin 1.7 doesn't store Cygwin's root as a mount point anymore, because mount points are now stored in /etc/fstab.
673         // However, /etc/fstab doesn't contain any information about where / is located as a Windows path, so we need to use Cygwin's
674         // new registry key that has the root.
675         result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygwin\\setup"), TEXT("rootdir"), &keyType, &rootPath, &rootPathSize);
676         if (result != ERROR_SUCCESS || keyType != REG_SZ)
677             return false;
678     }
679
680     windowsPath = wstring(rootPath, rootPathSize);
681
682     int oldPos = isFileProtocol ? 8 : 1;
683     while (1) {
684         int newPos = cygwinPath.find('/', oldPos);
685
686         if (newPos == -1) {
687             wstring pathComponent = cygwinPath.substr(oldPos);
688
689             if (!appendComponentToPath(windowsPath, pathComponent))
690                return false;
691
692             if (!followShortcuts(windowsPath))
693                 return false;
694
695             break;
696         }
697
698         wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos);
699         if (!appendComponentToPath(windowsPath, pathComponent))
700             return false;
701
702         if (!followShortcuts(windowsPath))
703             return false;
704
705         oldPos = newPos + 1;
706     }
707
708     if (isFileProtocol)
709         windowsPath = fileProtocol + windowsPath;
710
711     return true;
712 }
713
714 static wstring cfStringRefToWString(CFStringRef cfStr)
715 {
716     Vector<wchar_t> v(CFStringGetLength(cfStr));
717     CFStringGetCharacters(cfStr, CFRangeMake(0, CFStringGetLength(cfStr)), (UniChar *)v.data());
718
719     return wstring(v.data(), v.size());
720 }
721
722 void LayoutTestController::setUserStyleSheetLocation(JSStringRef jsURL)
723 {
724     COMPtr<IWebView> webView;
725     if (FAILED(frame->webView(&webView)))
726         return;
727
728     COMPtr<IWebPreferences> preferences;
729     if (FAILED(webView->preferences(&preferences)))
730         return;
731
732     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
733     RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, urlString.get(), 0));
734     if (!url)
735         return;
736
737     // Now copy the file system path, POSIX style.
738     RetainPtr<CFStringRef> pathCF(AdoptCF, CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle));
739     if (!pathCF)
740         return;
741
742     wstring path = cfStringRefToWString(pathCF.get());
743
744     wstring resultPath;
745     if (!resolveCygwinPath(path, resultPath))
746         return;
747
748     // The path has been resolved, now convert it back to a CFURL.
749     int result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, 0, 0, 0, 0);
750     Vector<char> utf8Vector(result);
751     result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, 0, 0);
752     if (!result)
753         return;
754
755     url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false);
756     if (!url)
757         return;
758
759     resultPath = cfStringRefToWString(CFURLGetString(url.get()));
760
761     BSTR resultPathBSTR = SysAllocStringLen(resultPath.data(), resultPath.size());
762     preferences->setUserStyleSheetLocation(resultPathBSTR);
763     SysFreeString(resultPathBSTR);
764 }
765
766 void LayoutTestController::setViewModeMediaFeature(JSStringRef mode)
767 {
768     // FIXME: implement
769 }
770
771 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
772 {
773     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
774     ::setPersistentUserStyleSheetLocation(urlString.get());
775 }
776
777 void LayoutTestController::clearPersistentUserStyleSheet()
778 {
779     ::setPersistentUserStyleSheetLocation(0);
780 }
781
782 void LayoutTestController::setWindowIsKey(bool flag)
783 {
784     COMPtr<IWebView> webView;
785     if (FAILED(frame->webView(&webView)))
786         return;
787
788     COMPtr<IWebViewPrivate> viewPrivate;
789     if (FAILED(webView->QueryInterface(&viewPrivate)))
790         return;
791
792     HWND webViewWindow;
793     if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow)))
794         return;
795
796     ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0);
797 }
798
799 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
800 {
801     COMPtr<IWebView> webView;
802     if (FAILED(frame->webView(&webView)))
803         return;
804
805     COMPtr<IWebViewEditing> viewEditing;
806     if (FAILED(webView->QueryInterface(&viewEditing)))
807         return;
808
809     viewEditing->setSmartInsertDeleteEnabled(flag ? TRUE : FALSE);
810 }
811
812 void LayoutTestController::setJavaScriptProfilingEnabled(bool flag)
813 {
814     COMPtr<IWebView> webView;
815     if (FAILED(frame->webView(&webView)))
816         return;
817
818     COMPtr<IWebViewPrivate> viewPrivate;
819     if (FAILED(webView->QueryInterface(&viewPrivate)))
820         return;
821
822     COMPtr<IWebInspector> inspector;
823     if (FAILED(viewPrivate->inspector(&inspector)))
824         return;
825
826     setDeveloperExtrasEnabled(flag);
827     inspector->setJavaScriptProfilingEnabled(flag);
828 }
829
830 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
831 {
832     COMPtr<IWebView> webView;
833     if (FAILED(frame->webView(&webView)))
834         return;
835
836     COMPtr<IWebViewEditing> viewEditing;
837     if (FAILED(webView->QueryInterface(&viewEditing)))
838         return;
839
840     viewEditing->setSelectTrailingWhitespaceEnabled(flag ? TRUE : FALSE);
841 }
842
843 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
844
845 static void CALLBACK waitUntilDoneWatchdogFired(HWND, UINT, UINT_PTR, DWORD)
846 {
847     gLayoutTestController->waitToDumpWatchdogTimerFired();
848 }
849
850 void LayoutTestController::setWaitToDump(bool waitUntilDone)
851 {
852     m_waitToDump = waitUntilDone;
853     if (m_waitToDump && !waitToDumpWatchdog)
854         waitToDumpWatchdog = SetTimer(0, 0, waitToDumpWatchdogInterval * 1000, waitUntilDoneWatchdogFired);
855 }
856
857 int LayoutTestController::windowCount()
858 {
859     return openWindows().size();
860 }
861
862 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
863 {
864     COMPtr<IDOMDocument> document;
865     if (FAILED(frame->DOMDocument(&document)))
866         return false;
867
868     wstring idWstring = jsStringRefToWString(id);
869     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
870     COMPtr<IDOMElement> element;
871     HRESULT result = document->getElementById(idBSTR, &element);
872     SysFreeString(idBSTR);
873
874     if (FAILED(result))
875         return false;
876
877     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
878     if (!framePrivate)
879         return false;
880
881     BOOL autoCompletes;
882     if (FAILED(framePrivate->elementDoesAutoComplete(element.get(), &autoCompletes)))
883         return false;
884
885     return autoCompletes;
886 }
887
888 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
889 {
890     wstring wName = jsStringRefToWString(name);
891     wstring wValue = jsStringRefToWString(value);
892
893     COMPtr<IWebView> webView;
894     if (FAILED(frame->webView(&webView)))
895         return;
896
897     COMPtr<IWebViewPrivate> viewPrivate;
898     if (FAILED(webView->QueryInterface(&viewPrivate)))
899         return;
900
901     BSTR nameBSTR = SysAllocStringLen((OLECHAR*)wName.c_str(), wName.length());
902     BSTR valueBSTR = SysAllocStringLen((OLECHAR*)wValue.c_str(), wValue.length());
903     viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR);
904
905     SysFreeString(nameBSTR);
906     SysFreeString(valueBSTR);
907 }
908
909 bool LayoutTestController::findString(JSContextRef /* context */, JSStringRef /* target */, JSObjectRef /* optionsArray */)
910 {
911     // FIXME: Implement
912     return false;
913 }
914
915 void LayoutTestController::setCacheModel(int)
916 {
917     // FIXME: Implement
918 }
919
920 bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/)
921 {
922     printf("ERROR: LayoutTestController::isCommandEnabled() not implemented\n");
923     return false;
924 }
925
926 void LayoutTestController::clearAllApplicationCaches()
927 {
928     // FIXME: implement to support Application Cache quotas.
929 }
930
931 void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
932 {
933     // FIXME: implement to support Application Cache quotas.
934 }
935
936 void LayoutTestController::clearAllDatabases()
937 {
938     COMPtr<IWebDatabaseManager> databaseManager;
939     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
940     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
941         return;
942     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
943         return;
944
945     databaseManager->deleteAllDatabases();
946 }
947
948 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
949 {
950     COMPtr<IWebView> webView;
951     if (FAILED(frame->webView(&webView)))
952         return;
953
954     COMPtr<IWebPreferences> preferences;
955     if (FAILED(webView->preferences(&preferences)))
956         return;
957
958     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
959     if (!prefsPrivate)
960         return;
961
962     BSTR keyBSTR = JSStringCopyBSTR(key);
963     BSTR valueBSTR = JSStringCopyBSTR(value);
964     prefsPrivate->setPreferenceForTest(keyBSTR, valueBSTR);
965     SysFreeString(keyBSTR);
966     SysFreeString(valueBSTR);
967 }
968
969 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
970 {
971     COMPtr<IWebDatabaseManager> databaseManager;
972     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
973
974     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
975         return;
976     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
977         return;
978
979     databaseManager->setQuota(TEXT("file:///"), quota);
980 }
981
982 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
983 {
984     COMPtr<IWebViewPrivate> webView;
985     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
986         return;
987
988     BSTR schemeBSTR = JSStringCopyBSTR(scheme);
989     webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR);
990     SysFreeString(schemeBSTR);
991 }
992
993 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
994 {
995     printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n");
996 }
997
998 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
999 {
1000     COMPtr<IDOMDocument> document;
1001     if (FAILED(frame->DOMDocument(&document)))
1002         return false;
1003
1004     BSTR idBSTR = JSStringCopyBSTR(elementId);
1005     COMPtr<IDOMElement> element;
1006     HRESULT hr = document->getElementById(idBSTR, &element);
1007     SysFreeString(idBSTR);
1008     if (FAILED(hr))
1009         return false;
1010
1011     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1012     if (!framePrivate)
1013         return false;
1014
1015     BSTR nameBSTR = JSStringCopyBSTR(animationName);
1016     BOOL wasRunning = FALSE;
1017     hr = framePrivate->pauseAnimation(nameBSTR, element.get(), time, &wasRunning);
1018     SysFreeString(nameBSTR);
1019
1020     return SUCCEEDED(hr) && wasRunning;
1021 }
1022
1023 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
1024 {
1025     COMPtr<IDOMDocument> document;
1026     if (FAILED(frame->DOMDocument(&document)))
1027         return false;
1028
1029     BSTR idBSTR = JSStringCopyBSTR(elementId);
1030     COMPtr<IDOMElement> element;
1031     HRESULT hr = document->getElementById(idBSTR, &element);
1032     SysFreeString(idBSTR);
1033     if (FAILED(hr))
1034         return false;
1035
1036     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1037     if (!framePrivate)
1038         return false;
1039
1040     BSTR nameBSTR = JSStringCopyBSTR(propertyName);
1041     BOOL wasRunning = FALSE;
1042     hr = framePrivate->pauseTransition(nameBSTR, element.get(), time, &wasRunning);
1043     SysFreeString(nameBSTR);
1044
1045     return SUCCEEDED(hr) && wasRunning;
1046 }
1047
1048 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
1049 {
1050     COMPtr<IDOMDocument> document;
1051     if (FAILED(frame->DOMDocument(&document)))
1052         return false;
1053
1054     BSTR idBSTR = JSStringCopyBSTR(animationId);
1055     COMPtr<IDOMElement> element;
1056     HRESULT hr = document->getElementById(idBSTR, &element);
1057     SysFreeString(idBSTR);
1058     if (FAILED(hr))
1059         return false;
1060
1061     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1062     if (!framePrivate)
1063         return false;
1064
1065     BSTR elementIdBSTR = JSStringCopyBSTR(elementId);
1066     BOOL wasRunning = FALSE;
1067     hr = framePrivate->pauseSVGAnimation(elementIdBSTR, element.get(), time, &wasRunning);
1068     SysFreeString(elementIdBSTR);
1069
1070     return SUCCEEDED(hr) && wasRunning;
1071 }
1072
1073 unsigned LayoutTestController::numberOfActiveAnimations() const
1074 {
1075     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1076     if (!framePrivate)
1077         return 0;
1078
1079     UINT number = 0;
1080     if (FAILED(framePrivate->numberOfActiveAnimations(&number)))
1081         return 0;
1082
1083     return number;
1084 }
1085
1086 void LayoutTestController::suspendAnimations() const
1087 {
1088     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1089     if (!framePrivate)
1090         return;
1091
1092     framePrivate->suspendAnimations();
1093 }
1094
1095 void LayoutTestController::resumeAnimations() const
1096 {
1097     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1098     if (!framePrivate)
1099         return;
1100
1101     framePrivate->resumeAnimations();
1102 }
1103
1104 static _bstr_t bstrT(JSStringRef jsString)
1105 {
1106     // The false parameter tells the _bstr_t constructor to adopt the BSTR we pass it.
1107     return _bstr_t(JSStringCopyBSTR(jsString), false);
1108 }
1109
1110 void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1111 {
1112     COMPtr<IWebViewPrivate> webView;
1113     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1114         return;
1115
1116     webView->addOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1117 }
1118
1119 void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1120 {
1121     COMPtr<IWebViewPrivate> webView;
1122     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1123         return;
1124
1125     webView->removeOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1126 }
1127
1128 void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
1129 {
1130     // FIXME: implement
1131 }
1132
1133 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1134 {
1135     COMPtr<IWebViewPrivate> webView;
1136     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1137         return;
1138
1139     COMPtr<IWebScriptWorld> world;
1140     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1141         return;
1142
1143     webView->addUserScriptToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0, runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd);
1144 }
1145
1146
1147 void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1148 {
1149     COMPtr<IWebViewPrivate> webView;
1150     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1151         return;
1152
1153     COMPtr<IWebScriptWorld> world;
1154     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1155         return;
1156
1157     webView->addUserStyleSheetToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0);
1158 }
1159
1160 void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
1161 {
1162     COMPtr<IWebView> webView;
1163     if (FAILED(frame->webView(&webView)))
1164         return;
1165
1166     COMPtr<IWebPreferences> preferences;
1167     if (FAILED(webView->preferences(&preferences)))
1168         return;
1169
1170     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
1171     if (!prefsPrivate)
1172         return;
1173
1174     prefsPrivate->setDeveloperExtrasEnabled(enabled);
1175 }
1176
1177 void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
1178 {
1179     // FIXME: Implement this.
1180 }
1181
1182 void LayoutTestController::showWebInspector()
1183 {
1184     COMPtr<IWebView> webView;
1185     if (FAILED(frame->webView(&webView)))
1186         return;
1187
1188     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1189     if (!viewPrivate)
1190         return;
1191
1192     COMPtr<IWebInspector> inspector;
1193     if (SUCCEEDED(viewPrivate->inspector(&inspector)))
1194         inspector->show();
1195 }
1196
1197 void LayoutTestController::closeWebInspector()
1198 {
1199     COMPtr<IWebView> webView;
1200     if (FAILED(frame->webView(&webView)))
1201         return;
1202
1203     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1204     if (!viewPrivate)
1205         return;
1206
1207     COMPtr<IWebInspector> inspector;
1208     if (FAILED(viewPrivate->inspector(&inspector)))
1209         return;
1210
1211     inspector->close();
1212 }
1213
1214 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
1215 {
1216     COMPtr<IWebView> webView;
1217     if (FAILED(frame->webView(&webView)))
1218         return;
1219
1220     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1221     if (!viewPrivate)
1222         return;
1223
1224     COMPtr<IWebInspector> inspector;
1225     if (FAILED(viewPrivate->inspector(&inspector)))
1226         return;
1227
1228     COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
1229     if (!inspectorPrivate)
1230         return;
1231
1232     inspectorPrivate->evaluateInFrontend(callId, bstrT(script).GetBSTR());
1233 }
1234
1235 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
1236 static WorldMap& worldMap()
1237 {
1238     static WorldMap& map = *new WorldMap;
1239     return map;
1240 }
1241
1242 unsigned worldIDForWorld(IWebScriptWorld* world)
1243 {
1244     WorldMap::const_iterator end = worldMap().end();
1245     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
1246         if (it->second == world)
1247             return it->first;
1248     }
1249
1250     return 0;
1251 }
1252
1253 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1254 {
1255     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1256     if (!framePrivate)
1257         return;
1258
1259     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
1260     // that is created once and cached forever.
1261     COMPtr<IWebScriptWorld> world;
1262     if (!worldID) {
1263         if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1264             return;
1265     } else {
1266         COMPtr<IWebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
1267         if (!worldSlot && FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(worldSlot), reinterpret_cast<void**>(&worldSlot))))
1268             return;
1269         world = worldSlot;
1270     }
1271
1272     BSTR result;
1273     if (FAILED(framePrivate->stringByEvaluatingJavaScriptInScriptWorld(world.get(), globalObject, bstrT(script).GetBSTR(), &result)))
1274         return;
1275     SysFreeString(result);
1276 }
1277
1278 void LayoutTestController::removeAllVisitedLinks()
1279 {
1280     COMPtr<IWebHistory> history;
1281     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
1282         return;
1283
1284     COMPtr<IWebHistory> sharedHistory;
1285     if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
1286         return;
1287
1288     COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
1289     if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
1290         return;
1291
1292     sharedHistoryPrivate->removeAllVisitedLinks();
1293 }
1294
1295 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
1296 {
1297     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1298     if (!framePrivate)
1299         return 0;
1300
1301     wstring idWstring = jsStringRefToWString(id);
1302     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1303     BSTR counterValueBSTR;
1304     if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR)))
1305         return 0;
1306
1307     wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR));
1308     SysFreeString(idBSTR);
1309     SysFreeString(counterValueBSTR);
1310     JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length()));
1311     return counterValueJS;
1312 }
1313
1314 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
1315 {
1316     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1317     if (!framePrivate)
1318         return 0;
1319
1320     wstring idWstring = jsStringRefToWString(id);
1321     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1322     int pageNumber = -1;
1323     if (FAILED(framePrivate->pageNumberForElementById(idBSTR, pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1324         pageNumber = -1;
1325     SysFreeString(idBSTR);
1326     return pageNumber;
1327 }
1328
1329 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
1330 {
1331     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1332     if (!framePrivate)
1333         return 0;
1334
1335     int pageNumber = -1;
1336     if (FAILED(framePrivate->numberOfPages(pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1337         pageNumber = -1;
1338     return pageNumber;
1339 }
1340
1341 JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
1342 {
1343     // FIXME: Implement this.
1344     return JSRetainPtr<JSStringRef>();
1345 }
1346
1347 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
1348 {
1349
1350 }
1351
1352 bool LayoutTestController::isPageBoxVisible(int pageNumber) const
1353 {
1354     // FIXME: implement
1355     return false;
1356 }
1357
1358 JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
1359 {
1360     // FIXME: implement
1361     return JSRetainPtr<JSStringRef>();
1362 }
1363
1364 void LayoutTestController::apiTestGoToCurrentBackForwardItem()
1365 {
1366     COMPtr<IWebView> webView;
1367     if (FAILED(frame->webView(&webView)))
1368         return;
1369
1370     COMPtr<IWebBackForwardList> backForwardList;
1371     if (FAILED(webView->backForwardList(&backForwardList)))
1372         return;
1373
1374     COMPtr<IWebHistoryItem> item;
1375     if (FAILED(backForwardList->currentItem(&item)))
1376         return;
1377
1378     BOOL success;
1379     webView->goToBackForwardItem(item.get(), &success);
1380 }
1381
1382 void LayoutTestController::setWebViewEditable(bool)
1383 {
1384 }
1385
1386 void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
1387 {
1388 }
1389
1390 void LayoutTestController::setEditingBehavior(const char* editingBehavior)
1391 {
1392     COMPtr<IWebView> webView;
1393     if (FAILED(frame->webView(&webView)))
1394         return;
1395
1396     COMPtr<IWebPreferences> preferences;
1397     if (FAILED(webView->preferences(&preferences)))
1398         return;
1399
1400     string behaviorString(editingBehavior);
1401     if (behaviorString == "mac")
1402         preferences->setEditingBehavior(WebKitEditingMacBehavior);
1403     else if (behaviorString == "win")
1404         preferences->setEditingBehavior(WebKitEditingWinBehavior);
1405     else if (behaviorString == "unix")
1406         preferences->setEditingBehavior(WebKitEditingUnixBehavior);
1407 }
1408
1409 void LayoutTestController::abortModal()
1410 {
1411 }
1412
1413 bool LayoutTestController::hasSpellingMarker(int from, int length)
1414 {
1415     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1416     if (!framePrivate)
1417         return false;
1418     BOOL ret = FALSE;
1419     if (FAILED(framePrivate->hasSpellingMarker(from, length, &ret)))
1420         return false;
1421     return ret;
1422 }
1423
1424 void LayoutTestController::dumpConfigurationForViewport(int /*availableWidth*/, int /*availableHeight*/)
1425 {
1426     // FIXME: Implement this.
1427 }
1428
1429 void LayoutTestController::setSerializeHTTPLoads(bool)
1430 {
1431     // FIXME: Implement.
1432 }