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