1/*
2 * Copyright (C) 2006-2009, 2011, 2013 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 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 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 "HTMLFrameOwnerElement.h"
35#include "MarshallingHelpers.h"
36#include "WebActionPropertyBag.h"
37#include "WebChromeClient.h"
38#include "WebDataSource.h"
39#include "WebDocumentLoader.h"
40#include "WebDownload.h"
41#include "WebEditorClient.h"
42#include "WebError.h"
43#include "WebFrameLoaderClient.h"
44#include "WebFramePolicyListener.h"
45#include "WebHistory.h"
46#include "WebHistoryItem.h"
47#include "WebKit.h"
48#include "WebKitStatisticsPrivate.h"
49#include "WebMutableURLRequest.h"
50#include "WebNotificationCenter.h"
51#include "WebScriptWorld.h"
52#include "WebURLResponse.h"
53#include "WebView.h"
54#include <WebCore/AnimationController.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/Editor.h>
64#include <WebCore/Event.h>
65#include <WebCore/EventHandler.h>
66#include <WebCore/FormState.h>
67#include <WebCore/FrameLoader.h>
68#include <WebCore/FrameLoadRequest.h>
69#include <WebCore/FrameTree.h>
70#include <WebCore/FrameView.h>
71#include <WebCore/FrameWin.h>
72#include <WebCore/GDIObjectCounter.h>
73#include <WebCore/GraphicsContext.h>
74#include <WebCore/HistoryItem.h>
75#include <WebCore/HTMLAppletElement.h>
76#include <WebCore/HTMLFormElement.h>
77#include <WebCore/HTMLFormControlElement.h>
78#include <WebCore/HTMLInputElement.h>
79#include <WebCore/HTMLNames.h>
80#include <WebCore/HTMLPlugInElement.h>
81#include <WebCore/JSDOMWindow.h>
82#include <WebCore/KeyboardEvent.h>
83#include <WebCore/MainFrame.h>
84#include <WebCore/MouseRelatedEvent.h>
85#include <WebCore/NotImplemented.h>
86#include <WebCore/Page.h>
87#include <WebCore/PlatformKeyboardEvent.h>
88#include <WebCore/PluginData.h>
89#include <WebCore/PluginDatabase.h>
90#include <WebCore/PluginView.h>
91#include <WebCore/PolicyChecker.h>
92#include <WebCore/PrintContext.h>
93#include <WebCore/ResourceHandle.h>
94#include <WebCore/ResourceLoader.h>
95#include <WebCore/ResourceRequest.h>
96#include <WebCore/RenderView.h>
97#include <WebCore/RenderTreeAsText.h>
98#include <WebCore/Settings.h>
99#include <WebCore/TextIterator.h>
100#include <WebCore/JSDOMBinding.h>
101#include <WebCore/ScriptController.h>
102#include <WebCore/SecurityOrigin.h>
103#include <JavaScriptCore/APICast.h>
104#include <JavaScriptCore/JSCJSValue.h>
105#include <JavaScriptCore/JSLock.h>
106#include <JavaScriptCore/JSObject.h>
107#include <bindings/ScriptValue.h>
108#include <wtf/MathExtras.h>
109
110#if USE(CG)
111#include <CoreGraphics/CoreGraphics.h>
112#elif USE(CAIRO)
113#include "PlatformContextCairo.h"
114#include <cairo-win32.h>
115#endif
116
117#if USE(CG)
118// CG SPI used for printing
119extern "C" {
120    CGAffineTransform CGContextGetBaseCTM(CGContextRef c);
121    void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m);
122}
123#endif
124
125using namespace WebCore;
126using namespace HTMLNames;
127using namespace std;
128
129using JSC::JSGlobalObject;
130using JSC::JSLock;
131using JSC::JSValue;
132
133#define FLASH_REDRAW 0
134
135
136// By imaging to a width a little wider than the available pixels,
137// thin pages will be scaled down a little, matching the way they
138// print in IE and Camino. This lets them use fewer sheets than they
139// would otherwise, which is presumably why other browsers do this.
140// Wide pages will be scaled down more than this.
141const float PrintingMinimumShrinkFactor = 1.25f;
142
143// This number determines how small we are willing to reduce the page content
144// in order to accommodate the widest line. If the page would have to be
145// reduced smaller to make the widest line fit, we just clip instead (this
146// behavior matches MacIE and Mozilla, at least)
147const float PrintingMaximumShrinkFactor = 2.0f;
148
149//-----------------------------------------------------------------------------
150// Helpers to convert from WebCore to WebKit type
151WebFrame* kit(Frame* frame)
152{
153    if (!frame)
154        return 0;
155
156    // FIXME: Doesn't this need to be aware of EmptyFrameLoaderClient?
157    FrameLoaderClient& frameLoaderClient = frame->loader().client();
158    return static_cast<WebFrameLoaderClient&>(frameLoaderClient).webFrame();
159}
160
161Frame* core(WebFrame* webFrame)
162{
163    if (!webFrame)
164        return 0;
165    return webFrame->impl();
166}
167
168// 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
169Frame* core(const WebFrame* webFrame)
170{
171    if (!webFrame)
172        return 0;
173    return const_cast<WebFrame*>(webFrame)->impl();
174}
175
176//-----------------------------------------------------------------------------
177
178static Element *elementFromDOMElement(IDOMElement *element)
179{
180    if (!element)
181        return 0;
182
183    COMPtr<IDOMElementPrivate> elePriv;
184    HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
185    if (SUCCEEDED(hr)) {
186        Element* ele;
187        hr = elePriv->coreElement((void**)&ele);
188        if (SUCCEEDED(hr))
189            return ele;
190    }
191    return 0;
192}
193
194static HTMLFormElement *formElementFromDOMElement(IDOMElement *element)
195{
196    if (!element)
197        return 0;
198
199    IDOMElementPrivate* elePriv;
200    HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
201    if (SUCCEEDED(hr)) {
202        Element* ele;
203        hr = elePriv->coreElement((void**)&ele);
204        elePriv->Release();
205        if (SUCCEEDED(hr) && ele && isHTMLFormElement(ele))
206            return toHTMLFormElement(ele);
207    }
208    return 0;
209}
210
211static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element)
212{
213    if (!element)
214        return 0;
215
216    IDOMElementPrivate* elePriv;
217    HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
218    if (SUCCEEDED(hr)) {
219        Element* ele;
220        hr = elePriv->coreElement((void**)&ele);
221        elePriv->Release();
222        if (SUCCEEDED(hr) && ele && isHTMLInputElement(ele))
223            return toHTMLInputElement(ele);
224    }
225    return 0;
226}
227
228// WebFramePrivate ------------------------------------------------------------
229
230class WebFrame::WebFramePrivate {
231public:
232    WebFramePrivate()
233        : frame(0)
234        , webView(0)
235    {
236    }
237
238    ~WebFramePrivate() { }
239    FrameView* frameView() { return frame ? frame->view() : 0; }
240
241    Frame* frame;
242    WebView* webView;
243};
244
245// WebFrame ----------------------------------------------------------------
246
247WebFrame::WebFrame()
248    : m_refCount(0)
249    , d(new WebFrame::WebFramePrivate)
250    , m_quickRedirectComing(false)
251    , m_inPrintingMode(false)
252    , m_pageHeight(0)
253{
254    WebFrameCount++;
255    gClassCount++;
256    gClassNameCount.add("WebFrame");
257}
258
259WebFrame::~WebFrame()
260{
261    delete d;
262    WebFrameCount--;
263    gClassCount--;
264    gClassNameCount.remove("WebFrame");
265}
266
267WebFrame* WebFrame::createInstance()
268{
269    WebFrame* instance = new WebFrame();
270    instance->AddRef();
271    return instance;
272}
273
274HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling(
275    /* [in] */ BOOL flag)
276{
277    if (Frame* frame = core(this))
278        if (FrameView* view = frame->view())
279            view->setCanHaveScrollbars(!!flag);
280
281    return S_OK;
282}
283
284HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling(
285    /* [retval][out] */ BOOL *flag)
286{
287    if (flag)
288        if (Frame* frame = core(this))
289            if (FrameView* view = frame->view())
290                *flag = view->canHaveScrollbars();
291
292    return S_OK;
293}
294
295HRESULT STDMETHODCALLTYPE WebFrame::setIsDisconnected(
296    /* [in] */ BOOL flag)
297{
298    return E_FAIL;
299}
300
301HRESULT STDMETHODCALLTYPE WebFrame::setExcludeFromTextSearch(
302    /* [in] */ BOOL flag)
303{
304    return E_FAIL;
305}
306
307HRESULT WebFrame::reloadFromOrigin()
308{
309    Frame* coreFrame = core(this);
310    if (!coreFrame)
311        return E_FAIL;
312
313    coreFrame->loader().reload(true);
314    return S_OK;
315}
316
317HRESULT WebFrame::paintDocumentRectToContext(RECT rect, HDC deviceContext)
318{
319    Frame* coreFrame = core(this);
320    if (!coreFrame)
321        return E_FAIL;
322
323    FrameView* view = coreFrame->view();
324    if (!view)
325        return E_FAIL;
326
327    // We can't paint with a layout still pending.
328    view->updateLayoutAndStyleIfNeededRecursive();
329
330    GraphicsContext gc(deviceContext);
331    gc.setShouldIncludeChildWindows(true);
332    gc.save();
333    LONG width = rect.right - rect.left;
334    LONG height = rect.bottom - rect.top;
335    FloatRect dirtyRect;
336    dirtyRect.setWidth(width);
337    dirtyRect.setHeight(height);
338    gc.clip(dirtyRect);
339    gc.translate(-rect.left, -rect.top);
340    view->paintContents(&gc, rect);
341    gc.restore();
342
343    return S_OK;
344}
345
346HRESULT WebFrame::paintScrollViewRectToContextAtPoint(RECT rect, POINT pt, HDC deviceContext)
347{
348    Frame* coreFrame = core(this);
349    if (!coreFrame)
350        return E_FAIL;
351
352    FrameView* view = coreFrame->view();
353    if (!view)
354        return E_FAIL;
355
356    // We can't paint with a layout still pending.
357    view->updateLayoutAndStyleIfNeededRecursive();
358
359    GraphicsContext gc(deviceContext);
360    gc.setShouldIncludeChildWindows(true);
361    gc.save();
362    IntRect dirtyRect(rect);
363    dirtyRect.move(-pt.x, -pt.y);
364    view->paint(&gc, dirtyRect);
365    gc.restore();
366
367    return S_OK;
368}
369
370// IUnknown -------------------------------------------------------------------
371
372HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
373{
374    *ppvObject = 0;
375    if (IsEqualGUID(riid, __uuidof(WebFrame)))
376        *ppvObject = this;
377    else if (IsEqualGUID(riid, IID_IUnknown))
378        *ppvObject = static_cast<IWebFrame*>(this);
379    else if (IsEqualGUID(riid, IID_IWebFrame))
380        *ppvObject = static_cast<IWebFrame*>(this);
381    else if (IsEqualGUID(riid, IID_IWebFramePrivate))
382        *ppvObject = static_cast<IWebFramePrivate*>(this);
383    else if (IsEqualGUID(riid, IID_IWebDocumentText))
384        *ppvObject = static_cast<IWebDocumentText*>(this);
385    else
386        return E_NOINTERFACE;
387
388    AddRef();
389    return S_OK;
390}
391
392ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
393{
394    return ++m_refCount;
395}
396
397ULONG STDMETHODCALLTYPE WebFrame::Release(void)
398{
399    ULONG newRef = --m_refCount;
400    if (!newRef)
401        delete(this);
402
403    return newRef;
404}
405
406// IWebFrame -------------------------------------------------------------------
407
408HRESULT STDMETHODCALLTYPE WebFrame::name(
409    /* [retval][out] */ BSTR* frameName)
410{
411    if (!frameName) {
412        ASSERT_NOT_REACHED();
413        return E_POINTER;
414    }
415
416    *frameName = 0;
417
418    Frame* coreFrame = core(this);
419    if (!coreFrame)
420        return E_FAIL;
421
422    *frameName = BString(coreFrame->tree().uniqueName()).release();
423    return S_OK;
424}
425
426HRESULT STDMETHODCALLTYPE WebFrame::webView(
427    /* [retval][out] */ IWebView** view)
428{
429    *view = 0;
430    if (!d->webView)
431        return E_FAIL;
432    *view = d->webView;
433    (*view)->AddRef();
434    return S_OK;
435}
436
437HRESULT STDMETHODCALLTYPE WebFrame::frameView(
438    /* [retval][out] */ IWebFrameView** /*view*/)
439{
440    ASSERT_NOT_REACHED();
441    return E_NOTIMPL;
442}
443
444HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument(
445    /* [retval][out] */ IDOMDocument** result)
446{
447    if (!result) {
448        ASSERT_NOT_REACHED();
449        return E_POINTER;
450    }
451
452    *result = 0;
453
454    if (Frame* coreFrame = core(this))
455        if (Document* document = coreFrame->document())
456            *result = DOMDocument::createInstance(document);
457
458    return *result ? S_OK : E_FAIL;
459}
460
461
462HRESULT WebFrame::DOMWindow(/* [retval][out] */ IDOMWindow** window)
463{
464    if (!window) {
465        ASSERT_NOT_REACHED();
466        return E_POINTER;
467    }
468
469    *window = 0;
470
471    if (Frame* coreFrame = core(this)) {
472        if (WebCore::DOMWindow* coreWindow = coreFrame->document()->domWindow())
473            *window = ::DOMWindow::createInstance(coreWindow);
474    }
475
476    return *window ? S_OK : E_FAIL;
477}
478
479HRESULT STDMETHODCALLTYPE WebFrame::frameElement(
480    /* [retval][out] */ IDOMHTMLElement** frameElement)
481{
482    if (!frameElement)
483        return E_POINTER;
484
485    *frameElement = 0;
486    Frame* coreFrame = core(this);
487    if (!coreFrame)
488        return E_FAIL;
489
490    COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(coreFrame->ownerElement()));
491    COMPtr<IDOMHTMLElement> htmlElement(Query, domElement);
492    if (!htmlElement)
493        return E_FAIL;
494    return htmlElement.copyRefTo(frameElement);
495}
496
497HRESULT STDMETHODCALLTYPE WebFrame::currentForm(
498        /* [retval][out] */ IDOMElement **currentForm)
499{
500    if (!currentForm) {
501        ASSERT_NOT_REACHED();
502        return E_POINTER;
503    }
504
505    *currentForm = 0;
506
507    if (Frame* coreFrame = core(this)) {
508        if (HTMLFormElement* formElement = coreFrame->selection().currentForm())
509            *currentForm = DOMElement::createInstance(formElement);
510    }
511
512    return *currentForm ? S_OK : E_FAIL;
513}
514
515JSGlobalContextRef STDMETHODCALLTYPE WebFrame::globalContext()
516{
517    Frame* coreFrame = core(this);
518    if (!coreFrame)
519        return 0;
520
521    return toGlobalRef(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
522}
523
524JSGlobalContextRef WebFrame::globalContextForScriptWorld(IWebScriptWorld* iWorld)
525{
526    Frame* coreFrame = core(this);
527    if (!coreFrame)
528        return 0;
529
530    COMPtr<WebScriptWorld> world(Query, iWorld);
531    if (!world)
532        return 0;
533
534    return toGlobalRef(coreFrame->script().globalObject(world->world())->globalExec());
535}
536
537HRESULT STDMETHODCALLTYPE WebFrame::loadRequest(
538    /* [in] */ IWebURLRequest* request)
539{
540    COMPtr<WebMutableURLRequest> requestImpl;
541
542    HRESULT hr = request->QueryInterface(&requestImpl);
543    if (FAILED(hr))
544        return hr;
545
546    Frame* coreFrame = core(this);
547    if (!coreFrame)
548        return E_FAIL;
549
550    coreFrame->loader().load(FrameLoadRequest(coreFrame, requestImpl->resourceRequest()));
551    return S_OK;
552}
553
554void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL)
555{
556    String mimeTypeString(mimeType, SysStringLen(mimeType));
557    if (!mimeType)
558        mimeTypeString = "text/html";
559
560    String encodingString(textEncodingName, SysStringLen(textEncodingName));
561
562    // FIXME: We should really be using MarshallingHelpers::BSTRToKURL here,
563    // but that would turn a null BSTR into a null URL, and we crash inside of
564    // WebCore if we use a null URL in constructing the ResourceRequest.
565    URL baseKURL = URL(URL(), String(baseURL ? baseURL : L"", SysStringLen(baseURL)));
566
567    URL failingKURL = MarshallingHelpers::BSTRToKURL(failingURL);
568
569    ResourceRequest request(baseKURL);
570    SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL);
571
572    // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null.
573    if (Frame* coreFrame = core(this))
574        coreFrame->loader().load(FrameLoadRequest(coreFrame, request, substituteData));
575}
576
577
578HRESULT STDMETHODCALLTYPE WebFrame::loadData(
579    /* [in] */ IStream* data,
580    /* [in] */ BSTR mimeType,
581    /* [in] */ BSTR textEncodingName,
582    /* [in] */ BSTR url)
583{
584    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create();
585
586    STATSTG stat;
587    if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) {
588        if (!stat.cbSize.HighPart && stat.cbSize.LowPart) {
589            Vector<char> dataBuffer(stat.cbSize.LowPart);
590            ULONG read;
591            // FIXME: this does a needless copy, would be better to read right into the SharedBuffer
592            // or adopt the Vector or something.
593            if (SUCCEEDED(data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read)))
594                sharedBuffer->append(dataBuffer.data(), static_cast<int>(dataBuffer.size()));
595        }
596    }
597
598    loadData(sharedBuffer, mimeType, textEncodingName, url, 0);
599    return S_OK;
600}
601
602HRESULT WebFrame::loadPlainTextString(
603    /* [in] */ BSTR string,
604    /* [in] */ BSTR url)
605{
606    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
607    BString plainTextMimeType(TEXT("text/plain"), 10);
608    BString utf16Encoding(TEXT("utf-16"), 6);
609    loadData(sharedBuffer.release(), plainTextMimeType, utf16Encoding, url, 0);
610    return S_OK;
611}
612
613void WebFrame::loadHTMLString(BSTR string, BSTR baseURL, BSTR unreachableURL)
614{
615    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
616    BString utf16Encoding(TEXT("utf-16"), 6);
617    loadData(sharedBuffer.release(), 0, utf16Encoding, baseURL, unreachableURL);
618}
619
620HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString(
621    /* [in] */ BSTR string,
622    /* [in] */ BSTR baseURL)
623{
624    loadHTMLString(string, baseURL, 0);
625    return S_OK;
626}
627
628HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString(
629    /* [in] */ BSTR str,
630    /* [in] */ BSTR baseURL,
631    /* [in] */ BSTR unreachableURL)
632{
633    loadHTMLString(str, baseURL, unreachableURL);
634    return S_OK;
635}
636
637HRESULT STDMETHODCALLTYPE WebFrame::loadArchive(
638    /* [in] */ IWebArchive* /*archive*/)
639{
640    ASSERT_NOT_REACHED();
641    return E_NOTIMPL;
642}
643
644static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
645{
646    return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
647}
648
649HRESULT STDMETHODCALLTYPE WebFrame::dataSource(
650    /* [retval][out] */ IWebDataSource** source)
651{
652    if (!source) {
653        ASSERT_NOT_REACHED();
654        return E_POINTER;
655    }
656
657    *source = 0;
658
659    Frame* coreFrame = core(this);
660    if (!coreFrame)
661        return E_FAIL;
662
663    WebDataSource* webDataSource = getWebDataSource(coreFrame->loader().documentLoader());
664
665    *source = webDataSource;
666
667    if (webDataSource)
668        webDataSource->AddRef();
669
670    return *source ? S_OK : E_FAIL;
671}
672
673HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource(
674    /* [retval][out] */ IWebDataSource** source)
675{
676    if (!source) {
677        ASSERT_NOT_REACHED();
678        return E_POINTER;
679    }
680
681    *source = 0;
682
683    Frame* coreFrame = core(this);
684    if (!coreFrame)
685        return E_FAIL;
686
687    WebDataSource* webDataSource = getWebDataSource(coreFrame->loader().provisionalDocumentLoader());
688
689    *source = webDataSource;
690
691    if (webDataSource)
692        webDataSource->AddRef();
693
694    return *source ? S_OK : E_FAIL;
695}
696
697URL WebFrame::url() const
698{
699    Frame* coreFrame = core(this);
700    if (!coreFrame)
701        return URL();
702
703    return coreFrame->document()->url();
704}
705
706HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
707{
708    if (Frame* coreFrame = core(this))
709        coreFrame->loader().stopAllLoaders();
710    return S_OK;
711}
712
713HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
714{
715    Frame* coreFrame = core(this);
716    if (!coreFrame)
717        return E_FAIL;
718
719    coreFrame->loader().reload();
720    return S_OK;
721}
722
723HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed(
724    /* [in] */ BSTR name,
725    /* [retval][out] */ IWebFrame** frame)
726{
727    if (!frame) {
728        ASSERT_NOT_REACHED();
729        return E_POINTER;
730    }
731
732    *frame = 0;
733
734    Frame* coreFrame = core(this);
735    if (!coreFrame)
736        return E_FAIL;
737
738    Frame* foundFrame = coreFrame->tree().find(AtomicString(name, SysStringLen(name)));
739    if (!foundFrame)
740        return S_OK;
741
742    WebFrame* foundWebFrame = kit(foundFrame);
743    if (!foundWebFrame)
744        return E_FAIL;
745
746    return foundWebFrame->QueryInterface(IID_IWebFrame, (void**)frame);
747}
748
749HRESULT STDMETHODCALLTYPE WebFrame::parentFrame(
750    /* [retval][out] */ IWebFrame** frame)
751{
752    HRESULT hr = S_OK;
753    *frame = 0;
754    if (Frame* coreFrame = core(this))
755        if (WebFrame* webFrame = kit(coreFrame->tree().parent()))
756            hr = webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
757
758    return hr;
759}
760
761class EnumChildFrames : public IEnumVARIANT
762{
763public:
764    EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree().firstChild() : 0) { }
765
766    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
767    {
768        *ppvObject = 0;
769        if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
770            *ppvObject = this;
771        else
772            return E_NOINTERFACE;
773
774        AddRef();
775        return S_OK;
776    }
777
778    virtual ULONG STDMETHODCALLTYPE AddRef(void)
779    {
780        return ++m_refCount;
781    }
782
783    virtual ULONG STDMETHODCALLTYPE Release(void)
784    {
785        ULONG newRef = --m_refCount;
786        if (!newRef)
787            delete(this);
788        return newRef;
789    }
790
791    virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
792    {
793        if (pCeltFetched)
794            *pCeltFetched = 0;
795        if (!rgVar)
796            return E_POINTER;
797        VariantInit(rgVar);
798        if (!celt || celt > 1)
799            return S_FALSE;
800        if (!m_frame || !m_curChild)
801            return S_FALSE;
802
803        WebFrame* webFrame = kit(m_curChild);
804        IUnknown* unknown;
805        HRESULT hr = webFrame->QueryInterface(IID_IUnknown, (void**)&unknown);
806        if (FAILED(hr))
807            return hr;
808
809        V_VT(rgVar) = VT_UNKNOWN;
810        V_UNKNOWN(rgVar) = unknown;
811
812        m_curChild = m_curChild->tree().nextSibling();
813        if (pCeltFetched)
814            *pCeltFetched = 1;
815        return S_OK;
816    }
817
818    virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
819    {
820        if (!m_frame)
821            return S_FALSE;
822        for (unsigned i = 0; i < celt && m_curChild; i++)
823            m_curChild = m_curChild->tree().nextSibling();
824        return m_curChild ? S_OK : S_FALSE;
825    }
826
827    virtual HRESULT STDMETHODCALLTYPE Reset(void)
828    {
829        if (!m_frame)
830            return S_FALSE;
831        m_curChild = m_frame->tree().firstChild();
832        return S_OK;
833    }
834
835    virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**)
836    {
837        return E_NOTIMPL;
838    }
839
840private:
841    ULONG m_refCount;
842    Frame* m_frame;
843    Frame* m_curChild;
844};
845
846HRESULT STDMETHODCALLTYPE WebFrame::childFrames(
847    /* [retval][out] */ IEnumVARIANT **enumFrames)
848{
849    if (!enumFrames)
850        return E_POINTER;
851
852    *enumFrames = new EnumChildFrames(core(this));
853    return S_OK;
854}
855
856// IWebFramePrivate ------------------------------------------------------
857
858HRESULT WebFrame::renderTreeAsExternalRepresentation(BOOL forPrinting, BSTR *result)
859{
860    if (!result)
861        return E_POINTER;
862
863    Frame* coreFrame = core(this);
864    if (!coreFrame)
865        return E_FAIL;
866
867    *result = BString(externalRepresentation(coreFrame, forPrinting ? RenderAsTextPrintingMode : RenderAsTextBehaviorNormal)).release();
868    return S_OK;
869}
870
871HRESULT STDMETHODCALLTYPE WebFrame::pageNumberForElementById(
872    /* [in] */ BSTR id,
873    /* [in] */ float pageWidthInPixels,
874    /* [in] */ float pageHeightInPixels,
875    /* [retval][out] */ int* result)
876{
877    // TODO: Please remove this function if not needed as this is LTC specific function
878    // and has been moved to Internals.
879    notImplemented();
880    return E_FAIL;
881}
882
883HRESULT STDMETHODCALLTYPE WebFrame::numberOfPages(
884    /* [in] */ float pageWidthInPixels,
885    /* [in] */ float pageHeightInPixels,
886    /* [retval][out] */ int* result)
887{
888    // TODO: Please remove this function if not needed as this is LTC specific function
889    // and has been moved to Internals.
890    notImplemented();
891    return E_FAIL;
892}
893
894HRESULT STDMETHODCALLTYPE WebFrame::scrollOffset(
895        /* [retval][out] */ SIZE* offset)
896{
897    if (!offset) {
898        ASSERT_NOT_REACHED();
899        return E_POINTER;
900    }
901
902    Frame* coreFrame = core(this);
903    if (!coreFrame)
904        return E_FAIL;
905
906    FrameView* view = coreFrame->view();
907    if (!view)
908        return E_FAIL;
909
910    *offset = view->scrollOffset();
911    return S_OK;
912}
913
914HRESULT STDMETHODCALLTYPE WebFrame::layout()
915{
916    Frame* coreFrame = core(this);
917    if (!coreFrame)
918        return E_FAIL;
919
920    FrameView* view = coreFrame->view();
921    if (!view)
922        return E_FAIL;
923
924    view->layout();
925    return S_OK;
926}
927
928HRESULT STDMETHODCALLTYPE WebFrame::firstLayoutDone(
929    /* [retval][out] */ BOOL* result)
930{
931    if (!result) {
932        ASSERT_NOT_REACHED();
933        return E_POINTER;
934    }
935
936    *result = 0;
937
938    Frame* coreFrame = core(this);
939    if (!coreFrame)
940        return E_FAIL;
941
942    *result = coreFrame->loader().stateMachine().firstLayoutDone();
943    return S_OK;
944}
945
946HRESULT STDMETHODCALLTYPE WebFrame::pendingFrameUnloadEventCount(
947    /* [retval][out] */ UINT* result)
948{
949    if (!result) {
950        ASSERT_NOT_REACHED();
951        return E_POINTER;
952    }
953
954    *result = 0;
955
956    Frame* coreFrame = core(this);
957    if (!coreFrame)
958        return E_FAIL;
959
960    *result = coreFrame->document()->domWindow()->pendingUnloadEventListeners();
961    return S_OK;
962}
963
964HRESULT STDMETHODCALLTYPE WebFrame::hasSpellingMarker(
965        /* [in] */ UINT from,
966        /* [in] */ UINT length,
967        /* [retval][out] */ BOOL* result)
968{
969    Frame* coreFrame = core(this);
970    if (!coreFrame)
971        return E_FAIL;
972    *result = coreFrame->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
973    return S_OK;
974}
975
976HRESULT STDMETHODCALLTYPE WebFrame::clearOpener()
977{
978    HRESULT hr = S_OK;
979    if (Frame* coreFrame = core(this))
980        coreFrame->loader().setOpener(0);
981
982    return hr;
983}
984
985HRESULT WebFrame::setTextDirection(BSTR direction)
986{
987    Frame* coreFrame = core(this);
988    if (!coreFrame)
989        return E_FAIL;
990
991    String directionString(direction, SysStringLen(direction));
992    if (directionString == "auto")
993        coreFrame->editor().setBaseWritingDirection(NaturalWritingDirection);
994    else if (directionString == "ltr")
995        coreFrame->editor().setBaseWritingDirection(LeftToRightWritingDirection);
996    else if (directionString == "rtl")
997        coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection);
998    return S_OK;
999}
1000
1001// IWebDocumentText -----------------------------------------------------------
1002
1003HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding(
1004    /* [retval][out] */ BOOL* result)
1005{
1006    *result = FALSE;
1007    return E_NOTIMPL;
1008}
1009
1010HRESULT STDMETHODCALLTYPE WebFrame::selectedString(
1011    /* [retval][out] */ BSTR* result)
1012{
1013    *result = 0;
1014
1015    Frame* coreFrame = core(this);
1016    if (!coreFrame)
1017        return E_FAIL;
1018
1019    String text = coreFrame->displayStringModifiedByEncoding(coreFrame->editor().selectedText());
1020
1021    *result = BString(text).release();
1022    return S_OK;
1023}
1024
1025HRESULT STDMETHODCALLTYPE WebFrame::selectAll()
1026{
1027    Frame* coreFrame = core(this);
1028    if (!coreFrame)
1029        return E_FAIL;
1030
1031    if (!coreFrame->editor().command("SelectAll").execute())
1032        return E_FAIL;
1033
1034    return S_OK;
1035}
1036
1037HRESULT STDMETHODCALLTYPE WebFrame::deselectAll()
1038{
1039    return E_NOTIMPL;
1040}
1041
1042// WebFrame ---------------------------------------------------------------
1043
1044PassRefPtr<Frame> WebFrame::createSubframeWithOwnerElement(IWebView* webView, Page* page, HTMLFrameOwnerElement* ownerElement)
1045{
1046    webView->QueryInterface(&d->webView);
1047    d->webView->Release(); // don't hold the extra ref
1048
1049    HWND viewWindow;
1050    d->webView->viewWindow(&viewWindow);
1051
1052    this->AddRef(); // We release this ref in frameLoaderDestroyed()
1053    RefPtr<Frame> frame = Frame::create(page, ownerElement, new WebFrameLoaderClient(this));
1054    d->frame = frame.get();
1055    return frame.release();
1056}
1057
1058void WebFrame::initWithWebView(IWebView* webView, Page* page)
1059{
1060    webView->QueryInterface(&d->webView);
1061    d->webView->Release(); // don't hold the extra ref
1062
1063    HWND viewWindow;
1064    d->webView->viewWindow(&viewWindow);
1065
1066    this->AddRef(); // We release this ref in frameLoaderDestroyed()
1067    d->frame = &page->mainFrame();
1068}
1069
1070Frame* WebFrame::impl()
1071{
1072    return d->frame;
1073}
1074
1075void WebFrame::invalidate()
1076{
1077    Frame* coreFrame = core(this);
1078    ASSERT(coreFrame);
1079
1080    if (Document* document = coreFrame->document())
1081        document->recalcStyle(Style::Force);
1082}
1083
1084HRESULT WebFrame::inViewSourceMode(BOOL* flag)
1085{
1086    return E_NOTIMPL;
1087}
1088
1089HRESULT WebFrame::setInViewSourceMode(BOOL flag)
1090{
1091    return E_NOTIMPL;
1092}
1093
1094HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** element)
1095{
1096    if (!form)
1097        return E_INVALIDARG;
1098
1099    HTMLFormElement* formElement = formElementFromDOMElement(form);
1100    if (formElement) {
1101        const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
1102        AtomicString targetName((UChar*)name, SysStringLen(name));
1103        for (unsigned int i = 0; i < elements.size(); i++) {
1104            if (!elements[i]->isFormControlElement())
1105                continue;
1106            HTMLFormControlElement* elt = toHTMLFormControlElement(elements[i]);
1107            // Skip option elements, other duds
1108            if (elt->name() == targetName) {
1109                *element = DOMElement::createInstance(elt);
1110                return S_OK;
1111            }
1112        }
1113    }
1114    return E_FAIL;
1115}
1116
1117HRESULT WebFrame::formForElement(IDOMElement* element, IDOMElement** form)
1118{
1119    if (!element)
1120        return E_INVALIDARG;
1121
1122    HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1123    if (!inputElement)
1124        return E_FAIL;
1125
1126    HTMLFormElement *formElement = inputElement->form();
1127    if (!formElement)
1128        return E_FAIL;
1129
1130    *form = DOMElement::createInstance(formElement);
1131    return S_OK;
1132}
1133
1134HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, BOOL *result)
1135{
1136    *result = false;
1137    if (!element)
1138        return E_INVALIDARG;
1139
1140    HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1141    if (!inputElement)
1142        *result = false;
1143    else
1144        *result = inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete();
1145
1146    return S_OK;
1147}
1148
1149HRESULT STDMETHODCALLTYPE WebFrame::resumeAnimations()
1150{
1151    Frame* frame = core(this);
1152    if (!frame)
1153        return E_FAIL;
1154
1155    frame->animation().resumeAnimations();
1156    return S_OK;
1157}
1158
1159HRESULT STDMETHODCALLTYPE WebFrame::suspendAnimations()
1160{
1161    Frame* frame = core(this);
1162    if (!frame)
1163        return E_FAIL;
1164
1165    frame->animation().suspendAnimations();
1166    return S_OK;
1167}
1168
1169HRESULT WebFrame::pauseAnimation(BSTR animationName, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
1170{
1171    if (!node || !animationWasRunning)
1172        return E_POINTER;
1173
1174    *animationWasRunning = FALSE;
1175
1176    Frame* frame = core(this);
1177    if (!frame)
1178        return E_FAIL;
1179
1180    COMPtr<DOMNode> domNode(Query, node);
1181    if (!domNode)
1182        return E_FAIL;
1183
1184    *animationWasRunning = frame->animation().pauseAnimationAtTime(toRenderElement(domNode->node()->renderer()), String(animationName, SysStringLen(animationName)), secondsFromNow);
1185    return S_OK;
1186}
1187
1188HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double secondsFromNow, BOOL* transitionWasRunning)
1189{
1190    if (!node || !transitionWasRunning)
1191        return E_POINTER;
1192
1193    *transitionWasRunning = FALSE;
1194
1195    Frame* frame = core(this);
1196    if (!frame)
1197        return E_FAIL;
1198
1199    COMPtr<DOMNode> domNode(Query, node);
1200    if (!domNode)
1201        return E_FAIL;
1202
1203    *transitionWasRunning = frame->animation().pauseTransitionAtTime(toRenderElement(domNode->node()->renderer()), String(propertyName, SysStringLen(propertyName)), secondsFromNow);
1204    return S_OK;
1205}
1206
1207HRESULT WebFrame::visibleContentRect(RECT* rect)
1208{
1209    if (!rect)
1210        return E_POINTER;
1211    SetRectEmpty(rect);
1212
1213    Frame* frame = core(this);
1214    if (!frame)
1215        return E_FAIL;
1216
1217    FrameView* view = frame->view();
1218    if (!view)
1219        return E_FAIL;
1220
1221    *rect = view->visibleContentRect();
1222    return S_OK;
1223}
1224
1225HRESULT WebFrame::numberOfActiveAnimations(UINT* number)
1226{
1227    if (!number)
1228        return E_POINTER;
1229
1230    *number = 0;
1231
1232    Frame* frame = core(this);
1233    if (!frame)
1234        return E_FAIL;
1235
1236    *number = frame->animation().numberOfActiveAnimations(frame->document());
1237    return S_OK;
1238}
1239
1240HRESULT WebFrame::isDisplayingStandaloneImage(BOOL* result)
1241{
1242    if (!result)
1243        return E_POINTER;
1244
1245    *result = FALSE;
1246
1247    Frame* frame = core(this);
1248    if (!frame)
1249        return E_FAIL;
1250
1251    Document* document = frame->document();
1252    *result = document && document->isImageDocument();
1253    return S_OK;
1254}
1255
1256HRESULT WebFrame::allowsFollowingLink(BSTR url, BOOL* result)
1257{
1258    if (!result)
1259        return E_POINTER;
1260
1261    *result = TRUE;
1262
1263    Frame* frame = core(this);
1264    if (!frame)
1265        return E_FAIL;
1266
1267    *result = frame->document()->securityOrigin()->canDisplay(MarshallingHelpers::BSTRToKURL(url));
1268    return S_OK;
1269}
1270
1271HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls)
1272{
1273    if (!form)
1274        return E_INVALIDARG;
1275
1276    HTMLFormElement* formElement = formElementFromDOMElement(form);
1277    if (!formElement)
1278        return E_FAIL;
1279
1280    int inCount = *cControls;
1281    int count = (int) formElement->associatedElements().size();
1282    *cControls = count;
1283    if (!controls)
1284        return S_OK;
1285    if (inCount < count)
1286        return E_FAIL;
1287
1288    *cControls = 0;
1289    const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
1290    for (int i = 0; i < count; i++) {
1291        if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1292            controls[*cControls] = DOMElement::createInstance(&elements.at(i)->asHTMLElement());
1293            (*cControls)++;
1294        }
1295    }
1296    return S_OK;
1297}
1298
1299HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result)
1300{
1301    HTMLInputElement* inputElement = inputElementFromDOMElement(element);
1302    *result = inputElement && inputElement->isPasswordField();
1303    return S_OK;
1304}
1305
1306HRESULT WebFrame::searchForLabelsBeforeElement(const BSTR* labels, unsigned cLabels, IDOMElement* beforeElement, unsigned* outResultDistance, BOOL* outResultIsInCellAbove, BSTR* result)
1307{
1308    if (!result) {
1309        ASSERT_NOT_REACHED();
1310        return E_POINTER;
1311    }
1312
1313    if (outResultDistance)
1314        *outResultDistance = 0;
1315    if (outResultIsInCellAbove)
1316        *outResultIsInCellAbove = FALSE;
1317    *result = 0;
1318
1319    if (!cLabels)
1320        return S_OK;
1321    if (cLabels < 1)
1322        return E_INVALIDARG;
1323
1324    Frame* coreFrame = core(this);
1325    if (!coreFrame)
1326        return E_FAIL;
1327
1328    Vector<String> labelStrings(cLabels);
1329    for (int i=0; i<cLabels; i++)
1330        labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1331    Element *coreElement = elementFromDOMElement(beforeElement);
1332    if (!coreElement)
1333        return E_FAIL;
1334
1335    size_t resultDistance;
1336    bool resultIsInCellAbove;
1337    String label = coreFrame->searchForLabelsBeforeElement(labelStrings, coreElement, &resultDistance, &resultIsInCellAbove);
1338
1339    *result = BString(label).release();
1340    if (label.length() && !*result)
1341        return E_OUTOFMEMORY;
1342    if (outResultDistance)
1343        *outResultDistance = resultDistance;
1344    if (outResultIsInCellAbove)
1345        *outResultIsInCellAbove = resultIsInCellAbove;
1346
1347    return S_OK;
1348}
1349
1350HRESULT WebFrame::matchLabelsAgainstElement(const BSTR* labels, int cLabels, IDOMElement* againstElement, BSTR* result)
1351{
1352    if (!result) {
1353        ASSERT_NOT_REACHED();
1354        return E_POINTER;
1355    }
1356
1357    *result = 0;
1358
1359    if (!cLabels)
1360        return S_OK;
1361    if (cLabels < 1)
1362        return E_INVALIDARG;
1363
1364    Frame* coreFrame = core(this);
1365    if (!coreFrame)
1366        return E_FAIL;
1367
1368    Vector<String> labelStrings(cLabels);
1369    for (int i=0; i<cLabels; i++)
1370        labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1371    Element *coreElement = elementFromDOMElement(againstElement);
1372    if (!coreElement)
1373        return E_FAIL;
1374
1375    String label = coreFrame->matchLabelsAgainstElement(labelStrings, coreElement);
1376
1377    *result = BString(label).release();
1378    if (label.length() && !*result)
1379        return E_OUTOFMEMORY;
1380    return S_OK;
1381}
1382
1383HRESULT WebFrame::canProvideDocumentSource(bool* result)
1384{
1385    HRESULT hr = S_OK;
1386    *result = false;
1387
1388    COMPtr<IWebDataSource> dataSource;
1389    hr = WebFrame::dataSource(&dataSource);
1390    if (FAILED(hr))
1391        return hr;
1392
1393    COMPtr<IWebURLResponse> urlResponse;
1394    hr = dataSource->response(&urlResponse);
1395    if (SUCCEEDED(hr) && urlResponse) {
1396        BString mimeTypeBStr;
1397        if (SUCCEEDED(urlResponse->MIMEType(&mimeTypeBStr))) {
1398            String mimeType(mimeTypeBStr, SysStringLen(mimeTypeBStr));
1399            *result = mimeType == "text/html" || WebCore::DOMImplementation::isXMLMIMEType(mimeType);
1400        }
1401    }
1402    return hr;
1403}
1404
1405HRESULT STDMETHODCALLTYPE WebFrame::layerTreeAsText(BSTR* result)
1406{
1407    if (!result)
1408        return E_POINTER;
1409    *result = 0;
1410
1411    Frame* frame = core(this);
1412    if (!frame)
1413        return E_FAIL;
1414
1415    String text = frame->layerTreeAsText();
1416    *result = BString(text).release();
1417    return S_OK;
1418}
1419
1420void WebFrame::frameLoaderDestroyed()
1421{
1422    // The FrameLoader going away is equivalent to the Frame going away,
1423    // so we now need to clear our frame pointer.
1424    d->frame = 0;
1425
1426    this->Release();
1427}
1428
1429static IntRect printerRect(HDC printDC)
1430{
1431    return IntRect(0, 0,
1432                   GetDeviceCaps(printDC, PHYSICALWIDTH)  - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETX),
1433                   GetDeviceCaps(printDC, PHYSICALHEIGHT) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETY));
1434}
1435
1436void WebFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot adjustViewSize)
1437{
1438    Frame* coreFrame = core(this);
1439    ASSERT(coreFrame);
1440    coreFrame->setPrinting(printing, pageSize, originalPageSize, maximumShrinkRatio, adjustViewSize ? AdjustViewSize : DoNotAdjustViewSize);
1441}
1442
1443HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode(
1444    /* [in] */ BOOL value,
1445    /* [in] */ HDC printDC)
1446{
1447    if (m_inPrintingMode == !!value)
1448        return S_OK;
1449
1450    Frame* coreFrame = core(this);
1451    if (!coreFrame || !coreFrame->document())
1452        return E_FAIL;
1453
1454    m_inPrintingMode = !!value;
1455
1456    // If we are a frameset just print with the layout we have onscreen, otherwise relayout
1457    // according to the paper size
1458    FloatSize minLayoutSize(0.0, 0.0);
1459    FloatSize originalPageSize(0.0, 0.0);
1460    if (m_inPrintingMode && !coreFrame->document()->isFrameSet()) {
1461        if (!printDC) {
1462            ASSERT_NOT_REACHED();
1463            return E_POINTER;
1464        }
1465
1466        const int desiredPixelsPerInch = 72;
1467        IntRect printRect = printerRect(printDC);
1468        int paperHorizontalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSX);
1469        int paperVerticalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSY);
1470        int paperWidth = printRect.width() * desiredPixelsPerInch / paperHorizontalPixelsPerInch;
1471        int paperHeight = printRect.height() * desiredPixelsPerInch / paperVerticalPixelsPerInch;
1472        originalPageSize = FloatSize(paperWidth, paperHeight);
1473        Frame* coreFrame = core(this);
1474        minLayoutSize = coreFrame->resizePageRectsKeepingRatio(originalPageSize, FloatSize(paperWidth * PrintingMinimumShrinkFactor, paperHeight * PrintingMinimumShrinkFactor));
1475    }
1476
1477    setPrinting(m_inPrintingMode, minLayoutSize, originalPageSize, PrintingMaximumShrinkFactor / PrintingMinimumShrinkFactor, AdjustViewSize);
1478
1479    if (!m_inPrintingMode)
1480        m_pageRects.clear();
1481
1482    return S_OK;
1483}
1484
1485void WebFrame::headerAndFooterHeights(float* headerHeight, float* footerHeight)
1486{
1487    if (headerHeight)
1488        *headerHeight = 0;
1489    if (footerHeight)
1490        *footerHeight = 0;
1491    float height = 0;
1492    COMPtr<IWebUIDelegate> ui;
1493    if (FAILED(d->webView->uiDelegate(&ui)))
1494        return;
1495    if (headerHeight && SUCCEEDED(ui->webViewHeaderHeight(d->webView, &height)))
1496        *headerHeight = height;
1497    if (footerHeight && SUCCEEDED(ui->webViewFooterHeight(d->webView, &height)))
1498        *footerHeight = height;
1499}
1500
1501IntRect WebFrame::printerMarginRect(HDC printDC)
1502{
1503    IntRect emptyRect(0, 0, 0, 0);
1504
1505    COMPtr<IWebUIDelegate> ui;
1506    if (FAILED(d->webView->uiDelegate(&ui)))
1507        return emptyRect;
1508
1509    RECT rect;
1510    if (FAILED(ui->webViewPrintingMarginRect(d->webView, &rect)))
1511        return emptyRect;
1512
1513    rect.left = MulDiv(rect.left, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
1514    rect.top = MulDiv(rect.top, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
1515    rect.right = MulDiv(rect.right, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
1516    rect.bottom = MulDiv(rect.bottom, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
1517
1518    return IntRect(rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top);
1519}
1520
1521const Vector<WebCore::IntRect>& WebFrame::computePageRects(HDC printDC)
1522{
1523    ASSERT(m_inPrintingMode);
1524
1525    Frame* coreFrame = core(this);
1526    ASSERT(coreFrame);
1527    ASSERT(coreFrame->document());
1528
1529    if (!printDC)
1530        return m_pageRects;
1531
1532    // adjust the page rect by the header and footer
1533    float headerHeight = 0, footerHeight = 0;
1534    headerAndFooterHeights(&headerHeight, &footerHeight);
1535    IntRect pageRect = printerRect(printDC);
1536    IntRect marginRect = printerMarginRect(printDC);
1537    IntRect adjustedRect = IntRect(
1538        pageRect.x() + marginRect.x(),
1539        pageRect.y() + marginRect.y(),
1540        pageRect.width() - marginRect.x() - marginRect.maxX(),
1541        pageRect.height() - marginRect.y() - marginRect.maxY());
1542
1543    computePageRectsForFrame(coreFrame, adjustedRect, headerHeight, footerHeight, 1.0,m_pageRects, m_pageHeight);
1544
1545    return m_pageRects;
1546}
1547
1548HRESULT STDMETHODCALLTYPE WebFrame::getPrintedPageCount(
1549    /* [in] */ HDC printDC,
1550    /* [retval][out] */ UINT *pageCount)
1551{
1552    if (!pageCount || !printDC) {
1553        ASSERT_NOT_REACHED();
1554        return E_POINTER;
1555    }
1556
1557    *pageCount = 0;
1558
1559    if (!m_inPrintingMode) {
1560        ASSERT_NOT_REACHED();
1561        return E_FAIL;
1562    }
1563
1564    Frame* coreFrame = core(this);
1565    if (!coreFrame || !coreFrame->document())
1566        return E_FAIL;
1567
1568    const Vector<IntRect>& pages = computePageRects(printDC);
1569    *pageCount = (UINT) pages.size();
1570
1571    return S_OK;
1572}
1573
1574#if USE(CG)
1575void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
1576{
1577    int x = pageRect.x();
1578    int y = 0;
1579    RECT headerRect = {x, y, x+pageRect.width(), y+static_cast<int>(headerHeight)};
1580    ui->drawHeaderInRect(d->webView, &headerRect, reinterpret_cast<ULONG_PTR>(pctx));
1581}
1582
1583void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
1584{
1585    int x = pageRect.x();
1586    int y = max((int)headerHeight+pageRect.height(), m_pageHeight-static_cast<int>(footerHeight));
1587    RECT footerRect = {x, y, x+pageRect.width(), y+static_cast<int>(footerHeight)};
1588    ui->drawFooterInRect(d->webView, &footerRect, reinterpret_cast<ULONG_PTR>(pctx), page + 1, pageCount);
1589}
1590
1591void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
1592{
1593    Frame* coreFrame = core(this);
1594
1595    IntRect pageRect = m_pageRects[page];
1596
1597    CGContextSaveGState(pctx);
1598
1599    IntRect printRect = printerRect(printDC);
1600    CGRect mediaBox = CGRectMake(CGFloat(0),
1601                                 CGFloat(0),
1602                                 CGFloat(printRect.width()),
1603                                 CGFloat(printRect.height()));
1604
1605    CGContextBeginPage(pctx, &mediaBox);
1606
1607    CGFloat scale = static_cast<float>(mediaBox.size.width)/static_cast<float>(pageRect.width());
1608    CGAffineTransform ctm = CGContextGetBaseCTM(pctx);
1609    ctm = CGAffineTransformScale(ctm, -scale, -scale);
1610    ctm = CGAffineTransformTranslate(ctm, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
1611    CGContextScaleCTM(pctx, scale, scale);
1612    CGContextTranslateCTM(pctx, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight));   // reserves space for header
1613    CGContextSetBaseCTM(pctx, ctm);
1614
1615    coreFrame->view()->paintContents(spoolCtx, pageRect);
1616
1617    CGContextTranslateCTM(pctx, CGFloat(pageRect.x()), CGFloat(pageRect.y())-headerHeight);
1618
1619    if (headerHeight)
1620        drawHeader(pctx, ui, pageRect, headerHeight);
1621
1622    if (footerHeight)
1623        drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
1624
1625    CGContextEndPage(pctx);
1626    CGContextRestoreGState(pctx);
1627}
1628#elif USE(CAIRO)
1629static float scaleFactor(HDC printDC, const IntRect& marginRect, const IntRect& pageRect)
1630{
1631    const IntRect& printRect = printerRect(printDC);
1632
1633    IntRect adjustedRect = IntRect(
1634        printRect.x() + marginRect.x(),
1635        printRect.y() + marginRect.y(),
1636        printRect.width() - marginRect.x() - marginRect.maxX(),
1637        printRect.height() - marginRect.y() - marginRect.maxY());
1638
1639    float scale = static_cast<float>(adjustedRect.width()) / static_cast<float>(pageRect.width());
1640    if (!scale)
1641       scale = 1.0;
1642
1643    return scale;
1644}
1645
1646static HDC hdcFromContext(PlatformGraphicsContext* pctx)
1647{
1648    return cairo_win32_surface_get_dc(cairo_get_target(pctx->cr()));
1649}
1650
1651void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
1652{
1653    HDC hdc = hdcFromContext(pctx);
1654
1655    int x = pageRect.x();
1656    int y = 0;
1657    RECT headerRect = {x, y, x + pageRect.width(), y + static_cast<int>(headerHeight)};
1658
1659    ui->drawHeaderInRect(d->webView, &headerRect, reinterpret_cast<ULONG_PTR>(hdc));
1660}
1661
1662void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
1663{
1664    HDC hdc = hdcFromContext(pctx);
1665
1666    int x = pageRect.x();
1667    int y = max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight  -static_cast<int>(footerHeight));
1668    RECT footerRect = {x, y, x + pageRect.width(), y + static_cast<int>(footerHeight)};
1669
1670    ui->drawFooterInRect(d->webView, &footerRect, reinterpret_cast<ULONG_PTR>(hdc), page+1, pageCount);
1671}
1672
1673static XFORM buildXFORMFromCairo(HDC targetDC, cairo_t* previewContext)
1674{
1675    XFORM scaled;
1676    GetWorldTransform(targetDC, &scaled);
1677
1678    cairo_matrix_t ctm;
1679    cairo_get_matrix(previewContext, &ctm);
1680
1681    // Scale to the preview screen bounds
1682    scaled.eM11 = ctm.xx;
1683    scaled.eM22 = ctm.yy;
1684
1685    return scaled;
1686}
1687
1688void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
1689{
1690    Frame* coreFrame = core(this);
1691
1692    const IntRect& pageRect = m_pageRects[page];
1693    const IntRect& marginRect = printerMarginRect(printDC);
1694
1695    // In preview, the printDC is a placeholder, so just always use the HDC backing the graphics context.
1696    HDC hdc = hdcFromContext(pctx);
1697
1698    spoolCtx->save();
1699
1700    XFORM original, scaled;
1701    GetWorldTransform(hdc, &original);
1702
1703    cairo_t* cr = pctx->cr();
1704    bool preview = (hdc != printDC);
1705    if (preview) {
1706        // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo will
1707        // draw correctly.  We need to retain the correct preview scale here for use when the Cairo
1708        // drawing completes so that we can scale our GDI-based header/footer calls. This is a
1709        // workaround for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
1710        scaled = buildXFORMFromCairo(hdc, cr);
1711    }
1712
1713    float scale = scaleFactor(printDC, marginRect, pageRect);
1714
1715    IntRect cairoMarginRect(marginRect);
1716    cairoMarginRect.scale(1 / scale);
1717
1718    // We cannot scale the display HDC because the print surface also scales fonts,
1719    // resulting in invalid printing (and print preview)
1720    cairo_scale(cr, scale, scale);
1721    cairo_translate(cr, cairoMarginRect.x(), cairoMarginRect.y() + headerHeight);
1722
1723    // Modify Cairo (only) to account for page position.
1724    cairo_translate(cr, -pageRect.x(), -pageRect.y());
1725    coreFrame->view()->paintContents(spoolCtx, pageRect);
1726    cairo_translate(cr, pageRect.x(), pageRect.y());
1727
1728    if (preview) {
1729        // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo would
1730        // draw correctly.  We need to rescale the HDC to the correct preview scale so our GDI-based
1731        // header/footer calls will draw properly.  This is a workaround for a bug in Cairo.
1732        // (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
1733        SetWorldTransform(hdc, &scaled);
1734    }
1735
1736    XFORM xform = TransformationMatrix().translate(marginRect.x(), marginRect.y()).scale(scale);
1737    ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
1738
1739    if (headerHeight)
1740        drawHeader(pctx, ui, pageRect, headerHeight);
1741
1742    if (footerHeight)
1743        drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
1744
1745    SetWorldTransform(hdc, &original);
1746
1747    cairo_show_page(cr);
1748    ASSERT(!cairo_status(cr));
1749    spoolCtx->restore();
1750}
1751
1752static void setCairoTransformToPreviewHDC(cairo_t* previewCtx, HDC previewDC)
1753{
1754    XFORM passedCTM;
1755    GetWorldTransform(previewDC, &passedCTM);
1756
1757    // Reset HDC WorldTransform to unscaled state.  Scaling must be
1758    // done in Cairo to avoid drawing errors.
1759    XFORM unscaledCTM = passedCTM;
1760    unscaledCTM.eM11 = 1.0;
1761    unscaledCTM.eM22 = 1.0;
1762
1763    SetWorldTransform(previewDC, &unscaledCTM);
1764
1765    // Make the Cairo transform match the information passed to WebKit
1766    // in the HDC's WorldTransform.
1767    cairo_matrix_t ctm = { passedCTM.eM11, passedCTM.eM12, passedCTM.eM21,
1768                           passedCTM.eM22, passedCTM.eDx, passedCTM.eDy };
1769
1770    cairo_set_matrix(previewCtx, &ctm);
1771}
1772
1773#endif
1774
1775HRESULT STDMETHODCALLTYPE WebFrame::spoolPages(
1776    /* [in] */ HDC printDC,
1777    /* [in] */ UINT startPage,
1778    /* [in] */ UINT endPage,
1779    /* [retval][out] */ void* ctx)
1780{
1781#if USE(CG)
1782    if (!printDC || !ctx) {
1783        ASSERT_NOT_REACHED();
1784        return E_POINTER;
1785    }
1786#elif USE(CAIRO)
1787    if (!printDC) {
1788        ASSERT_NOT_REACHED();
1789        return E_POINTER;
1790    }
1791
1792    HDC targetDC = (ctx) ? (HDC)ctx : printDC;
1793
1794    cairo_surface_t* printSurface = 0;
1795    if (ctx)
1796        printSurface = cairo_win32_surface_create(targetDC); // in-memory
1797    else
1798        printSurface = cairo_win32_printing_surface_create(targetDC); // metafile
1799
1800    cairo_t* cr = cairo_create(printSurface);
1801    if (!cr) {
1802        cairo_surface_destroy(printSurface);
1803        return E_FAIL;
1804    }
1805
1806    PlatformContextCairo platformContext(cr);
1807    PlatformGraphicsContext* pctx = &platformContext;
1808    cairo_destroy(cr);
1809
1810    if (ctx) {
1811        // If this is a preview, the Windows HDC was sent with scaling information.
1812        // Retrieve it and reset it so that it draws properly.  This is a workaround
1813        // for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
1814        setCairoTransformToPreviewHDC(cr, targetDC);
1815    }
1816
1817    cairo_surface_set_fallback_resolution(printSurface, 72.0, 72.0);
1818#endif
1819
1820    if (!m_inPrintingMode) {
1821        ASSERT_NOT_REACHED();
1822        return E_FAIL;
1823    }
1824
1825    Frame* coreFrame = core(this);
1826    if (!coreFrame || !coreFrame->document())
1827        return E_FAIL;
1828
1829    UINT pageCount = (UINT) m_pageRects.size();
1830#if USE(CG)
1831    PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx;
1832#endif
1833
1834    if (!pageCount || startPage > pageCount) {
1835        ASSERT_NOT_REACHED();
1836        return E_FAIL;
1837    }
1838
1839    if (startPage > 0)
1840        startPage--;
1841
1842    if (endPage == 0)
1843        endPage = pageCount;
1844
1845    COMPtr<IWebUIDelegate> ui;
1846    if (FAILED(d->webView->uiDelegate(&ui)))
1847        return E_FAIL;
1848
1849    float headerHeight = 0, footerHeight = 0;
1850    headerAndFooterHeights(&headerHeight, &footerHeight);
1851    GraphicsContext spoolCtx(pctx);
1852    spoolCtx.setShouldIncludeChildWindows(true);
1853
1854    for (UINT ii = startPage; ii < endPage; ii++)
1855        spoolPage(pctx, &spoolCtx, printDC, ui.get(), headerHeight, footerHeight, ii, pageCount);
1856
1857#if USE(CAIRO)
1858    cairo_surface_finish(printSurface);
1859    ASSERT(!cairo_surface_status(printSurface));
1860    cairo_surface_destroy(printSurface);
1861#endif
1862
1863    return S_OK;
1864}
1865
1866HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet(
1867    /* [retval][out] */ BOOL* result)
1868{
1869    *result = FALSE;
1870
1871    Frame* coreFrame = core(this);
1872    if (!coreFrame || !coreFrame->document())
1873        return E_FAIL;
1874
1875    *result = coreFrame->document()->isFrameSet() ? TRUE : FALSE;
1876    return S_OK;
1877}
1878
1879HRESULT STDMETHODCALLTYPE WebFrame::string(
1880    /* [retval][out] */ BSTR *result)
1881{
1882    *result = 0;
1883
1884    Frame* coreFrame = core(this);
1885    if (!coreFrame)
1886        return E_FAIL;
1887
1888    RefPtr<Range> allRange(rangeOfContents(*coreFrame->document()));
1889    String allString = plainText(allRange.get());
1890    *result = BString(allString).release();
1891    return S_OK;
1892}
1893
1894HRESULT STDMETHODCALLTYPE WebFrame::size(
1895    /* [retval][out] */ SIZE *size)
1896{
1897    if (!size)
1898        return E_POINTER;
1899    size->cx = size->cy = 0;
1900
1901    Frame* coreFrame = core(this);
1902    if (!coreFrame)
1903        return E_FAIL;
1904    FrameView* view = coreFrame->view();
1905    if (!view)
1906        return E_FAIL;
1907    size->cx = view->width();
1908    size->cy = view->height();
1909    return S_OK;
1910}
1911
1912HRESULT STDMETHODCALLTYPE WebFrame::hasScrollBars(
1913    /* [retval][out] */ BOOL *result)
1914{
1915    if (!result)
1916        return E_POINTER;
1917    *result = FALSE;
1918
1919    Frame* coreFrame = core(this);
1920    if (!coreFrame)
1921        return E_FAIL;
1922
1923    FrameView* view = coreFrame->view();
1924    if (!view)
1925        return E_FAIL;
1926
1927    if (view->horizontalScrollbar() || view->verticalScrollbar())
1928        *result = TRUE;
1929
1930    return S_OK;
1931}
1932
1933HRESULT STDMETHODCALLTYPE WebFrame::contentBounds(
1934    /* [retval][out] */ RECT *result)
1935{
1936    if (!result)
1937        return E_POINTER;
1938    ::SetRectEmpty(result);
1939
1940    Frame* coreFrame = core(this);
1941    if (!coreFrame)
1942        return E_FAIL;
1943
1944    FrameView* view = coreFrame->view();
1945    if (!view)
1946        return E_FAIL;
1947
1948    result->bottom = view->contentsHeight();
1949    result->right = view->contentsWidth();
1950    return S_OK;
1951}
1952
1953HRESULT STDMETHODCALLTYPE WebFrame::frameBounds(
1954    /* [retval][out] */ RECT *result)
1955{
1956    if (!result)
1957        return E_POINTER;
1958    ::SetRectEmpty(result);
1959
1960    Frame* coreFrame = core(this);
1961    if (!coreFrame)
1962        return E_FAIL;
1963
1964    FrameView* view = coreFrame->view();
1965    if (!view)
1966        return E_FAIL;
1967
1968    FloatRect bounds = view->visibleContentRectIncludingScrollbars();
1969    result->bottom = (LONG) bounds.height();
1970    result->right = (LONG) bounds.width();
1971    return S_OK;
1972}
1973
1974HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame(
1975    /* [in] */ IWebFrame *ancestor,
1976    /* [retval][out] */ BOOL *result)
1977{
1978    if (!result)
1979        return E_POINTER;
1980    *result = FALSE;
1981
1982    Frame* coreFrame = core(this);
1983    COMPtr<WebFrame> ancestorWebFrame(Query, ancestor);
1984    if (!ancestorWebFrame)
1985        return S_OK;
1986
1987    *result = (coreFrame && coreFrame->tree().isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE;
1988    return S_OK;
1989}
1990
1991HRESULT WebFrame::stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld* iWorld, JSObjectRef globalObjectRef, BSTR script, BSTR* evaluationResult)
1992{
1993    if (!evaluationResult)
1994        return E_POINTER;
1995    *evaluationResult = 0;
1996
1997    if (!iWorld)
1998        return E_POINTER;
1999
2000    COMPtr<WebScriptWorld> world(Query, iWorld);
2001    if (!world)
2002        return E_INVALIDARG;
2003
2004    Frame* coreFrame = core(this);
2005    String string = String(script, SysStringLen(script));
2006
2007    // Start off with some guess at a frame and a global object, we'll try to do better...!
2008    JSDOMWindow* anyWorldGlobalObject = coreFrame->script().globalObject(mainThreadNormalWorld());
2009
2010    // The global object is probably a shell object? - if so, we know how to use this!
2011    JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
2012    if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
2013        anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
2014
2015    // Get the frame frome the global object we've settled on.
2016    Frame* frame = anyWorldGlobalObject->impl().frame();
2017    ASSERT(frame->document());
2018    JSValue result = frame->script().executeScriptInWorld(world->world(), string, true).jsValue();
2019
2020    if (!frame) // In case the script removed our frame from the page.
2021        return S_OK;
2022
2023    // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
2024    // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
2025    // JSEvaluateScript instead, since they have less surprising semantics.
2026    if (!result || !result.isBoolean() && !result.isString() && !result.isNumber())
2027        return S_OK;
2028
2029    JSC::ExecState* exec = anyWorldGlobalObject->globalExec();
2030    JSC::JSLockHolder lock(exec);
2031    String resultString = result.toWTFString(exec);
2032    *evaluationResult = BString(resultString).release();
2033
2034    return S_OK;
2035}
2036
2037void WebFrame::unmarkAllMisspellings()
2038{
2039    Frame* coreFrame = core(this);
2040    for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
2041        Document *doc = frame->document();
2042        if (!doc)
2043            return;
2044
2045        doc->markers().removeMarkers(DocumentMarker::Spelling);
2046    }
2047}
2048
2049void WebFrame::unmarkAllBadGrammar()
2050{
2051    Frame* coreFrame = core(this);
2052    for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
2053        Document *doc = frame->document();
2054        if (!doc)
2055            return;
2056
2057        doc->markers().removeMarkers(DocumentMarker::Grammar);
2058    }
2059}
2060
2061WebView* WebFrame::webView() const
2062{
2063    return d->webView;
2064}
2065
2066void WebFrame::setWebView(WebView* webView)
2067{
2068    d->webView = webView;
2069}
2070
2071COMPtr<IAccessible> WebFrame::accessible() const
2072{
2073    Frame* coreFrame = core(this);
2074    ASSERT(coreFrame);
2075
2076    Document* currentDocument = coreFrame->document();
2077    if (!currentDocument)
2078        m_accessible = 0;
2079    else if (!m_accessible || m_accessible->document() != currentDocument) {
2080        // Either we've never had a wrapper for this frame's top-level Document,
2081        // the Document renderer was destroyed and its wrapper was detached, or
2082        // the previous Document is in the page cache, and the current document
2083        // needs to be wrapped.
2084        m_accessible = new AccessibleDocument(currentDocument, webView()->viewWindow());
2085    }
2086    return m_accessible.get();
2087}
2088
2089void WebFrame::updateBackground()
2090{
2091    Color backgroundColor = webView()->transparent() ? Color::transparent : Color::white;
2092    Frame* coreFrame = core(this);
2093
2094    if (!coreFrame || !coreFrame->view())
2095        return;
2096
2097    coreFrame->view()->updateBackgroundRecursively(backgroundColor, webView()->transparent());
2098}
2099
2100