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