Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
      3  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      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  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "WebKitDLL.h"
     29 #include "WebFrame.h"
     30 
     31 #include "CFDictionaryPropertyBag.h"
     32 #include "COMPropertyBag.h"
     33 #include "DOMCoreClasses.h"
     34 #include "DefaultPolicyDelegate.h"
     35 #include "HTMLFrameOwnerElement.h"
     36 #include "MarshallingHelpers.h"
     37 #include "WebActionPropertyBag.h"
     38 #include "WebChromeClient.h"
     39 #include "WebDataSource.h"
     40 #include "WebDocumentLoader.h"
     41 #include "WebDownload.h"
     42 #include "WebEditorClient.h"
     43 #include "WebError.h"
     44 #include "WebFrameNetworkingContext.h"
     45 #include "WebFramePolicyListener.h"
     46 #include "WebHistory.h"
     47 #include "WebHistoryItem.h"
     48 #include "WebKit.h"
     49 #include "WebKitStatisticsPrivate.h"
     50 #include "WebMutableURLRequest.h"
     51 #include "WebNotificationCenter.h"
     52 #include "WebScriptWorld.h"
     53 #include "WebURLResponse.h"
     54 #include "WebView.h"
     55 #include <WebCore/BString.h>
     56 #include <WebCore/COMPtr.h>
     57 #include <WebCore/MemoryCache.h>
     58 #include <WebCore/Document.h>
     59 #include <WebCore/DocumentLoader.h>
     60 #include <WebCore/DocumentMarkerController.h>
     61 #include <WebCore/DOMImplementation.h>
     62 #include <WebCore/DOMWindow.h>
     63 #include <WebCore/Event.h>
     64 #include <WebCore/EventHandler.h>
     65 #include <WebCore/FormState.h>
     66 #include <WebCore/FrameLoader.h>
     67 #include <WebCore/FrameLoadRequest.h>
     68 #include <WebCore/FrameTree.h>
     69 #include <WebCore/FrameView.h>
     70 #include <WebCore/FrameWin.h>
     71 #include <WebCore/GDIObjectCounter.h>
     72 #include <WebCore/GraphicsContext.h>
     73 #include <WebCore/HistoryItem.h>
     74 #include <WebCore/HTMLAppletElement.h>
     75 #include <WebCore/HTMLFormElement.h>
     76 #include <WebCore/HTMLFormControlElement.h>
     77 #include <WebCore/HTMLInputElement.h>
     78 #include <WebCore/HTMLNames.h>
     79 #include <WebCore/HTMLPlugInElement.h>
     80 #include <WebCore/JSDOMWindow.h>
     81 #include <WebCore/KeyboardEvent.h>
     82 #include <WebCore/MouseRelatedEvent.h>
     83 #include <WebCore/NotImplemented.h>
     84 #include <WebCore/Page.h>
     85 #include <WebCore/PlatformKeyboardEvent.h>
     86 #include <WebCore/PluginData.h>
     87 #include <WebCore/PluginDatabase.h>
     88 #include <WebCore/PluginView.h>
     89 #include <WebCore/PrintContext.h>
     90 #include <WebCore/ResourceHandle.h>
     91 #include <WebCore/ResourceRequest.h>
     92 #include <WebCore/RenderView.h>
     93 #include <WebCore/RenderTreeAsText.h>
     94 #include <WebCore/Settings.h>
     95 #include <WebCore/SVGDocumentExtensions.h>
     96 #include <WebCore/SVGSMILElement.h>
     97 #include <WebCore/TextIterator.h>
     98 #include <WebCore/JSDOMBinding.h>
     99 #include <WebCore/ScriptController.h>
    100 #include <WebCore/SecurityOrigin.h>
    101 #include <JavaScriptCore/APICast.h>
    102 #include <JavaScriptCore/JSLock.h>
    103 #include <JavaScriptCore/JSObject.h>
    104 #include <JavaScriptCore/JSValue.h>
    105 #include <wtf/MathExtras.h>
    106 
    107 #if USE(CG)
    108 #include <CoreGraphics/CoreGraphics.h>
    109 #elif USE(CAIRO)
    110 #include "PlatformContextCairo.h"
    111 #include <cairo-win32.h>
    112 #endif
    113 
    114 #if USE(CG)
    115 // CG SPI used for printing
    116 extern "C" {
    117     CGAffineTransform CGContextGetBaseCTM(CGContextRef c);
    118     void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m);
    119 }
    120 #endif
    121 
    122 using namespace WebCore;
    123 using namespace HTMLNames;
    124 using namespace std;
    125 
    126 using JSC::JSGlobalObject;
    127 using JSC::JSLock;
    128 using JSC::JSValue;
    129 using JSC::SilenceAssertionsOnly;
    130 
    131 #define FLASH_REDRAW 0
    132 
    133 
    134 // By imaging to a width a little wider than the available pixels,
    135 // thin pages will be scaled down a little, matching the way they
    136 // print in IE and Camino. This lets them use fewer sheets than they
    137 // would otherwise, which is presumably why other browsers do this.
    138 // Wide pages will be scaled down more than this.
    139 const float PrintingMinimumShrinkFactor = 1.25f;
    140 
    141 // This number determines how small we are willing to reduce the page content
    142 // in order to accommodate the widest line. If the page would have to be
    143 // reduced smaller to make the widest line fit, we just clip instead (this
    144 // behavior matches MacIE and Mozilla, at least)
    145 const float PrintingMaximumShrinkFactor = 2.0f;
    146 
    147 //-----------------------------------------------------------------------------
    148 // Helpers to convert from WebCore to WebKit type
    149 WebFrame* kit(Frame* frame)
    150 {
    151     if (!frame)
    152         return 0;
    153 
    154     FrameLoaderClient* frameLoaderClient = frame->loader()->client();
    155     if (frameLoaderClient)
    156         return static_cast<WebFrame*>(frameLoaderClient);  // eek, is there a better way than static cast?
    157     return 0;
    158 }
    159 
    160 Frame* core(WebFrame* webFrame)
    161 {
    162     if (!webFrame)
    163         return 0;
    164     return webFrame->impl();
    165 }
    166 
    167 // This function is not in WebFrame.h because we don't want to advertise the ability to get a non-const Frame from a const WebFrame
    168 Frame* core(const WebFrame* webFrame)
    169 {
    170     if (!webFrame)
    171         return 0;
    172     return const_cast<WebFrame*>(webFrame)->impl();
    173 }
    174 
    175 //-----------------------------------------------------------------------------
    176 
    177 static Element *elementFromDOMElement(IDOMElement *element)
    178 {
    179     if (!element)
    180         return 0;
    181 
    182     COMPtr<IDOMElementPrivate> elePriv;
    183     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
    184     if (SUCCEEDED(hr)) {
    185         Element* ele;
    186         hr = elePriv->coreElement((void**)&ele);
    187         if (SUCCEEDED(hr))
    188             return ele;
    189     }
    190     return 0;
    191 }
    192 
    193 static HTMLFormElement *formElementFromDOMElement(IDOMElement *element)
    194 {
    195     if (!element)
    196         return 0;
    197 
    198     IDOMElementPrivate* elePriv;
    199     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
    200     if (SUCCEEDED(hr)) {
    201         Element* ele;
    202         hr = elePriv->coreElement((void**)&ele);
    203         elePriv->Release();
    204         if (SUCCEEDED(hr) && ele && ele->hasTagName(formTag))
    205             return static_cast<HTMLFormElement*>(ele);
    206     }
    207     return 0;
    208 }
    209 
    210 static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element)
    211 {
    212     if (!element)
    213         return 0;
    214 
    215     IDOMElementPrivate* elePriv;
    216     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
    217     if (SUCCEEDED(hr)) {
    218         Element* ele;
    219         hr = elePriv->coreElement((void**)&ele);
    220         elePriv->Release();
    221         if (SUCCEEDED(hr) && ele && ele->hasTagName(inputTag))
    222             return static_cast<HTMLInputElement*>(ele);
    223     }
    224     return 0;
    225 }
    226 
    227 // WebFramePrivate ------------------------------------------------------------
    228 
    229 class WebFrame::WebFramePrivate {
    230 public:
    231     WebFramePrivate()
    232         : frame(0)
    233         , webView(0)
    234         , m_policyFunction(0)
    235     {
    236     }
    237 
    238     ~WebFramePrivate() { }
    239     FrameView* frameView() { return frame ? frame->view() : 0; }
    240 
    241     Frame* frame;
    242     WebView* webView;
    243     FramePolicyFunction m_policyFunction;
    244     COMPtr<WebFramePolicyListener> m_policyListener;
    245 };
    246 
    247 // WebFrame ----------------------------------------------------------------
    248 
    249 WebFrame::WebFrame()
    250     : WebFrameLoaderClient(this)
    251     , m_refCount(0)
    252     , d(new WebFrame::WebFramePrivate)
    253     , m_quickRedirectComing(false)
    254     , m_inPrintingMode(false)
    255     , m_pageHeight(0)
    256 {
    257     WebFrameCount++;
    258     gClassCount++;
    259     gClassNameCount.add("WebFrame");
    260 }
    261 
    262 WebFrame::~WebFrame()
    263 {
    264     delete d;
    265     WebFrameCount--;
    266     gClassCount--;
    267     gClassNameCount.remove("WebFrame");
    268 }
    269 
    270 WebFrame* WebFrame::createInstance()
    271 {
    272     WebFrame* instance = new WebFrame();
    273     instance->AddRef();
    274     return instance;
    275 }
    276 
    277 HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling(
    278     /* [in] */ BOOL flag)
    279 {
    280     if (Frame* frame = core(this))
    281         if (FrameView* view = frame->view())
    282             view->setCanHaveScrollbars(!!flag);
    283 
    284     return S_OK;
    285 }
    286 
    287 HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling(
    288     /* [retval][out] */ BOOL *flag)
    289 {
    290     if (flag)
    291         if (Frame* frame = core(this))
    292             if (FrameView* view = frame->view())
    293                 *flag = view->canHaveScrollbars();
    294 
    295     return S_OK;
    296 }
    297 
    298 HRESULT STDMETHODCALLTYPE WebFrame::setIsDisconnected(
    299     /* [in] */ BOOL flag)
    300 {
    301     if (Frame* frame = core(this)) {
    302         frame->setIsDisconnected(flag);
    303         return S_OK;
    304     }
    305 
    306     return E_FAIL;
    307 }
    308 
    309 HRESULT STDMETHODCALLTYPE WebFrame::setExcludeFromTextSearch(
    310     /* [in] */ BOOL flag)
    311 {
    312     if (Frame* frame = core(this)) {
    313         frame->setExcludeFromTextSearch(flag);
    314         return S_OK;
    315     }
    316 
    317     return E_FAIL;
    318 }
    319 
    320 HRESULT WebFrame::reloadFromOrigin()
    321 {
    322     Frame* coreFrame = core(this);
    323     if (!coreFrame)
    324         return E_FAIL;
    325 
    326     coreFrame->loader()->reload(true);
    327     return S_OK;
    328 }
    329 
    330 HRESULT STDMETHODCALLTYPE WebFrame::paintDocumentRectToContext(
    331     /* [in] */ RECT rect,
    332     /* [in] */ OLE_HANDLE deviceContext)
    333 {
    334     Frame* coreFrame = core(this);
    335     if (!coreFrame)
    336         return E_FAIL;
    337 
    338     FrameView* view = coreFrame->view();
    339     if (!view)
    340         return E_FAIL;
    341 
    342     // We can't paint with a layout still pending.
    343     view->updateLayoutAndStyleIfNeededRecursive();
    344 
    345     HDC dc = reinterpret_cast<HDC>(static_cast<ULONG64>(deviceContext));
    346     GraphicsContext gc(dc);
    347     gc.setShouldIncludeChildWindows(true);
    348     gc.save();
    349     LONG width = rect.right - rect.left;
    350     LONG height = rect.bottom - rect.top;
    351     FloatRect dirtyRect;
    352     dirtyRect.setWidth(width);
    353     dirtyRect.setHeight(height);
    354     gc.clip(dirtyRect);
    355     gc.translate(-rect.left, -rect.top);
    356     view->paintContents(&gc, rect);
    357     gc.restore();
    358 
    359     return S_OK;
    360 }
    361 
    362 HRESULT STDMETHODCALLTYPE WebFrame::paintScrollViewRectToContextAtPoint(
    363     /* [in] */ RECT rect,
    364     /* [in] */ POINT pt,
    365     /* [in] */ OLE_HANDLE deviceContext)
    366 {
    367     Frame* coreFrame = core(this);
    368     if (!coreFrame)
    369         return E_FAIL;
    370 
    371     FrameView* view = coreFrame->view();
    372     if (!view)
    373         return E_FAIL;
    374 
    375     // We can't paint with a layout still pending.
    376     view->updateLayoutAndStyleIfNeededRecursive();
    377 
    378     HDC dc = reinterpret_cast<HDC>(static_cast<ULONG64>(deviceContext));
    379     GraphicsContext gc(dc);
    380     gc.setShouldIncludeChildWindows(true);
    381     gc.save();
    382     IntRect dirtyRect(rect);
    383     dirtyRect.move(-pt.x, -pt.y);
    384     view->paint(&gc, dirtyRect);
    385     gc.restore();
    386 
    387     return S_OK;
    388 }
    389 
    390 // IUnknown -------------------------------------------------------------------
    391 
    392 HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
    393 {
    394     *ppvObject = 0;
    395     if (IsEqualGUID(riid, __uuidof(WebFrame)))
    396         *ppvObject = this;
    397     else if (IsEqualGUID(riid, IID_IUnknown))
    398         *ppvObject = static_cast<IWebFrame*>(this);
    399     else if (IsEqualGUID(riid, IID_IWebFrame))
    400         *ppvObject = static_cast<IWebFrame*>(this);
    401     else if (IsEqualGUID(riid, IID_IWebFramePrivate))
    402         *ppvObject = static_cast<IWebFramePrivate*>(this);
    403     else if (IsEqualGUID(riid, IID_IWebDocumentText))
    404         *ppvObject = static_cast<IWebDocumentText*>(this);
    405     else
    406         return E_NOINTERFACE;
    407 
    408     AddRef();
    409     return S_OK;
    410 }
    411 
    412 ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
    413 {
    414     return ++m_refCount;
    415 }
    416 
    417 ULONG STDMETHODCALLTYPE WebFrame::Release(void)
    418 {
    419     ULONG newRef = --m_refCount;
    420     if (!newRef)
    421         delete(this);
    422 
    423     return newRef;
    424 }
    425 
    426 // IWebFrame -------------------------------------------------------------------
    427 
    428 HRESULT STDMETHODCALLTYPE WebFrame::name(
    429     /* [retval][out] */ BSTR* frameName)
    430 {
    431     if (!frameName) {
    432         ASSERT_NOT_REACHED();
    433         return E_POINTER;
    434     }
    435 
    436     *frameName = 0;
    437 
    438     Frame* coreFrame = core(this);
    439     if (!coreFrame)
    440         return E_FAIL;
    441 
    442     *frameName = BString(coreFrame->tree()->uniqueName()).release();
    443     return S_OK;
    444 }
    445 
    446 HRESULT STDMETHODCALLTYPE WebFrame::webView(
    447     /* [retval][out] */ IWebView** view)
    448 {
    449     *view = 0;
    450     if (!d->webView)
    451         return E_FAIL;
    452     *view = d->webView;
    453     (*view)->AddRef();
    454     return S_OK;
    455 }
    456 
    457 HRESULT STDMETHODCALLTYPE WebFrame::frameView(
    458     /* [retval][out] */ IWebFrameView** /*view*/)
    459 {
    460     ASSERT_NOT_REACHED();
    461     return E_NOTIMPL;
    462 }
    463 
    464 HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument(
    465     /* [retval][out] */ IDOMDocument** result)
    466 {
    467     if (!result) {
    468         ASSERT_NOT_REACHED();
    469         return E_POINTER;
    470     }
    471 
    472     *result = 0;
    473 
    474     if (Frame* coreFrame = core(this))
    475         if (Document* document = coreFrame->document())
    476             *result = DOMDocument::createInstance(document);
    477 
    478     return *result ? S_OK : E_FAIL;
    479 }
    480 
    481 HRESULT STDMETHODCALLTYPE WebFrame::frameElement(
    482     /* [retval][out] */ IDOMHTMLElement** frameElement)
    483 {
    484     if (!frameElement)
    485         return E_POINTER;
    486 
    487     *frameElement = 0;
    488     Frame* coreFrame = core(this);
    489     if (!coreFrame)
    490         return E_FAIL;
    491 
    492     COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(coreFrame->ownerElement()));
    493     COMPtr<IDOMHTMLElement> htmlElement(Query, domElement);
    494     if (!htmlElement)
    495         return E_FAIL;
    496     return htmlElement.copyRefTo(frameElement);
    497 }
    498 
    499 HRESULT STDMETHODCALLTYPE WebFrame::currentForm(
    500         /* [retval][out] */ IDOMElement **currentForm)
    501 {
    502     if (!currentForm) {
    503         ASSERT_NOT_REACHED();
    504         return E_POINTER;
    505     }
    506 
    507     *currentForm = 0;
    508 
    509     if (Frame* coreFrame = core(this)) {
    510         if (HTMLFormElement* formElement = coreFrame->selection()->currentForm())
    511             *currentForm = DOMElement::createInstance(formElement);
    512     }
    513 
    514     return *currentForm ? S_OK : E_FAIL;
    515 }
    516 
    517 JSGlobalContextRef STDMETHODCALLTYPE WebFrame::globalContext()
    518 {
    519     Frame* coreFrame = core(this);
    520     if (!coreFrame)
    521         return 0;
    522 
    523     return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
    524 }
    525 
    526 JSGlobalContextRef WebFrame::globalContextForScriptWorld(IWebScriptWorld* iWorld)
    527 {
    528     Frame* coreFrame = core(this);
    529     if (!coreFrame)
    530         return 0;
    531 
    532     COMPtr<WebScriptWorld> world(Query, iWorld);
    533     if (!world)
    534         return 0;
    535 
    536     return toGlobalRef(coreFrame->script()->globalObject(world->world())->globalExec());
    537 }
    538 
    539 HRESULT STDMETHODCALLTYPE WebFrame::loadRequest(
    540     /* [in] */ IWebURLRequest* request)
    541 {
    542     COMPtr<WebMutableURLRequest> requestImpl;
    543 
    544     HRESULT hr = request->QueryInterface(&requestImpl);
    545     if (FAILED(hr))
    546         return hr;
    547 
    548     Frame* coreFrame = core(this);
    549     if (!coreFrame)
    550         return E_FAIL;
    551 
    552     coreFrame->loader()->load(requestImpl->resourceRequest(), false);
    553     return S_OK;
    554 }
    555 
    556 void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL)
    557 {
    558     String mimeTypeString(mimeType, SysStringLen(mimeType));
    559     if (!mimeType)
    560         mimeTypeString = "text/html";
    561 
    562     String encodingString(textEncodingName, SysStringLen(textEncodingName));
    563 
    564     // FIXME: We should really be using MarshallingHelpers::BSTRToKURL here,
    565     // but that would turn a null BSTR into a null KURL, and we crash inside of
    566     // WebCore if we use a null KURL in constructing the ResourceRequest.
    567     KURL baseKURL = KURL(KURL(), String(baseURL ? baseURL : L"", SysStringLen(baseURL)));
    568 
    569     KURL failingKURL = MarshallingHelpers::BSTRToKURL(failingURL);
    570 
    571     ResourceRequest request(baseKURL);
    572     SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL);
    573 
    574     // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null.
    575     if (Frame* coreFrame = core(this))
    576         coreFrame->loader()->load(request, substituteData, false);
    577 }
    578 
    579 
    580 HRESULT STDMETHODCALLTYPE WebFrame::loadData(
    581     /* [in] */ IStream* data,
    582     /* [in] */ BSTR mimeType,
    583     /* [in] */ BSTR textEncodingName,
    584     /* [in] */ BSTR url)
    585 {
    586     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create();
    587 
    588     STATSTG stat;
    589     if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) {
    590         if (!stat.cbSize.HighPart && stat.cbSize.LowPart) {
    591             Vector<char> dataBuffer(stat.cbSize.LowPart);
    592             ULONG read;
    593             // FIXME: this does a needless copy, would be better to read right into the SharedBuffer
    594             // or adopt the Vector or something.
    595             if (SUCCEEDED(data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read)))
    596                 sharedBuffer->append(dataBuffer.data(), static_cast<int>(dataBuffer.size()));
    597         }
    598     }
    599 
    600     loadData(sharedBuffer, mimeType, textEncodingName, url, 0);
    601     return S_OK;
    602 }
    603 
    604 HRESULT WebFrame::loadPlainTextString(
    605     /* [in] */ BSTR string,
    606     /* [in] */ BSTR url)
    607 {
    608     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
    609     BString plainTextMimeType(TEXT("text/plain"), 10);
    610     BString utf16Encoding(TEXT("utf-16"), 6);
    611     loadData(sharedBuffer.release(), plainTextMimeType, utf16Encoding, url, 0);
    612     return S_OK;
    613 }
    614 
    615 void WebFrame::loadHTMLString(BSTR string, BSTR baseURL, BSTR unreachableURL)
    616 {
    617     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
    618     BString utf16Encoding(TEXT("utf-16"), 6);
    619     loadData(sharedBuffer.release(), 0, utf16Encoding, baseURL, unreachableURL);
    620 }
    621 
    622 HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString(
    623     /* [in] */ BSTR string,
    624     /* [in] */ BSTR baseURL)
    625 {
    626     loadHTMLString(string, baseURL, 0);
    627     return S_OK;
    628 }
    629 
    630 HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString(
    631     /* [in] */ BSTR str,
    632     /* [in] */ BSTR baseURL,
    633     /* [in] */ BSTR unreachableURL)
    634 {
    635     loadHTMLString(str, baseURL, unreachableURL);
    636     return S_OK;
    637 }
    638 
    639 HRESULT STDMETHODCALLTYPE WebFrame::loadArchive(
    640     /* [in] */ IWebArchive* /*archive*/)
    641 {
    642     ASSERT_NOT_REACHED();
    643     return E_NOTIMPL;
    644 }
    645 
    646 static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
    647 {
    648     return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
    649 }
    650 
    651 HRESULT STDMETHODCALLTYPE WebFrame::dataSource(
    652     /* [retval][out] */ IWebDataSource** source)
    653 {
    654     if (!source) {
    655         ASSERT_NOT_REACHED();
    656         return E_POINTER;
    657     }
    658 
    659     *source = 0;
    660 
    661     Frame* coreFrame = core(this);
    662     if (!coreFrame)
    663         return E_FAIL;
    664 
    665     WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->documentLoader());
    666 
    667     *source = webDataSource;
    668 
    669     if (webDataSource)
    670         webDataSource->AddRef();
    671 
    672     return *source ? S_OK : E_FAIL;
    673 }
    674 
    675 HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource(
    676     /* [retval][out] */ IWebDataSource** source)
    677 {
    678     if (!source) {
    679         ASSERT_NOT_REACHED();
    680         return E_POINTER;
    681     }
    682 
    683     *source = 0;
    684 
    685     Frame* coreFrame = core(this);
    686     if (!coreFrame)
    687         return E_FAIL;
    688 
    689     WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->provisionalDocumentLoader());
    690 
    691     *source = webDataSource;
    692 
    693     if (webDataSource)
    694         webDataSource->AddRef();
    695 
    696     return *source ? S_OK : E_FAIL;
    697 }
    698 
    699 KURL WebFrame::url() const
    700 {
    701     Frame* coreFrame = core(this);
    702     if (!coreFrame)
    703         return KURL();
    704 
    705     return coreFrame->document()->url();
    706 }
    707 
    708 HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
    709 {
    710     if (Frame* coreFrame = core(this))
    711         coreFrame->loader()->stopAllLoaders();
    712     return S_OK;
    713 }
    714 
    715 HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
    716 {
    717     Frame* coreFrame = core(this);
    718     if (!coreFrame)
    719         return E_FAIL;
    720 
    721     coreFrame->loader()->reload();
    722     return S_OK;
    723 }
    724 
    725 HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed(
    726     /* [in] */ BSTR name,
    727     /* [retval][out] */ IWebFrame** frame)
    728 {
    729     if (!frame) {
    730         ASSERT_NOT_REACHED();
    731         return E_POINTER;
    732     }
    733 
    734     *frame = 0;
    735 
    736     Frame* coreFrame = core(this);
    737     if (!coreFrame)
    738         return E_FAIL;
    739 
    740     Frame* foundFrame = coreFrame->tree()->find(AtomicString(name, SysStringLen(name)));
    741     if (!foundFrame)
    742         return S_OK;
    743 
    744     WebFrame* foundWebFrame = kit(foundFrame);
    745     if (!foundWebFrame)
    746         return E_FAIL;
    747 
    748     return foundWebFrame->QueryInterface(IID_IWebFrame, (void**)frame);
    749 }
    750 
    751 HRESULT STDMETHODCALLTYPE WebFrame::parentFrame(
    752     /* [retval][out] */ IWebFrame** frame)
    753 {
    754     HRESULT hr = S_OK;
    755     *frame = 0;
    756     if (Frame* coreFrame = core(this))
    757         if (WebFrame* webFrame = kit(coreFrame->tree()->parent()))
    758             hr = webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
    759 
    760     return hr;
    761 }
    762 
    763 class EnumChildFrames : public IEnumVARIANT
    764 {
    765 public:
    766     EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree()->firstChild() : 0) { }
    767 
    768     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
    769     {
    770         *ppvObject = 0;
    771         if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
    772             *ppvObject = this;
    773         else
    774             return E_NOINTERFACE;
    775 
    776         AddRef();
    777         return S_OK;
    778     }
    779 
    780     virtual ULONG STDMETHODCALLTYPE AddRef(void)
    781     {
    782         return ++m_refCount;
    783     }
    784 
    785     virtual ULONG STDMETHODCALLTYPE Release(void)
    786     {
    787         ULONG newRef = --m_refCount;
    788         if (!newRef)
    789             delete(this);
    790         return newRef;
    791     }
    792 
    793     virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
    794     {
    795         if (pCeltFetched)
    796             *pCeltFetched = 0;
    797         if (!rgVar)
    798             return E_POINTER;
    799         VariantInit(rgVar);
    800         if (!celt || celt > 1)
    801             return S_FALSE;
    802         if (!m_frame || !m_curChild)
    803             return S_FALSE;
    804 
    805         WebFrame* webFrame = kit(m_curChild);
    806         IUnknown* unknown;
    807         HRESULT hr = webFrame->QueryInterface(IID_IUnknown, (void**)&unknown);
    808         if (FAILED(hr))
    809             return hr;
    810 
    811         V_VT(rgVar) = VT_UNKNOWN;
    812         V_UNKNOWN(rgVar) = unknown;
    813 
    814         m_curChild = m_curChild->tree()->nextSibling();
    815         if (pCeltFetched)
    816             *pCeltFetched = 1;
    817         return S_OK;
    818     }
    819 
    820     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
    821     {
    822         if (!m_frame)
    823             return S_FALSE;
    824         for (unsigned i = 0; i < celt && m_curChild; i++)
    825             m_curChild = m_curChild->tree()->nextSibling();
    826         return m_curChild ? S_OK : S_FALSE;
    827     }
    828 
    829     virtual HRESULT STDMETHODCALLTYPE Reset(void)
    830     {
    831         if (!m_frame)
    832             return S_FALSE;
    833         m_curChild = m_frame->tree()->firstChild();
    834         return S_OK;
    835     }
    836 
    837     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**)
    838     {
    839         return E_NOTIMPL;
    840     }
    841 
    842 private:
    843     ULONG m_refCount;
    844     Frame* m_frame;
    845     Frame* m_curChild;
    846 };
    847 
    848 HRESULT STDMETHODCALLTYPE WebFrame::childFrames(
    849     /* [retval][out] */ IEnumVARIANT **enumFrames)
    850 {
    851     if (!enumFrames)
    852         return E_POINTER;
    853 
    854     *enumFrames = new EnumChildFrames(core(this));
    855     return S_OK;
    856 }
    857 
    858 // IWebFramePrivate ------------------------------------------------------
    859 
    860 HRESULT WebFrame::renderTreeAsExternalRepresentation(BOOL forPrinting, BSTR *result)
    861 {
    862     if (!result)
    863         return E_POINTER;
    864 
    865     Frame* coreFrame = core(this);
    866     if (!coreFrame)
    867         return E_FAIL;
    868 
    869     *result = BString(externalRepresentation(coreFrame, forPrinting ? RenderAsTextPrintingMode : RenderAsTextBehaviorNormal)).release();
    870     return S_OK;
    871 }
    872 
    873 HRESULT STDMETHODCALLTYPE WebFrame::counterValueForElementById(
    874     /* [in] */ BSTR id, /* [retval][out] */ BSTR *result)
    875 {
    876     if (!result)
    877         return E_POINTER;
    878 
    879     Frame* coreFrame = core(this);
    880     if (!coreFrame)
    881         return E_FAIL;
    882 
    883     String coreId = String(id, SysStringLen(id));
    884 
    885     Element* element = coreFrame->document()->getElementById(coreId);
    886     if (!element)
    887         return E_FAIL;
    888     *result = BString(counterValueForElement(element)).release();
    889     return S_OK;
    890 }
    891 
    892 HRESULT STDMETHODCALLTYPE WebFrame::pageNumberForElementById(
    893     /* [in] */ BSTR id,
    894     /* [in] */ float pageWidthInPixels,
    895     /* [in] */ float pageHeightInPixels,
    896     /* [retval][out] */ int* result)
    897 {
    898     if (!result)
    899         return E_POINTER;
    900 
    901     Frame* coreFrame = core(this);
    902     if (!coreFrame)
    903         return E_FAIL;
    904 
    905     String coreId = String(id, SysStringLen(id));
    906 
    907     Element* element = coreFrame->document()->getElementById(coreId);
    908     if (!element)
    909         return E_FAIL;
    910     *result = PrintContext::pageNumberForElement(element, FloatSize(pageWidthInPixels, pageHeightInPixels));
    911     return S_OK;
    912 }
    913 
    914 HRESULT STDMETHODCALLTYPE WebFrame::numberOfPages(
    915     /* [in] */ float pageWidthInPixels,
    916     /* [in] */ float pageHeightInPixels,
    917     /* [retval][out] */ int* result)
    918 {
    919     if (!result)
    920         return E_POINTER;
    921 
    922     Frame* coreFrame = core(this);
    923     if (!coreFrame)
    924         return E_FAIL;
    925 
    926     *result = PrintContext::numberOfPages(coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels));
    927     return S_OK;
    928 }
    929 
    930 HRESULT STDMETHODCALLTYPE WebFrame::scrollOffset(
    931         /* [retval][out] */ SIZE* offset)
    932 {
    933     if (!offset) {
    934         ASSERT_NOT_REACHED();
    935         return E_POINTER;
    936     }
    937 
    938     Frame* coreFrame = core(this);
    939     if (!coreFrame)
    940         return E_FAIL;
    941 
    942     FrameView* view = coreFrame->view();
    943     if (!view)
    944         return E_FAIL;
    945 
    946     *offset = view->scrollOffset();
    947     return S_OK;
    948 }
    949 
    950 HRESULT STDMETHODCALLTYPE WebFrame::layout()
    951 {
    952     Frame* coreFrame = core(this);
    953     if (!coreFrame)
    954         return E_FAIL;
    955 
    956     FrameView* view = coreFrame->view();
    957     if (!view)
    958         return E_FAIL;
    959 
    960     view->layout();
    961     return S_OK;
    962 }
    963 
    964 HRESULT STDMETHODCALLTYPE WebFrame::firstLayoutDone(
    965     /* [retval][out] */ BOOL* result)
    966 {
    967     if (!result) {
    968         ASSERT_NOT_REACHED();
    969         return E_POINTER;
    970     }
    971 
    972     *result = 0;
    973 
    974     Frame* coreFrame = core(this);
    975     if (!coreFrame)
    976         return E_FAIL;
    977 
    978     *result = coreFrame->loader()->stateMachine()->firstLayoutDone();
    979     return S_OK;
    980 }
    981 
    982 HRESULT STDMETHODCALLTYPE WebFrame::loadType(
    983     /* [retval][out] */ WebFrameLoadType* type)
    984 {
    985     if (!type) {
    986         ASSERT_NOT_REACHED();
    987         return E_POINTER;
    988     }
    989 
    990     *type = (WebFrameLoadType)0;
    991 
    992     Frame* coreFrame = core(this);
    993     if (!coreFrame)
    994         return E_FAIL;
    995 
    996     *type = (WebFrameLoadType)coreFrame->loader()->loadType();
    997     return S_OK;
    998 }
    999 
   1000 HRESULT STDMETHODCALLTYPE WebFrame::pendingFrameUnloadEventCount(
   1001     /* [retval][out] */ UINT* result)
   1002 {
   1003     if (!result) {
   1004         ASSERT_NOT_REACHED();
   1005         return E_POINTER;
   1006     }
   1007 
   1008     *result = 0;
   1009 
   1010     Frame* coreFrame = core(this);
   1011     if (!coreFrame)
   1012         return E_FAIL;
   1013 
   1014     *result = coreFrame->domWindow()->pendingUnloadEventListeners();
   1015     return S_OK;
   1016 }
   1017 
   1018 HRESULT STDMETHODCALLTYPE WebFrame::unused2()
   1019 {
   1020     return E_NOTIMPL;
   1021 }
   1022 
   1023 HRESULT STDMETHODCALLTYPE WebFrame::hasSpellingMarker(
   1024         /* [in] */ UINT from,
   1025         /* [in] */ UINT length,
   1026         /* [retval][out] */ BOOL* result)
   1027 {
   1028     Frame* coreFrame = core(this);
   1029     if (!coreFrame)
   1030         return E_FAIL;
   1031     *result = coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
   1032     return S_OK;
   1033 }
   1034 
   1035 HRESULT STDMETHODCALLTYPE WebFrame::clearOpener()
   1036 {
   1037     HRESULT hr = S_OK;
   1038     if (Frame* coreFrame = core(this))
   1039         coreFrame->loader()->setOpener(0);
   1040 
   1041     return hr;
   1042 }
   1043 
   1044 // IWebDocumentText -----------------------------------------------------------
   1045 
   1046 HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding(
   1047     /* [retval][out] */ BOOL* result)
   1048 {
   1049     *result = FALSE;
   1050     return E_NOTIMPL;
   1051 }
   1052 
   1053 HRESULT STDMETHODCALLTYPE WebFrame::selectedString(
   1054     /* [retval][out] */ BSTR* result)
   1055 {
   1056     *result = 0;
   1057 
   1058     Frame* coreFrame = core(this);
   1059     if (!coreFrame)
   1060         return E_FAIL;
   1061 
   1062     String text = coreFrame->displayStringModifiedByEncoding(coreFrame->editor()->selectedText());
   1063 
   1064     *result = BString(text).release();
   1065     return S_OK;
   1066 }
   1067 
   1068 HRESULT STDMETHODCALLTYPE WebFrame::selectAll()
   1069 {
   1070     Frame* coreFrame = core(this);
   1071     if (!coreFrame)
   1072         return E_FAIL;
   1073 
   1074     if (!coreFrame->editor()->command("SelectAll").execute())
   1075         return E_FAIL;
   1076 
   1077     return S_OK;
   1078 }
   1079 
   1080 HRESULT STDMETHODCALLTYPE WebFrame::deselectAll()
   1081 {
   1082     return E_NOTIMPL;
   1083 }
   1084 
   1085 // WebFrame ---------------------------------------------------------------
   1086 
   1087 PassRefPtr<Frame> WebFrame::init(IWebView* webView, Page* page, HTMLFrameOwnerElement* ownerElement)
   1088 {
   1089     webView->QueryInterface(&d->webView);
   1090     d->webView->Release(); // don't hold the extra ref
   1091 
   1092     HWND viewWindow;
   1093     d->webView->viewWindow((OLE_HANDLE*)&viewWindow);
   1094 
   1095     this->AddRef(); // We release this ref in frameLoaderDestroyed()
   1096     RefPtr<Frame> frame = Frame::create(page, ownerElement, this);
   1097     d->frame = frame.get();
   1098     return frame.release();
   1099 }
   1100 
   1101 Frame* WebFrame::impl()
   1102 {
   1103     return d->frame;
   1104 }
   1105 
   1106 void WebFrame::invalidate()
   1107 {
   1108     Frame* coreFrame = core(this);
   1109     ASSERT(coreFrame);
   1110 
   1111     if (Document* document = coreFrame->document())
   1112         document->recalcStyle(Node::Force);
   1113 }
   1114 
   1115 HRESULT WebFrame::inViewSourceMode(BOOL* flag)
   1116 {
   1117     if (!flag) {
   1118         ASSERT_NOT_REACHED();
   1119         return E_POINTER;
   1120     }
   1121 
   1122     *flag = FALSE;
   1123 
   1124     Frame* coreFrame = core(this);
   1125     if (!coreFrame)
   1126         return E_FAIL;
   1127 
   1128     *flag = coreFrame->inViewSourceMode() ? TRUE : FALSE;
   1129     return S_OK;
   1130 }
   1131 
   1132 HRESULT WebFrame::setInViewSourceMode(BOOL flag)
   1133 {
   1134     Frame* coreFrame = core(this);
   1135     if (!coreFrame)
   1136         return E_FAIL;
   1137 
   1138     coreFrame->setInViewSourceMode(!!flag);
   1139     return S_OK;
   1140 }
   1141 
   1142 HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** element)
   1143 {
   1144     if (!form)
   1145         return E_INVALIDARG;
   1146 
   1147     HTMLFormElement* formElement = formElementFromDOMElement(form);
   1148     if (formElement) {
   1149         const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
   1150         AtomicString targetName((UChar*)name, SysStringLen(name));
   1151         for (unsigned int i = 0; i < elements.size(); i++) {
   1152             if (!elements[i]->isFormControlElement())
   1153                 continue;
   1154             HTMLFormControlElement* elt = static_cast<HTMLFormControlElement*>(elements[i]);
   1155             // Skip option elements, other duds
   1156             if (elt->name() == targetName) {
   1157                 *element = DOMElement::createInstance(elt);
   1158                 return S_OK;
   1159             }
   1160         }
   1161     }
   1162     return E_FAIL;
   1163 }
   1164 
   1165 HRESULT WebFrame::formForElement(IDOMElement* element, IDOMElement** form)
   1166 {
   1167     if (!element)
   1168         return E_INVALIDARG;
   1169 
   1170     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
   1171     if (!inputElement)
   1172         return E_FAIL;
   1173 
   1174     HTMLFormElement *formElement = inputElement->form();
   1175     if (!formElement)
   1176         return E_FAIL;
   1177 
   1178     *form = DOMElement::createInstance(formElement);
   1179     return S_OK;
   1180 }
   1181 
   1182 HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, BOOL *result)
   1183 {
   1184     *result = false;
   1185     if (!element)
   1186         return E_INVALIDARG;
   1187 
   1188     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
   1189     if (!inputElement)
   1190         *result = false;
   1191     else
   1192         *result = inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->autoComplete();
   1193 
   1194     return S_OK;
   1195 }
   1196 
   1197 HRESULT WebFrame::pauseAnimation(BSTR animationName, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
   1198 {
   1199     if (!node || !animationWasRunning)
   1200         return E_POINTER;
   1201 
   1202     *animationWasRunning = FALSE;
   1203 
   1204     Frame* frame = core(this);
   1205     if (!frame)
   1206         return E_FAIL;
   1207 
   1208     AnimationController* controller = frame->animation();
   1209     if (!controller)
   1210         return E_FAIL;
   1211 
   1212     COMPtr<DOMNode> domNode(Query, node);
   1213     if (!domNode)
   1214         return E_FAIL;
   1215 
   1216     *animationWasRunning = controller->pauseAnimationAtTime(domNode->node()->renderer(), String(animationName, SysStringLen(animationName)), secondsFromNow);
   1217     return S_OK;
   1218 }
   1219 
   1220 HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double secondsFromNow, BOOL* transitionWasRunning)
   1221 {
   1222     if (!node || !transitionWasRunning)
   1223         return E_POINTER;
   1224 
   1225     *transitionWasRunning = FALSE;
   1226 
   1227     Frame* frame = core(this);
   1228     if (!frame)
   1229         return E_FAIL;
   1230 
   1231     AnimationController* controller = frame->animation();
   1232     if (!controller)
   1233         return E_FAIL;
   1234 
   1235     COMPtr<DOMNode> domNode(Query, node);
   1236     if (!domNode)
   1237         return E_FAIL;
   1238 
   1239     *transitionWasRunning = controller->pauseTransitionAtTime(domNode->node()->renderer(), String(propertyName, SysStringLen(propertyName)), secondsFromNow);
   1240     return S_OK;
   1241 }
   1242 
   1243 HRESULT WebFrame::pauseSVGAnimation(BSTR elementId, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
   1244 {
   1245     if (!node || !animationWasRunning)
   1246         return E_POINTER;
   1247 
   1248     *animationWasRunning = FALSE;
   1249 
   1250     Frame* frame = core(this);
   1251     if (!frame)
   1252         return E_FAIL;
   1253 
   1254     Document* document = frame->document();
   1255     if (!document || !document->svgExtensions())
   1256         return E_FAIL;
   1257 
   1258     COMPtr<DOMNode> domNode(Query, node);
   1259     if (!domNode || !SVGSMILElement::isSMILElement(domNode->node()))
   1260         return E_FAIL;
   1261 
   1262 #if ENABLE(SVG)
   1263     *animationWasRunning = document->accessSVGExtensions()->sampleAnimationAtTime(String(elementId, SysStringLen(elementId)), static_cast<SVGSMILElement*>(domNode->node()), secondsFromNow);
   1264 #else
   1265     *animationWasRunning = FALSE;
   1266 #endif
   1267 
   1268     return S_OK;
   1269 }
   1270 
   1271 HRESULT WebFrame::visibleContentRect(RECT* rect)
   1272 {
   1273     if (!rect)
   1274         return E_POINTER;
   1275     SetRectEmpty(rect);
   1276 
   1277     Frame* frame = core(this);
   1278     if (!frame)
   1279         return E_FAIL;
   1280 
   1281     FrameView* view = frame->view();
   1282     if (!view)
   1283         return E_FAIL;
   1284 
   1285     *rect = view->visibleContentRect(false);
   1286     return S_OK;
   1287 }
   1288 
   1289 HRESULT WebFrame::numberOfActiveAnimations(UINT* number)
   1290 {
   1291     if (!number)
   1292         return E_POINTER;
   1293 
   1294     *number = 0;
   1295 
   1296     Frame* frame = core(this);
   1297     if (!frame)
   1298         return E_FAIL;
   1299 
   1300     AnimationController* controller = frame->animation();
   1301     if (!controller)
   1302         return E_FAIL;
   1303 
   1304     *number = controller->numberOfActiveAnimations();
   1305     return S_OK;
   1306 }
   1307 
   1308 HRESULT WebFrame::suspendAnimations()
   1309 {
   1310     Frame* frame = core(this);
   1311     if (!frame)
   1312         return E_FAIL;
   1313 
   1314     frame->animation()->suspendAnimations();
   1315     return S_OK;
   1316 }
   1317 
   1318 HRESULT WebFrame::resumeAnimations()
   1319 {
   1320     Frame* frame = core(this);
   1321     if (!frame)
   1322         return E_FAIL;
   1323 
   1324     frame->animation()->resumeAnimations();
   1325     return S_OK;
   1326 }
   1327 
   1328 HRESULT WebFrame::isDisplayingStandaloneImage(BOOL* result)
   1329 {
   1330     if (!result)
   1331         return E_POINTER;
   1332 
   1333     *result = FALSE;
   1334 
   1335     Frame* frame = core(this);
   1336     if (!frame)
   1337         return E_FAIL;
   1338 
   1339     Document* document = frame->document();
   1340     *result = document && document->isImageDocument();
   1341     return S_OK;
   1342 }
   1343 
   1344 HRESULT WebFrame::allowsFollowingLink(BSTR url, BOOL* result)
   1345 {
   1346     if (!result)
   1347         return E_POINTER;
   1348 
   1349     *result = TRUE;
   1350 
   1351     Frame* frame = core(this);
   1352     if (!frame)
   1353         return E_FAIL;
   1354 
   1355     *result = frame->document()->securityOrigin()->canDisplay(MarshallingHelpers::BSTRToKURL(url));
   1356     return S_OK;
   1357 }
   1358 
   1359 HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls)
   1360 {
   1361     if (!form)
   1362         return E_INVALIDARG;
   1363 
   1364     HTMLFormElement* formElement = formElementFromDOMElement(form);
   1365     if (!formElement)
   1366         return E_FAIL;
   1367 
   1368     int inCount = *cControls;
   1369     int count = (int) formElement->associatedElements().size();
   1370     *cControls = count;
   1371     if (!controls)
   1372         return S_OK;
   1373     if (inCount < count)
   1374         return E_FAIL;
   1375 
   1376     *cControls = 0;
   1377     const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
   1378     for (int i = 0; i < count; i++) {
   1379         if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
   1380             controls[*cControls] = DOMElement::createInstance(toHTMLElement(elements.at(i)));
   1381             (*cControls)++;
   1382         }
   1383     }
   1384     return S_OK;
   1385 }
   1386 
   1387 HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result)
   1388 {
   1389     HTMLInputElement* inputElement = inputElementFromDOMElement(element);
   1390     *result = inputElement && inputElement->isPasswordField();
   1391     return S_OK;
   1392 }
   1393 
   1394 HRESULT WebFrame::searchForLabelsBeforeElement(const BSTR* labels, unsigned cLabels, IDOMElement* beforeElement, unsigned* outResultDistance, BOOL* outResultIsInCellAbove, BSTR* result)
   1395 {
   1396     if (!result) {
   1397         ASSERT_NOT_REACHED();
   1398         return E_POINTER;
   1399     }
   1400 
   1401     if (outResultDistance)
   1402         *outResultDistance = 0;
   1403     if (outResultIsInCellAbove)
   1404         *outResultIsInCellAbove = FALSE;
   1405     *result = 0;
   1406 
   1407     if (!cLabels)
   1408         return S_OK;
   1409     if (cLabels < 1)
   1410         return E_INVALIDARG;
   1411 
   1412     Frame* coreFrame = core(this);
   1413     if (!coreFrame)
   1414         return E_FAIL;
   1415 
   1416     Vector<String> labelStrings(cLabels);
   1417     for (int i=0; i<cLabels; i++)
   1418         labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
   1419     Element *coreElement = elementFromDOMElement(beforeElement);
   1420     if (!coreElement)
   1421         return E_FAIL;
   1422 
   1423     size_t resultDistance;
   1424     bool resultIsInCellAbove;
   1425     String label = coreFrame->searchForLabelsBeforeElement(labelStrings, coreElement, &resultDistance, &resultIsInCellAbove);
   1426 
   1427     *result = SysAllocStringLen(label.characters(), label.length());
   1428     if (label.length() && !*result)
   1429         return E_OUTOFMEMORY;
   1430     if (outResultDistance)
   1431         *outResultDistance = resultDistance;
   1432     if (outResultIsInCellAbove)
   1433         *outResultIsInCellAbove = resultIsInCellAbove;
   1434 
   1435     return S_OK;
   1436 }
   1437 
   1438 HRESULT WebFrame::matchLabelsAgainstElement(const BSTR* labels, int cLabels, IDOMElement* againstElement, BSTR* result)
   1439 {
   1440     if (!result) {
   1441         ASSERT_NOT_REACHED();
   1442         return E_POINTER;
   1443     }
   1444 
   1445     *result = 0;
   1446 
   1447     if (!cLabels)
   1448         return S_OK;
   1449     if (cLabels < 1)
   1450         return E_INVALIDARG;
   1451 
   1452     Frame* coreFrame = core(this);
   1453     if (!coreFrame)
   1454         return E_FAIL;
   1455 
   1456     Vector<String> labelStrings(cLabels);
   1457     for (int i=0; i<cLabels; i++)
   1458         labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
   1459     Element *coreElement = elementFromDOMElement(againstElement);
   1460     if (!coreElement)
   1461         return E_FAIL;
   1462 
   1463     String label = coreFrame->matchLabelsAgainstElement(labelStrings, coreElement);
   1464 
   1465     *result = SysAllocStringLen(label.characters(), label.length());
   1466     if (label.length() && !*result)
   1467         return E_OUTOFMEMORY;
   1468     return S_OK;
   1469 }
   1470 
   1471 HRESULT WebFrame::canProvideDocumentSource(bool* result)
   1472 {
   1473     HRESULT hr = S_OK;
   1474     *result = false;
   1475 
   1476     COMPtr<IWebDataSource> dataSource;
   1477     hr = WebFrame::dataSource(&dataSource);
   1478     if (FAILED(hr))
   1479         return hr;
   1480 
   1481     COMPtr<IWebURLResponse> urlResponse;
   1482     hr = dataSource->response(&urlResponse);
   1483     if (SUCCEEDED(hr) && urlResponse) {
   1484         BSTR mimeTypeBStr;
   1485         if (SUCCEEDED(urlResponse->MIMEType(&mimeTypeBStr))) {
   1486             String mimeType(mimeTypeBStr, SysStringLen(mimeTypeBStr));
   1487             *result = mimeType == "text/html" || WebCore::DOMImplementation::isXMLMIMEType(mimeType);
   1488             SysFreeString(mimeTypeBStr);
   1489         }
   1490     }
   1491     return hr;
   1492 }
   1493 
   1494 HRESULT STDMETHODCALLTYPE WebFrame::layerTreeAsText(BSTR* result)
   1495 {
   1496     if (!result)
   1497         return E_POINTER;
   1498     *result = 0;
   1499 
   1500     Frame* frame = core(this);
   1501     if (!frame)
   1502         return E_FAIL;
   1503 
   1504     String text = frame->layerTreeAsText();
   1505     *result = BString(text).release();
   1506     return S_OK;
   1507 }
   1508 
   1509 void WebFrame::frameLoaderDestroyed()
   1510 {
   1511     // The FrameLoader going away is equivalent to the Frame going away,
   1512     // so we now need to clear our frame pointer.
   1513     d->frame = 0;
   1514 
   1515     this->Release();
   1516 }
   1517 
   1518 void WebFrame::makeRepresentation(DocumentLoader*)
   1519 {
   1520     notImplemented();
   1521 }
   1522 
   1523 void WebFrame::forceLayoutForNonHTML()
   1524 {
   1525     notImplemented();
   1526 }
   1527 
   1528 void WebFrame::setCopiesOnScroll()
   1529 {
   1530     notImplemented();
   1531 }
   1532 
   1533 void WebFrame::detachedFromParent2()
   1534 {
   1535     notImplemented();
   1536 }
   1537 
   1538 void WebFrame::detachedFromParent3()
   1539 {
   1540     notImplemented();
   1541 }
   1542 
   1543 void WebFrame::cancelPolicyCheck()
   1544 {
   1545     if (d->m_policyListener) {
   1546         d->m_policyListener->invalidate();
   1547         d->m_policyListener = 0;
   1548     }
   1549 
   1550     d->m_policyFunction = 0;
   1551 }
   1552 
   1553 void WebFrame::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
   1554 {
   1555     Frame* coreFrame = core(this);
   1556     ASSERT(coreFrame);
   1557 
   1558     COMPtr<IWebFormDelegate> formDelegate;
   1559 
   1560     if (FAILED(d->webView->formDelegate(&formDelegate))) {
   1561         (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
   1562         return;
   1563     }
   1564 
   1565     COMPtr<IDOMElement> formElement(AdoptCOM, DOMElement::createInstance(formState->form()));
   1566 
   1567     HashMap<String, String> formValuesMap;
   1568     const StringPairVector& textFieldValues = formState->textFieldValues();
   1569     size_t size = textFieldValues.size();
   1570     for (size_t i = 0; i < size; ++i)
   1571         formValuesMap.add(textFieldValues[i].first, textFieldValues[i].second);
   1572 
   1573     COMPtr<IPropertyBag> formValuesPropertyBag(AdoptCOM, COMPropertyBag<String>::createInstance(formValuesMap));
   1574 
   1575     COMPtr<WebFrame> sourceFrame(kit(formState->sourceFrame()));
   1576     if (SUCCEEDED(formDelegate->willSubmitForm(this, sourceFrame.get(), formElement.get(), formValuesPropertyBag.get(), setUpPolicyListener(function).get())))
   1577         return;
   1578 
   1579     // FIXME: Add a sane default implementation
   1580     (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
   1581 }
   1582 
   1583 void WebFrame::revertToProvisionalState(DocumentLoader*)
   1584 {
   1585     notImplemented();
   1586 }
   1587 
   1588 void WebFrame::setMainFrameDocumentReady(bool)
   1589 {
   1590     notImplemented();
   1591 }
   1592 
   1593 void WebFrame::willChangeTitle(DocumentLoader*)
   1594 {
   1595     notImplemented();
   1596 }
   1597 
   1598 void WebFrame::didChangeTitle(DocumentLoader*)
   1599 {
   1600     notImplemented();
   1601 }
   1602 
   1603 void WebFrame::didChangeIcons(DocumentLoader*)
   1604 {
   1605     notImplemented();
   1606 }
   1607 
   1608 bool WebFrame::canHandleRequest(const ResourceRequest& request) const
   1609 {
   1610     return WebView::canHandleRequest(request);
   1611 }
   1612 
   1613 bool WebFrame::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
   1614 {
   1615     notImplemented();
   1616     return true;
   1617 }
   1618 
   1619 bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const
   1620 {
   1621     notImplemented();
   1622     return true;
   1623 }
   1624 
   1625 bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const
   1626 {
   1627     notImplemented();
   1628     return false;
   1629 }
   1630 
   1631 String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
   1632 {
   1633     notImplemented();
   1634     ASSERT_NOT_REACHED();
   1635     return String();
   1636 }
   1637 
   1638 void WebFrame::frameLoadCompleted()
   1639 {
   1640 }
   1641 
   1642 void WebFrame::restoreViewState()
   1643 {
   1644 }
   1645 
   1646 void WebFrame::provisionalLoadStarted()
   1647 {
   1648     notImplemented();
   1649 }
   1650 
   1651 bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const
   1652 {
   1653     notImplemented();
   1654     return false;
   1655 }
   1656 
   1657 void WebFrame::addHistoryItemForFragmentScroll()
   1658 {
   1659     notImplemented();
   1660 }
   1661 
   1662 void WebFrame::didFinishLoad()
   1663 {
   1664     notImplemented();
   1665 }
   1666 
   1667 void WebFrame::prepareForDataSourceReplacement()
   1668 {
   1669     notImplemented();
   1670 }
   1671 
   1672 String WebFrame::userAgent(const KURL& url)
   1673 {
   1674     return d->webView->userAgentForKURL(url);
   1675 }
   1676 
   1677 void WebFrame::saveViewStateToItem(HistoryItem*)
   1678 {
   1679 }
   1680 
   1681 ResourceError WebFrame::cancelledError(const ResourceRequest& request)
   1682 {
   1683     // FIXME: Need ChickenCat to include CFNetwork/CFURLError.h to get these values
   1684     // Alternatively, we could create our own error domain/codes.
   1685     return ResourceError(String(WebURLErrorDomain), -999, request.url().string(), String());
   1686 }
   1687 
   1688 ResourceError WebFrame::blockedError(const ResourceRequest& request)
   1689 {
   1690     // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
   1691     return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotUseRestrictedPort, request.url().string(), String());
   1692 }
   1693 
   1694 ResourceError WebFrame::cannotShowURLError(const ResourceRequest& request)
   1695 {
   1696     // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
   1697     return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotShowURL, request.url().string(), String());
   1698 }
   1699 
   1700 ResourceError WebFrame::interruptForPolicyChangeError(const ResourceRequest& request)
   1701 {
   1702     // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
   1703     return ResourceError(String(WebKitErrorDomain), WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), String());
   1704 }
   1705 
   1706 ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&)
   1707 {
   1708     notImplemented();
   1709     return ResourceError();
   1710 }
   1711 
   1712 ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&)
   1713 {
   1714     notImplemented();
   1715     return ResourceError();
   1716 }
   1717 
   1718 ResourceError WebFrame::pluginWillHandleLoadError(const ResourceResponse& response)
   1719 {
   1720     return ResourceError(String(WebKitErrorDomain), WebKitErrorPlugInWillHandleLoad, response.url().string(), String());
   1721 }
   1722 
   1723 bool WebFrame::shouldFallBack(const ResourceError& error)
   1724 {
   1725     if (error.errorCode() == WebURLErrorCancelled && error.domain() == String(WebURLErrorDomain))
   1726         return false;
   1727 
   1728     if (error.errorCode() == WebKitErrorPlugInWillHandleLoad && error.domain() == String(WebKitErrorDomain))
   1729         return false;
   1730 
   1731     return true;
   1732 }
   1733 
   1734 COMPtr<WebFramePolicyListener> WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction function)
   1735 {
   1736     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
   1737 
   1738     if (d->m_policyListener)
   1739         d->m_policyListener->invalidate();
   1740 
   1741     Frame* coreFrame = core(this);
   1742     ASSERT(coreFrame);
   1743 
   1744     d->m_policyListener.adoptRef(WebFramePolicyListener::createInstance(coreFrame));
   1745     d->m_policyFunction = function;
   1746 
   1747     return d->m_policyListener;
   1748 }
   1749 
   1750 void WebFrame::receivedPolicyDecision(PolicyAction action)
   1751 {
   1752     ASSERT(d->m_policyListener);
   1753     ASSERT(d->m_policyFunction);
   1754 
   1755     FramePolicyFunction function = d->m_policyFunction;
   1756 
   1757     d->m_policyListener = 0;
   1758     d->m_policyFunction = 0;
   1759 
   1760     Frame* coreFrame = core(this);
   1761     ASSERT(coreFrame);
   1762 
   1763     (coreFrame->loader()->policyChecker()->*function)(action);
   1764 }
   1765 
   1766 void WebFrame::dispatchDecidePolicyForResponse(FramePolicyFunction function, const ResourceResponse& response, const ResourceRequest& request)
   1767 {
   1768     Frame* coreFrame = core(this);
   1769     ASSERT(coreFrame);
   1770 
   1771     COMPtr<IWebPolicyDelegate> policyDelegate;
   1772     if (FAILED(d->webView->policyDelegate(&policyDelegate)))
   1773         policyDelegate = DefaultPolicyDelegate::sharedInstance();
   1774 
   1775     COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
   1776 
   1777     if (SUCCEEDED(policyDelegate->decidePolicyForMIMEType(d->webView, BString(response.mimeType()), urlRequest.get(), this, setUpPolicyListener(function).get())))
   1778         return;
   1779 
   1780     (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
   1781 }
   1782 
   1783 void WebFrame::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
   1784 {
   1785     Frame* coreFrame = core(this);
   1786     ASSERT(coreFrame);
   1787 
   1788     COMPtr<IWebPolicyDelegate> policyDelegate;
   1789     if (FAILED(d->webView->policyDelegate(&policyDelegate)))
   1790         policyDelegate = DefaultPolicyDelegate::sharedInstance();
   1791 
   1792     COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
   1793     COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
   1794 
   1795     if (SUCCEEDED(policyDelegate->decidePolicyForNewWindowAction(d->webView, actionInformation.get(), urlRequest.get(), BString(frameName), setUpPolicyListener(function).get())))
   1796         return;
   1797 
   1798     (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
   1799 }
   1800 
   1801 void WebFrame::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
   1802 {
   1803     Frame* coreFrame = core(this);
   1804     ASSERT(coreFrame);
   1805 
   1806     COMPtr<IWebPolicyDelegate> policyDelegate;
   1807     if (FAILED(d->webView->policyDelegate(&policyDelegate)))
   1808         policyDelegate = DefaultPolicyDelegate::sharedInstance();
   1809 
   1810     COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
   1811     COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
   1812 
   1813     if (SUCCEEDED(policyDelegate->decidePolicyForNavigationAction(d->webView, actionInformation.get(), urlRequest.get(), this, setUpPolicyListener(function).get())))
   1814         return;
   1815 
   1816     (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
   1817 }
   1818 
   1819 void WebFrame::dispatchUnableToImplementPolicy(const ResourceError& error)
   1820 {
   1821     COMPtr<IWebPolicyDelegate> policyDelegate;
   1822     if (FAILED(d->webView->policyDelegate(&policyDelegate)))
   1823         policyDelegate = DefaultPolicyDelegate::sharedInstance();
   1824 
   1825     COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error));
   1826     policyDelegate->unableToImplementPolicyWithError(d->webView, webError.get(), this);
   1827 }
   1828 
   1829 void WebFrame::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
   1830 {
   1831     COMPtr<IWebDownloadDelegate> downloadDelegate;
   1832     COMPtr<IWebView> webView;
   1833     if (SUCCEEDED(this->webView(&webView))) {
   1834         if (FAILED(webView->downloadDelegate(&downloadDelegate))) {
   1835             // If the WebView doesn't successfully provide a download delegate we'll pass a null one
   1836             // into the WebDownload - which may or may not decide to use a DefaultDownloadDelegate
   1837             LOG_ERROR("Failed to get downloadDelegate from WebView");
   1838             downloadDelegate = 0;
   1839         }
   1840     }
   1841 
   1842     // Its the delegate's job to ref the WebDownload to keep it alive - otherwise it will be destroyed
   1843     // when this method returns
   1844     COMPtr<WebDownload> download;
   1845     download.adoptRef(WebDownload::createInstance(handle, request, response, downloadDelegate.get()));
   1846 }
   1847 
   1848 bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
   1849 {
   1850     notImplemented();
   1851     return false;
   1852 }
   1853 
   1854 void WebFrame::dispatchDidFailProvisionalLoad(const ResourceError& error)
   1855 {
   1856     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
   1857     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
   1858         COMPtr<IWebError> webError;
   1859         webError.adoptRef(WebError::createInstance(error));
   1860         frameLoadDelegate->didFailProvisionalLoadWithError(d->webView, webError.get(), this);
   1861     }
   1862 }
   1863 
   1864 void WebFrame::dispatchDidFailLoad(const ResourceError& error)
   1865 {
   1866     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
   1867     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
   1868         COMPtr<IWebError> webError;
   1869         webError.adoptRef(WebError::createInstance(error));
   1870         frameLoadDelegate->didFailLoadWithError(d->webView, webError.get(), this);
   1871     }
   1872 }
   1873 
   1874 void WebFrame::startDownload(const ResourceRequest& request)
   1875 {
   1876     d->webView->downloadURL(request.url());
   1877 }
   1878 
   1879 PassRefPtr<Widget> WebFrame::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues)
   1880 {
   1881     RefPtr<PluginView> pluginView = PluginView::create(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false);
   1882 
   1883     // Check if the plugin can be loaded successfully
   1884     if (pluginView->plugin() && pluginView->plugin()->load())
   1885         return pluginView;
   1886 
   1887     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
   1888     if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
   1889         return pluginView;
   1890 
   1891     COMPtr<CFDictionaryPropertyBag> userInfoBag = CFDictionaryPropertyBag::createInstance();
   1892 
   1893     ResourceError resourceError(String(WebKitErrorDomain), WebKitErrorJavaUnavailable, String(), String());
   1894     COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
   1895 
   1896     resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader()));
   1897 
   1898     return pluginView;
   1899 }
   1900 
   1901 ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
   1902 {
   1903     return WebCore::FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages);
   1904 }
   1905 
   1906 String WebFrame::overrideMediaType() const
   1907 {
   1908     notImplemented();
   1909     return String();
   1910 }
   1911 
   1912 void WebFrame::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
   1913 {
   1914     Frame* coreFrame = core(this);
   1915     ASSERT(coreFrame);
   1916 
   1917     Settings* settings = coreFrame->settings();
   1918     if (!settings || !settings->isJavaScriptEnabled())
   1919         return;
   1920 
   1921     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
   1922     if (FAILED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
   1923         return;
   1924 
   1925     COMPtr<IWebFrameLoadDelegatePrivate2> delegatePrivate(Query, frameLoadDelegate);
   1926     if (delegatePrivate && delegatePrivate->didClearWindowObjectForFrameInScriptWorld(d->webView, this, WebScriptWorld::findOrCreateWorld(world).get()) != E_NOTIMPL)
   1927         return;
   1928 
   1929     if (world != mainThreadNormalWorld())
   1930         return;
   1931 
   1932     JSContextRef context = toRef(coreFrame->script()->globalObject(world)->globalExec());
   1933     JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(world));
   1934     ASSERT(windowObject);
   1935 
   1936     if (FAILED(frameLoadDelegate->didClearWindowObject(d->webView, context, windowObject, this)))
   1937         frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject);
   1938 }
   1939 
   1940 void WebFrame::documentElementAvailable()
   1941 {
   1942 }
   1943 
   1944 void WebFrame::didPerformFirstNavigation() const
   1945 {
   1946     COMPtr<IWebPreferences> preferences;
   1947     if (FAILED(d->webView->preferences(&preferences)))
   1948         return;
   1949 
   1950     COMPtr<IWebPreferencesPrivate> preferencesPrivate(Query, preferences);
   1951     if (!preferencesPrivate)
   1952         return;
   1953     BOOL automaticallyDetectsCacheModel;
   1954     if (FAILED(preferencesPrivate->automaticallyDetectsCacheModel(&automaticallyDetectsCacheModel)))
   1955         return;
   1956 
   1957     WebCacheModel cacheModel;
   1958     if (FAILED(preferences->cacheModel(&cacheModel)))
   1959         return;
   1960 
   1961     if (automaticallyDetectsCacheModel && cacheModel < WebCacheModelDocumentBrowser)
   1962         preferences->setCacheModel(WebCacheModelDocumentBrowser);
   1963 }
   1964 
   1965 void WebFrame::registerForIconNotification(bool listen)
   1966 {
   1967     d->webView->registerForIconNotification(listen);
   1968 }
   1969 
   1970 static IntRect printerRect(HDC printDC)
   1971 {
   1972     return IntRect(0, 0,
   1973                    GetDeviceCaps(printDC, PHYSICALWIDTH)  - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETX),
   1974                    GetDeviceCaps(printDC, PHYSICALHEIGHT) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETY));
   1975 }
   1976 
   1977 void WebFrame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, float minPageHeight, bool adjustViewSize)
   1978 {
   1979     Frame* coreFrame = core(this);
   1980     ASSERT(coreFrame);
   1981     coreFrame->setPrinting(printing, FloatSize(minPageWidth, minPageHeight), maxPageWidth / minPageWidth, adjustViewSize ? Frame::AdjustViewSize : Frame::DoNotAdjustViewSize);
   1982 }
   1983 
   1984 HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode(
   1985     /* [in] */ BOOL value,
   1986     /* [in] */ HDC printDC)
   1987 {
   1988     if (m_inPrintingMode == !!value)
   1989         return S_OK;
   1990 
   1991     Frame* coreFrame = core(this);
   1992     if (!coreFrame || !coreFrame->document())
   1993         return E_FAIL;
   1994 
   1995     m_inPrintingMode = !!value;
   1996 
   1997     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
   1998     // according to the paper size
   1999     float minLayoutWidth = 0.0f;
   2000     float maxLayoutWidth = 0.0f;
   2001     float minLayoutHeight = 0.0f;
   2002     if (m_inPrintingMode && !coreFrame->document()->isFrameSet()) {
   2003         if (!printDC) {
   2004             ASSERT_NOT_REACHED();
   2005             return E_POINTER;
   2006         }
   2007 
   2008         const int desiredPixelsPerInch = 72;
   2009         IntRect printRect = printerRect(printDC);
   2010         int paperHorizontalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSX);
   2011         int paperWidth = printRect.width() * desiredPixelsPerInch / paperHorizontalPixelsPerInch;
   2012         int paperVerticalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSY);
   2013         int paperHeight = printRect.height() * desiredPixelsPerInch / paperVerticalPixelsPerInch;
   2014         minLayoutWidth = paperWidth * PrintingMinimumShrinkFactor;
   2015         maxLayoutWidth = paperWidth * PrintingMaximumShrinkFactor;
   2016         minLayoutHeight = paperHeight * PrintingMinimumShrinkFactor;
   2017     }
   2018 
   2019     setPrinting(m_inPrintingMode, minLayoutWidth, maxLayoutWidth, minLayoutHeight, true);
   2020 
   2021     if (!m_inPrintingMode)
   2022         m_pageRects.clear();
   2023 
   2024     return S_OK;
   2025 }
   2026 
   2027 void WebFrame::headerAndFooterHeights(float* headerHeight, float* footerHeight)
   2028 {
   2029     if (headerHeight)
   2030         *headerHeight = 0;
   2031     if (footerHeight)
   2032         *footerHeight = 0;
   2033     float height = 0;
   2034     COMPtr<IWebUIDelegate> ui;
   2035     if (FAILED(d->webView->uiDelegate(&ui)))
   2036         return;
   2037     if (headerHeight && SUCCEEDED(ui->webViewHeaderHeight(d->webView, &height)))
   2038         *headerHeight = height;
   2039     if (footerHeight && SUCCEEDED(ui->webViewFooterHeight(d->webView, &height)))
   2040         *footerHeight = height;
   2041 }
   2042 
   2043 IntRect WebFrame::printerMarginRect(HDC printDC)
   2044 {
   2045     IntRect emptyRect(0, 0, 0, 0);
   2046 
   2047     COMPtr<IWebUIDelegate> ui;
   2048     if (FAILED(d->webView->uiDelegate(&ui)))
   2049         return emptyRect;
   2050 
   2051     RECT rect;
   2052     if (FAILED(ui->webViewPrintingMarginRect(d->webView, &rect)))
   2053         return emptyRect;
   2054 
   2055     rect.left = MulDiv(rect.left, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
   2056     rect.top = MulDiv(rect.top, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
   2057     rect.right = MulDiv(rect.right, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
   2058     rect.bottom = MulDiv(rect.bottom, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
   2059 
   2060     return IntRect(rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top);
   2061 }
   2062 
   2063 const Vector<WebCore::IntRect>& WebFrame::computePageRects(HDC printDC)
   2064 {
   2065     ASSERT(m_inPrintingMode);
   2066 
   2067     Frame* coreFrame = core(this);
   2068     ASSERT(coreFrame);
   2069     ASSERT(coreFrame->document());
   2070 
   2071     if (!printDC)
   2072         return m_pageRects;
   2073 
   2074     // adjust the page rect by the header and footer
   2075     float headerHeight = 0, footerHeight = 0;
   2076     headerAndFooterHeights(&headerHeight, &footerHeight);
   2077     IntRect pageRect = printerRect(printDC);
   2078     IntRect marginRect = printerMarginRect(printDC);
   2079     IntRect adjustedRect = IntRect(
   2080         pageRect.x() + marginRect.x(),
   2081         pageRect.y() + marginRect.y(),
   2082         pageRect.width() - marginRect.x() - marginRect.maxX(),
   2083         pageRect.height() - marginRect.y() - marginRect.maxY());
   2084 
   2085     computePageRectsForFrame(coreFrame, adjustedRect, headerHeight, footerHeight, 1.0,m_pageRects, m_pageHeight);
   2086 
   2087     return m_pageRects;
   2088 }
   2089 
   2090 HRESULT STDMETHODCALLTYPE WebFrame::getPrintedPageCount(
   2091     /* [in] */ HDC printDC,
   2092     /* [retval][out] */ UINT *pageCount)
   2093 {
   2094     if (!pageCount || !printDC) {
   2095         ASSERT_NOT_REACHED();
   2096         return E_POINTER;
   2097     }
   2098 
   2099     *pageCount = 0;
   2100 
   2101     if (!m_inPrintingMode) {
   2102         ASSERT_NOT_REACHED();
   2103         return E_FAIL;
   2104     }
   2105 
   2106     Frame* coreFrame = core(this);
   2107     if (!coreFrame || !coreFrame->document())
   2108         return E_FAIL;
   2109 
   2110     const Vector<IntRect>& pages = computePageRects(printDC);
   2111     *pageCount = (UINT) pages.size();
   2112 
   2113     return S_OK;
   2114 }
   2115 
   2116 #if USE(CG)
   2117 void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
   2118 {
   2119     int x = pageRect.x();
   2120     int y = 0;
   2121     RECT headerRect = {x, y, x+pageRect.width(), y+static_cast<int>(headerHeight)};
   2122     ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)));
   2123 }
   2124 
   2125 void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
   2126 {
   2127     int x = pageRect.x();
   2128     int y = max((int)headerHeight+pageRect.height(), m_pageHeight-static_cast<int>(footerHeight));
   2129     RECT footerRect = {x, y, x+pageRect.width(), y+static_cast<int>(footerHeight)};
   2130     ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)), page+1, pageCount);
   2131 }
   2132 
   2133 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
   2134 {
   2135     Frame* coreFrame = core(this);
   2136 
   2137     IntRect pageRect = m_pageRects[page];
   2138 
   2139     CGContextSaveGState(pctx);
   2140 
   2141     IntRect printRect = printerRect(printDC);
   2142     CGRect mediaBox = CGRectMake(CGFloat(0),
   2143                                  CGFloat(0),
   2144                                  CGFloat(printRect.width()),
   2145                                  CGFloat(printRect.height()));
   2146 
   2147     CGContextBeginPage(pctx, &mediaBox);
   2148 
   2149     CGFloat scale = static_cast<float>(mediaBox.size.width)/static_cast<float>(pageRect.width());
   2150     CGAffineTransform ctm = CGContextGetBaseCTM(pctx);
   2151     ctm = CGAffineTransformScale(ctm, -scale, -scale);
   2152     ctm = CGAffineTransformTranslate(ctm, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
   2153     CGContextScaleCTM(pctx, scale, scale);
   2154     CGContextTranslateCTM(pctx, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight));   // reserves space for header
   2155     CGContextSetBaseCTM(pctx, ctm);
   2156 
   2157     coreFrame->view()->paintContents(spoolCtx, pageRect);
   2158 
   2159     CGContextTranslateCTM(pctx, CGFloat(pageRect.x()), CGFloat(pageRect.y())-headerHeight);
   2160 
   2161     if (headerHeight)
   2162         drawHeader(pctx, ui, pageRect, headerHeight);
   2163 
   2164     if (footerHeight)
   2165         drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
   2166 
   2167     CGContextEndPage(pctx);
   2168     CGContextRestoreGState(pctx);
   2169 }
   2170 #elif USE(CAIRO)
   2171 static float scaleFactor(HDC printDC, const IntRect& marginRect, const IntRect& pageRect)
   2172 {
   2173     const IntRect& printRect = printerRect(printDC);
   2174 
   2175     IntRect adjustedRect = IntRect(
   2176         printRect.x() + marginRect.x(),
   2177         printRect.y() + marginRect.y(),
   2178         printRect.width() - marginRect.x() - marginRect.maxX(),
   2179         printRect.height() - marginRect.y() - marginRect.maxY());
   2180 
   2181     float scale = static_cast<float>(adjustedRect.width()) / static_cast<float>(pageRect.width());
   2182     if (!scale)
   2183        scale = 1.0;
   2184 
   2185     return scale;
   2186 }
   2187 
   2188 static HDC hdcFromContext(PlatformGraphicsContext* pctx)
   2189 {
   2190     return cairo_win32_surface_get_dc(cairo_get_target(pctx->cr()));
   2191 }
   2192 
   2193 void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
   2194 {
   2195     HDC hdc = hdcFromContext(pctx);
   2196 
   2197     int x = pageRect.x();
   2198     int y = 0;
   2199     RECT headerRect = {x, y, x + pageRect.width(), y + static_cast<int>(headerHeight)};
   2200 
   2201     ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc)));
   2202 }
   2203 
   2204 void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
   2205 {
   2206     HDC hdc = hdcFromContext(pctx);
   2207 
   2208     int x = pageRect.x();
   2209     int y = max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight  -static_cast<int>(footerHeight));
   2210     RECT footerRect = {x, y, x + pageRect.width(), y + static_cast<int>(footerHeight)};
   2211 
   2212     ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc)), page+1, pageCount);
   2213 }
   2214 
   2215 static XFORM buildXFORMFromCairo(HDC targetDC, cairo_t* previewContext)
   2216 {
   2217     XFORM scaled;
   2218     GetWorldTransform(targetDC, &scaled);
   2219 
   2220     cairo_matrix_t ctm;
   2221     cairo_get_matrix(previewContext, &ctm);
   2222 
   2223     // Scale to the preview screen bounds
   2224     scaled.eM11 = ctm.xx;
   2225     scaled.eM22 = ctm.yy;
   2226 
   2227     return scaled;
   2228 }
   2229 
   2230 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
   2231 {
   2232     Frame* coreFrame = core(this);
   2233 
   2234     const IntRect& pageRect = m_pageRects[page];
   2235     const IntRect& marginRect = printerMarginRect(printDC);
   2236 
   2237     // In preview, the printDC is a placeholder, so just always use the HDC backing the graphics context.
   2238     HDC hdc = hdcFromContext(pctx);
   2239 
   2240     spoolCtx->save();
   2241 
   2242     XFORM original, scaled;
   2243     GetWorldTransform(hdc, &original);
   2244 
   2245     cairo_t* cr = pctx->cr();
   2246     bool preview = (hdc != printDC);
   2247     if (preview) {
   2248         // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo will
   2249         // draw correctly.  We need to retain the correct preview scale here for use when the Cairo
   2250         // drawing completes so that we can scale our GDI-based header/footer calls. This is a
   2251         // workaround for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
   2252         scaled = buildXFORMFromCairo(hdc, cr);
   2253     }
   2254 
   2255     float scale = scaleFactor(printDC, marginRect, pageRect);
   2256 
   2257     IntRect cairoMarginRect(marginRect);
   2258     cairoMarginRect.scale(1 / scale);
   2259 
   2260     // We cannot scale the display HDC because the print surface also scales fonts,
   2261     // resulting in invalid printing (and print preview)
   2262     cairo_scale(cr, scale, scale);
   2263     cairo_translate(cr, cairoMarginRect.x(), cairoMarginRect.y() + headerHeight);
   2264 
   2265     // Modify Cairo (only) to account for page position.
   2266     cairo_translate(cr, -pageRect.x(), -pageRect.y());
   2267     coreFrame->view()->paintContents(spoolCtx, pageRect);
   2268     cairo_translate(cr, pageRect.x(), pageRect.y());
   2269 
   2270     if (preview) {
   2271         // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo would
   2272         // draw correctly.  We need to rescale the HDC to the correct preview scale so our GDI-based
   2273         // header/footer calls will draw properly.  This is a workaround for a bug in Cairo.
   2274         // (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
   2275         SetWorldTransform(hdc, &scaled);
   2276     }
   2277 
   2278     XFORM xform = TransformationMatrix().translate(marginRect.x(), marginRect.y()).scale(scale);
   2279     ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
   2280 
   2281     if (headerHeight)
   2282         drawHeader(pctx, ui, pageRect, headerHeight);
   2283 
   2284     if (footerHeight)
   2285         drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
   2286 
   2287     SetWorldTransform(hdc, &original);
   2288 
   2289     cairo_show_page(cr);
   2290     ASSERT(!cairo_status(cr));
   2291     spoolCtx->restore();
   2292 }
   2293 
   2294 static void setCairoTransformToPreviewHDC(cairo_t* previewCtx, HDC previewDC)
   2295 {
   2296     XFORM passedCTM;
   2297     GetWorldTransform(previewDC, &passedCTM);
   2298 
   2299     // Reset HDC WorldTransform to unscaled state.  Scaling must be
   2300     // done in Cairo to avoid drawing errors.
   2301     XFORM unscaledCTM = passedCTM;
   2302     unscaledCTM.eM11 = 1.0;
   2303     unscaledCTM.eM22 = 1.0;
   2304 
   2305     SetWorldTransform(previewDC, &unscaledCTM);
   2306 
   2307     // Make the Cairo transform match the information passed to WebKit
   2308     // in the HDC's WorldTransform.
   2309     cairo_matrix_t ctm = { passedCTM.eM11, passedCTM.eM12, passedCTM.eM21,
   2310                            passedCTM.eM22, passedCTM.eDx, passedCTM.eDy };
   2311 
   2312     cairo_set_matrix(previewCtx, &ctm);
   2313 }
   2314 
   2315 #endif
   2316 
   2317 HRESULT STDMETHODCALLTYPE WebFrame::spoolPages(
   2318     /* [in] */ HDC printDC,
   2319     /* [in] */ UINT startPage,
   2320     /* [in] */ UINT endPage,
   2321     /* [retval][out] */ void* ctx)
   2322 {
   2323 #if USE(CG)
   2324     if (!printDC || !ctx) {
   2325         ASSERT_NOT_REACHED();
   2326         return E_POINTER;
   2327     }
   2328 #elif USE(CAIRO)
   2329     if (!printDC) {
   2330         ASSERT_NOT_REACHED();
   2331         return E_POINTER;
   2332     }
   2333 
   2334     HDC targetDC = (ctx) ? (HDC)ctx : printDC;
   2335 
   2336     cairo_surface_t* printSurface = 0;
   2337     if (ctx)
   2338         printSurface = cairo_win32_surface_create(targetDC); // in-memory
   2339     else
   2340         printSurface = cairo_win32_printing_surface_create(targetDC); // metafile
   2341 
   2342     cairo_t* cr = cairo_create(printSurface);
   2343     if (!cr) {
   2344         cairo_surface_destroy(printSurface);
   2345         return E_FAIL;
   2346     }
   2347 
   2348     PlatformContextCairo platformContext(cr);
   2349     PlatformGraphicsContext* pctx = &platformContext;
   2350     cairo_destroy(cr);
   2351 
   2352     if (ctx) {
   2353         // If this is a preview, the Windows HDC was sent with scaling information.
   2354         // Retrieve it and reset it so that it draws properly.  This is a workaround
   2355         // for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
   2356         setCairoTransformToPreviewHDC(cr, targetDC);
   2357     }
   2358 
   2359     cairo_surface_set_fallback_resolution(printSurface, 72.0, 72.0);
   2360 #endif
   2361 
   2362     if (!m_inPrintingMode) {
   2363         ASSERT_NOT_REACHED();
   2364         return E_FAIL;
   2365     }
   2366 
   2367     Frame* coreFrame = core(this);
   2368     if (!coreFrame || !coreFrame->document())
   2369         return E_FAIL;
   2370 
   2371     UINT pageCount = (UINT) m_pageRects.size();
   2372 #if USE(CG)
   2373     PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx;
   2374 #endif
   2375 
   2376     if (!pageCount || startPage > pageCount) {
   2377         ASSERT_NOT_REACHED();
   2378         return E_FAIL;
   2379     }
   2380 
   2381     if (startPage > 0)
   2382         startPage--;
   2383 
   2384     if (endPage == 0)
   2385         endPage = pageCount;
   2386 
   2387     COMPtr<IWebUIDelegate> ui;
   2388     if (FAILED(d->webView->uiDelegate(&ui)))
   2389         return E_FAIL;
   2390 
   2391     float headerHeight = 0, footerHeight = 0;
   2392     headerAndFooterHeights(&headerHeight, &footerHeight);
   2393     GraphicsContext spoolCtx(pctx);
   2394     spoolCtx.setShouldIncludeChildWindows(true);
   2395 
   2396     for (UINT ii = startPage; ii < endPage; ii++)
   2397         spoolPage(pctx, &spoolCtx, printDC, ui.get(), headerHeight, footerHeight, ii, pageCount);
   2398 
   2399 #if USE(CAIRO)
   2400     cairo_surface_finish(printSurface);
   2401     ASSERT(!cairo_surface_status(printSurface));
   2402     cairo_surface_destroy(printSurface);
   2403 #endif
   2404 
   2405     return S_OK;
   2406 }
   2407 
   2408 HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet(
   2409     /* [retval][out] */ BOOL* result)
   2410 {
   2411     *result = FALSE;
   2412 
   2413     Frame* coreFrame = core(this);
   2414     if (!coreFrame || !coreFrame->document())
   2415         return E_FAIL;
   2416 
   2417     *result = coreFrame->document()->isFrameSet() ? TRUE : FALSE;
   2418     return S_OK;
   2419 }
   2420 
   2421 HRESULT STDMETHODCALLTYPE WebFrame::string(
   2422     /* [retval][out] */ BSTR *result)
   2423 {
   2424     *result = 0;
   2425 
   2426     Frame* coreFrame = core(this);
   2427     if (!coreFrame)
   2428         return E_FAIL;
   2429 
   2430     RefPtr<Range> allRange(rangeOfContents(coreFrame->document()));
   2431     String allString = plainText(allRange.get());
   2432     *result = BString(allString).release();
   2433     return S_OK;
   2434 }
   2435 
   2436 HRESULT STDMETHODCALLTYPE WebFrame::size(
   2437     /* [retval][out] */ SIZE *size)
   2438 {
   2439     if (!size)
   2440         return E_POINTER;
   2441     size->cx = size->cy = 0;
   2442 
   2443     Frame* coreFrame = core(this);
   2444     if (!coreFrame)
   2445         return E_FAIL;
   2446     FrameView* view = coreFrame->view();
   2447     if (!view)
   2448         return E_FAIL;
   2449     size->cx = view->width();
   2450     size->cy = view->height();
   2451     return S_OK;
   2452 }
   2453 
   2454 HRESULT STDMETHODCALLTYPE WebFrame::hasScrollBars(
   2455     /* [retval][out] */ BOOL *result)
   2456 {
   2457     if (!result)
   2458         return E_POINTER;
   2459     *result = FALSE;
   2460 
   2461     Frame* coreFrame = core(this);
   2462     if (!coreFrame)
   2463         return E_FAIL;
   2464 
   2465     FrameView* view = coreFrame->view();
   2466     if (!view)
   2467         return E_FAIL;
   2468 
   2469     if (view->horizontalScrollbar() || view->verticalScrollbar())
   2470         *result = TRUE;
   2471 
   2472     return S_OK;
   2473 }
   2474 
   2475 HRESULT STDMETHODCALLTYPE WebFrame::contentBounds(
   2476     /* [retval][out] */ RECT *result)
   2477 {
   2478     if (!result)
   2479         return E_POINTER;
   2480     ::SetRectEmpty(result);
   2481 
   2482     Frame* coreFrame = core(this);
   2483     if (!coreFrame)
   2484         return E_FAIL;
   2485 
   2486     FrameView* view = coreFrame->view();
   2487     if (!view)
   2488         return E_FAIL;
   2489 
   2490     result->bottom = view->contentsHeight();
   2491     result->right = view->contentsWidth();
   2492     return S_OK;
   2493 }
   2494 
   2495 HRESULT STDMETHODCALLTYPE WebFrame::frameBounds(
   2496     /* [retval][out] */ RECT *result)
   2497 {
   2498     if (!result)
   2499         return E_POINTER;
   2500     ::SetRectEmpty(result);
   2501 
   2502     Frame* coreFrame = core(this);
   2503     if (!coreFrame)
   2504         return E_FAIL;
   2505 
   2506     FrameView* view = coreFrame->view();
   2507     if (!view)
   2508         return E_FAIL;
   2509 
   2510     FloatRect bounds = view->visibleContentRect(true);
   2511     result->bottom = (LONG) bounds.height();
   2512     result->right = (LONG) bounds.width();
   2513     return S_OK;
   2514 }
   2515 
   2516 HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame(
   2517     /* [in] */ IWebFrame *ancestor,
   2518     /* [retval][out] */ BOOL *result)
   2519 {
   2520     if (!result)
   2521         return E_POINTER;
   2522     *result = FALSE;
   2523 
   2524     Frame* coreFrame = core(this);
   2525     COMPtr<WebFrame> ancestorWebFrame(Query, ancestor);
   2526     if (!ancestorWebFrame)
   2527         return S_OK;
   2528 
   2529     *result = (coreFrame && coreFrame->tree()->isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE;
   2530     return S_OK;
   2531 }
   2532 
   2533 HRESULT WebFrame::stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld* iWorld, JSObjectRef globalObjectRef, BSTR script, BSTR* evaluationResult)
   2534 {
   2535     if (!evaluationResult)
   2536         return E_POINTER;
   2537     *evaluationResult = 0;
   2538 
   2539     if (!iWorld)
   2540         return E_POINTER;
   2541 
   2542     COMPtr<WebScriptWorld> world(Query, iWorld);
   2543     if (!world)
   2544         return E_INVALIDARG;
   2545 
   2546     Frame* coreFrame = core(this);
   2547     String string = String(script, SysStringLen(script));
   2548 
   2549     // Start off with some guess at a frame and a global object, we'll try to do better...!
   2550     JSDOMWindow* anyWorldGlobalObject = coreFrame->script()->globalObject(mainThreadNormalWorld());
   2551 
   2552     // The global object is probably a shell object? - if so, we know how to use this!
   2553     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
   2554     if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
   2555         anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
   2556 
   2557     // Get the frame frome the global object we've settled on.
   2558     Frame* frame = anyWorldGlobalObject->impl()->frame();
   2559     ASSERT(frame->document());
   2560     JSValue result = frame->script()->executeScriptInWorld(world->world(), string, true).jsValue();
   2561 
   2562     if (!frame) // In case the script removed our frame from the page.
   2563         return S_OK;
   2564 
   2565     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
   2566     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
   2567     // JSEvaluateScript instead, since they have less surprising semantics.
   2568     if (!result || !result.isBoolean() && !result.isString() && !result.isNumber())
   2569         return S_OK;
   2570 
   2571     JSLock lock(SilenceAssertionsOnly);
   2572     String resultString = ustringToString(result.toString(anyWorldGlobalObject->globalExec()));
   2573     *evaluationResult = BString(resultString).release();
   2574 
   2575     return S_OK;
   2576 }
   2577 
   2578 void WebFrame::unmarkAllMisspellings()
   2579 {
   2580     Frame* coreFrame = core(this);
   2581     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
   2582         Document *doc = frame->document();
   2583         if (!doc)
   2584             return;
   2585 
   2586         doc->markers()->removeMarkers(DocumentMarker::Spelling);
   2587     }
   2588 }
   2589 
   2590 void WebFrame::unmarkAllBadGrammar()
   2591 {
   2592     Frame* coreFrame = core(this);
   2593     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
   2594         Document *doc = frame->document();
   2595         if (!doc)
   2596             return;
   2597 
   2598         doc->markers()->removeMarkers(DocumentMarker::Grammar);
   2599     }
   2600 }
   2601 
   2602 WebView* WebFrame::webView() const
   2603 {
   2604     return d->webView;
   2605 }
   2606 
   2607 void WebFrame::setWebView(WebView* webView)
   2608 {
   2609     d->webView = webView;
   2610 }
   2611 
   2612 COMPtr<IAccessible> WebFrame::accessible() const
   2613 {
   2614     Frame* coreFrame = core(this);
   2615     ASSERT(coreFrame);
   2616 
   2617     Document* currentDocument = coreFrame->document();
   2618     if (!currentDocument)
   2619         m_accessible = 0;
   2620     else if (!m_accessible || m_accessible->document() != currentDocument) {
   2621         // Either we've never had a wrapper for this frame's top-level Document,
   2622         // the Document renderer was destroyed and its wrapper was detached, or
   2623         // the previous Document is in the page cache, and the current document
   2624         // needs to be wrapped.
   2625         m_accessible = new AccessibleDocument(currentDocument);
   2626     }
   2627     return m_accessible.get();
   2628 }
   2629 
   2630 void WebFrame::updateBackground()
   2631 {
   2632     Color backgroundColor = webView()->transparent() ? Color::transparent : Color::white;
   2633     Frame* coreFrame = core(this);
   2634 
   2635     if (!coreFrame || !coreFrame->view())
   2636         return;
   2637 
   2638     coreFrame->view()->updateBackgroundRecursively(backgroundColor, webView()->transparent());
   2639 }
   2640 
   2641 PassRefPtr<FrameNetworkingContext> WebFrame::createNetworkingContext()
   2642 {
   2643     return WebFrameNetworkingContext::create(core(this), userAgent(url()));
   2644 }
   2645