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