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
115extern "C" {
116    CGAffineTransform CGContextGetBaseCTM(CGContextRef c);
117    void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m);
118}
119#endif
120
121using namespace WebCore;
122using namespace HTMLNames;
123using namespace std;
124
125using JSC::JSGlobalObject;
126using JSC::JSLock;
127using JSC::JSValue;
128using 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.
138const 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)
144const float PrintingMaximumShrinkFactor = 2.0f;
145
146//-----------------------------------------------------------------------------
147// Helpers to convert from WebCore to WebKit type
148WebFrame* 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
159Frame* 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
167Frame* core(const WebFrame* webFrame)
168{
169    if (!webFrame)
170        return 0;
171    return const_cast<WebFrame*>(webFrame)->impl();
172}
173
174//-----------------------------------------------------------------------------
175
176static 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
192static 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
209static 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
228class WebFrame::WebFramePrivate {
229public:
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
248WebFrame::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
261WebFrame::~WebFrame()
262{
263    delete d;
264    WebFrameCount--;
265    gClassCount--;
266    gClassNameCount.remove("WebFrame");
267}
268
269WebFrame* WebFrame::createInstance()
270{
271    WebFrame* instance = new WebFrame();
272    instance->AddRef();
273    return instance;
274}
275
276HRESULT 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
286HRESULT 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
297HRESULT 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
308HRESULT 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
319HRESULT 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
329HRESULT 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
363HRESULT 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
383ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
384{
385    return ++m_refCount;
386}
387
388ULONG 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
399HRESULT 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
417HRESULT 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
428HRESULT STDMETHODCALLTYPE WebFrame::frameView(
429    /* [retval][out] */ IWebFrameView** /*view*/)
430{
431    ASSERT_NOT_REACHED();
432    return E_NOTIMPL;
433}
434
435HRESULT 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
452HRESULT 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
470HRESULT 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
487JSGlobalContextRef 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
496JSGlobalContextRef 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
509HRESULT 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
526void 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
550HRESULT 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
574void 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
581HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString(
582    /* [in] */ BSTR string,
583    /* [in] */ BSTR baseURL)
584{
585    loadHTMLString(string, baseURL, 0);
586    return S_OK;
587}
588
589HRESULT 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
598HRESULT STDMETHODCALLTYPE WebFrame::loadArchive(
599    /* [in] */ IWebArchive* /*archive*/)
600{
601    ASSERT_NOT_REACHED();
602    return E_NOTIMPL;
603}
604
605static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
606{
607    return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
608}
609
610HRESULT 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
634HRESULT 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
658KURL WebFrame::url() const
659{
660    Frame* coreFrame = core(this);
661    if (!coreFrame)
662        return KURL();
663
664    return coreFrame->loader()->url();
665}
666
667HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
668{
669    if (Frame* coreFrame = core(this))
670        coreFrame->loader()->stopAllLoaders();
671    return S_OK;
672}
673
674HRESULT 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
684HRESULT 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
710HRESULT 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
722class EnumChildFrames : public IEnumVARIANT
723{
724public:
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
801private:
802    ULONG m_refCount;
803    Frame* m_frame;
804    Frame* m_curChild;
805};
806
807HRESULT 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
819HRESULT 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
833HRESULT 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
852HRESULT 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
872HRESULT 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
886HRESULT 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
904HRESULT 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
922HRESULT 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
940HRESULT 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
965HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding(
966    /* [retval][out] */ BOOL* result)
967{
968    *result = FALSE;
969    return E_NOTIMPL;
970}
971
972HRESULT 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
987HRESULT 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
999HRESULT STDMETHODCALLTYPE WebFrame::deselectAll()
1000{
1001    return E_NOTIMPL;
1002}
1003
1004// WebFrame ---------------------------------------------------------------
1005
1006PassRefPtr<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
1020Frame* WebFrame::impl()
1021{
1022    return d->frame;
1023}
1024
1025void 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
1034void WebFrame::setTextSizeMultiplier(float multiplier)
1035{
1036    Frame* coreFrame = core(this);
1037    ASSERT(coreFrame);
1038    coreFrame->setZoomFactor(multiplier, true);
1039}
1040
1041HRESULT 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
1058HRESULT 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
1068HRESULT 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
1089HRESULT 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
1106HRESULT 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
1121HRESULT 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
1144HRESULT 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
1167HRESULT 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
1195HRESULT 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
1214HRESULT 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
1230HRESULT 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
1245HRESULT 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
1273HRESULT 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
1281HRESULT 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
1325HRESULT 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
1358HRESULT 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
1381void 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
1390void WebFrame::makeRepresentation(DocumentLoader*)
1391{
1392    notImplemented();
1393}
1394
1395void WebFrame::forceLayoutForNonHTML()
1396{
1397    notImplemented();
1398}
1399
1400void WebFrame::setCopiesOnScroll()
1401{
1402    notImplemented();
1403}
1404
1405void WebFrame::detachedFromParent2()
1406{
1407    notImplemented();
1408}
1409
1410void WebFrame::detachedFromParent3()
1411{
1412    notImplemented();
1413}
1414
1415void 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
1425void 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
1455void WebFrame::revertToProvisionalState(DocumentLoader*)
1456{
1457    notImplemented();
1458}
1459
1460void WebFrame::setMainFrameDocumentReady(bool)
1461{
1462    notImplemented();
1463}
1464
1465void WebFrame::willChangeTitle(DocumentLoader*)
1466{
1467    notImplemented();
1468}
1469
1470void WebFrame::didChangeTitle(DocumentLoader*)
1471{
1472    notImplemented();
1473}
1474
1475bool WebFrame::canHandleRequest(const ResourceRequest& request) const
1476{
1477    return WebView::canHandleRequest(request);
1478}
1479
1480bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const
1481{
1482    notImplemented();
1483    return true;
1484}
1485
1486bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const
1487{
1488    notImplemented();
1489    return false;
1490}
1491
1492String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1493{
1494    notImplemented();
1495    ASSERT_NOT_REACHED();
1496    return String();
1497}
1498
1499void WebFrame::frameLoadCompleted()
1500{
1501}
1502
1503void WebFrame::restoreViewState()
1504{
1505}
1506
1507void WebFrame::provisionalLoadStarted()
1508{
1509    notImplemented();
1510}
1511
1512bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const
1513{
1514    notImplemented();
1515    return false;
1516}
1517
1518void WebFrame::addHistoryItemForFragmentScroll()
1519{
1520    notImplemented();
1521}
1522
1523void WebFrame::didFinishLoad()
1524{
1525    notImplemented();
1526}
1527
1528void WebFrame::prepareForDataSourceReplacement()
1529{
1530    notImplemented();
1531}
1532
1533String WebFrame::userAgent(const KURL& url)
1534{
1535    return d->webView->userAgentForKURL(url);
1536}
1537
1538void WebFrame::saveViewStateToItem(HistoryItem*)
1539{
1540}
1541
1542ResourceError 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
1549ResourceError 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
1555ResourceError 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
1561ResourceError 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
1567ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&)
1568{
1569    notImplemented();
1570    return ResourceError();
1571}
1572
1573ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&)
1574{
1575    notImplemented();
1576    return ResourceError();
1577}
1578
1579ResourceError WebFrame::pluginWillHandleLoadError(const ResourceResponse& response)
1580{
1581    return ResourceError(String(WebKitErrorDomain), WebKitErrorPlugInWillHandleLoad, response.url().string(), String());
1582}
1583
1584bool WebFrame::shouldFallBack(const ResourceError& error)
1585{
1586    return error.errorCode() != WebURLErrorCancelled;
1587}
1588
1589COMPtr<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
1605void 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
1621void 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
1638void 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
1656void 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
1674void 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
1684void 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
1703bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
1704{
1705    notImplemented();
1706    return false;
1707}
1708
1709void 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
1719void 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
1729void WebFrame::startDownload(const ResourceRequest& request)
1730{
1731    d->webView->downloadURL(request.url());
1732}
1733
1734PassRefPtr<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
1756ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeType)
1757{
1758    return WebCore::FrameLoader::defaultObjectContentType(url, mimeType);
1759}
1760
1761String WebFrame::overrideMediaType() const
1762{
1763    notImplemented();
1764    return String();
1765}
1766
1767void 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
1795void WebFrame::documentElementAvailable()
1796{
1797}
1798
1799void 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
1820void WebFrame::registerForIconNotification(bool listen)
1821{
1822    d->webView->registerForIconNotification(listen);
1823}
1824
1825static 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
1832void 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
1839HRESULT 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
1877void 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
1893IntRect 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
1913const 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
1940HRESULT 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)
1967void 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
1975void 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
1983void 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)
2021static 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
2038static HDC hdcFromContext(PlatformGraphicsContext* pctx)
2039{
2040    cairo_surface_t* surface = cairo_get_target(pctx);
2041    return cairo_win32_surface_get_dc(surface);
2042}
2043
2044void 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
2057void 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
2070void 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
2121HRESULT 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
2192HRESULT 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
2205HRESULT 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
2220HRESULT 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
2238HRESULT 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
2259HRESULT 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
2279HRESULT 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
2300HRESULT 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
2317HRESULT 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
2362void 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
2374void 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
2386WebView* WebFrame::webView() const
2387{
2388    return d->webView;
2389}
2390
2391COMPtr<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
2409void 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