[Win] The test storage/indexeddb/modern/handle-user-delete.html is timing out.
[WebKit-https.git] / Tools / DumpRenderTree / win / TestRunnerWin.cpp
1 /*
2  * Copyright (C) 2006-2014 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 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 "TestRunner.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/JSRetainPtr.h>
39 #include <JavaScriptCore/JSStringRefBSTR.h>
40 #include <JavaScriptCore/JavaScriptCore.h>
41 #include <WebCore/COMPtr.h>
42 #include <WebKit/WebKit.h>
43 #include <WebKit/WebKitCOMAPI.h>
44 #include <comutil.h>
45 #include <shlguid.h>
46 #include <shlwapi.h>
47 #include <shobjidl.h>
48 #include <string>
49 #include <wtf/Assertions.h>
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 TestRunner::~TestRunner()
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     COMPtr<IWebViewEditing> viewEditing;
67     if (FAILED(webView->QueryInterface(&viewEditing)))
68         return;
69     COMPtr<IWebEditingDelegate> delegate;
70     if (FAILED(viewEditing->editingDelegate(&delegate)))
71         return;
72     COMPtr<EditingDelegate> editingDelegate(Query, viewEditing.get());
73     if (editingDelegate)
74         editingDelegate->setAcceptsEditing(TRUE);
75 }
76
77 void TestRunner::addDisallowedURL(JSStringRef url)
78 {
79     // FIXME: Implement!
80     printf("ERROR: TestRunner::addDisallowedURL(JSStringRef) not implemented\n");
81 }
82
83 bool TestRunner::callShouldCloseOnWebView()
84 {
85     COMPtr<IWebView> webView;
86     if (FAILED(frame->webView(&webView)))
87         return false;
88
89     COMPtr<IWebViewPrivate2> viewPrivate;
90     if (FAILED(webView->QueryInterface(&viewPrivate)))
91         return false;
92
93     BOOL result;
94     viewPrivate->shouldClose(&result);
95     return result;
96 }
97
98 void TestRunner::clearAllApplicationCaches()
99 {
100     COMPtr<IWebApplicationCache> applicationCache;
101     if (FAILED(WebKitCreateInstance(CLSID_WebApplicationCache, 0, IID_IWebApplicationCache, reinterpret_cast<void**>(&applicationCache))))
102         return;
103
104     applicationCache->deleteAllApplicationCaches();
105 }
106
107 long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef url)
108 {
109     COMPtr<IWebSecurityOrigin2> origin;
110     if (FAILED(WebKitCreateInstance(CLSID_WebSecurityOrigin, 0, IID_IWebSecurityOrigin2, reinterpret_cast<void**>(&origin))))
111         return 0;
112
113     COMPtr<IWebApplicationCache> applicationCache;
114     if (FAILED(WebKitCreateInstance(CLSID_WebApplicationCache, 0, IID_IWebApplicationCache, reinterpret_cast<void**>(&applicationCache))))
115         return 0;
116
117     _bstr_t urlBstr(JSStringCopyBSTR(url), false);
118     origin->initWithURL(urlBstr.GetBSTR());
119
120     long long usage = 0;
121     if (FAILED(applicationCache->diskUsageForOrigin(origin.get(), &usage)))
122         return 0;
123
124     return usage;
125 }
126
127 void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin)
128 {
129     COMPtr<IWebSecurityOrigin2> securityOrigin;
130     if (FAILED(WebKitCreateInstance(CLSID_WebSecurityOrigin, 0, IID_IWebSecurityOrigin2, reinterpret_cast<void**>(&securityOrigin))))
131         return;
132
133     _bstr_t originBstr(JSStringCopyBSTR(origin), false);
134     if (FAILED(securityOrigin->initWithURL(originBstr.GetBSTR())))
135         return;
136
137     COMPtr<IWebApplicationCache> applicationCache;
138     if (FAILED(WebKitCreateInstance(CLSID_WebApplicationCache, 0, IID_IWebApplicationCache, reinterpret_cast<void**>(&applicationCache))))
139         return;
140
141     applicationCache->deleteCacheForOrigin(securityOrigin.get());
142 }
143
144 JSValueRef TestRunner::originsWithApplicationCache(JSContextRef context)
145 {
146     // FIXME: Implement to get origins that have application caches.
147     printf("ERROR: TestRunner::originsWithApplicationCache(JSContextRef) not implemented\n");
148     return JSValueMakeUndefined(context);
149 }
150
151
152 void TestRunner::clearAllDatabases()
153 {
154     COMPtr<IWebDatabaseManager> databaseManager;
155     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
156     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
157         return;
158     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
159         return;
160
161     databaseManager->deleteAllDatabases();
162
163     COMPtr<IWebDatabaseManager2> databaseManager2;
164     if (FAILED(databaseManager->QueryInterface(&databaseManager2)))
165         return;
166
167     databaseManager2->deleteAllIndexedDatabases();
168 }
169
170 void TestRunner::setStorageDatabaseIdleInterval(double)
171 {
172     // FIXME: Implement. Requires non-existant (on Windows) WebStorageManager
173     printf("ERROR: TestRunner::setStorageDatabaseIdleInterval(double) not implemented\n");
174 }
175
176 void TestRunner::closeIdleLocalStorageDatabases()
177 {
178     // FIXME: Implement. Requires non-existant (on Windows) WebStorageManager
179     printf("ERROR: TestRunner::closeIdleLocalStorageDatabases(double) not implemented\n");
180 }
181
182 void TestRunner::clearBackForwardList()
183 {
184     COMPtr<IWebView> webView;
185     if (FAILED(frame->webView(&webView)))
186         return;
187
188     COMPtr<IWebBackForwardList> backForwardList;
189     if (FAILED(webView->backForwardList(&backForwardList)))
190         return;
191
192     COMPtr<IWebHistoryItem> item;
193     if (FAILED(backForwardList->currentItem(&item)))
194         return;
195
196     // We clear the history by setting the back/forward list's capacity to 0
197     // then restoring it back and adding back the current item.
198     int capacity;
199     if (FAILED(backForwardList->capacity(&capacity)))
200         return;
201
202     backForwardList->setCapacity(0);
203     backForwardList->setCapacity(capacity);
204     backForwardList->addItem(item.get());
205     backForwardList->goToItem(item.get());
206 }
207
208 JSStringRef TestRunner::copyDecodedHostName(JSStringRef name)
209 {
210     // FIXME: Implement!
211     printf("ERROR: TestRunner::copyDecodedHostName(JSStringRef) not implemented\n");
212     return 0;
213 }
214
215 JSStringRef TestRunner::copyEncodedHostName(JSStringRef name)
216 {
217     // FIXME: Implement!
218     printf("ERROR: TestRunner::copyEncodedHostName(JSStringRef) not implemented\n");
219     return 0;
220 }
221
222 void TestRunner::display()
223 {
224     displayWebView();
225 }
226
227 void TestRunner::keepWebHistory()
228 {
229     COMPtr<IWebHistory> history;
230     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
231         return;
232
233     COMPtr<IWebHistory> sharedHistory;
234     if (SUCCEEDED(history->optionalSharedHistory(&sharedHistory)) && sharedHistory)
235         return;
236
237     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(sharedHistory), reinterpret_cast<void**>(&sharedHistory))))
238         return;
239
240     history->setOptionalSharedHistory(sharedHistory.get());
241 }
242
243 int TestRunner::numberOfPendingGeolocationPermissionRequests()
244 {
245     // FIXME: Implement for Geolocation layout tests.
246     printf("ERROR: TestRunner::numberOfPendingGeolocationPermissionRequests() not implemented\n");
247     return -1;
248 }
249
250 bool TestRunner::isGeolocationProviderActive()
251 {
252     // FIXME: Implement for Geolocation layout tests.
253     printf("ERROR: TestRunner::isGeolocationProviderActive() not implemented\n");
254     return false;
255 }
256
257 size_t TestRunner::webHistoryItemCount()
258 {
259     COMPtr<IWebHistory> history;
260     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
261         return 0;
262
263     COMPtr<IWebHistory> sharedHistory;
264     if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
265         return 0;
266
267     COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
268     if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
269         return 0;
270
271     int count = 0;
272     if (FAILED(sharedHistoryPrivate->allItems(&count, 0)))
273         return 0;
274
275     return count;
276 }
277
278 void TestRunner::notifyDone()
279 {
280     // Same as on mac.  This can be shared.
281     if (m_waitToDump && !topLoadingFrame && !WorkQueue::singleton().count())
282         dump();
283     m_waitToDump = false;
284 }
285
286 static wstring jsStringRefToWString(JSStringRef jsStr)
287 {
288     size_t length = JSStringGetLength(jsStr);
289     Vector<WCHAR> buffer(length + 1, 0);
290     memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR));
291     buffer[length] = 0;
292
293     return buffer.data();
294 }
295
296 JSStringRef TestRunner::pathToLocalResource(JSContextRef context, JSStringRef url)
297 {
298     wstring input(JSStringGetCharactersPtr(url), JSStringGetLength(url));
299
300     wstring localPath;
301     if (!resolveCygwinPath(input, localPath)) {
302         printf("ERROR: Failed to resolve Cygwin path %S\n", input.c_str());
303         return nullptr;
304     }
305
306     return JSStringCreateWithCharacters(localPath.c_str(), localPath.length());
307 }
308
309 void TestRunner::queueLoad(JSStringRef url, JSStringRef target)
310 {
311     COMPtr<IWebDataSource> dataSource;
312     if (FAILED(frame->dataSource(&dataSource)))
313         return;
314
315     COMPtr<IWebURLResponse> response;
316     if (FAILED(dataSource->response(&response)) || !response)
317         return;
318
319     _bstr_t responseURLBSTR;
320     if (FAILED(response->URL(&responseURLBSTR.GetBSTR())))
321         return;
322     wstring responseURL(responseURLBSTR, responseURLBSTR.length());
323
324     // FIXME: We should do real relative URL resolution here.
325     int lastSlash = responseURL.rfind('/');
326     if (lastSlash != -1)
327         responseURL = responseURL.substr(0, lastSlash);
328
329     wstring wURL = jsStringRefToWString(url);
330     wstring wAbsoluteURL = responseURL + TEXT("/") + wURL;
331     JSRetainPtr<JSStringRef> jsAbsoluteURL(Adopt, JSStringCreateWithCharacters(wAbsoluteURL.data(), wAbsoluteURL.length()));
332
333     WorkQueue::singleton().queue(new LoadItem(jsAbsoluteURL.get(), target));
334 }
335
336 void TestRunner::setAcceptsEditing(bool acceptsEditing)
337 {
338     COMPtr<IWebView> webView;
339     if (FAILED(frame->webView(&webView)))
340         return;
341
342     COMPtr<IWebViewEditing> viewEditing;
343     if (FAILED(webView->QueryInterface(&viewEditing)))
344         return;
345
346     COMPtr<IWebEditingDelegate> delegate;
347     if (FAILED(viewEditing->editingDelegate(&delegate)))
348         return;
349
350     EditingDelegate* editingDelegate = (EditingDelegate*)(IWebEditingDelegate*)delegate.get();
351     editingDelegate->setAcceptsEditing(acceptsEditing);
352 }
353
354 void TestRunner::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
355 {
356     if (alwaysAcceptCookies == m_alwaysAcceptCookies)
357         return;
358
359     if (!::setAlwaysAcceptCookies(alwaysAcceptCookies))
360         return;
361     m_alwaysAcceptCookies = alwaysAcceptCookies;
362 }
363
364 void TestRunner::setAppCacheMaximumSize(unsigned long long size)
365 {
366     COMPtr<IWebApplicationCache> applicationCache;
367     if (FAILED(WebKitCreateInstance(CLSID_WebApplicationCache, 0, IID_IWebApplicationCache, reinterpret_cast<void**>(&applicationCache))))
368         return;
369
370     applicationCache->setMaximumSize(size);
371 }
372
373 void TestRunner::setAuthorAndUserStylesEnabled(bool flag)
374 {
375     COMPtr<IWebView> webView;
376     if (FAILED(frame->webView(&webView)))
377         return;
378
379     COMPtr<IWebPreferences> preferences;
380     if (FAILED(webView->preferences(&preferences)))
381         return;
382
383     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
384     if (!prefsPrivate)
385         return;
386
387     prefsPrivate->setAuthorAndUserStylesEnabled(flag);
388 }
389
390 void TestRunner::setCustomPolicyDelegate(bool setDelegate, bool permissive)
391 {
392     COMPtr<IWebView> webView;
393     if (FAILED(frame->webView(&webView)))
394         return;
395
396     if (!setDelegate) {
397         webView->setPolicyDelegate(nullptr);
398         return;
399     }
400
401     policyDelegate->setPermissive(permissive);
402     webView->setPolicyDelegate(policyDelegate);
403 }
404
405 void TestRunner::setDatabaseQuota(unsigned long long quota)
406 {
407     COMPtr<IWebDatabaseManager> databaseManager;
408     COMPtr<IWebDatabaseManager> tmpDatabaseManager;
409
410     if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
411         return;
412     if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
413         return;
414
415     databaseManager->setQuota(TEXT("file:///"), quota);
416 }
417
418 void TestRunner::goBack()
419 {
420     COMPtr<IWebView> webView;
421     if (FAILED(frame->webView(&webView)))
422         return;
423
424     BOOL ignore = TRUE;
425     webView->goBack(&ignore);
426 }
427
428 void TestRunner::setDefersLoading(bool defers)
429 {
430     COMPtr<IWebView> webView;
431     if (FAILED(frame->webView(&webView)))
432         return;
433
434     COMPtr<IWebViewPrivate2> viewPrivate;
435     if (FAILED(webView->QueryInterface(&viewPrivate)))
436         return;
437
438     viewPrivate->setDefersCallbacks(defers);
439 }
440
441 void TestRunner::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
442 {
443     COMPtr<IWebViewPrivate2> webView;
444     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
445         return;
446
447     _bstr_t schemeBSTR(JSStringCopyBSTR(scheme), false);
448     webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR.GetBSTR());
449 }
450
451 void TestRunner::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
452 {
453     // FIXME: Implement for DeviceOrientation layout tests.
454     // See https://bugs.webkit.org/show_bug.cgi?id=30335.
455     printf("ERROR: TestRunner::setMockDeviceOrientation() not implemented\n");
456 }
457
458 void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed)
459 {
460     // FIXME: Implement for Geolocation layout tests.
461     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
462     printf("ERROR: TestRunner::setMockGeolocationPosition() not implemented\n");
463 }
464
465 void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
466 {
467     // FIXME: Implement for Geolocation layout tests.
468     // See https://bugs.webkit.org/show_bug.cgi?id=28264.
469     printf("ERROR: TestRunner::setMockGeolocationPositionUnavailableError() not implemented\n");
470 }
471
472 void TestRunner::setGeolocationPermission(bool allow)
473 {
474     // FIXME: Implement for Geolocation layout tests.
475     setGeolocationPermissionCommon(allow);
476 }
477
478 void TestRunner::setIconDatabaseEnabled(bool iconDatabaseEnabled)
479 {
480 #if ENABLE(ICONDATABASE)
481     // See also <rdar://problem/6480108>
482     COMPtr<IWebIconDatabase> iconDatabase;
483     COMPtr<IWebIconDatabase> tmpIconDatabase;
484     if (FAILED(WebKitCreateInstance(CLSID_WebIconDatabase, 0, IID_IWebIconDatabase, (void**)&tmpIconDatabase)))
485         return;
486     if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase)))
487         return;
488
489     iconDatabase->setEnabled(iconDatabaseEnabled);
490 #endif
491 }
492
493 void TestRunner::setMainFrameIsFirstResponder(bool)
494 {
495     // Nothing to do here on Windows
496 }
497
498 void TestRunner::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
499 {
500     COMPtr<IWebView> webView;
501     if (FAILED(frame->webView(&webView)))
502         return;
503
504     COMPtr<IWebPreferences> preferences;
505     if (FAILED(webView->preferences(&preferences)))
506         return;
507
508     preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
509 }
510
511 void TestRunner::setXSSAuditorEnabled(bool enabled)
512 {
513     COMPtr<IWebView> webView;
514     if (FAILED(frame->webView(&webView)))
515         return;
516
517     COMPtr<IWebPreferences> preferences;
518     if (FAILED(webView->preferences(&preferences)))
519         return;
520
521     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
522     if (!prefsPrivate)
523         return;
524
525     prefsPrivate->setXSSAuditorEnabled(enabled);
526 }
527
528 void TestRunner::setSpatialNavigationEnabled(bool enabled)
529 {
530     // FIXME: Implement for SpatialNavigation layout tests.
531     printf("ERROR: TestRunner::setSpatialNavigationEnabled(bool) not implemented\n");
532 }
533
534 void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled)
535 {
536     COMPtr<IWebView> webView;
537     if (FAILED(frame->webView(&webView)))
538         return;
539
540     COMPtr<IWebPreferences> preferences;
541     if (FAILED(webView->preferences(&preferences)))
542         return;
543
544     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
545     if (!prefsPrivate)
546         return;
547
548     prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
549 }
550
551 void TestRunner::setAllowFileAccessFromFileURLs(bool enabled)
552 {
553     COMPtr<IWebView> webView;
554     if (FAILED(frame->webView(&webView)))
555         return;
556
557     COMPtr<IWebPreferences> preferences;
558     if (FAILED(webView->preferences(&preferences)))
559         return;
560
561     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
562     if (!prefsPrivate)
563         return;
564
565     prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
566 }
567
568 void TestRunner::setPopupBlockingEnabled(bool enabled)
569 {
570     COMPtr<IWebView> webView;
571     if (FAILED(frame->webView(&webView)))
572         return;
573
574     COMPtr<IWebPreferences> preferences;
575     if (FAILED(webView->preferences(&preferences)))
576         return;
577
578     preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled);
579 }
580
581 void TestRunner::setPluginsEnabled(bool flag)
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     preferences->setPlugInsEnabled(flag);
592 }
593
594 void TestRunner::setJavaScriptCanAccessClipboard(bool enabled)
595 {
596     COMPtr<IWebView> webView;
597     if (FAILED(frame->webView(&webView)))
598         return;
599
600     COMPtr<IWebPreferences> preferences;
601     if (FAILED(webView->preferences(&preferences)))
602         return;
603
604     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
605     if (!prefsPrivate)
606         return;
607
608     prefsPrivate->setJavaScriptCanAccessClipboard(enabled);
609 }
610
611 void TestRunner::setAutomaticLinkDetectionEnabled(bool)
612 {
613     // FIXME: Implement this.
614     printf("ERROR: TestRunner::setAutomaticLinkDetectionEnabled(bool) not implemented\n");
615 }
616
617 void TestRunner::setTabKeyCyclesThroughElements(bool shouldCycle)
618 {
619     COMPtr<IWebView> webView;
620     if (FAILED(frame->webView(&webView)))
621         return;
622
623     COMPtr<IWebViewPrivate2> viewPrivate;
624     if (FAILED(webView->QueryInterface(&viewPrivate)))
625         return;
626
627     viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE);
628 }
629
630 void TestRunner::setUseDashboardCompatibilityMode(bool flag)
631 {
632     // Not implemented on Windows.
633 }
634
635 void TestRunner::setUserStyleSheetEnabled(bool flag)
636 {
637     COMPtr<IWebView> webView;
638     if (FAILED(frame->webView(&webView)))
639         return;
640
641     COMPtr<IWebPreferences> preferences;
642     if (FAILED(webView->preferences(&preferences)))
643         return;
644
645     preferences->setUserStyleSheetEnabled(flag);
646 }
647
648 bool appendComponentToPath(wstring& path, const wstring& component)
649 {
650     WCHAR buffer[MAX_PATH];
651
652     if (path.size() + 1 > MAX_PATH)
653         return false;
654
655     memcpy(buffer, path.data(), path.size() * sizeof(WCHAR));
656     buffer[path.size()] = '\0';
657
658     if (!PathAppendW(buffer, component.c_str()))
659         return false;
660
661     path = wstring(buffer);
662     return true;
663 }
664
665 static bool followShortcuts(wstring& path)
666 {
667     if (PathFileExists(path.c_str()))
668         return true;
669
670     // Do we have a shortcut?
671     wstring linkPath = path;
672     linkPath.append(TEXT(".lnk"));
673     if (!PathFileExists(linkPath.c_str()))
674        return true;
675
676     // We have a shortcut, find its target.
677     COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink);
678     if (!shortcut)
679        return false;
680     COMPtr<IPersistFile> persistFile(Query, shortcut);
681     if (!shortcut)
682         return false;
683     if (FAILED(persistFile->Load(linkPath.c_str(), STGM_READ)))
684         return false;
685     if (FAILED(shortcut->Resolve(0, 0)))
686         return false;
687     WCHAR targetPath[MAX_PATH];
688     DWORD targetPathLen = _countof(targetPath);
689     if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0)))
690         return false;
691     if (!PathFileExists(targetPath))
692         return false;
693     // Use the target path as the result path instead.
694     path = wstring(targetPath);
695
696     return true;
697 }
698
699 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath)
700 {
701     wstring fileProtocol = L"file://";
702     bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos;
703     if (cygwinPath[isFileProtocol ? 7 : 0] != '/') // ensure path is absolute
704         return false;
705
706     // Get the Root path.
707     WCHAR rootPath[MAX_PATH];
708     DWORD rootPathSize = _countof(rootPath);
709     DWORD keyType;
710     DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize);
711
712     if (result != ERROR_SUCCESS || keyType != REG_SZ) {
713         // Cygwin 1.7 doesn't store Cygwin's root as a mount point anymore, because mount points are now stored in /etc/fstab.
714         // However, /etc/fstab doesn't contain any information about where / is located as a Windows path, so we need to use Cygwin's
715         // new registry key that has the root.
716         result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygwin\\setup"), TEXT("rootdir"), &keyType, &rootPath, &rootPathSize);
717         if (result != ERROR_SUCCESS || keyType != REG_SZ)
718             return false;
719     }
720
721     windowsPath = wstring(rootPath, rootPathSize);
722
723     int oldPos = isFileProtocol ? 8 : 1;
724     while (1) {
725         int newPos = cygwinPath.find('/', oldPos);
726
727         if (newPos == -1) {
728             wstring pathComponent = cygwinPath.substr(oldPos);
729
730             if (!appendComponentToPath(windowsPath, pathComponent))
731                return false;
732
733             if (!followShortcuts(windowsPath))
734                 return false;
735
736             break;
737         }
738
739         wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos);
740         if (!appendComponentToPath(windowsPath, pathComponent))
741             return false;
742
743         if (!followShortcuts(windowsPath))
744             return false;
745
746         oldPos = newPos + 1;
747     }
748
749     if (isFileProtocol)
750         windowsPath = fileProtocol + windowsPath;
751
752     return true;
753 }
754
755 void TestRunner::setUserStyleSheetLocation(JSStringRef jsURL)
756 {
757     COMPtr<IWebView> webView;
758     if (FAILED(frame->webView(&webView)))
759         return;
760
761     COMPtr<IWebPreferences> preferences;
762     if (FAILED(webView->preferences(&preferences)))
763         return;
764
765     RetainPtr<CFStringRef> urlString = adoptCF(JSStringCopyCFString(0, jsURL));
766     RetainPtr<CFURLRef> url = adoptCF(CFURLCreateWithString(0, urlString.get(), 0));
767     if (!url)
768         return;
769
770     // Now copy the file system path, POSIX style.
771     RetainPtr<CFStringRef> pathCF = adoptCF(CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle));
772     if (!pathCF)
773         return;
774
775     wstring path = cfStringRefToWString(pathCF.get());
776
777     wstring resultPath;
778     if (!resolveCygwinPath(path, resultPath))
779         return;
780
781     // The path has been resolved, now convert it back to a CFURL.
782     int result = ::WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, nullptr, 0, nullptr, nullptr);
783     Vector<char> utf8Vector(result);
784     result = ::WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, nullptr, nullptr);
785     if (!result)
786         return;
787
788     url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false);
789     if (!url)
790         return;
791
792     resultPath = cfStringRefToWString(CFURLGetString(url.get()));
793
794     _bstr_t resultPathBSTR(resultPath.data());
795     preferences->setUserStyleSheetLocation(resultPathBSTR);
796 }
797
798 void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
799 {
800     COMPtr<IWebView> webView;
801     if (FAILED(frame->webView(&webView)))
802         return;
803
804     COMPtr<IWebViewPrivate2> webViewPrivate(Query, webView);
805     if (!webViewPrivate)
806         return;
807
808     COMPtr<IDOMElement> domElement;
809     if (FAILED(webViewPrivate->elementFromJS(context, element, &domElement)))
810         return;
811
812     COMPtr<IDOMHTMLInputElement> domInputElement;
813     if (FAILED(domElement->QueryInterface(IID_IDOMHTMLInputElement, reinterpret_cast<void**>(&domInputElement))))
814         return;
815
816     _bstr_t valueBSTR(JSStringCopyBSTR(value), false);
817
818     domInputElement->setValueForUser(valueBSTR);
819 }
820
821 void TestRunner::setViewModeMediaFeature(JSStringRef mode)
822 {
823     // FIXME: implement
824 }
825
826 void TestRunner::dispatchPendingLoadRequests()
827 {
828     COMPtr<IWebView> webView;
829     if (FAILED(frame->webView(&webView)))
830         return;
831
832     COMPtr<IWebViewPrivate2> viewPrivate;
833     if (FAILED(webView->QueryInterface(&viewPrivate)))
834         return;
835
836     viewPrivate->dispatchPendingLoadRequests();
837 }
838
839 void TestRunner::overridePreference(JSStringRef key, JSStringRef value)
840 {
841     COMPtr<IWebView> webView;
842     if (FAILED(frame->webView(&webView)))
843         return;
844
845     COMPtr<IWebPreferences> preferences;
846     if (FAILED(webView->preferences(&preferences)))
847         return;
848
849     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
850     if (!prefsPrivate)
851         return;
852
853     _bstr_t keyBSTR(JSStringCopyBSTR(key), false);
854     _bstr_t valueBSTR(JSStringCopyBSTR(value), false);
855     prefsPrivate->setPreferenceForTest(keyBSTR, valueBSTR);
856 }
857
858 void TestRunner::removeAllVisitedLinks()
859 {
860     COMPtr<IWebHistory> history;
861     if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
862         return;
863
864     COMPtr<IWebHistory> sharedHistory;
865     if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
866         return;
867
868     COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
869     if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
870         return;
871
872     sharedHistoryPrivate->removeAllVisitedLinks();
873 }
874
875 void TestRunner::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
876 {
877     RetainPtr<CFStringRef> urlString = adoptCF(JSStringCopyCFString(0, jsURL));
878     ::setPersistentUserStyleSheetLocation(urlString.get());
879 }
880
881 void TestRunner::clearPersistentUserStyleSheet()
882 {
883     ::setPersistentUserStyleSheetLocation(nullptr);
884 }
885
886 void TestRunner::setWindowIsKey(bool flag)
887 {
888     COMPtr<IWebView> webView;
889     if (FAILED(frame->webView(&webView)))
890         return;
891
892     COMPtr<IWebViewPrivate2> viewPrivate;
893     if (FAILED(webView->QueryInterface(&viewPrivate)))
894         return;
895
896     HWND webViewWindow;
897     if (FAILED(viewPrivate->viewWindow(&webViewWindow)))
898         return;
899
900     ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0);
901 }
902
903 void TestRunner::setViewSize(double width, double height)
904 {
905     COMPtr<IWebView> webView;
906     if (FAILED(frame->webView(&webView)))
907         return;
908
909     COMPtr<IWebViewPrivate2> viewPrivate;
910     if (FAILED(webView->QueryInterface(&viewPrivate)))
911         return;
912
913     HWND webViewWindow;
914     if (FAILED(viewPrivate->viewWindow(&webViewWindow)))
915         return;
916
917     ::SetWindowPos(webViewWindow, 0, 0, 0, width, height, SWP_NOMOVE);
918 }
919
920 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
921
922 static void CALLBACK waitUntilDoneWatchdogFired(HWND, UINT, UINT_PTR, DWORD)
923 {
924     gTestRunner->waitToDumpWatchdogTimerFired();
925 }
926
927 void TestRunner::setWaitToDump(bool waitUntilDone)
928 {
929     m_waitToDump = waitUntilDone;
930     if (m_waitToDump && !waitToDumpWatchdog)
931         waitToDumpWatchdog = SetTimer(0, 0, waitToDumpWatchdogInterval * 1000, waitUntilDoneWatchdogFired);
932 }
933
934 int TestRunner::windowCount()
935 {
936     return openWindows().size();
937 }
938
939 void TestRunner::execCommand(JSStringRef name, JSStringRef value)
940 {
941     COMPtr<IWebView> webView;
942     if (FAILED(frame->webView(&webView)))
943         return;
944
945     COMPtr<IWebViewPrivate2> viewPrivate;
946     if (FAILED(webView->QueryInterface(&viewPrivate)))
947         return;
948
949     _bstr_t nameBSTR(JSStringCopyBSTR(name), false);
950     _bstr_t valueBSTR(JSStringCopyBSTR(value), false);
951     viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR);
952 }
953
954 bool TestRunner::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray)
955 {
956     COMPtr<IWebView> webView;
957     if (FAILED(frame->webView(&webView)))
958         return false;
959
960     COMPtr<IWebViewPrivate3> viewPrivate;
961     if (FAILED(webView->QueryInterface(&viewPrivate)))
962         return false;
963
964     unsigned char options = 0;
965
966     JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
967     JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), nullptr);
968     if (!JSValueIsNumber(context, lengthValue))
969         return false;
970
971     _bstr_t targetBSTR(JSStringCopyBSTR(target), false);
972
973     size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, nullptr));
974     for (size_t i = 0; i < length; ++i) {
975         JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, nullptr);
976         if (!JSValueIsString(context, value))
977             continue;
978
979         JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, nullptr));
980
981         if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
982             options |= WebFindOptionsCaseInsensitive;
983         else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
984             options |= WebFindOptionsAtWordStarts;
985         else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
986             options |= WebFindOptionsTreatMedialCapitalAsWordStart;
987         else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
988             options |= WebFindOptionsBackwards;
989         else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
990             options |= WebFindOptionsWrapAround;
991         else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection"))
992             options |= WebFindOptionsStartInSelection;
993     }
994
995     BOOL found = FALSE;
996     if (FAILED(viewPrivate->findString(targetBSTR, static_cast<WebFindOptions>(options), &found)))
997         return false;
998
999     return found;
1000 }
1001
1002 void TestRunner::setCacheModel(int cacheModel)
1003 {
1004     COMPtr<IWebView> webView;
1005     if (FAILED(frame->webView(&webView)))
1006         return;
1007
1008     COMPtr<IWebPreferences> preferences;
1009     if (FAILED(webView->preferences(&preferences)))
1010         return;
1011
1012     preferences->setCacheModel(static_cast<WebCacheModel>(cacheModel));
1013 }
1014
1015 bool TestRunner::isCommandEnabled(JSStringRef /*name*/)
1016 {
1017     printf("ERROR: TestRunner::isCommandEnabled() not implemented\n");
1018     return false;
1019 }
1020
1021 void TestRunner::waitForPolicyDelegate()
1022 {
1023     COMPtr<IWebView> webView;
1024     if (FAILED(frame->webView(&webView)))
1025         return;
1026
1027     setWaitToDump(true);
1028     policyDelegate->setControllerToNotifyDone(this);
1029     webView->setPolicyDelegate(policyDelegate);
1030 }
1031
1032 static _bstr_t bstrT(JSStringRef jsString)
1033 {
1034     // The false parameter tells the _bstr_t constructor to adopt the BSTR we pass it.
1035     return _bstr_t(JSStringCopyBSTR(jsString), false);
1036 }
1037
1038 void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1039 {
1040     COMPtr<IWebViewPrivate2> webView;
1041     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1042         return;
1043
1044     webView->addOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1045 }
1046
1047 void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1048 {
1049     COMPtr<IWebViewPrivate2> webView;
1050     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1051         return;
1052
1053     webView->removeOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1054 }
1055
1056 void TestRunner::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
1057 {
1058     // FIXME: implement
1059 }
1060
1061 void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1062 {
1063     COMPtr<IWebViewPrivate2> webView;
1064     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1065         return;
1066
1067     COMPtr<IWebScriptWorld> world;
1068     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1069         return;
1070
1071     webView->addUserScriptToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(),
1072         nullptr, 0, nullptr, 0, nullptr, runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd,
1073         allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly);
1074 }
1075
1076 void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
1077 {
1078     COMPtr<IWebViewPrivate2> webView;
1079     if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1080         return;
1081
1082     COMPtr<IWebScriptWorld> world;
1083     if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1084         return;
1085
1086     webView->addUserStyleSheetToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(),
1087         nullptr, 0, nullptr, 0, nullptr, allFrames ? WebInjectInAllFrames : WebInjectInTopFrameOnly);
1088 }
1089
1090 void TestRunner::setDeveloperExtrasEnabled(bool enabled)
1091 {
1092     COMPtr<IWebView> webView;
1093     if (FAILED(frame->webView(&webView)))
1094         return;
1095
1096     COMPtr<IWebPreferences> preferences;
1097     if (FAILED(webView->preferences(&preferences)))
1098         return;
1099
1100     COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
1101     if (!prefsPrivate)
1102         return;
1103
1104     prefsPrivate->setDeveloperExtrasEnabled(enabled);
1105 }
1106
1107 void TestRunner::showWebInspector()
1108 {
1109     COMPtr<IWebView> webView;
1110     if (FAILED(frame->webView(&webView)))
1111         return;
1112
1113     COMPtr<IWebViewPrivate2> viewPrivate(Query, webView);
1114     if (!viewPrivate)
1115         return;
1116
1117     COMPtr<IWebInspector> inspector;
1118     if (SUCCEEDED(viewPrivate->inspector(&inspector)))
1119         inspector->show();
1120 }
1121
1122 void TestRunner::closeWebInspector()
1123 {
1124     COMPtr<IWebView> webView;
1125     if (FAILED(frame->webView(&webView)))
1126         return;
1127
1128     COMPtr<IWebViewPrivate2> viewPrivate(Query, webView);
1129     if (!viewPrivate)
1130         return;
1131
1132     COMPtr<IWebInspector> inspector;
1133     if (FAILED(viewPrivate->inspector(&inspector)))
1134         return;
1135
1136     inspector->close();
1137 }
1138
1139 void TestRunner::evaluateInWebInspector(JSStringRef script)
1140 {
1141     COMPtr<IWebView> webView;
1142     if (FAILED(frame->webView(&webView)))
1143         return;
1144
1145     COMPtr<IWebViewPrivate2> viewPrivate(Query, webView);
1146     if (!viewPrivate)
1147         return;
1148
1149     COMPtr<IWebInspector> inspector;
1150     if (FAILED(viewPrivate->inspector(&inspector)))
1151         return;
1152
1153     COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
1154     if (!inspectorPrivate)
1155         return;
1156
1157     inspectorPrivate->evaluateInFrontend(bstrT(script).GetBSTR());
1158 }
1159
1160 JSStringRef TestRunner::inspectorTestStubURL()
1161 {
1162     CFBundleRef webkitBundle = webKitBundle();
1163     if (!webkitBundle)
1164         return nullptr;
1165
1166     RetainPtr<CFURLRef> url = adoptCF(CFBundleCopyResourceURL(webkitBundle, CFSTR("TestStub"), CFSTR("html"), CFSTR("WebInspectorUI")));
1167     if (!url)
1168         return nullptr;
1169
1170     return JSStringCreateWithCFString(CFURLGetString(url.get()));
1171 }
1172
1173 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
1174 static WorldMap& worldMap()
1175 {
1176     static WorldMap& map = *new WorldMap;
1177     return map;
1178 }
1179
1180 unsigned worldIDForWorld(IWebScriptWorld* world)
1181 {
1182     WorldMap::const_iterator end = worldMap().end();
1183     for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
1184         if (it->value == world)
1185             return it->key;
1186     }
1187
1188     return 0;
1189 }
1190
1191 void TestRunner::evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1192 {
1193     // FIXME: Implement this.
1194 }
1195
1196 void TestRunner::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1197 {
1198     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1199     if (!framePrivate)
1200         return;
1201
1202     // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
1203     // that is created once and cached forever.
1204     COMPtr<IWebScriptWorld> world;
1205     if (!worldID) {
1206         if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1207             return;
1208     } else {
1209         COMPtr<IWebScriptWorld>& worldSlot = worldMap().add(worldID, nullptr).iterator->value;
1210         if (!worldSlot && FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(worldSlot), reinterpret_cast<void**>(&worldSlot))))
1211             return;
1212         world = worldSlot;
1213     }
1214
1215     _bstr_t result;
1216     if (FAILED(framePrivate->stringByEvaluatingJavaScriptInScriptWorld(world.get(), globalObject, bstrT(script).GetBSTR(), &result.GetBSTR())))
1217         return;
1218 }
1219
1220 void TestRunner::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
1221 {
1222     // Nothing implemented here (compare to Mac)
1223 }
1224
1225 void TestRunner::apiTestGoToCurrentBackForwardItem()
1226 {
1227     COMPtr<IWebView> webView;
1228     if (FAILED(frame->webView(&webView)))
1229         return;
1230
1231     COMPtr<IWebBackForwardList> backForwardList;
1232     if (FAILED(webView->backForwardList(&backForwardList)))
1233         return;
1234
1235     COMPtr<IWebHistoryItem> item;
1236     if (FAILED(backForwardList->currentItem(&item)))
1237         return;
1238
1239     BOOL success;
1240     webView->goToBackForwardItem(item.get(), &success);
1241 }
1242
1243 void TestRunner::setWebViewEditable(bool editable)
1244 {
1245     COMPtr<IWebView> webView;
1246     if (FAILED(frame->webView(&webView)))
1247         return;
1248
1249     COMPtr<IWebViewEditing> viewEditing;
1250     if (FAILED(webView->QueryInterface(&viewEditing)))
1251         return;
1252
1253     viewEditing->setEditable(editable);
1254 }
1255
1256 void TestRunner::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
1257 {
1258     printf("ERROR: TestRunner::authenticateSession() not implemented\n");
1259 }
1260
1261 void TestRunner::abortModal()
1262 {
1263     // Nothing to do
1264 }
1265
1266 void TestRunner::setSerializeHTTPLoads(bool serializeLoads)
1267 {
1268     COMPtr<IWebView> webView;
1269     if (FAILED(frame->webView(&webView)))
1270         return;
1271
1272     COMPtr<IWebViewPrivate2> viewPrivate;
1273     if (FAILED(webView->QueryInterface(&viewPrivate)))
1274         return;
1275
1276     viewPrivate->setLoadResourcesSerially(serializeLoads);
1277 }
1278
1279 void TestRunner::setTextDirection(JSStringRef direction)
1280 {
1281     COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1282     if (!framePrivate)
1283         return;
1284
1285     framePrivate->setTextDirection(bstrT(direction).GetBSTR());
1286 }
1287
1288 void TestRunner::addChromeInputField()
1289 {
1290     printf("ERROR: TestRunner::addChromeInputField() not implemented\n");
1291 }
1292
1293 void TestRunner::removeChromeInputField()
1294 {
1295     printf("ERROR: TestRunner::removeChromeInputField() not implemented\n");
1296 }
1297
1298 void TestRunner::focusWebView()
1299 {
1300     printf("ERROR: TestRunner::focusWebView() not implemented\n");
1301 }
1302
1303 void TestRunner::setBackingScaleFactor(double)
1304 {
1305     // Not applicable
1306 }
1307
1308 void TestRunner::resetPageVisibility()
1309 {
1310     // FIXME: Implement this.
1311 }
1312
1313 void TestRunner::setPageVisibility(const char*)
1314 {
1315     // FIXME: Implement this.
1316 }
1317
1318 void TestRunner::grantWebNotificationPermission(JSStringRef origin)
1319 {
1320     printf("ERROR: TestRunner::grantWebNotificationPermission(JSStringRef) not implemented\n");
1321 }
1322
1323 void TestRunner::denyWebNotificationPermission(JSStringRef jsOrigin)
1324 {
1325     printf("ERROR: TestRunner::denyWebNotificationPermission(JSStringRef) not implemented\n");
1326 }
1327
1328 void TestRunner::removeAllWebNotificationPermissions()
1329 {
1330     printf("ERROR: TestRunner::removeAllWebNotificationPermissions() not implemented\n");
1331 }
1332
1333 void TestRunner::simulateWebNotificationClick(JSValueRef jsNotification)
1334 {
1335     printf("ERROR: TestRunner::simulateWebNotificationClick() not implemented\n");
1336 }
1337
1338 void TestRunner::simulateLegacyWebNotificationClick(JSStringRef title)
1339 {
1340     // FIXME: Implement.
1341 }
1342
1343 unsigned TestRunner::imageCountInGeneralPasteboard() const
1344 {
1345     printf("ERROR: TestRunner::imageCountInGeneralPasteboard() not implemented\n");
1346     return 0;
1347 }
1348