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