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