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