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