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