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