991db4effc048aec108e51812eeb93d82253ca06
[WebKit-https.git] / WebKit / win / WebFrame.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "WebFrame.h"
29
30 #include "CFDictionaryPropertyBag.h"
31 #include "COMPtr.h"
32 #include "DOMCoreClasses.h"
33 #include "IWebError.h"
34 #include "IWebErrorPrivate.h"
35 #include "IWebHistory.h"
36 #include "IWebHistoryItemPrivate.h"
37 #include "IWebFrameLoadDelegatePrivate.h"
38 #include "IWebFormDelegate.h"
39 #include "IWebUIDelegatePrivate.h"
40 #include "MarshallingHelpers.h"
41 #include "WebActionPropertyBag.h"
42 #include "WebDocumentLoader.h"
43 #include "WebDownload.h"
44 #include "WebError.h"
45 #include "WebMutableURLRequest.h"
46 #include "WebEditorClient.h"
47 #include "WebFramePolicyListener.h"
48 #include "WebHistory.h"
49 #include "WebKit.h"
50 #include "WebKitStatisticsPrivate.h"
51 #include "WebNotificationCenter.h"
52 #include "WebView.h"
53 #include "WebDataSource.h"
54 #include "WebHistoryItem.h"
55 #include "WebURLAuthenticationChallenge.h"
56 #include "WebURLResponse.h"
57 #pragma warning( push, 0 )
58 #include <WebCore/AuthenticationChallenge.h>
59 #include <WebCore/BString.h>
60 #include <WebCore/Cache.h>
61 #include <WebCore/Document.h>
62 #include <WebCore/DocumentLoader.h>
63 #include <WebCore/DOMImplementation.h>
64 #include <WebCore/DOMWindow.h>
65 #include <WebCore/Event.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/HTMLFormElement.h>
76 #include <WebCore/HTMLGenericFormElement.h>
77 #include <WebCore/HTMLInputElement.h>
78 #include <WebCore/HTMLNames.h>
79 #include <WebCore/KeyboardEvent.h>
80 #include <WebCore/MIMETypeRegistry.h>
81 #include <WebCore/MouseRelatedEvent.h>
82 #include <WebCore/NotImplemented.h>
83 #include <WebCore/Page.h>
84 #include <WebCore/PlatformKeyboardEvent.h>
85 #include <WebCore/PlugInInfoStore.h>
86 #include <WebCore/PluginDatabaseWin.h>
87 #include <WebCore/PluginViewWin.h>
88 #include <WebCore/ResourceHandle.h>
89 #include <WebCore/ResourceHandleWin.h>
90 #include <WebCore/ResourceRequest.h>
91 #include <WebCore/RenderFrame.h>
92 #include <WebCore/RenderTreeAsText.h>
93 #include <WebCore/Settings.h>
94 #include <WebCore/TextIterator.h>
95 #include <WebCore/kjs_binding.h>
96 #include <WebCore/kjs_proxy.h>
97 #include <WebCore/kjs_window.h>
98 #include <JavaScriptCore/APICast.h>
99 #include <wtf/MathExtras.h>
100 #pragma warning(pop)
101
102 #include <CoreGraphics/CoreGraphics.h>
103
104 // CG SPI used for printing
105 extern "C" {
106     CGAffineTransform CGContextGetBaseCTM(CGContextRef c); 
107     void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m); 
108 }
109
110 using namespace WebCore;
111 using namespace HTMLNames;
112
113 #define FLASH_REDRAW 0
114
115
116 // By imaging to a width a little wider than the available pixels,
117 // thin pages will be scaled down a little, matching the way they
118 // print in IE and Camino. This lets them use fewer sheets than they
119 // would otherwise, which is presumably why other browsers do this.
120 // Wide pages will be scaled down more than this.
121 const float PrintingMinimumShrinkFactor = 1.25f;
122
123 // This number determines how small we are willing to reduce the page content
124 // in order to accommodate the widest line. If the page would have to be
125 // reduced smaller to make the widest line fit, we just clip instead (this
126 // behavior matches MacIE and Mozilla, at least)
127 const float PrintingMaximumShrinkFactor = 2.0f;
128
129
130 // {A3676398-4485-4a9d-87DC-CB5A40E6351D}
131 const GUID IID_WebFrame = 
132 { 0xa3676398, 0x4485, 0x4a9d, { 0x87, 0xdc, 0xcb, 0x5a, 0x40, 0xe6, 0x35, 0x1d } };
133
134
135 //-----------------------------------------------------------------------------
136 // Helpers to convert from WebCore to WebKit type
137 WebFrame* kit(Frame* frame)
138 {
139     if (!frame)
140         return 0;
141
142     FrameLoaderClient* frameLoaderClient = frame->loader()->client();
143     if (frameLoaderClient)
144         return static_cast<WebFrame*>(frameLoaderClient);  // eek, is there a better way than static cast?
145     return 0;
146 }
147
148 Frame* core(WebFrame* webFrame)
149 {
150     if (!webFrame)
151         return 0;
152     return webFrame->impl();
153 }
154
155 // 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
156 Frame* core(const WebFrame* webFrame)
157 {
158     if (!webFrame)
159         return 0;
160     return const_cast<WebFrame*>(webFrame)->impl();
161 }
162
163 //-----------------------------------------------------------------------------
164
165 class FormValuesPropertyBag : public IPropertyBag, public IPropertyBag2
166 {
167 public:
168     FormValuesPropertyBag(HashMap<String, String>* formValues) : m_formValues(formValues) {}
169
170     // IUnknown
171     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
172     virtual ULONG STDMETHODCALLTYPE AddRef(void);
173     virtual ULONG STDMETHODCALLTYPE Release(void);
174
175     // IPropertyBag
176     virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( 
177         /* [in] */ LPCOLESTR pszPropName,
178         /* [out][in] */ VARIANT* pVar,
179         /* [in] */ IErrorLog* pErrorLog);
180
181     virtual HRESULT STDMETHODCALLTYPE Write( 
182         /* [in] */ LPCOLESTR pszPropName,
183         /* [in] */ VARIANT* pVar);
184
185     // IPropertyBag2
186     virtual HRESULT STDMETHODCALLTYPE Read( 
187         /* [in] */ ULONG cProperties,
188         /* [in] */ PROPBAG2 *pPropBag,
189         /* [in] */ IErrorLog *pErrLog,
190         /* [out] */ VARIANT *pvarValue,
191         /* [out] */ HRESULT *phrError);
192     
193     virtual HRESULT STDMETHODCALLTYPE Write( 
194         /* [in] */ ULONG cProperties,
195         /* [in] */ PROPBAG2 *pPropBag,
196         /* [in] */ VARIANT *pvarValue);
197     
198     virtual HRESULT STDMETHODCALLTYPE CountProperties( 
199         /* [out] */ ULONG *pcProperties);
200     
201     virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo( 
202         /* [in] */ ULONG iProperty,
203         /* [in] */ ULONG cProperties,
204         /* [out] */ PROPBAG2 *pPropBag,
205         /* [out] */ ULONG *pcProperties);
206     
207     virtual HRESULT STDMETHODCALLTYPE LoadObject( 
208         /* [in] */ LPCOLESTR pstrName,
209         /* [in] */ DWORD dwHint,
210         /* [in] */ IUnknown *pUnkObject,
211         /* [in] */ IErrorLog *pErrLog);
212     
213 protected:
214     HashMap<String, String>* m_formValues;
215 };
216
217 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::QueryInterface(REFIID riid, void** ppvObject)
218 {
219     *ppvObject = 0;
220     if (IsEqualGUID(riid, IID_IUnknown))
221         *ppvObject = this;
222     else if (IsEqualGUID(riid, IID_IPropertyBag))
223         *ppvObject = static_cast<IPropertyBag*>(this);
224     else if (IsEqualGUID(riid, IID_IPropertyBag2))
225         *ppvObject = static_cast<IPropertyBag2*>(this);
226     else
227         return E_NOINTERFACE;
228
229     AddRef();
230     return S_OK;
231 }
232
233 ULONG STDMETHODCALLTYPE FormValuesPropertyBag::AddRef(void)
234 {
235     return 1;
236 }
237
238 ULONG STDMETHODCALLTYPE FormValuesPropertyBag::Release(void)
239 {
240     return 0;
241 }
242
243 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* /*pErrorLog*/)
244 {
245     HRESULT hr = S_OK;
246
247     if (!pszPropName || !pVar)
248         return E_POINTER;
249
250     String key(pszPropName);
251     if (!m_formValues->contains(key))
252         return E_INVALIDARG;
253     
254     String value = m_formValues->get(key);
255
256     VARTYPE requestedType = V_VT(pVar);
257     VariantClear(pVar);
258     V_VT(pVar) = VT_BSTR;
259     V_BSTR(pVar) = SysAllocStringLen(value.characters(), value.length());
260     if (value.length() && !V_BSTR(pVar))
261         return E_OUTOFMEMORY;
262
263     if (requestedType != VT_BSTR && requestedType != VT_EMPTY)
264         hr = VariantChangeType(pVar, pVar, VARIANT_NOUSEROVERRIDE | VARIANT_ALPHABOOL, requestedType);
265     
266     return hr;
267 }
268
269 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)
270 {
271     if (!pszPropName || !pVar)
272         return E_POINTER;
273     VariantClear(pVar);
274     return E_FAIL;
275 }
276
277 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Read( 
278     /* [in] */ ULONG cProperties,
279     /* [in] */ PROPBAG2* pPropBag,
280     /* [in] */ IErrorLog* pErrLog,
281     /* [out] */ VARIANT* pvarValue,
282     /* [out] */ HRESULT* phrError)
283 {
284     if (cProperties > (size_t)m_formValues->size())
285         return E_INVALIDARG;
286     if (!pPropBag || !pvarValue || !phrError)
287         return E_POINTER;
288
289     for (ULONG i=0; i<cProperties; i++) {
290         VariantInit(&pvarValue[i]);
291         phrError[i] = Read(pPropBag->pstrName, &pvarValue[i], pErrLog);
292     }
293
294     return S_OK;
295 }
296
297 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::Write( 
298     /* [in] */ ULONG /*cProperties*/,
299     /* [in] */ PROPBAG2* pPropBag,
300     /* [in] */ VARIANT* pvarValue)
301 {
302     if (!pPropBag || !pvarValue)
303         return E_POINTER;
304     return E_FAIL;
305 }
306
307 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::CountProperties( 
308     /* [out] */ ULONG* pcProperties)
309 {
310     *pcProperties = m_formValues->size();
311     return S_OK;
312 }
313
314 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::GetPropertyInfo( 
315     /* [in] */ ULONG iProperty,
316     /* [in] */ ULONG cProperties,
317     /* [out] */ PROPBAG2* pPropBag,
318     /* [out] */ ULONG* pcProperties)
319 {
320     if (iProperty > (size_t)m_formValues->size() || iProperty+cProperties > (size_t)m_formValues->size())
321         return E_INVALIDARG;
322     if (!pPropBag || !pcProperties)
323         return E_POINTER;
324
325     *pcProperties = 0;
326     ULONG i = 0;
327     ULONG endProperty = iProperty + cProperties;
328     for (HashMap<String, String>::iterator it = m_formValues->begin(); i<endProperty; i++) {
329         if (i >= iProperty) {
330             int storeIndex = (*pcProperties)++;
331             pPropBag[storeIndex].dwType = PROPBAG2_TYPE_DATA;
332             pPropBag[storeIndex].vt = VT_BSTR;
333             pPropBag[storeIndex].cfType = CF_TEXT;
334             pPropBag[storeIndex].dwHint = 0;
335             pPropBag[storeIndex].pstrName = const_cast<LPOLESTR>(it->first.charactersWithNullTermination());
336         }
337         ++it;
338     }
339
340     return S_OK;
341 }
342
343 HRESULT STDMETHODCALLTYPE FormValuesPropertyBag::LoadObject( 
344     /* [in] */ LPCOLESTR pstrName,
345     /* [in] */ DWORD /*dwHint*/,
346     /* [in] */ IUnknown* pUnkObject,
347     /* [in] */ IErrorLog* /*pErrLog*/)
348 {
349     if (!pstrName || !pUnkObject)
350         return E_POINTER;
351     return E_FAIL;
352 }
353
354 //-----------------------------------------------------------------------------
355
356 static Element *elementFromDOMElement(IDOMElement *element)
357 {
358     if (!element)
359         return 0;
360
361     COMPtr<IDOMElementPrivate> elePriv;
362     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
363     if (SUCCEEDED(hr)) {
364         Element* ele;
365         hr = elePriv->coreElement((void**)&ele);
366         if (SUCCEEDED(hr))
367             return ele;
368     }
369     return 0;
370 }
371
372 static HTMLFormElement *formElementFromDOMElement(IDOMElement *element)
373 {
374     if (!element)
375         return 0;
376
377     IDOMElementPrivate* elePriv;
378     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
379     if (SUCCEEDED(hr)) {
380         Element* ele;
381         hr = elePriv->coreElement((void**)&ele);
382         elePriv->Release();
383         if (SUCCEEDED(hr) && ele && ele->hasTagName(formTag))
384             return static_cast<HTMLFormElement*>(ele);
385     }
386     return 0;
387 }
388
389 static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element)
390 {
391     if (!element)
392         return 0;
393
394     IDOMElementPrivate* elePriv;
395     HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
396     if (SUCCEEDED(hr)) {
397         Element* ele;
398         hr = elePriv->coreElement((void**)&ele);
399         elePriv->Release();
400         if (SUCCEEDED(hr) && ele && ele->hasTagName(inputTag))
401             return static_cast<HTMLInputElement*>(ele);
402     }
403     return 0;
404 }
405
406 // WebFramePrivate ------------------------------------------------------------
407
408 class WebFrame::WebFramePrivate {
409 public:
410     WebFramePrivate() 
411         : frame(0)
412         , webView(0)
413         , m_policyFunction(0)
414         , m_pluginView(0) 
415         , m_hasSentResponseToPlugin(false) 
416     { 
417     }
418
419     ~WebFramePrivate() { }
420     FrameView* frameView() { return frame ? frame->view() : 0; }
421
422     Frame* frame;
423     WebView* webView;
424     FramePolicyFunction m_policyFunction;
425     COMPtr<WebFramePolicyListener> m_policyListener;
426     
427     // Points to the plugin view that data should be redirected to.
428     PluginViewWin* m_pluginView;
429     bool m_hasSentResponseToPlugin;
430 };
431
432 // WebFrame ----------------------------------------------------------------
433
434 WebFrame::WebFrame()
435 : m_refCount(0)
436 , d(new WebFrame::WebFramePrivate)
437 , m_quickRedirectComing(false)
438 , m_inPrintingMode(false)
439 , m_pageHeight(0)
440 {
441     WebFrameCount++;
442     gClassCount++;
443 }
444
445 WebFrame::~WebFrame()
446 {
447     delete d;
448     WebFrameCount--;
449     gClassCount--;
450 }
451
452 WebFrame* WebFrame::createInstance()
453 {
454     WebFrame* instance = new WebFrame();
455     instance->AddRef();
456     return instance;
457 }
458
459 HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling(
460     /* [in] */ BOOL flag)
461 {
462     if (Frame* frame = core(this))
463         if (FrameView* view = frame->view())
464             view->setAllowsScrolling(!!flag);
465
466     return S_OK;
467 }
468
469 HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling(
470     /* [retval][out] */ BOOL *flag)
471 {
472     if (flag)
473         if (Frame* frame = core(this))
474             if (FrameView* view = frame->view())
475                 *flag = view->allowsScrolling();
476
477     return S_OK;
478 }
479
480
481 // IUnknown -------------------------------------------------------------------
482
483 HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
484 {
485     *ppvObject = 0;
486     if (IsEqualGUID(riid, IID_WebFrame))
487         *ppvObject = this;
488     else if (IsEqualGUID(riid, IID_IUnknown))
489         *ppvObject = static_cast<IWebFrame*>(this);
490     else if (IsEqualGUID(riid, IID_IWebFrame))
491         *ppvObject = static_cast<IWebFrame*>(this);
492     else if (IsEqualGUID(riid, IID_IWebFramePrivate))
493         *ppvObject = static_cast<IWebFramePrivate*>(this);
494     else
495         return E_NOINTERFACE;
496
497     AddRef();
498     return S_OK;
499 }
500
501 ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
502 {
503     return ++m_refCount;
504 }
505
506 ULONG STDMETHODCALLTYPE WebFrame::Release(void)
507 {
508     ULONG newRef = --m_refCount;
509     if (!newRef)
510         delete(this);
511
512     return newRef;
513 }
514
515 // IWebFrame -------------------------------------------------------------------
516
517 HRESULT STDMETHODCALLTYPE WebFrame::name( 
518     /* [retval][out] */ BSTR* frameName)
519 {
520     if (!frameName) {
521         ASSERT_NOT_REACHED();
522         return E_POINTER;
523     }
524
525     *frameName = 0;
526
527     Frame* coreFrame = core(this);
528     if (!coreFrame)
529         return E_FAIL;
530
531     *frameName = BString(coreFrame->tree()->name()).release();
532     return S_OK;
533 }
534
535 HRESULT STDMETHODCALLTYPE WebFrame::webView( 
536     /* [retval][out] */ IWebView** view)
537 {
538     *view = 0;
539     if (!d->webView)
540         return E_FAIL;
541     *view = d->webView;
542     (*view)->AddRef();
543     return S_OK;
544 }
545
546 HRESULT STDMETHODCALLTYPE WebFrame::frameView(
547     /* [retval][out] */ IWebFrameView** /*view*/)
548 {
549     ASSERT_NOT_REACHED();
550     return E_NOTIMPL;
551 }
552
553 HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument( 
554     /* [retval][out] */ IDOMDocument** result)
555 {
556     if (!result) {
557         ASSERT_NOT_REACHED();
558         return E_POINTER;
559     }
560
561     *result = 0;
562
563     if (Frame* coreFrame = core(this))
564         if (Document* document = coreFrame->document())
565             *result = DOMDocument::createInstance(document);
566
567     return *result ? S_OK : E_FAIL;
568 }
569
570 HRESULT STDMETHODCALLTYPE WebFrame::frameElement( 
571     /* [retval][out] */ IDOMHTMLElement** /*frameElement*/)
572 {
573     ASSERT_NOT_REACHED();
574     return E_NOTIMPL;
575 }
576
577 HRESULT STDMETHODCALLTYPE WebFrame::currentForm( 
578         /* [retval][out] */ IDOMElement **currentForm)
579 {
580     if (!currentForm) {
581         ASSERT_NOT_REACHED();
582         return E_POINTER;
583     }
584
585     *currentForm = 0;
586
587     if (Frame* coreFrame = core(this))
588         if (HTMLFormElement* formElement = coreFrame->currentForm())
589             *currentForm = DOMElement::createInstance(formElement);
590
591     return *currentForm ? S_OK : E_FAIL;
592 }
593
594 HRESULT STDMETHODCALLTYPE WebFrame::loadRequest( 
595     /* [in] */ IWebURLRequest* request)
596 {
597     COMPtr<WebMutableURLRequest> requestImpl;
598
599     HRESULT hr = request->QueryInterface(CLSID_WebMutableURLRequest, (void**)&requestImpl);
600     if (FAILED(hr))
601         return hr;
602  
603     Frame* coreFrame = core(this);
604     if (!coreFrame)
605         return E_FAIL;
606
607     coreFrame->loader()->load(requestImpl->resourceRequest());
608     return S_OK;
609 }
610
611 void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL)
612 {
613     String mimeTypeString(mimeType, SysStringLen(mimeType));
614     if (!mimeType)
615         mimeTypeString = "text/html";
616
617     String encodingString(textEncodingName, SysStringLen(textEncodingName));
618     KURL baseKURL = DeprecatedString((DeprecatedChar*)baseURL, SysStringLen(baseURL));
619     KURL failingKURL = DeprecatedString((DeprecatedChar*)failingURL, SysStringLen(failingURL));
620
621     ResourceRequest request(baseKURL);
622     SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL);
623
624     // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null.
625     if (Frame* coreFrame = core(this))
626         coreFrame->loader()->load(request, substituteData);
627 }
628
629
630 HRESULT STDMETHODCALLTYPE WebFrame::loadData( 
631     /* [in] */ IStream* data,
632     /* [in] */ BSTR mimeType,
633     /* [in] */ BSTR textEncodingName,
634     /* [in] */ BSTR url)
635 {
636     RefPtr<SharedBuffer> sharedBuffer = new SharedBuffer();
637
638     STATSTG stat;
639     if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) {
640         if (!stat.cbSize.HighPart && stat.cbSize.LowPart) {
641             Vector<char> dataBuffer(stat.cbSize.LowPart);
642             ULONG read;
643             // FIXME: this does a needless copy, would be better to read right into the SharedBuffer
644             // or adopt the Vector or something.
645             if (SUCCEEDED(data->Read(dataBuffer.data(), (ULONG)dataBuffer.size(), &read)))
646                 sharedBuffer->append(dataBuffer.data(), (int)dataBuffer.size());
647         }
648     }
649
650     loadData(sharedBuffer, mimeType, textEncodingName, url, 0);
651     return S_OK;
652 }
653
654 void WebFrame::loadHTMLString(BSTR string, BSTR baseURL, BSTR unreachableURL)
655 {
656     RefPtr<SharedBuffer> sharedBuffer = new SharedBuffer(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
657     BString utf16Encoding(TEXT("utf-16"), 6);
658     loadData(sharedBuffer.release(), 0, utf16Encoding, baseURL, unreachableURL);
659 }
660
661 HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString( 
662     /* [in] */ BSTR string,
663     /* [in] */ BSTR baseURL)
664 {
665     loadHTMLString(string, baseURL, 0);
666     return S_OK;
667 }
668
669 HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString( 
670     /* [in] */ BSTR str,
671     /* [in] */ BSTR baseURL,
672     /* [in] */ BSTR unreachableURL)
673 {
674     loadHTMLString(str, baseURL, unreachableURL);
675     return S_OK;
676 }
677
678 HRESULT STDMETHODCALLTYPE WebFrame::loadArchive( 
679     /* [in] */ IWebArchive* /*archive*/)
680 {
681     ASSERT_NOT_REACHED();
682     return E_NOTIMPL;
683 }
684
685 static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
686 {
687     return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
688 }
689
690 HRESULT STDMETHODCALLTYPE WebFrame::dataSource( 
691     /* [retval][out] */ IWebDataSource** source)
692 {
693     if (!source) {
694         ASSERT_NOT_REACHED();
695         return E_POINTER;
696     }
697
698     *source = 0;
699
700     Frame* coreFrame = core(this);
701     if (!coreFrame)
702         return E_FAIL;
703
704     WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->documentLoader());
705
706     *source = webDataSource;
707
708     if (webDataSource)
709         webDataSource->AddRef(); 
710
711     return *source ? S_OK : E_FAIL;
712 }
713
714 HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource( 
715     /* [retval][out] */ IWebDataSource** source)
716 {
717     if (!source) {
718         ASSERT_NOT_REACHED();
719         return E_POINTER;
720     }
721
722     *source = 0;
723
724     Frame* coreFrame = core(this);
725     if (!coreFrame)
726         return E_FAIL;
727
728     WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->provisionalDocumentLoader());
729
730     *source = webDataSource;
731
732     if (webDataSource)
733         webDataSource->AddRef(); 
734
735     return *source ? S_OK : E_FAIL;
736 }
737
738 KURL WebFrame::url() const
739 {
740     Frame* coreFrame = core(this);
741     if (!coreFrame)
742         return KURL();
743
744     return coreFrame->loader()->URL();
745 }
746
747 HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
748 {
749     if (Frame* coreFrame = core(this))
750         coreFrame->loader()->stopAllLoaders();
751     return S_OK;
752 }
753
754 HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
755 {
756     Frame* coreFrame = core(this);
757     if (!coreFrame)
758         return E_FAIL;
759
760     coreFrame->loader()->reload();
761     return S_OK;
762 }
763
764 HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed( 
765     /* [in] */ BSTR name,
766     /* [retval][out] */ IWebFrame** frame)
767 {
768     if (!frame) {
769         ASSERT_NOT_REACHED();
770         return E_POINTER;
771     }
772
773     *frame = 0;
774
775     Frame* coreFrame = core(this);
776     if (!coreFrame)
777         return E_FAIL;
778
779     Frame* foundFrame = coreFrame->tree()->find(AtomicString(name, SysStringLen(name)));
780     if (!foundFrame)
781         return S_OK;
782
783     WebFrame* foundWebFrame = kit(foundFrame);
784     if (!foundWebFrame)
785         return E_FAIL;
786
787     return foundWebFrame->QueryInterface(IID_IWebFrame, (void**)frame);
788 }
789
790 HRESULT STDMETHODCALLTYPE WebFrame::parentFrame( 
791     /* [retval][out] */ IWebFrame** frame)
792 {
793     HRESULT hr = S_OK;
794     *frame = 0;
795     if (Frame* coreFrame = core(this))
796         if (WebFrame* webFrame = kit(coreFrame->tree()->parent()))
797             hr = webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
798
799     return hr;
800 }
801
802 class EnumChildFrames : public IEnumVARIANT
803 {
804 public:
805     EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree()->firstChild() : 0) { }
806
807     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
808     {
809         *ppvObject = 0;
810         if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
811             *ppvObject = this;
812         else
813             return E_NOINTERFACE;
814
815         AddRef();
816         return S_OK;
817     }
818
819     virtual ULONG STDMETHODCALLTYPE AddRef(void)
820     {
821         return ++m_refCount;
822     }
823
824     virtual ULONG STDMETHODCALLTYPE Release(void)
825     {
826         ULONG newRef = --m_refCount;
827         if (!newRef)
828             delete(this);
829         return newRef;
830     }
831
832     virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
833     {
834         if (pCeltFetched)
835             *pCeltFetched = 0;
836         if (!rgVar)
837             return E_POINTER;
838         VariantInit(rgVar);
839         if (!celt || celt > 1)
840             return S_FALSE;
841         if (!m_frame || !m_curChild)
842             return S_FALSE;
843
844         WebFrame* webFrame = kit(m_curChild);
845         IUnknown* unknown;
846         HRESULT hr = webFrame->QueryInterface(IID_IUnknown, (void**)&unknown);
847         if (FAILED(hr))
848             return hr;
849
850         V_VT(rgVar) = VT_UNKNOWN;
851         V_UNKNOWN(rgVar) = unknown;
852
853         m_curChild = m_curChild->tree()->nextSibling();
854         if (pCeltFetched)
855             *pCeltFetched = 1;
856         return S_OK;
857     }
858
859     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
860     {
861         if (!m_frame)
862             return S_FALSE;
863         for (unsigned i = 0; i < celt && m_curChild; i++)
864             m_curChild = m_curChild->tree()->nextSibling();
865         return m_curChild ? S_OK : S_FALSE;
866     }
867
868     virtual HRESULT STDMETHODCALLTYPE Reset(void)
869     {
870         if (!m_frame)
871             return S_FALSE;
872         m_curChild = m_frame->tree()->firstChild();
873         return S_OK;
874     }
875
876     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**)
877     {
878         return E_NOTIMPL;
879     }
880
881 private:
882     ULONG m_refCount;
883     Frame* m_frame;
884     Frame* m_curChild;
885 };
886
887 HRESULT STDMETHODCALLTYPE WebFrame::childFrames( 
888     /* [retval][out] */ IEnumVARIANT **enumFrames)
889 {
890     if (!enumFrames)
891         return E_POINTER;
892
893     *enumFrames = new EnumChildFrames(core(this));
894     return S_OK;
895 }
896
897 // IWebFramePrivaete ------------------------------------------------------
898
899 HRESULT STDMETHODCALLTYPE WebFrame::renderTreeAsExternalRepresentation(
900     /* [retval][out] */ BSTR *result)
901 {
902     if (!result) {
903         ASSERT_NOT_REACHED();
904         return E_POINTER;
905     }
906
907     *result = 0;
908
909     Frame* coreFrame = core(this);
910     if (!coreFrame)
911         return E_FAIL;
912
913     DeprecatedString representation = externalRepresentation(coreFrame->renderer());
914
915     *result = SysAllocStringLen((LPCOLESTR)representation.unicode(), representation.length());
916
917     return S_OK;
918 }
919
920 HRESULT STDMETHODCALLTYPE WebFrame::scrollOffset(
921         /* [retval][out] */ SIZE* offset)
922 {
923     if (!offset) {
924         ASSERT_NOT_REACHED();
925         return E_POINTER;
926     }
927
928     Frame* coreFrame = core(this);
929     if (!coreFrame)
930         return E_FAIL;
931
932     FrameView* view = coreFrame->view();
933     if (!view)
934         return E_FAIL;
935
936     *offset = view->scrollOffset();
937     return S_OK;
938 }
939
940 HRESULT STDMETHODCALLTYPE WebFrame::layout()
941 {
942     Frame* coreFrame = core(this);
943     if (!coreFrame)
944         return E_FAIL;
945
946     FrameView* view = coreFrame->view();
947     if (!view)
948         return E_FAIL;
949
950     view->layout();
951     return S_OK;
952 }
953
954 HRESULT STDMETHODCALLTYPE WebFrame::firstLayoutDone(
955     /* [retval][out] */ BOOL* result)
956 {
957     if (!result) {
958         ASSERT_NOT_REACHED();
959         return E_POINTER;
960     }
961
962     *result = 0;
963
964     Frame* coreFrame = core(this);
965     if (!coreFrame)
966         return E_FAIL;
967
968     *result = coreFrame->loader()->firstLayoutDone();
969     return S_OK;
970 }
971
972 HRESULT STDMETHODCALLTYPE WebFrame::loadType( 
973     /* [retval][out] */ WebFrameLoadType* type)
974 {
975     if (!type) {
976         ASSERT_NOT_REACHED();
977         return E_POINTER;
978     }
979
980     *type = (WebFrameLoadType)0;
981
982     Frame* coreFrame = core(this);
983     if (!coreFrame)
984         return E_FAIL;
985
986     *type = (WebFrameLoadType)coreFrame->loader()->loadType();
987     return S_OK;
988 }
989
990
991 // WebFrame ---------------------------------------------------------------
992
993 void WebFrame::initWithWebFrameView(IWebFrameView* /*view*/, IWebView* webView, Page* page, HTMLFrameOwnerElement* ownerElement)
994 {
995     if (FAILED(webView->QueryInterface(CLSID_WebView, (void**)&d->webView)))
996         return;
997     d->webView->Release(); // don't hold the extra ref
998
999     HWND viewWindow;
1000     d->webView->viewWindow((OLE_HANDLE*)&viewWindow);
1001
1002     this->AddRef(); // We release this ref in frameLoaderDestroyed()
1003     Frame* frame = new Frame(page, ownerElement, this);
1004     d->frame = frame;
1005
1006     FrameView* frameView = new FrameView(frame);
1007
1008     frame->setView(frameView);
1009     frameView->deref(); // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame.
1010
1011     frameView->setContainingWindow(viewWindow);
1012 }
1013
1014 Frame* WebFrame::impl()
1015 {
1016     return d->frame;
1017 }
1018
1019 void WebFrame::invalidate()
1020 {
1021     Frame* coreFrame = core(this);
1022     ASSERT(coreFrame);
1023
1024     if (Document* document = coreFrame->document())
1025         document->recalcStyle(Node::Force);
1026 }
1027
1028 void WebFrame::setTextSizeMultiplier(float multiplier)
1029 {
1030     int newZoomFactor = (int)round(multiplier * 100);
1031     Frame* coreFrame = core(this);
1032     ASSERT(coreFrame);
1033
1034     if (coreFrame->zoomFactor() == newZoomFactor)
1035         return;
1036
1037     coreFrame->setZoomFactor(newZoomFactor);
1038 }
1039
1040 HRESULT WebFrame::inViewSourceMode(BOOL* flag)
1041 {
1042     if (!flag) {
1043         ASSERT_NOT_REACHED();
1044         return E_POINTER;
1045     }
1046
1047     *flag = FALSE;
1048
1049     Frame* coreFrame = core(this);
1050     if (!coreFrame)
1051         return E_FAIL;
1052
1053     *flag = coreFrame->inViewSourceMode() ? TRUE : FALSE;
1054     return S_OK;
1055 }
1056
1057 HRESULT WebFrame::setInViewSourceMode(BOOL flag)
1058 {
1059     Frame* coreFrame = core(this);
1060     if (!coreFrame)
1061         return E_FAIL;
1062
1063     coreFrame->setInViewSourceMode(!!flag);
1064     return S_OK;
1065 }
1066
1067 HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** element)
1068 {
1069     if (!form)
1070         return E_INVALIDARG;
1071
1072     HTMLFormElement *formElement = formElementFromDOMElement(form);
1073     if (formElement) {
1074         Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
1075         AtomicString targetName((UChar*)name, SysStringLen(name));
1076         for (unsigned int i = 0; i < elements.size(); i++) {
1077             HTMLGenericFormElement *elt = elements[i];
1078             // Skip option elements, other duds
1079             if (elt->name() == targetName) {
1080                 *element = DOMElement::createInstance(elt);
1081                 return S_OK;
1082             }
1083         }
1084     }
1085     return E_FAIL;
1086 }
1087
1088 HRESULT WebFrame::formForElement(IDOMElement* element, IDOMElement** form)
1089 {
1090     if (!element)
1091         return E_INVALIDARG;
1092
1093     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1094     if (!inputElement)
1095         return E_FAIL;
1096
1097     HTMLFormElement *formElement = inputElement->form();
1098     if (!formElement)
1099         return E_FAIL;
1100
1101     *form = DOMElement::createInstance(formElement);
1102     return S_OK;
1103 }
1104
1105 HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, bool *result)
1106 {
1107     *result = false;
1108     if (!element)
1109         return E_INVALIDARG;
1110
1111     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1112     if (!inputElement)
1113         *result = false;
1114     else
1115         *result = (inputElement->inputType() == HTMLInputElement::TEXT && inputElement->autoComplete());
1116
1117     return S_OK;
1118 }
1119
1120 HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls)
1121 {
1122     if (!form)
1123         return E_INVALIDARG;
1124
1125     HTMLFormElement *formElement = formElementFromDOMElement(form);
1126     if (!formElement)
1127         return E_FAIL;
1128
1129     int inCount = *cControls;
1130     int count = (int) formElement->formElements.size();
1131     *cControls = count;
1132     if (!controls)
1133         return S_OK;
1134     if (inCount < count)
1135         return E_FAIL;
1136
1137     *cControls = 0;
1138     Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
1139     for (int i = 0; i < count; i++) {
1140         if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1141             controls[*cControls] = DOMElement::createInstance(elements.at(i));
1142             (*cControls)++;
1143         }
1144     }
1145     return S_OK;
1146 }
1147
1148 HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result)
1149 {
1150     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1151     *result = inputElement != 0
1152         && inputElement->inputType() == HTMLInputElement::PASSWORD;
1153     return S_OK;
1154 }
1155
1156 HRESULT WebFrame::searchForLabelsBeforeElement(const BSTR* labels, int cLabels, IDOMElement* beforeElement, BSTR* result)
1157 {
1158     if (!result) {
1159         ASSERT_NOT_REACHED();
1160         return E_POINTER;
1161     }
1162
1163     *result = 0;
1164
1165     if (!cLabels)
1166         return S_OK;
1167     if (cLabels < 1)
1168         return E_INVALIDARG;
1169
1170     Frame* coreFrame = core(this);
1171     if (!coreFrame)
1172         return E_FAIL;
1173
1174     Vector<String> labelStrings(cLabels);
1175     for (int i=0; i<cLabels; i++)
1176         labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1177     Element *coreElement = elementFromDOMElement(beforeElement);
1178     if (!coreElement)
1179         return E_FAIL;
1180
1181     String label = coreFrame->searchForLabelsBeforeElement(labelStrings, coreElement);
1182     
1183     *result = SysAllocStringLen(label.characters(), label.length());
1184     if (label.length() && !*result)
1185         return E_OUTOFMEMORY;
1186     return S_OK;
1187 }
1188
1189 HRESULT WebFrame::matchLabelsAgainstElement(const BSTR* labels, int cLabels, IDOMElement* againstElement, BSTR* result)
1190 {
1191     if (!result) {
1192         ASSERT_NOT_REACHED();
1193         return E_POINTER;
1194     }
1195
1196     *result = 0;
1197
1198     if (!cLabels)
1199         return S_OK;
1200     if (cLabels < 1)
1201         return E_INVALIDARG;
1202
1203     Frame* coreFrame = core(this);
1204     if (!coreFrame)
1205         return E_FAIL;
1206
1207     Vector<String> labelStrings(cLabels);
1208     for (int i=0; i<cLabels; i++)
1209         labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1210     Element *coreElement = elementFromDOMElement(againstElement);
1211     if (!coreElement)
1212         return E_FAIL;
1213
1214     String label = coreFrame->matchLabelsAgainstElement(labelStrings, coreElement);
1215     
1216     *result = SysAllocStringLen(label.characters(), label.length());
1217     if (label.length() && !*result)
1218         return E_OUTOFMEMORY;
1219     return S_OK;
1220 }
1221
1222 HRESULT WebFrame::canProvideDocumentSource(bool* result)
1223 {
1224     HRESULT hr = S_OK;
1225     *result = false;
1226
1227     COMPtr<IWebDataSource> dataSource;
1228     hr = WebFrame::dataSource(&dataSource);
1229     if (FAILED(hr))
1230         return hr;
1231
1232     COMPtr<IWebURLResponse> urlResponse;
1233     hr = dataSource->response(&urlResponse);
1234     if (SUCCEEDED(hr) && urlResponse) {
1235         BSTR mimeTypeBStr;
1236         if (SUCCEEDED(urlResponse->MIMEType(&mimeTypeBStr))) {
1237             String mimeType(mimeTypeBStr, SysStringLen(mimeTypeBStr));
1238             *result = mimeType == "text/html" || WebCore::DOMImplementation::isXMLMIMEType(mimeType);
1239             SysFreeString(mimeTypeBStr);
1240         }
1241     }
1242     return hr;
1243 }
1244
1245 // FrameWinClient
1246
1247 void WebFrame::ref()
1248 {
1249     this->AddRef();
1250 }
1251
1252 void WebFrame::deref()
1253 {
1254     this->Release();
1255 }
1256
1257 void WebFrame::frameLoaderDestroyed()
1258 {
1259     // The FrameLoader going away is equivalent to the Frame going away,
1260     // so we now need to clear our frame pointer.
1261     d->frame = 0;
1262
1263     this->Release();
1264 }
1265
1266 PassRefPtr<Frame> WebFrame::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer)
1267 {
1268     Frame* coreFrame = core(this);
1269     ASSERT(coreFrame);
1270
1271     COMPtr<WebFrame> webFrame;
1272     webFrame.adoptRef(WebFrame::createInstance());
1273
1274     webFrame->initWithWebFrameView(0, d->webView, coreFrame->page(), ownerElement);
1275
1276     RefPtr<Frame> childFrame(adoptRef(core(webFrame.get()))); // We have to adopt, because Frames start out with a refcount of 1.
1277     ASSERT(childFrame);
1278
1279     coreFrame->tree()->appendChild(childFrame);
1280     childFrame->tree()->setName(name);
1281     childFrame->init();
1282
1283     loadURLIntoChild(URL, referrer, webFrame.get());
1284
1285     // The frame's onload handler may have removed it from the document.
1286     if (!childFrame->tree()->parent())
1287         return 0;
1288
1289     return childFrame.release();
1290 }
1291
1292 void WebFrame::loadURLIntoChild(const KURL& originalURL, const String& referrer, WebFrame* childFrame)
1293 {
1294     ASSERT(childFrame);
1295     ASSERT(core(childFrame));
1296
1297     Frame* coreFrame = core(this);
1298     ASSERT(coreFrame);
1299
1300     HistoryItem* parentItem = coreFrame->loader()->currentHistoryItem();
1301     FrameLoadType loadType = coreFrame->loader()->loadType();
1302     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
1303
1304     KURL url = originalURL;
1305
1306     // If we're moving in the backforward list, we might want to replace the content
1307     // of this child frame with whatever was there at that point.
1308     // Reload will maintain the frame contents, LoadSame will not.
1309     if (parentItem && parentItem->children().size() &&
1310         (isBackForwardLoadType(loadType)
1311          || loadType == FrameLoadTypeReload
1312          || loadType == FrameLoadTypeReloadAllowingStaleData))
1313     {
1314         if (HistoryItem* childItem = parentItem->childItemWithName(core(childFrame)->tree()->name())) {
1315             // Use the original URL to ensure we get all the side-effects, such as
1316             // onLoad handlers, of any redirects that happened. An example of where
1317             // this is needed is Radar 3213556.
1318             url = childItem->originalURLString().deprecatedString();
1319             // These behaviors implied by these loadTypes should apply to the child frames
1320             childLoadType = loadType;
1321
1322             if (isBackForwardLoadType(loadType))
1323                 // For back/forward, remember this item so we can traverse any child items as child frames load
1324                 core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
1325             else
1326                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
1327                 core(childFrame)->loader()->setCurrentHistoryItem(childItem);
1328         }
1329     }
1330
1331     // FIXME: Handle loading WebArchives here
1332
1333     core(childFrame)->loader()->load(url, referrer, childLoadType, String(), 0, 0);
1334 }
1335
1336 void WebFrame::openURL(const String& URL, const Event* triggeringEvent, bool newWindow, bool lockHistory)
1337 {
1338     bool ctrlPressed = false;
1339     bool shiftPressed = false;
1340     if (triggeringEvent) {
1341         if (triggeringEvent->isMouseEvent()) {
1342             const MouseRelatedEvent* mouseEvent = static_cast<const MouseRelatedEvent*>(triggeringEvent);
1343             ctrlPressed = mouseEvent->ctrlKey();
1344             shiftPressed = mouseEvent->shiftKey();
1345         } else if (triggeringEvent->isKeyboardEvent()) {
1346             const KeyboardEvent* keyEvent = static_cast<const KeyboardEvent*>(triggeringEvent);
1347             ctrlPressed = keyEvent->ctrlKey();
1348             shiftPressed = keyEvent->shiftKey();
1349         }
1350     }
1351
1352     if (ctrlPressed)
1353         newWindow = true;
1354
1355     BString urlBStr = URL;
1356
1357     IWebMutableURLRequest* request = WebMutableURLRequest::createInstance();
1358     if (FAILED(request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0)))
1359         goto exit;
1360
1361     if (newWindow) {
1362         // new tab/window
1363         IWebUIDelegate* ui;
1364         IWebView* newWebView;
1365         if (SUCCEEDED(d->webView->uiDelegate(&ui)) && ui) {
1366             if (SUCCEEDED(ui->createWebViewWithRequest(d->webView, request, &newWebView))) {
1367                 if (shiftPressed) {
1368                     // Ctrl-Option-Shift-click:  Opens a link in a new window and selects it.
1369                     // Ctrl-Shift-click:  Opens a link in a new tab and selects it.
1370                     ui->webViewShow(d->webView);
1371                 }
1372                 newWebView->Release();
1373                 newWebView = 0;
1374             }
1375             ui->Release();
1376         }
1377     } else {
1378         m_quickRedirectComing = lockHistory;
1379         loadRequest(request);
1380     }
1381
1382 exit:
1383     request->Release();
1384 }
1385
1386 void WebFrame::dispatchDidHandleOnloadEvents()
1387 {
1388     IWebFrameLoadDelegatePrivate* frameLoadDelegatePriv;
1389     if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv))  && frameLoadDelegatePriv) {
1390         frameLoadDelegatePriv->didHandleOnloadEventsForFrame(d->webView, this);
1391         frameLoadDelegatePriv->Release();
1392     }
1393 }
1394
1395 void WebFrame::windowScriptObjectAvailable(JSContextRef context, JSObjectRef windowObject)
1396 {
1397     IWebFrameLoadDelegate* frameLoadDelegate;
1398     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)) && frameLoadDelegate) {
1399         frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject);
1400         frameLoadDelegate->Release();
1401     }
1402 }
1403
1404 WebHistory* WebFrame::webHistory()
1405 {
1406     if (this != d->webView->topLevelFrame())
1407         return 0;
1408
1409     IWebHistoryPrivate* historyInternal = WebHistory::optionalSharedHistoryInternal(); // does not add a ref
1410     if (!historyInternal)
1411         return 0;
1412
1413     WebHistory* webHistory;
1414     if (FAILED(historyInternal->QueryInterface(CLSID_WebHistory, (void**)&webHistory)))
1415         return 0;
1416
1417     return webHistory;
1418 }
1419
1420 bool WebFrame::hasWebView() const
1421 {
1422     return !!d->webView;
1423 }
1424
1425 bool WebFrame::hasFrameView() const
1426 {
1427     return !!d->frameView();
1428 }
1429
1430 bool WebFrame::privateBrowsingEnabled() const
1431 {
1432     BOOL privateBrowsingEnabled = FALSE;
1433     COMPtr<IWebPreferences> preferences;
1434     if (SUCCEEDED(d->webView->preferences(&preferences)))
1435         preferences->privateBrowsingEnabled(&privateBrowsingEnabled);
1436     return !!privateBrowsingEnabled;
1437 }
1438
1439 void WebFrame::makeDocumentView()
1440 {
1441     ASSERT(core(this));
1442     
1443     // On the mac, this is done in Frame::setView, but since we don't have separate 
1444     // frame views, we'll just do it here instead.
1445     core(this)->loader()->resetMultipleFormSubmissionProtection();
1446 }
1447
1448 void WebFrame::makeRepresentation(DocumentLoader*)
1449 {
1450     notImplemented();
1451 }
1452
1453 void WebFrame::forceLayout()
1454 {
1455     notImplemented();
1456 }
1457
1458 void WebFrame::forceLayoutForNonHTML()
1459 {
1460     notImplemented();
1461 }
1462
1463 void WebFrame::setCopiesOnScroll()
1464 {
1465     notImplemented();
1466 }
1467
1468 void WebFrame::detachedFromParent1()
1469 {
1470     notImplemented();
1471 }
1472
1473 void WebFrame::detachedFromParent2()
1474 {
1475     notImplemented();
1476 }
1477
1478 void WebFrame::detachedFromParent3()
1479 {
1480     notImplemented();
1481 }
1482
1483 void WebFrame::detachedFromParent4()
1484 {
1485     notImplemented();
1486 }
1487
1488 void WebFrame::loadedFromCachedPage()
1489 {
1490     notImplemented();
1491 }
1492
1493 void WebFrame::dispatchDidReceiveServerRedirectForProvisionalLoad()
1494 {
1495     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1496     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1497         frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(d->webView, this);
1498 }
1499
1500 void WebFrame::dispatchDidCancelClientRedirect()
1501 {
1502     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1503     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1504         frameLoadDelegate->didCancelClientRedirectForFrame(d->webView, this);
1505 }
1506
1507 void WebFrame::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
1508 {
1509     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1510     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1511         frameLoadDelegate->willPerformClientRedirectToURL(d->webView, BString(url.url()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), this);
1512 }
1513
1514 void WebFrame::dispatchDidChangeLocationWithinPage()
1515 {
1516     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1517     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1518         frameLoadDelegate->didChangeLocationWithinPageForFrame(d->webView, this);
1519 }
1520
1521 void WebFrame::dispatchWillClose()
1522 {
1523     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1524     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1525         frameLoadDelegate->willCloseFrame(d->webView, this);
1526 }
1527
1528 void WebFrame::dispatchDidReceiveIcon()
1529 {
1530     d->webView->dispatchDidReceiveIconFromWebFrame(this);
1531 }
1532
1533 void WebFrame::dispatchDidStartProvisionalLoad()
1534 {
1535     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1536     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1537         frameLoadDelegate->didStartProvisionalLoadForFrame(d->webView, this);
1538 }
1539
1540 void WebFrame::dispatchDidReceiveTitle(const String& title)
1541 {
1542     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1543     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1544         frameLoadDelegate->didReceiveTitle(d->webView, BString(title), this);
1545 }
1546
1547 void WebFrame::dispatchDidCommitLoad()
1548 {
1549     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1550     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) 
1551         frameLoadDelegate->didCommitLoadForFrame(d->webView, this);
1552 }
1553
1554 void WebFrame::dispatchDidFinishDocumentLoad()
1555 {
1556     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
1557     if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
1558         frameLoadDelegatePriv->didFinishDocumentLoadForFrame(d->webView, this);
1559 }
1560
1561 void WebFrame::dispatchDidFinishLoad()
1562 {
1563     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1564     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) 
1565         frameLoadDelegate->didFinishLoadForFrame(d->webView, this);
1566 }
1567
1568 void WebFrame::dispatchDidFirstLayout()
1569 {
1570     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
1571     if (SUCCEEDED(d->webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
1572         frameLoadDelegatePriv->didFirstLayoutInFrame(d->webView, this);
1573 }
1574
1575 void WebFrame::dispatchShow()
1576 {
1577     COMPtr<IWebUIDelegate> ui;
1578
1579     if (SUCCEEDED(d->webView->uiDelegate(&ui)))
1580         ui->webViewShow(d->webView);
1581 }
1582
1583 void WebFrame::cancelPolicyCheck()
1584 {
1585     if (d->m_policyListener) {
1586         d->m_policyListener->invalidate();
1587         d->m_policyListener = 0;
1588     }
1589
1590     d->m_policyFunction = 0;
1591 }
1592
1593 void WebFrame::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
1594 {
1595     Frame* coreFrame = core(this);
1596     ASSERT(coreFrame);
1597
1598     COMPtr<IWebFormDelegate> formDelegate;
1599
1600     if (FAILED(d->webView->formDelegate(&formDelegate))) {
1601         (coreFrame->loader()->*function)(PolicyUse);
1602         return;
1603     }
1604
1605     COMPtr<IDOMElement> formElement;
1606     formElement.adoptRef(DOMElement::createInstance(formState->form()));
1607
1608     // FIXME: The FormValuesPropertyBag constructor should take a const pointer
1609     FormValuesPropertyBag formValuesPropBag(const_cast<HashMap<String, String>*>(&formState->values()));
1610
1611     COMPtr<WebFrame> sourceFrame(kit(formState->sourceFrame()));
1612     if (SUCCEEDED(formDelegate->willSubmitForm(this, sourceFrame.get(), formElement.get(), &formValuesPropBag, setUpPolicyListener(function).get())))
1613         return;
1614
1615     // FIXME: Add a sane default implementation
1616     (coreFrame->loader()->*function)(PolicyUse);
1617 }
1618
1619 void WebFrame::dispatchDidLoadMainResource(DocumentLoader*)
1620 {
1621     notImplemented();
1622 }
1623
1624 void WebFrame::revertToProvisionalState(DocumentLoader*)
1625 {
1626     notImplemented();
1627 }
1628
1629 void WebFrame::clearUnarchivingState(DocumentLoader*)
1630 {
1631     notImplemented();
1632 }
1633
1634 void WebFrame::setMainFrameDocumentReady(bool)
1635 {
1636     notImplemented();
1637 }
1638
1639 void WebFrame::willChangeTitle(DocumentLoader*)
1640 {
1641     notImplemented();
1642 }
1643
1644 void WebFrame::didChangeTitle(DocumentLoader*)
1645 {
1646     notImplemented();
1647 }
1648
1649 void WebFrame::finishedLoading(DocumentLoader* loader)
1650 {
1651     // Telling the frame we received some data and passing 0 as the data is our
1652     // way to get work done that is noramlly done when the first bit of data is
1653     // received, even for the case of a documenbt with no data (like about:blank)
1654     if (!d->m_pluginView)
1655         committedLoad(loader, 0, 0);
1656     else {
1657         d->m_pluginView->didFinishLoading();
1658         d->m_pluginView = 0;
1659         d->m_hasSentResponseToPlugin = false;
1660     }
1661 }
1662
1663 void WebFrame::finalSetupForReplace(DocumentLoader*)
1664 {
1665     notImplemented();
1666 }
1667
1668 void WebFrame::setDefersLoading(bool)
1669 {
1670     notImplemented();
1671 }
1672
1673 bool WebFrame::isArchiveLoadPending(ResourceLoader*) const
1674 {
1675     notImplemented();
1676     return false;
1677 }
1678
1679 void WebFrame::cancelPendingArchiveLoad(ResourceLoader*)
1680 {
1681     notImplemented();
1682 }
1683
1684 void WebFrame::clearArchivedResources()
1685 {
1686     notImplemented();
1687 }
1688
1689 bool WebFrame::canHandleRequest(const ResourceRequest& request) const
1690 {
1691     return WebView::canHandleRequest(request);
1692 }
1693
1694 bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const
1695 {
1696     notImplemented();
1697     return true;
1698 }
1699
1700 bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const
1701 {
1702     notImplemented();
1703     return false;
1704 }
1705
1706 String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1707 {
1708     notImplemented();
1709     ASSERT_NOT_REACHED();
1710     return String();
1711 }
1712
1713 void WebFrame::frameLoadCompleted()
1714 {
1715     if (Frame* coreFrame = core(this))
1716         coreFrame->loader()->setPreviousHistoryItem(0);
1717 }
1718
1719 void WebFrame::restoreViewState()
1720 {
1721     // FIXME: Need to restore view state for page caching
1722     notImplemented();
1723 }
1724
1725 void WebFrame::provisionalLoadStarted()
1726 {
1727     notImplemented();
1728 }
1729
1730 bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const
1731 {
1732     notImplemented();
1733     return false;
1734 }
1735
1736 void WebFrame::addHistoryItemForFragmentScroll()
1737 {
1738     notImplemented();
1739 }
1740
1741 void WebFrame::didFinishLoad()
1742 {
1743     notImplemented();
1744 }
1745
1746 void WebFrame::prepareForDataSourceReplacement()
1747 {
1748     notImplemented();
1749 }
1750
1751 void WebFrame::setTitle(const String& title, const KURL& url)
1752 {
1753     BOOL privateBrowsingEnabled = FALSE;
1754     COMPtr<IWebPreferences> preferences;
1755     if (SUCCEEDED(d->webView->preferences(&preferences)))
1756         preferences->privateBrowsingEnabled(&privateBrowsingEnabled);
1757     if (!privateBrowsingEnabled) {
1758         // update title in global history
1759         COMPtr<WebHistory> history;
1760         history.adoptRef(webHistory());
1761         if (history) {
1762             COMPtr<IWebHistoryItem> item;
1763             if (SUCCEEDED(history->itemForURL(BString(url.url()), &item))) {
1764                 COMPtr<IWebHistoryItemPrivate> itemPrivate;
1765                 if (SUCCEEDED(item->QueryInterface(IID_IWebHistoryItemPrivate, (void**)&itemPrivate)))
1766                     itemPrivate->setTitle(BString(title));
1767             }
1768         }
1769     }
1770 }
1771
1772 String WebFrame::userAgent(const KURL& url)
1773 {
1774     return d->webView->userAgentForKURL(url);
1775 }
1776
1777 void WebFrame::setDocumentViewFromCachedPage(CachedPage*)
1778 {
1779     notImplemented();
1780 }
1781
1782 void WebFrame::updateGlobalHistoryForStandardLoad(const KURL& url)
1783 {
1784     COMPtr<WebHistory> history;
1785     history.adoptRef(webHistory());
1786
1787     if (!history)
1788         return;
1789
1790     history->addItemForURL(BString(url.url()), 0);                 
1791 }
1792
1793 void WebFrame::updateGlobalHistoryForReload(const KURL& url)
1794 {
1795     BString urlBStr(url.url());
1796
1797     COMPtr<WebHistory> history;
1798     history.adoptRef(webHistory());
1799
1800     if (!history)
1801         return;
1802
1803     COMPtr<IWebHistoryItem> item;
1804     if (SUCCEEDED(history->itemForURL(urlBStr, &item))) {
1805         COMPtr<IWebHistoryItemPrivate> itemPrivate;
1806         if (SUCCEEDED(item->QueryInterface(IID_IWebHistoryItemPrivate, (void**)&itemPrivate))) {
1807             SYSTEMTIME currentTime;
1808             GetSystemTime(&currentTime);
1809             DATE visitedTime = 0;
1810             SystemTimeToVariantTime(&currentTime, &visitedTime);
1811
1812             // FIXME - bumping the last visited time doesn't mark the history as changed
1813             itemPrivate->setLastVisitedTimeInterval(visitedTime);
1814         }
1815     }
1816 }
1817
1818 bool WebFrame::shouldGoToHistoryItem(HistoryItem*) const
1819 {
1820     notImplemented();
1821     return true;
1822 }
1823
1824 void WebFrame::saveViewStateToItem(HistoryItem*)
1825 {
1826     // FIXME: Need to save view state for page caching
1827     notImplemented();
1828 }
1829
1830 void WebFrame::saveDocumentViewToCachedPage(CachedPage*)
1831 {
1832     notImplemented();
1833 }
1834
1835 bool WebFrame::canCachePage() const
1836 {
1837     notImplemented();
1838     return false;
1839 }
1840
1841 PassRefPtr<DocumentLoader> WebFrame::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1842 {
1843     RefPtr<WebDocumentLoader> loader = new WebDocumentLoader(request, substituteData);
1844  
1845     COMPtr<WebDataSource> dataSource;
1846     dataSource.adoptRef(WebDataSource::createInstance(loader.get()));
1847
1848     loader->setDataSource(dataSource.get());
1849     return loader.release();
1850 }
1851
1852 void WebFrame::setMainDocumentError(DocumentLoader*, const ResourceError& error)
1853 {
1854     if (d->m_pluginView) {
1855         d->m_pluginView->didFail(error);
1856         d->m_pluginView = 0;
1857         d->m_hasSentResponseToPlugin = false;
1858     }
1859 }
1860
1861 ResourceError WebFrame::cancelledError(const ResourceRequest& request)
1862 {
1863     // FIXME: Need ChickenCat to include CFNetwork/CFURLError.h to get these values
1864     // Alternatively, we could create our own error domain/codes.
1865     return ResourceError(String(WebURLErrorDomain), -999, request.url().url(), String());
1866 }
1867
1868 ResourceError WebFrame::blockedError(const ResourceRequest& request)
1869 {
1870     // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1871     return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotUseRestrictedPort, request.url().url(), String());
1872 }
1873
1874 ResourceError WebFrame::cannotShowURLError(const ResourceRequest&)
1875 {
1876     notImplemented();
1877     return ResourceError();
1878 }
1879
1880 ResourceError WebFrame::interruptForPolicyChangeError(const ResourceRequest& request)
1881 {
1882     // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1883     return ResourceError(String(WebKitErrorDomain), WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().url(), String());
1884 }
1885
1886 ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&)
1887 {
1888     notImplemented();
1889     return ResourceError();
1890 }
1891
1892 ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&)
1893 {
1894     notImplemented();
1895     return ResourceError();
1896 }
1897
1898 bool WebFrame::shouldFallBack(const ResourceError& error)
1899 {
1900     return error.errorCode() != WebURLErrorCancelled;
1901 }
1902
1903 void WebFrame::receivedData(const char* data, int length, const String& textEncoding)
1904 {
1905     Frame* coreFrame = core(this);
1906     if (!coreFrame)
1907         return;
1908
1909     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
1910     String encoding = coreFrame->loader()->documentLoader()->overrideEncoding();
1911     bool userChosen = !encoding.isNull();
1912     if (encoding.isNull())
1913         encoding = textEncoding;
1914     coreFrame->loader()->setEncoding(encoding, userChosen);
1915
1916     coreFrame->loader()->addData(data, length);
1917 }
1918
1919 COMPtr<WebFramePolicyListener> WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction function)
1920 {
1921     ASSERT(!d->m_policyListener);
1922     ASSERT(!d->m_policyFunction);
1923
1924     Frame* coreFrame = core(this);
1925     ASSERT(coreFrame);
1926
1927     d->m_policyListener.adoptRef(WebFramePolicyListener::createInstance(coreFrame));
1928     d->m_policyFunction = function;
1929
1930     return d->m_policyListener;
1931 }
1932
1933 void WebFrame::receivedPolicyDecision(PolicyAction action)
1934 {
1935     ASSERT(d->m_policyListener);
1936     ASSERT(d->m_policyFunction);
1937
1938     FramePolicyFunction function = d->m_policyFunction;
1939
1940     d->m_policyListener = 0;
1941     d->m_policyFunction = 0;
1942
1943     Frame* coreFrame = core(this);
1944     ASSERT(coreFrame);
1945
1946     (coreFrame->loader()->*function)(action);
1947 }
1948
1949 void WebFrame::committedLoad(DocumentLoader* loader, const char* data, int length)
1950 {
1951     // FIXME: This should probably go through the data source.
1952     const String& textEncoding = loader->response().textEncodingName();
1953
1954     if (!d->m_pluginView)
1955         receivedData(data, length, textEncoding);
1956
1957     if (d->m_pluginView) {
1958         if (!d->m_hasSentResponseToPlugin) {
1959             d->m_pluginView->didReceiveResponse(d->frame->loader()->documentLoader()->response());
1960             d->m_hasSentResponseToPlugin = true;
1961         }
1962         d->m_pluginView->didReceiveData(data, length);
1963     }
1964 }
1965
1966 void WebFrame::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const String& mimeType, const ResourceRequest& request)
1967 {
1968     COMPtr<IWebPolicyDelegate> policyDelegate;
1969     if (SUCCEEDED(d->webView->policyDelegate(&policyDelegate))) {
1970         COMPtr<IWebURLRequest> urlRequest;
1971         urlRequest.adoptRef(WebMutableURLRequest::createInstance(request));
1972         if (SUCCEEDED(policyDelegate->decidePolicyForMIMEType(d->webView, BString(mimeType), urlRequest.get(), this, setUpPolicyListener(function).get())))
1973             return;
1974     }
1975
1976     Frame* coreFrame = core(this);
1977     ASSERT(coreFrame);
1978
1979     // FIXME: This is a stopgap default implementation to tide us over until
1980     // <rdar://4911042/> is taken care of
1981     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1982         (coreFrame->loader()->*function)(PolicyUse);
1983     else
1984         (coreFrame->loader()->*function)(PolicyDownload);
1985 }
1986
1987 void WebFrame::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, const String& frameName)
1988 {
1989     Frame* coreFrame = core(this);
1990     ASSERT(coreFrame);
1991
1992     COMPtr<IWebPolicyDelegate> policyDelegate;
1993     if (SUCCEEDED(d->webView->policyDelegate(&policyDelegate))) {
1994         COMPtr<IWebURLRequest> urlRequest;
1995         urlRequest.adoptRef(WebMutableURLRequest::createInstance(request));
1996         COMPtr<WebActionPropertyBag> actionInformation;
1997         actionInformation.adoptRef(WebActionPropertyBag::createInstance(action, coreFrame));
1998
1999         if (SUCCEEDED(policyDelegate->decidePolicyForNewWindowAction(d->webView, actionInformation.get(), urlRequest.get(), BString(frameName), setUpPolicyListener(function).get())))
2000             return;
2001     }
2002
2003     // FIXME: Add a sane default implementation
2004     (coreFrame->loader()->*function)(PolicyUse);
2005 }
2006
2007 void WebFrame::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request)
2008 {
2009     Frame* coreFrame = core(this);
2010     ASSERT(coreFrame);
2011
2012     COMPtr<IWebPolicyDelegate> policyDelegate;
2013     if (SUCCEEDED(d->webView->policyDelegate(&policyDelegate))) {
2014         COMPtr<IWebURLRequest> urlRequest;
2015         urlRequest.adoptRef(WebMutableURLRequest::createInstance(request));
2016         COMPtr<WebActionPropertyBag> actionInformation;
2017         actionInformation.adoptRef(WebActionPropertyBag::createInstance(action, coreFrame));
2018
2019         if (SUCCEEDED(policyDelegate->decidePolicyForNavigationAction(d->webView, actionInformation.get(), urlRequest.get(), this, setUpPolicyListener(function).get())))
2020             return;
2021     }
2022
2023     // FIXME: Add a sane default implementation
2024     (coreFrame->loader()->*function)(PolicyUse);
2025 }
2026
2027 void WebFrame::dispatchUnableToImplementPolicy(const ResourceError& error)
2028 {
2029     COMPtr<IWebPolicyDelegate> policyDelegate;
2030     if (SUCCEEDED(d->webView->policyDelegate(&policyDelegate))) {
2031         COMPtr<IWebError> webError;
2032         webError.adoptRef(WebError::createInstance(error));
2033         policyDelegate->unableToImplementPolicyWithError(d->webView, webError.get(), this);
2034     }
2035 }
2036
2037 void WebFrame::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
2038 {
2039     COMPtr<IWebDownloadDelegate> downloadDelegate;
2040     COMPtr<IWebView> webView;
2041     if (SUCCEEDED(this->webView(&webView))) {
2042         if (FAILED(webView->downloadDelegate(&downloadDelegate))) {
2043             // If the WebView doesn't successfully provide a download delegate we'll pass a null one
2044             // into the WebDownload - which may or may not decide to use a DefaultDownloadDelegate
2045             LOG_ERROR("Failed to get downloadDelegate from WebView");
2046             downloadDelegate = 0;
2047         }
2048     }
2049
2050     // Its the delegate's job to ref the WebDownload to keep it alive - otherwise it will be destroyed
2051     // when this method returns
2052     COMPtr<WebDownload> download;
2053     download.adoptRef(WebDownload::createInstance(handle, request, response, downloadDelegate.get()));
2054 }
2055
2056 bool WebFrame::willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL&) const
2057 {
2058     notImplemented();
2059     return false;
2060 }
2061
2062 void WebFrame::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
2063 {
2064     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2065     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2066         COMPtr<IWebURLRequest> webURLRequest;
2067         webURLRequest.adoptRef(WebMutableURLRequest::createInstance(request));
2068
2069         resourceLoadDelegate->identifierForInitialRequest(d->webView, webURLRequest.get(), getWebDataSource(loader), identifier);
2070     }
2071 }
2072
2073 void WebFrame::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
2074 {
2075     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2076     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2077         COMPtr<IWebURLRequest> webURLRequest;
2078         webURLRequest.adoptRef(WebMutableURLRequest::createInstance(request));
2079         COMPtr<IWebURLResponse> webURLRedirectResponse;
2080         webURLRedirectResponse.adoptRef(WebURLResponse::createInstance(redirectResponse));
2081         COMPtr<IWebURLRequest> newWebURLRequest;
2082
2083         if (FAILED(resourceLoadDelegate->willSendRequest(d->webView, identifier, webURLRequest.get(), webURLRedirectResponse.get(), getWebDataSource(loader), &newWebURLRequest)))
2084             return;
2085
2086         if (webURLRequest == newWebURLRequest)
2087             return;
2088
2089         COMPtr<WebMutableURLRequest> newWebURLRequestImpl;
2090         if (FAILED(newWebURLRequest->QueryInterface(CLSID_WebMutableURLRequest, (void**)&newWebURLRequestImpl)))
2091             return;
2092
2093         request = newWebURLRequestImpl->resourceRequest();
2094     }
2095 }
2096
2097 void WebFrame::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
2098 {
2099     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2100     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2101         COMPtr<IWebURLResponse> webURLResponse;
2102         webURLResponse.adoptRef(WebURLResponse::createInstance(response));
2103
2104         resourceLoadDelegate->didReceiveResponse(d->webView, identifier, webURLResponse.get(), getWebDataSource(loader));
2105     }
2106 }
2107
2108 void WebFrame::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length)
2109 {
2110     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2111     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
2112         resourceLoadDelegate->didReceiveContentLength(d->webView, identifier, length, getWebDataSource(loader));
2113 }
2114
2115 void WebFrame::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
2116 {
2117     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2118     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
2119         resourceLoadDelegate->didFinishLoadingFromDataSource(d->webView, identifier, getWebDataSource(loader));
2120 }
2121
2122 void WebFrame::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
2123 {
2124     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2125     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2126         COMPtr<IWebError> webError;
2127         webError.adoptRef(WebError::createInstance(error));
2128         resourceLoadDelegate->didFailLoadingWithError(d->webView, identifier, webError.get(), getWebDataSource(loader));
2129     }
2130 }
2131
2132 bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
2133 {
2134     notImplemented();
2135     return false;
2136 }
2137
2138 void WebFrame::dispatchDidFailProvisionalLoad(const ResourceError& error)
2139 {
2140     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
2141     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
2142         COMPtr<IWebError> webError;
2143         webError.adoptRef(WebError::createInstance(error));
2144         frameLoadDelegate->didFailProvisionalLoadWithError(d->webView, webError.get(), this);
2145     }
2146 }
2147
2148 void WebFrame::dispatchDidFailLoad(const ResourceError& error)
2149 {
2150     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
2151     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
2152         COMPtr<IWebError> webError;
2153         webError.adoptRef(WebError::createInstance(error));
2154         frameLoadDelegate->didFailLoadWithError(d->webView, webError.get(), this);
2155     }
2156 }
2157
2158 Frame* WebFrame::dispatchCreatePage()
2159 {
2160     COMPtr<IWebUIDelegate> ui;
2161
2162     if (SUCCEEDED(d->webView->uiDelegate(&ui))) {
2163         COMPtr<IWebView> newWebView;
2164
2165         if (SUCCEEDED(ui->createWebViewWithRequest(d->webView, 0, &newWebView))) {
2166             COMPtr<IWebFrame> mainFrame;
2167
2168             if (SUCCEEDED(newWebView->mainFrame(&mainFrame))) {
2169                 COMPtr<WebFrame> mainFrameImpl;
2170
2171                 if (SUCCEEDED(mainFrame->QueryInterface(IID_WebFrame, (void**)&mainFrameImpl)))
2172                     return core(mainFrameImpl.get());
2173             }
2174         }
2175     }
2176     return 0;
2177 }
2178
2179 void WebFrame::postProgressStartedNotification()
2180 {
2181     static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification);
2182     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2183     notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(d->webView), 0);
2184 }
2185
2186 void WebFrame::postProgressEstimateChangedNotification()
2187 {
2188     static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification);
2189     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2190     notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(d->webView), 0);
2191 }
2192
2193 void WebFrame::postProgressFinishedNotification()
2194 {
2195     static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification);
2196     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
2197     notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(d->webView), 0);
2198 }
2199
2200 void WebFrame::startDownload(const ResourceRequest&)
2201 {
2202     notImplemented();
2203 }
2204
2205 void WebFrame::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
2206 {
2207     ASSERT(challenge.sourceHandle());
2208
2209     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2210     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2211         COMPtr<IWebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
2212
2213         if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(d->webView, identifier, webChallenge.get(), getWebDataSource(loader))))
2214             return;
2215     }
2216
2217     // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle
2218     // to continue without credential - this is the best approximation of Mac behavior
2219     challenge.sourceHandle()->receivedRequestToContinueWithoutCredential(challenge);
2220 }
2221
2222 void WebFrame::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
2223 {
2224     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2225     if (SUCCEEDED(d->webView->resourceLoadDelegate(&resourceLoadDelegate))) {
2226         COMPtr<IWebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
2227
2228         if (SUCCEEDED(resourceLoadDelegate->didCancelAuthenticationChallenge(d->webView, identifier, webChallenge.get(), getWebDataSource(loader))))
2229             return;
2230     }
2231 }
2232
2233 PassRefPtr<Frame> WebFrame::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
2234                             const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
2235 {
2236     RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer);
2237     if (!result)
2238         return 0;
2239
2240     // Propagate the marginwidth/height and scrolling modes to the view.
2241     if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
2242         HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
2243         if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
2244             result->view()->setScrollbarsMode(ScrollbarAlwaysOff);
2245         int marginWidth = frameElt->getMarginWidth();
2246         int marginHeight = frameElt->getMarginHeight();
2247         if (marginWidth != -1)
2248             result->view()->setMarginWidth(marginWidth);
2249         if (marginHeight != -1)
2250             result->view()->setMarginHeight(marginHeight);
2251     }
2252
2253     return result.release();
2254 }
2255
2256 Widget* WebFrame::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
2257 {
2258     PluginViewWin* pluginView = PluginDatabaseWin::installedPlugins()->createPluginView(core(this), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
2259
2260     if (pluginView->status() == PluginStatusLoadedSuccessfully)
2261         return pluginView;
2262
2263     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2264
2265     if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
2266         return pluginView;
2267
2268     RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2269
2270     unsigned count = (unsigned)paramNames.size();
2271     for (unsigned i = 0; i < count; i++) {
2272         if (paramNames[i] == "pluginspage") {
2273             static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey);
2274             RetainPtr<CFStringRef> str(AdoptCF, paramValues[i].createCFString());
2275             CFDictionarySetValue(userInfo.get(), key, str.get());
2276             break;
2277         }
2278     }
2279
2280     if (!mimeType.isNull()) {
2281         static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey);
2282
2283         RetainPtr<CFStringRef> str(AdoptCF, mimeType.createCFString());
2284         CFDictionarySetValue(userInfo.get(), key, str.get());
2285     }
2286
2287     String pluginName;
2288     if (pluginView->plugin())
2289         pluginName = pluginView->plugin()->name();
2290     if (!pluginName.isNull()) {
2291         static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey);
2292         RetainPtr<CFStringRef> str(AdoptCF, mimeType.createCFString());
2293         CFDictionarySetValue(userInfo.get(), key, str.get());
2294     }
2295
2296     COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance());
2297     userInfoBag->setDictionary(userInfo.get());
2298  
2299     int errorCode = 0;
2300     switch (pluginView->status()) {
2301         case PluginStatusCanNotFindPlugin:
2302             errorCode = WebKitErrorCannotFindPlugIn;
2303             break;
2304         case PluginStatusCanNotLoadPlugin:
2305             errorCode = WebKitErrorCannotLoadPlugIn;
2306             break;
2307         default:
2308             ASSERT_NOT_REACHED();
2309     }
2310
2311     ResourceError resourceError(String(WebKitErrorDomain), errorCode, url.url(), String());
2312     COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
2313      
2314     resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader()));
2315
2316     return pluginView;
2317 }
2318
2319 void WebFrame::redirectDataToPlugin(Widget* pluginWidget)
2320 {
2321     // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889>
2322
2323     d->m_pluginView = static_cast<PluginViewWin*>(pluginWidget);
2324 }
2325
2326 Widget* WebFrame::createJavaAppletWidget(const IntSize& pluginSize, Element* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues)
2327 {
2328     PluginViewWin* pluginView = PluginDatabaseWin::installedPlugins()->
2329         createPluginView(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false);
2330
2331     // Check if the plugin can be loaded successfully
2332     if (pluginView->plugin()->load())
2333         return pluginView;
2334
2335     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
2336     if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
2337         return pluginView;
2338
2339     COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance());
2340
2341     ResourceError resourceError(String(WebKitErrorDomain), WebKitErrorJavaUnavailable, String(), String());
2342     COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
2343      
2344     resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader()));
2345
2346     return pluginView;
2347 }
2348
2349 ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeTypeIn)
2350 {
2351     String mimeType = mimeTypeIn;
2352     if (mimeType.isEmpty())
2353         mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().mid(url.path().findRev('.')+1));
2354
2355     if (mimeType.isEmpty())
2356         return ObjectContentFrame; // Go ahead and hope that we can display the content.
2357
2358     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
2359         return WebCore::ObjectContentImage;
2360
2361     if (PluginDatabaseWin::installedPlugins()->isMIMETypeRegistered(mimeType))
2362         return WebCore::ObjectContentNetscapePlugin;
2363
2364     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
2365         return WebCore::ObjectContentFrame;
2366
2367     return WebCore::ObjectContentNone;
2368 }
2369
2370 String WebFrame::overrideMediaType() const
2371 {
2372     notImplemented();
2373     return String();
2374 }
2375
2376 void WebFrame::windowObjectCleared() const
2377 {
2378     Frame* coreFrame = core(this);
2379     ASSERT(coreFrame);
2380
2381     Settings* settings = coreFrame->settings();
2382     if (!settings || !settings->isJavaScriptEnabled())
2383         return;
2384
2385     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
2386     if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
2387         JSContextRef context = toRef(coreFrame->scriptProxy()->interpreter()->globalExec());
2388         JSObjectRef windowObject = toRef(KJS::Window::retrieve(coreFrame)->getObject());
2389         ASSERT(windowObject);
2390
2391         frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject);
2392     }
2393 }
2394
2395 void WebFrame::didPerformFirstNavigation() const
2396 {
2397 }
2398
2399 void WebFrame::registerForIconNotification(bool listen)
2400 {
2401     d->webView->registerForIconNotification(listen);
2402 }
2403
2404 static IntRect printerRect(HDC printDC)
2405 {
2406     return IntRect(0, 0, 
2407                    GetDeviceCaps(printDC, PHYSICALWIDTH)  - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETX),
2408                    GetDeviceCaps(printDC, PHYSICALHEIGHT) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETY));
2409 }
2410
2411 void WebFrame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
2412 {
2413     Frame* coreFrame = core(this);
2414     ASSERT(coreFrame);
2415     coreFrame->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
2416 }
2417
2418 HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode( 
2419     /* [in] */ BOOL value,
2420     /* [in] */ HDC printDC)
2421 {
2422     if (m_inPrintingMode == !!value)
2423         return S_OK;
2424
2425     Frame* coreFrame = core(this);
2426     if (!coreFrame)
2427         return E_FAIL;
2428
2429     m_inPrintingMode = !!value;
2430
2431     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
2432     // according to the paper size
2433     float minLayoutWidth = 0.0f;
2434     float maxLayoutWidth = 0.0f;
2435     if (m_inPrintingMode && !coreFrame->isFrameSet()) {
2436         if (!printDC) {
2437             ASSERT_NOT_REACHED();
2438             return E_POINTER;
2439         }
2440
2441         const int desiredHorizontalPixelsPerInch = 72;
2442         int paperHorizontalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSX);
2443         int paperWidth = printerRect(printDC).width() * desiredHorizontalPixelsPerInch / paperHorizontalPixelsPerInch;
2444         minLayoutWidth = paperWidth * PrintingMinimumShrinkFactor;
2445         maxLayoutWidth = paperWidth * PrintingMaximumShrinkFactor;
2446     }
2447
2448     setPrinting(m_inPrintingMode, minLayoutWidth, maxLayoutWidth, true);
2449
2450     if (!m_inPrintingMode)
2451         m_pageRects.clear();
2452
2453     return S_OK;
2454 }
2455
2456 void WebFrame::headerAndFooterHeights(float* headerHeight, float* footerHeight)
2457 {
2458     if (headerHeight)
2459         *headerHeight = 0;
2460     if (footerHeight)
2461         *footerHeight = 0;
2462     float height = 0;
2463     COMPtr<IWebUIDelegate> ui;
2464     if (FAILED(d->webView->uiDelegate(&ui)))
2465         return;
2466     COMPtr<IWebUIDelegate2> ui2;
2467     if (FAILED(ui->QueryInterface(IID_IWebUIDelegate2, (void**) &ui2)))
2468         return;
2469     if (headerHeight && SUCCEEDED(ui2->webViewHeaderHeight(d->webView, &height)))
2470         *headerHeight = height;
2471     if (footerHeight && SUCCEEDED(ui2->webViewFooterHeight(d->webView, &height)))
2472         *footerHeight = height;
2473 }
2474
2475 IntRect WebFrame::printerMarginRect(HDC printDC)
2476 {
2477     IntRect emptyRect(0, 0, 0, 0);
2478
2479     COMPtr<IWebUIDelegate> ui;
2480     if (FAILED(d->webView->uiDelegate(&ui)))
2481         return emptyRect;
2482     COMPtr<IWebUIDelegate2> ui2;
2483     if (FAILED(ui->QueryInterface(IID_IWebUIDelegate2, (void**) &ui2)))
2484         return emptyRect;
2485
2486     RECT rect;
2487     if (FAILED(ui2->webViewPrintingMarginRect(d->webView, &rect)))
2488         return emptyRect;
2489
2490     rect.left = MulDiv(rect.left, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
2491     rect.top = MulDiv(rect.top, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
2492     rect.right = MulDiv(rect.right, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
2493     rect.bottom = MulDiv(rect.bottom, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
2494
2495     return IntRect(rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top);
2496 }
2497
2498 const Vector<WebCore::IntRect>& WebFrame::computePageRects(HDC printDC)
2499 {
2500     ASSERT(m_inPrintingMode);
2501     
2502     Frame* coreFrame = core(this);
2503     ASSERT(coreFrame);
2504     ASSERT(coreFrame->document());
2505
2506     if (!printDC)
2507         return m_pageRects;
2508
2509     // adjust the page rect by the header and footer
2510     float headerHeight = 0, footerHeight = 0;
2511     headerAndFooterHeights(&headerHeight, &footerHeight);
2512     IntRect pageRect = printerRect(printDC);
2513     IntRect marginRect = printerMarginRect(printDC);
2514     IntRect adjustedRect = IntRect(
2515         pageRect.x() + marginRect.x(),
2516         pageRect.y() + marginRect.y(),
2517         pageRect.width() - marginRect.x() - marginRect.right(),
2518         pageRect.height() - marginRect.y() - marginRect.bottom());
2519
2520     computePageRectsForFrame(coreFrame, adjustedRect, headerHeight, footerHeight, 1.0,m_pageRects, m_pageHeight);
2521     
2522     return m_pageRects;
2523 }
2524
2525 HRESULT STDMETHODCALLTYPE WebFrame::getPrintedPageCount( 
2526     /* [in] */ HDC printDC,
2527     /* [retval][out] */ UINT *pageCount)
2528 {
2529     if (!pageCount || !printDC) {
2530         ASSERT_NOT_REACHED();
2531         return E_POINTER;
2532     }
2533
2534     *pageCount = 0;
2535
2536     if (!m_inPrintingMode) {
2537         ASSERT_NOT_REACHED();
2538         return E_FAIL;
2539     }
2540
2541     Frame* coreFrame = core(this);
2542     if (!coreFrame || !coreFrame->document())
2543         return E_FAIL;
2544
2545     const Vector<IntRect>& pages = computePageRects(printDC);
2546     *pageCount = (UINT) pages.size();
2547     
2548     return S_OK;
2549 }
2550
2551 HRESULT STDMETHODCALLTYPE WebFrame::spoolPages( 
2552     /* [in] */ HDC printDC,
2553     /* [in] */ UINT startPage,
2554     /* [in] */ UINT endPage,
2555     /* [retval][out] */ void* ctx)
2556 {
2557     if (!printDC || !ctx) {
2558         ASSERT_NOT_REACHED();
2559         return E_POINTER;
2560     }
2561
2562     if (!m_inPrintingMode) {
2563         ASSERT_NOT_REACHED();
2564         return E_FAIL;
2565     }
2566
2567     Frame* coreFrame = core(this);
2568     if (!coreFrame || !coreFrame->document())
2569         return E_FAIL;
2570
2571     UINT pageCount = (UINT) m_pageRects.size();
2572     PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx;
2573
2574     if (!pageCount || startPage > pageCount) {
2575         ASSERT_NOT_REACHED();
2576         return E_FAIL;
2577     }
2578
2579     if (startPage > 0)
2580         startPage--;
2581
2582     if (endPage == 0)
2583         endPage = pageCount;
2584
2585     COMPtr<IWebUIDelegate> ui;
2586     if (FAILED(d->webView->uiDelegate(&ui)))
2587         return E_FAIL;
2588     // FIXME: we can return early after the updated app is released
2589     COMPtr<IWebUIDelegate2> ui2;
2590     if (FAILED(ui->QueryInterface(IID_IWebUIDelegate2, (void**) &ui2)))
2591         ui2 = 0;
2592
2593     float headerHeight = 0, footerHeight = 0;
2594     headerAndFooterHeights(&headerHeight, &footerHeight);
2595     GraphicsContext spoolCtx(pctx);
2596
2597     for (UINT ii = startPage; ii < endPage; ii++) {
2598         IntRect pageRect = m_pageRects[ii];
2599
2600         CGContextSaveGState(pctx);
2601
2602         IntRect printRect = printerRect(printDC);
2603         CGRect mediaBox = CGRectMake(CGFloat(0),
2604                                      CGFloat(0),
2605                                      CGFloat(printRect.width()),
2606                                      CGFloat(printRect.height()));
2607
2608         CGContextBeginPage(pctx, &mediaBox);
2609
2610         CGFloat scale = (float)mediaBox.size.width/ (float)pageRect.width();
2611         CGAffineTransform ctm = CGContextGetBaseCTM(pctx);
2612         ctm = CGAffineTransformScale(ctm, -scale, -scale);
2613         ctm = CGAffineTransformTranslate(ctm, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
2614         CGContextScaleCTM(pctx, scale, scale);
2615         CGContextTranslateCTM(pctx, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight));   // reserves space for header
2616         CGContextSetBaseCTM(pctx, ctm);
2617
2618         coreFrame->paint(&spoolCtx, pageRect);
2619
2620         if (ui2) {
2621             CGContextTranslateCTM(pctx, CGFloat(pageRect.x()), CGFloat(pageRect.y())-headerHeight);
2622
2623             int x = pageRect.x();
2624             int y = 0;
2625             if (headerHeight) {
2626                 RECT headerRect = {x, y, x+pageRect.width(), y+(int)headerHeight};
2627                 ui2->drawHeaderInRect(d->webView, &headerRect, (OLE_HANDLE)(LONG64)pctx);
2628             }
2629
2630             if (footerHeight) {
2631                 y = max((int)headerHeight+pageRect.height(), m_pageHeight-(int)footerHeight);
2632                 RECT footerRect = {x, y, x+pageRect.width(), y+(int)footerHeight};
2633                 ui2->drawFooterInRect(d->webView, &footerRect, (OLE_HANDLE)(LONG64)pctx, ii+1, pageCount);
2634             }
2635         }
2636
2637         CGContextEndPage(pctx);
2638         CGContextRestoreGState(pctx);
2639     }
2640  
2641     return S_OK;
2642 }
2643
2644 HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet( 
2645     /* [retval][out] */ BOOL* result)
2646 {
2647     *result = FALSE;
2648
2649     Frame* coreFrame = core(this);
2650     if (!coreFrame)
2651         return E_FAIL;
2652
2653     *result = coreFrame->isFrameSet() ? TRUE : FALSE;
2654     return S_OK;
2655 }
2656
2657 HRESULT STDMETHODCALLTYPE WebFrame::string( 
2658     /* [retval][out] */ BSTR *result)
2659 {
2660     *result = 0;
2661
2662     Frame* coreFrame = core(this);
2663     if (!coreFrame)
2664         return E_FAIL;
2665
2666     RefPtr<Range> allRange(rangeOfContents(coreFrame->document()));
2667     DeprecatedString allString = plainText(allRange.get());
2668     *result = BString(allString).release();
2669     return S_OK;
2670 }
2671
2672 HRESULT STDMETHODCALLTYPE WebFrame::size( 
2673     /* [retval][out] */ SIZE *size)
2674 {
2675     if (!size)
2676         return E_POINTER;
2677     size->cx = size->cy = 0;
2678
2679     Frame* coreFrame = core(this);
2680     if (!coreFrame)
2681         return E_FAIL;
2682     FrameView* view = coreFrame->view();
2683     if (!view)
2684         return E_FAIL;
2685     size->cx = view->width();
2686     size->cy = view->height();
2687     return S_OK;
2688 }
2689
2690 HRESULT STDMETHODCALLTYPE WebFrame::hasScrollBars( 
2691     /* [retval][out] */ BOOL *result)
2692 {
2693     if (!result)
2694         return E_POINTER;
2695     *result = FALSE;
2696
2697     Frame* coreFrame = core(this);
2698     if (!coreFrame)
2699         return E_FAIL;
2700
2701     FrameView* view = coreFrame->view();
2702     if (!view)
2703         return E_FAIL;
2704
2705     if (view->vScrollbarMode() == ScrollbarAlwaysOn || view->visibleHeight() < view->contentsHeight() ||
2706             view->hScrollbarMode() == ScrollbarAlwaysOn || view->visibleWidth() < view->contentsWidth())
2707         *result = TRUE;
2708
2709     return S_OK;
2710 }
2711
2712 HRESULT STDMETHODCALLTYPE WebFrame::contentBounds( 
2713     /* [retval][out] */ RECT *result)
2714 {
2715     if (!result)
2716         return E_POINTER;
2717     ::SetRectEmpty(result);
2718
2719     Frame* coreFrame = core(this);
2720     if (!coreFrame)
2721         return E_FAIL;
2722
2723     FrameView* view = coreFrame->view();
2724     if (!view)
2725         return E_FAIL;
2726
2727     result->bottom = view->contentsHeight();
2728     result->right = view->contentsWidth();
2729     return S_OK;
2730 }
2731
2732 HRESULT STDMETHODCALLTYPE WebFrame::frameBounds( 
2733     /* [retval][out] */ RECT *result)
2734 {
2735     if (!result)
2736         return E_POINTER;
2737     ::SetRectEmpty(result);
2738
2739     Frame* coreFrame = core(this);
2740     if (!coreFrame)
2741         return E_FAIL;
2742
2743     FrameView* view = coreFrame->view();
2744     if (!view)
2745         return E_FAIL;
2746
2747     FloatRect bounds = view->visibleContentRectConsideringExternalScrollers();
2748     result->bottom = (LONG) bounds.height();
2749     result->right = (LONG) bounds.width();
2750     return S_OK;
2751 }
2752
2753 HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame( 
2754     /* [in] */ IWebFrame *ancestor,
2755     /* [retval][out] */ BOOL *result)
2756 {
2757     if (!result)
2758         return E_POINTER;
2759     *result = FALSE;
2760
2761     Frame* coreFrame = core(this);
2762     COMPtr<WebFrame> ancestorWebFrame;
2763     if (!ancestor || FAILED(ancestor->QueryInterface(IID_WebFrame, (void**)&ancestorWebFrame)))
2764         return S_OK;
2765
2766     *result = (coreFrame && coreFrame->tree()->isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE;
2767     return S_OK;
2768 }
2769
2770 void WebFrame::unmarkAllMisspellings()
2771 {
2772     Frame* coreFrame = core(this);
2773     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2774         Document *doc = frame->document();
2775         if (!doc)
2776             return;
2777
2778         doc->removeMarkers(DocumentMarker::Spelling);
2779     }
2780 }
2781
2782 void WebFrame::unmarkAllBadGrammar()
2783 {
2784     Frame* coreFrame = core(this);
2785     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2786         Document *doc = frame->document();
2787         if (!doc)
2788             return;
2789
2790         doc->removeMarkers(DocumentMarker::Grammar);
2791     }
2792 }