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