2011-03-15 Ilya Sherman <isherman@chromium.org>
[WebKit-https.git] / Tools / 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::setAutofilled(JSContextRef, JSValueRef element, bool isAutofilled)
378 {
379     // FIXME: implement
380 }
381
382 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
383 {
384     COMPtr<IWebView> webView;
385     if (FAILED(frame->webView(&webView)))
386         return;
387
388     if (setDelegate) {
389         policyDelegate->setPermissive(permissive);
390         webView->setPolicyDelegate(policyDelegate);
391     } else
392         webView->setPolicyDelegate(0);
393 }
394
395 void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
396 {
397     // FIXME: Implement for DeviceOrientation layout tests.
398     // See https://bugs.webkit.org/show_bug.cgi?id=30335.
399 }
400
401 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
402 {
403     // FIXME: Implement for Geolocation layout tests.
404     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
405 }
406
407 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
408 {
409     // FIXME: Implement for Geolocation layout tests.
410     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
411 }
412
413 void LayoutTestController::setGeolocationPermission(bool allow)
414 {
415     // FIXME: Implement for Geolocation layout tests.
416     setGeolocationPermissionCommon(allow);
417 }
418
419 int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
420 {
421     // FIXME: Implement for Geolocation layout tests.
422     return -1;
423 }
424
425 void LayoutTestController::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
426 {
427     // FIXME: Implement for speech input layout tests.
428     // See https://bugs.webkit.org/show_bug.cgi?id=39485.
429 }
430
431 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
432 {
433     // See also <rdar://problem/6480108>
434     COMPtr<IWebIconDatabase> iconDatabase;
435     COMPtr<IWebIconDatabase> tmpIconDatabase;
436     if (FAILED(WebKitCreateInstance(CLSID_WebIconDatabase, 0, IID_IWebIconDatabase, (void**)&tmpIconDatabase)))
437         return;
438     if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase)))
439         return;
440
441     iconDatabase->setEnabled(iconDatabaseEnabled);
442 }
443
444 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
445 {
446     // FIXME: Implement!
447 }
448
449 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
450 {
451     COMPtr<IWebView> webView;
452     if (FAILED(frame->webView(&webView)))
453         return;
454
455     COMPtr<IWebPreferences> preferences;
456     if (FAILED(webView->preferences(&preferences)))
457         return;
458
459     preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
460 }
461
462 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
463 {
464     COMPtr<IWebView> webView;
465     if (FAILED(frame->webView(&webView)))
466         return;
467
468     COMPtr<IWebPreferences> preferences;
469     if (FAILED(webView->preferences(&preferences)))
470         return;
471
472     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
473     if (!prefsPrivate)
474         return;
475
476     prefsPrivate->setXSSAuditorEnabled(enabled);
477 }
478
479 void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
480 {
481     COMPtr<IWebView> webView;
482     if (FAILED(frame->webView(&webView)))
483         return;
484
485     COMPtr<IWebPreferences> preferences;
486     if (FAILED(webView->preferences(&preferences)))
487         return;
488
489     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
490     if (!prefsPrivate)
491         return;
492
493     prefsPrivate->setFrameFlatteningEnabled(enabled);
494 }
495
496 void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
497 {
498     // FIXME: Implement for SpatialNavigation layout tests.
499 }
500
501 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
502 {
503     COMPtr<IWebView> webView;
504     if (FAILED(frame->webView(&webView)))
505         return;
506
507     COMPtr<IWebPreferences> preferences;
508     if (FAILED(webView->preferences(&preferences)))
509         return;
510
511     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
512     if (!prefsPrivate)
513         return;
514
515     prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
516 }
517
518 void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
519 {
520     COMPtr<IWebView> webView;
521     if (FAILED(frame->webView(&webView)))
522         return;
523
524     COMPtr<IWebPreferences> preferences;
525     if (FAILED(webView->preferences(&preferences)))
526         return;
527
528     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
529     if (!prefsPrivate)
530         return;
531
532     prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
533 }
534
535 void LayoutTestController::setPopupBlockingEnabled(bool enabled)
536 {
537     COMPtr<IWebView> webView;
538     if (FAILED(frame->webView(&webView)))
539         return;
540
541     COMPtr<IWebPreferences> preferences;
542     if (FAILED(webView->preferences(&preferences)))
543         return;
544
545     preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled);
546 }
547
548 void LayoutTestController::setPluginsEnabled(bool flag)
549 {
550     // FIXME: Implement
551 }
552
553 void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
554 {
555     COMPtr<IWebView> webView;
556     if (FAILED(frame->webView(&webView)))
557         return;
558
559     COMPtr<IWebPreferences> preferences;
560     if (FAILED(webView->preferences(&preferences)))
561         return;
562
563     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
564     if (!prefsPrivate)
565         return;
566
567     prefsPrivate->setJavaScriptCanAccessClipboard(enabled);
568 }
569
570 void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle)
571 {
572     COMPtr<IWebView> webView;
573     if (FAILED(frame->webView(&webView)))
574         return;
575
576     COMPtr<IWebViewPrivate> viewPrivate;
577     if (FAILED(webView->QueryInterface(&viewPrivate)))
578         return;
579
580     viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE);
581 }
582
583 void LayoutTestController::setTimelineProfilingEnabled(bool flag)
584 {
585     COMPtr<IWebView> webView;
586     if (FAILED(frame->webView(&webView)))
587         return;
588
589     COMPtr<IWebViewPrivate> viewPrivate;
590     if (FAILED(webView->QueryInterface(&viewPrivate)))
591         return;
592
593     COMPtr<IWebInspector> inspector;
594     if (FAILED(viewPrivate->inspector(&inspector)))
595         return;
596
597     inspector->setTimelineProfilingEnabled(flag);
598 }
599
600 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
601 {
602     // FIXME: Implement!
603 }
604
605 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
606 {
607     COMPtr<IWebView> webView;
608     if (FAILED(frame->webView(&webView)))
609         return;
610
611     COMPtr<IWebPreferences> preferences;
612     if (FAILED(webView->preferences(&preferences)))
613         return;
614
615    preferences->setUserStyleSheetEnabled(flag);
616 }
617
618 bool appendComponentToPath(wstring& path, const wstring& component)
619 {
620     WCHAR buffer[MAX_PATH];
621
622     if (path.size() + 1 > MAX_PATH)
623         return false;
624
625     memcpy(buffer, path.data(), path.size() * sizeof(WCHAR));
626     buffer[path.size()] = '\0';
627
628     if (!PathAppendW(buffer, component.c_str()))
629         return false;
630
631     path = wstring(buffer);
632     return true;
633 }
634
635 static bool followShortcuts(wstring& path)
636 {
637     if (PathFileExists(path.c_str()))
638         return true;
639
640     // Do we have a shortcut?
641     wstring linkPath = path;
642     linkPath.append(TEXT(".lnk"));
643     if (!PathFileExists(linkPath.c_str()))
644        return true;
645
646     // We have a shortcut, find its target.
647     COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink);
648     if (!shortcut)
649        return false;
650     COMPtr<IPersistFile> persistFile(Query, shortcut);
651     if (!shortcut)
652         return false;
653     if (FAILED(persistFile->Load(linkPath.c_str(), STGM_READ)))
654         return false;
655     if (FAILED(shortcut->Resolve(0, 0)))
656         return false;
657     WCHAR targetPath[MAX_PATH];
658     DWORD targetPathLen = _countof(targetPath);
659     if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0)))
660         return false;
661     if (!PathFileExists(targetPath))
662         return false;
663     // Use the target path as the result path instead.
664     path = wstring(targetPath);
665
666     return true;
667 }
668
669 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath)
670 {
671     wstring fileProtocol = L"file://";
672     bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos;
673     if (cygwinPath[isFileProtocol ? 7 : 0] != '/')  // ensure path is absolute
674         return false;
675
676     // Get the Root path.
677     WCHAR rootPath[MAX_PATH];
678     DWORD rootPathSize = _countof(rootPath);
679     DWORD keyType;
680     DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize);
681
682     if (result != ERROR_SUCCESS || keyType != REG_SZ) {
683         // Cygwin 1.7 doesn't store Cygwin's root as a mount point anymore, because mount points are now stored in /etc/fstab.
684         // However, /etc/fstab doesn't contain any information about where / is located as a Windows path, so we need to use Cygwin's
685         // new registry key that has the root.
686         result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygwin\\setup"), TEXT("rootdir"), &keyType, &rootPath, &rootPathSize);
687         if (result != ERROR_SUCCESS || keyType != REG_SZ)
688             return false;
689     }
690
691     windowsPath = wstring(rootPath, rootPathSize);
692
693     int oldPos = isFileProtocol ? 8 : 1;
694     while (1) {
695         int newPos = cygwinPath.find('/', oldPos);
696
697         if (newPos == -1) {
698             wstring pathComponent = cygwinPath.substr(oldPos);
699
700             if (!appendComponentToPath(windowsPath, pathComponent))
701                return false;
702
703             if (!followShortcuts(windowsPath))
704                 return false;
705
706             break;
707         }
708
709         wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos);
710         if (!appendComponentToPath(windowsPath, pathComponent))
711             return false;
712
713         if (!followShortcuts(windowsPath))
714             return false;
715
716         oldPos = newPos + 1;
717     }
718
719     if (isFileProtocol)
720         windowsPath = fileProtocol + windowsPath;
721
722     return true;
723 }
724
725 void LayoutTestController::setUserStyleSheetLocation(JSStringRef jsURL)
726 {
727     COMPtr<IWebView> webView;
728     if (FAILED(frame->webView(&webView)))
729         return;
730
731     COMPtr<IWebPreferences> preferences;
732     if (FAILED(webView->preferences(&preferences)))
733         return;
734
735     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
736     RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, urlString.get(), 0));
737     if (!url)
738         return;
739
740     // Now copy the file system path, POSIX style.
741     RetainPtr<CFStringRef> pathCF(AdoptCF, CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle));
742     if (!pathCF)
743         return;
744
745     wstring path = cfStringRefToWString(pathCF.get());
746
747     wstring resultPath;
748     if (!resolveCygwinPath(path, resultPath))
749         return;
750
751     // The path has been resolved, now convert it back to a CFURL.
752     int result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, 0, 0, 0, 0);
753     Vector<char> utf8Vector(result);
754     result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, 0, 0);
755     if (!result)
756         return;
757
758     url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false);
759     if (!url)
760         return;
761
762     resultPath = cfStringRefToWString(CFURLGetString(url.get()));
763
764     BSTR resultPathBSTR = SysAllocStringLen(resultPath.data(), resultPath.size());
765     preferences->setUserStyleSheetLocation(resultPathBSTR);
766     SysFreeString(resultPathBSTR);
767 }
768
769 void LayoutTestController::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
770 {
771     // FIXME: implement
772 }
773
774 void LayoutTestController::setViewModeMediaFeature(JSStringRef mode)
775 {
776     // FIXME: implement
777 }
778
779 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
780 {
781     RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
782     ::setPersistentUserStyleSheetLocation(urlString.get());
783 }
784
785 void LayoutTestController::clearPersistentUserStyleSheet()
786 {
787     ::setPersistentUserStyleSheetLocation(0);
788 }
789
790 void LayoutTestController::setWindowIsKey(bool flag)
791 {
792     COMPtr<IWebView> webView;
793     if (FAILED(frame->webView(&webView)))
794         return;
795
796     COMPtr<IWebViewPrivate> viewPrivate;
797     if (FAILED(webView->QueryInterface(&viewPrivate)))
798         return;
799
800     HWND webViewWindow;
801     if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow)))
802         return;
803
804     ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0);
805 }
806
807 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
808 {
809     COMPtr<IWebView> webView;
810     if (FAILED(frame->webView(&webView)))
811         return;
812
813     COMPtr<IWebViewEditing> viewEditing;
814     if (FAILED(webView->QueryInterface(&viewEditing)))
815         return;
816
817     viewEditing->setSmartInsertDeleteEnabled(flag ? TRUE : FALSE);
818 }
819
820 void LayoutTestController::setJavaScriptProfilingEnabled(bool flag)
821 {
822     COMPtr<IWebView> webView;
823     if (FAILED(frame->webView(&webView)))
824         return;
825
826     COMPtr<IWebViewPrivate> viewPrivate;
827     if (FAILED(webView->QueryInterface(&viewPrivate)))
828         return;
829
830     COMPtr<IWebInspector> inspector;
831     if (FAILED(viewPrivate->inspector(&inspector)))
832         return;
833
834     setDeveloperExtrasEnabled(flag);
835     inspector->setJavaScriptProfilingEnabled(flag);
836 }
837
838 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
839 {
840     COMPtr<IWebView> webView;
841     if (FAILED(frame->webView(&webView)))
842         return;
843
844     COMPtr<IWebViewEditing> viewEditing;
845     if (FAILED(webView->QueryInterface(&viewEditing)))
846         return;
847
848     viewEditing->setSelectTrailingWhitespaceEnabled(flag ? TRUE : FALSE);
849 }
850
851 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
852
853 static void CALLBACK waitUntilDoneWatchdogFired(HWND, UINT, UINT_PTR, DWORD)
854 {
855     gLayoutTestController->waitToDumpWatchdogTimerFired();
856 }
857
858 void LayoutTestController::setWaitToDump(bool waitUntilDone)
859 {
860     m_waitToDump = waitUntilDone;
861     if (m_waitToDump && !waitToDumpWatchdog)
862         waitToDumpWatchdog = SetTimer(0, 0, waitToDumpWatchdogInterval * 1000, waitUntilDoneWatchdogFired);
863 }
864
865 int LayoutTestController::windowCount()
866 {
867     return openWindows().size();
868 }
869
870 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
871 {
872     COMPtr<IDOMDocument> document;
873     if (FAILED(frame->DOMDocument(&document)))
874         return false;
875
876     wstring idWstring = jsStringRefToWString(id);
877     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
878     COMPtr<IDOMElement> element;
879     HRESULT result = document->getElementById(idBSTR, &element);
880     SysFreeString(idBSTR);
881
882     if (FAILED(result))
883         return false;
884
885     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
886     if (!framePrivate)
887         return false;
888
889     BOOL autoCompletes;
890     if (FAILED(framePrivate->elementDoesAutoComplete(element.get(), &autoCompletes)))
891         return false;
892
893     return autoCompletes;
894 }
895
896 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
897 {
898     wstring wName = jsStringRefToWString(name);
899     wstring wValue = jsStringRefToWString(value);
900
901     COMPtr<IWebView> webView;
902     if (FAILED(frame->webView(&webView)))
903         return;
904
905     COMPtr<IWebViewPrivate> viewPrivate;
906     if (FAILED(webView->QueryInterface(&viewPrivate)))
907         return;
908
909     BSTR nameBSTR = SysAllocStringLen((OLECHAR*)wName.c_str(), wName.length());
910     BSTR valueBSTR = SysAllocStringLen((OLECHAR*)wValue.c_str(), wValue.length());
911     viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR);
912
913     SysFreeString(nameBSTR);
914     SysFreeString(valueBSTR);
915 }
916
917 bool LayoutTestController::findString(JSContextRef /* context */, JSStringRef /* target */, JSObjectRef /* optionsArray */)
918 {
919     // FIXME: Implement
920     return false;
921 }
922
923 void LayoutTestController::setCacheModel(int)
924 {
925     // FIXME: Implement
926 }
927
928 bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/)
929 {
930     printf("ERROR: LayoutTestController::isCommandEnabled() not implemented\n");
931     return false;
932 }
933
934 void LayoutTestController::clearAllApplicationCaches()
935 {
936     // FIXME: implement to support Application Cache quotas.
937 }
938
939 void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
940 {
941     // FIXME: implement to support Application Cache quotas.
942 }
943
944 void LayoutTestController::clearAllDatabases()
945 {
946     COMPtr<IWebDatabaseManager> databaseManager;
947     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
948     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
949         return;
950     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
951         return;
952
953     databaseManager->deleteAllDatabases();
954 }
955
956 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
957 {
958     COMPtr<IWebView> webView;
959     if (FAILED(frame->webView(&webView)))
960         return;
961
962     COMPtr<IWebPreferences> preferences;
963     if (FAILED(webView->preferences(&preferences)))
964         return;
965
966     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
967     if (!prefsPrivate)
968         return;
969
970     BSTR keyBSTR = JSStringCopyBSTR(key);
971     BSTR valueBSTR = JSStringCopyBSTR(value);
972     prefsPrivate->setPreferenceForTest(keyBSTR, valueBSTR);
973     SysFreeString(keyBSTR);
974     SysFreeString(valueBSTR);
975 }
976
977 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
978 {
979     COMPtr<IWebDatabaseManager> databaseManager;
980     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
981
982     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
983         return;
984     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
985         return;
986
987     databaseManager->setQuota(TEXT("file:///"), quota);
988 }
989
990 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
991 {
992     COMPtr<IWebViewPrivate> webView;
993     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
994         return;
995
996     BSTR schemeBSTR = JSStringCopyBSTR(scheme);
997     webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR);
998     SysFreeString(schemeBSTR);
999 }
1000
1001 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
1002 {
1003     printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n");
1004 }
1005
1006 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
1007 {
1008     COMPtr<IDOMDocument> document;
1009     if (FAILED(frame->DOMDocument(&document)))
1010         return false;
1011
1012     BSTR idBSTR = JSStringCopyBSTR(elementId);
1013     COMPtr<IDOMElement> element;
1014     HRESULT hr = document->getElementById(idBSTR, &element);
1015     SysFreeString(idBSTR);
1016     if (FAILED(hr))
1017         return false;
1018
1019     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1020     if (!framePrivate)
1021         return false;
1022
1023     BSTR nameBSTR = JSStringCopyBSTR(animationName);
1024     BOOL wasRunning = FALSE;
1025     hr = framePrivate->pauseAnimation(nameBSTR, element.get(), time, &wasRunning);
1026     SysFreeString(nameBSTR);
1027
1028     return SUCCEEDED(hr) && wasRunning;
1029 }
1030
1031 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
1032 {
1033     COMPtr<IDOMDocument> document;
1034     if (FAILED(frame->DOMDocument(&document)))
1035         return false;
1036
1037     BSTR idBSTR = JSStringCopyBSTR(elementId);
1038     COMPtr<IDOMElement> element;
1039     HRESULT hr = document->getElementById(idBSTR, &element);
1040     SysFreeString(idBSTR);
1041     if (FAILED(hr))
1042         return false;
1043
1044     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1045     if (!framePrivate)
1046         return false;
1047
1048     BSTR nameBSTR = JSStringCopyBSTR(propertyName);
1049     BOOL wasRunning = FALSE;
1050     hr = framePrivate->pauseTransition(nameBSTR, element.get(), time, &wasRunning);
1051     SysFreeString(nameBSTR);
1052
1053     return SUCCEEDED(hr) && wasRunning;
1054 }
1055
1056 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
1057 {
1058     COMPtr<IDOMDocument> document;
1059     if (FAILED(frame->DOMDocument(&document)))
1060         return false;
1061
1062     BSTR idBSTR = JSStringCopyBSTR(animationId);
1063     COMPtr<IDOMElement> element;
1064     HRESULT hr = document->getElementById(idBSTR, &element);
1065     SysFreeString(idBSTR);
1066     if (FAILED(hr))
1067         return false;
1068
1069     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1070     if (!framePrivate)
1071         return false;
1072
1073     BSTR elementIdBSTR = JSStringCopyBSTR(elementId);
1074     BOOL wasRunning = FALSE;
1075     hr = framePrivate->pauseSVGAnimation(elementIdBSTR, element.get(), time, &wasRunning);
1076     SysFreeString(elementIdBSTR);
1077
1078     return SUCCEEDED(hr) && wasRunning;
1079 }
1080
1081 unsigned LayoutTestController::numberOfActiveAnimations() const
1082 {
1083     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1084     if (!framePrivate)
1085         return 0;
1086
1087     UINT number = 0;
1088     if (FAILED(framePrivate->numberOfActiveAnimations(&number)))
1089         return 0;
1090
1091     return number;
1092 }
1093
1094 void LayoutTestController::suspendAnimations() const
1095 {
1096     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1097     if (!framePrivate)
1098         return;
1099
1100     framePrivate->suspendAnimations();
1101 }
1102
1103 void LayoutTestController::resumeAnimations() const
1104 {
1105     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1106     if (!framePrivate)
1107         return;
1108
1109     framePrivate->resumeAnimations();
1110 }
1111
1112 static _bstr_t bstrT(JSStringRef jsString)
1113 {
1114     // The false parameter tells the _bstr_t constructor to adopt the BSTR we pass it.
1115     return _bstr_t(JSStringCopyBSTR(jsString), false);
1116 }
1117
1118 void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1119 {
1120     COMPtr<IWebViewPrivate> webView;
1121     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1122         return;
1123
1124     webView->addOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1125 }
1126
1127 void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1128 {
1129     COMPtr<IWebViewPrivate> webView;
1130     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1131         return;
1132
1133     webView->removeOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1134 }
1135
1136 void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
1137 {
1138     // FIXME: implement
1139 }
1140
1141 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1142 {
1143     COMPtr<IWebViewPrivate> webView;
1144     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1145         return;
1146
1147     COMPtr<IWebScriptWorld> world;
1148     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1149         return;
1150
1151     webView->addUserScriptToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0, runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd);
1152 }
1153
1154
1155 void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1156 {
1157     COMPtr<IWebViewPrivate> webView;
1158     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1159         return;
1160
1161     COMPtr<IWebScriptWorld> world;
1162     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1163         return;
1164
1165     webView->addUserStyleSheetToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0);
1166 }
1167
1168 void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
1169 {
1170     COMPtr<IWebView> webView;
1171     if (FAILED(frame->webView(&webView)))
1172         return;
1173
1174     COMPtr<IWebPreferences> preferences;
1175     if (FAILED(webView->preferences(&preferences)))
1176         return;
1177
1178     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
1179     if (!prefsPrivate)
1180         return;
1181
1182     prefsPrivate->setDeveloperExtrasEnabled(enabled);
1183 }
1184
1185 void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
1186 {
1187     // FIXME: Implement this.
1188 }
1189
1190 void LayoutTestController::showWebInspector()
1191 {
1192     COMPtr<IWebView> webView;
1193     if (FAILED(frame->webView(&webView)))
1194         return;
1195
1196     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1197     if (!viewPrivate)
1198         return;
1199
1200     COMPtr<IWebInspector> inspector;
1201     if (SUCCEEDED(viewPrivate->inspector(&inspector)))
1202         inspector->show();
1203 }
1204
1205 void LayoutTestController::closeWebInspector()
1206 {
1207     COMPtr<IWebView> webView;
1208     if (FAILED(frame->webView(&webView)))
1209         return;
1210
1211     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1212     if (!viewPrivate)
1213         return;
1214
1215     COMPtr<IWebInspector> inspector;
1216     if (FAILED(viewPrivate->inspector(&inspector)))
1217         return;
1218
1219     inspector->close();
1220 }
1221
1222 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
1223 {
1224     COMPtr<IWebView> webView;
1225     if (FAILED(frame->webView(&webView)))
1226         return;
1227
1228     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1229     if (!viewPrivate)
1230         return;
1231
1232     COMPtr<IWebInspector> inspector;
1233     if (FAILED(viewPrivate->inspector(&inspector)))
1234         return;
1235
1236     COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
1237     if (!inspectorPrivate)
1238         return;
1239
1240     inspectorPrivate->evaluateInFrontend(callId, bstrT(script).GetBSTR());
1241 }
1242
1243 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
1244 static WorldMap& worldMap()
1245 {
1246     static WorldMap& map = *new WorldMap;
1247     return map;
1248 }
1249
1250 unsigned worldIDForWorld(IWebScriptWorld* world)
1251 {
1252     WorldMap::const_iterator end = worldMap().end();
1253     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
1254         if (it->second == world)
1255             return it->first;
1256     }
1257
1258     return 0;
1259 }
1260
1261 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1262 {
1263     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1264     if (!framePrivate)
1265         return;
1266
1267     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
1268     // that is created once and cached forever.
1269     COMPtr<IWebScriptWorld> world;
1270     if (!worldID) {
1271         if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1272             return;
1273     } else {
1274         COMPtr<IWebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
1275         if (!worldSlot && FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(worldSlot), reinterpret_cast<void**>(&worldSlot))))
1276             return;
1277         world = worldSlot;
1278     }
1279
1280     BSTR result;
1281     if (FAILED(framePrivate->stringByEvaluatingJavaScriptInScriptWorld(world.get(), globalObject, bstrT(script).GetBSTR(), &result)))
1282         return;
1283     SysFreeString(result);
1284 }
1285
1286 void LayoutTestController::removeAllVisitedLinks()
1287 {
1288     COMPtr<IWebHistory> history;
1289     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
1290         return;
1291
1292     COMPtr<IWebHistory> sharedHistory;
1293     if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
1294         return;
1295
1296     COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
1297     if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
1298         return;
1299
1300     sharedHistoryPrivate->removeAllVisitedLinks();
1301 }
1302
1303 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
1304 {
1305     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1306     if (!framePrivate)
1307         return 0;
1308
1309     wstring idWstring = jsStringRefToWString(id);
1310     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1311     BSTR counterValueBSTR;
1312     if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR)))
1313         return 0;
1314
1315     wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR));
1316     SysFreeString(idBSTR);
1317     SysFreeString(counterValueBSTR);
1318     JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length()));
1319     return counterValueJS;
1320 }
1321
1322 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
1323 {
1324     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1325     if (!framePrivate)
1326         return 0;
1327
1328     wstring idWstring = jsStringRefToWString(id);
1329     BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1330     int pageNumber = -1;
1331     if (FAILED(framePrivate->pageNumberForElementById(idBSTR, pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1332         pageNumber = -1;
1333     SysFreeString(idBSTR);
1334     return pageNumber;
1335 }
1336
1337 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
1338 {
1339     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1340     if (!framePrivate)
1341         return 0;
1342
1343     int pageNumber = -1;
1344     if (FAILED(framePrivate->numberOfPages(pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1345         pageNumber = -1;
1346     return pageNumber;
1347 }
1348
1349 JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
1350 {
1351     // FIXME: Implement this.
1352     return JSRetainPtr<JSStringRef>();
1353 }
1354
1355 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
1356 {
1357
1358 }
1359
1360 bool LayoutTestController::isPageBoxVisible(int pageNumber) const
1361 {
1362     // FIXME: implement
1363     return false;
1364 }
1365
1366 JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
1367 {
1368     // FIXME: implement
1369     return JSRetainPtr<JSStringRef>();
1370 }
1371
1372 void LayoutTestController::apiTestGoToCurrentBackForwardItem()
1373 {
1374     COMPtr<IWebView> webView;
1375     if (FAILED(frame->webView(&webView)))
1376         return;
1377
1378     COMPtr<IWebBackForwardList> backForwardList;
1379     if (FAILED(webView->backForwardList(&backForwardList)))
1380         return;
1381
1382     COMPtr<IWebHistoryItem> item;
1383     if (FAILED(backForwardList->currentItem(&item)))
1384         return;
1385
1386     BOOL success;
1387     webView->goToBackForwardItem(item.get(), &success);
1388 }
1389
1390 void LayoutTestController::setWebViewEditable(bool)
1391 {
1392 }
1393
1394 void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
1395 {
1396 }
1397
1398 void LayoutTestController::setEditingBehavior(const char* editingBehavior)
1399 {
1400     COMPtr<IWebView> webView;
1401     if (FAILED(frame->webView(&webView)))
1402         return;
1403
1404     COMPtr<IWebPreferences> preferences;
1405     if (FAILED(webView->preferences(&preferences)))
1406         return;
1407
1408     string behaviorString(editingBehavior);
1409     if (behaviorString == "mac")
1410         preferences->setEditingBehavior(WebKitEditingMacBehavior);
1411     else if (behaviorString == "win")
1412         preferences->setEditingBehavior(WebKitEditingWinBehavior);
1413     else if (behaviorString == "unix")
1414         preferences->setEditingBehavior(WebKitEditingUnixBehavior);
1415 }
1416
1417 void LayoutTestController::abortModal()
1418 {
1419 }
1420
1421 bool LayoutTestController::hasSpellingMarker(int from, int length)
1422 {
1423     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1424     if (!framePrivate)
1425         return false;
1426     BOOL ret = FALSE;
1427     if (FAILED(framePrivate->hasSpellingMarker(from, length, &ret)))
1428         return false;
1429     return ret;
1430 }
1431
1432 void LayoutTestController::dumpConfigurationForViewport(int /*deviceDPI*/, int /*deviceWidth*/, int /*deviceHeight*/, int /*availableWidth*/, int /*availableHeight*/)
1433 {
1434     // FIXME: Implement this.
1435 }
1436
1437 void LayoutTestController::setSerializeHTTPLoads(bool)
1438 {
1439     // FIXME: Implement.
1440 }
1441
1442 void LayoutTestController::syncLocalStorage()
1443 {
1444     // FIXME: Implement.
1445 }
1446
1447 void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
1448 {
1449     // FIXME: Implement.
1450 }
1451
1452 void LayoutTestController::deleteAllLocalStorage()
1453 {
1454     // FIXME: Implement.
1455 }
1456
1457 JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
1458 {
1459     // FIXME: Implement.
1460     return JSValueMakeUndefined(context);
1461 }
1462
1463 void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
1464 {
1465     // FIXME: Implement.
1466 }
1467
1468 void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
1469 {
1470     COMPtr<IWebView> webView;
1471     if (FAILED(frame->webView(&webView)))
1472         return;
1473
1474     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1475     if (!viewPrivate)
1476         return;
1477
1478     viewPrivate->setMinimumTimerInterval(minimumTimerInterval);
1479 }
1480
1481