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