1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009 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 "COMPropertyBag.h"
33 #include "DefaultPolicyDelegate.h"
34 #include "DOMCoreClasses.h"
35 #include "HTMLFrameOwnerElement.h"
36 #include "MarshallingHelpers.h"
37 #include "WebActionPropertyBag.h"
38 #include "WebChromeClient.h"
39 #include "WebDocumentLoader.h"
40 #include "WebDownload.h"
41 #include "WebError.h"
42 #include "WebMutableURLRequest.h"
43 #include "WebEditorClient.h"
44 #include "WebFramePolicyListener.h"
45 #include "WebHistory.h"
46 #include "WebIconFetcher.h"
47 #include "WebKit.h"
48 #include "WebKitStatisticsPrivate.h"
49 #include "WebNotificationCenter.h"
50 #include "WebView.h"
51 #include "WebDataSource.h"
52 #include "WebHistoryItem.h"
53 #include "WebURLResponse.h"
54 #pragma warning( push, 0 )
55 #include <WebCore/BString.h>
56 #include <WebCore/Cache.h>
57 #include <WebCore/Document.h>
58 #include <WebCore/DocumentLoader.h>
59 #include <WebCore/DOMImplementation.h>
60 #include <WebCore/DOMWindow.h>
61 #include <WebCore/Event.h>
62 #include <WebCore/EventHandler.h>
63 #include <WebCore/FormState.h>
64 #include <WebCore/FrameLoader.h>
65 #include <WebCore/FrameLoadRequest.h>
66 #include <WebCore/FrameTree.h>
67 #include <WebCore/FrameView.h>
68 #include <WebCore/FrameWin.h>
69 #include <WebCore/GDIObjectCounter.h>
70 #include <WebCore/GraphicsContext.h>
71 #include <WebCore/HistoryItem.h>
72 #include <WebCore/HTMLAppletElement.h>
73 #include <WebCore/HTMLFormElement.h>
74 #include <WebCore/HTMLFormControlElement.h>
75 #include <WebCore/HTMLInputElement.h>
76 #include <WebCore/HTMLNames.h>
77 #include <WebCore/HTMLPlugInElement.h>
78 #include <WebCore/JSDOMWindow.h>
79 #include <WebCore/KeyboardEvent.h>
80 #include <WebCore/MIMETypeRegistry.h>
81 #include <WebCore/MouseRelatedEvent.h>
82 #include <WebCore/NotImplemented.h>
83 #include <WebCore/Page.h>
84 #include <WebCore/PlatformKeyboardEvent.h>
85 #include <WebCore/PluginInfoStore.h>
86 #include <WebCore/PluginDatabase.h>
87 #include <WebCore/PluginView.h>
88 #include <WebCore/ResourceHandle.h>
89 #include <WebCore/ResourceHandleWin.h>
90 #include <WebCore/ResourceRequest.h>
91 #include <WebCore/RenderView.h>
92 #include <WebCore/RenderTreeAsText.h>
93 #include <WebCore/Settings.h>
94 #include <WebCore/TextIterator.h>
95 #include <WebCore/JSDOMBinding.h>
96 #include <WebCore/ScriptController.h>
97 #include <JavaScriptCore/APICast.h>
98 #include <wtf/MathExtras.h>
99 #pragma warning(pop)
100
101 #if PLATFORM(CG)
102 #include <CoreGraphics/CoreGraphics.h>
103 #elif PLATFORM(CAIRO)
104 #include <cairo-win32.h>
105 #endif
106
107 #if PLATFORM(CG)
108 // CG SPI used for printing
109 extern "C" {
110 CGAffineTransform CGContextGetBaseCTM(CGContextRef c);
111 void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m);
112 }
113 #endif
114
115 using namespace WebCore;
116 using namespace HTMLNames;
117
118 #define FLASH_REDRAW 0
119
120
121 // By imaging to a width a little wider than the available pixels,
122 // thin pages will be scaled down a little, matching the way they
123 // print in IE and Camino. This lets them use fewer sheets than they
124 // would otherwise, which is presumably why other browsers do this.
125 // Wide pages will be scaled down more than this.
126 const float PrintingMinimumShrinkFactor = 1.25f;
127
128 // This number determines how small we are willing to reduce the page content
129 // in order to accommodate the widest line. If the page would have to be
130 // reduced smaller to make the widest line fit, we just clip instead (this
131 // behavior matches MacIE and Mozilla, at least)
132 const float PrintingMaximumShrinkFactor = 2.0f;
133
134 //-----------------------------------------------------------------------------
135 // Helpers to convert from WebCore to WebKit type
kit(Frame * frame)136 WebFrame* kit(Frame* frame)
137 {
138 if (!frame)
139 return 0;
140
141 FrameLoaderClient* frameLoaderClient = frame->loader()->client();
142 if (frameLoaderClient)
143 return static_cast<WebFrame*>(frameLoaderClient); // eek, is there a better way than static cast?
144 return 0;
145 }
146
core(WebFrame * webFrame)147 Frame* core(WebFrame* webFrame)
148 {
149 if (!webFrame)
150 return 0;
151 return webFrame->impl();
152 }
153
154 // 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
core(const WebFrame * webFrame)155 Frame* core(const WebFrame* webFrame)
156 {
157 if (!webFrame)
158 return 0;
159 return const_cast<WebFrame*>(webFrame)->impl();
160 }
161
162 //-----------------------------------------------------------------------------
163
elementFromDOMElement(IDOMElement * element)164 static Element *elementFromDOMElement(IDOMElement *element)
165 {
166 if (!element)
167 return 0;
168
169 COMPtr<IDOMElementPrivate> elePriv;
170 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
171 if (SUCCEEDED(hr)) {
172 Element* ele;
173 hr = elePriv->coreElement((void**)&ele);
174 if (SUCCEEDED(hr))
175 return ele;
176 }
177 return 0;
178 }
179
formElementFromDOMElement(IDOMElement * element)180 static HTMLFormElement *formElementFromDOMElement(IDOMElement *element)
181 {
182 if (!element)
183 return 0;
184
185 IDOMElementPrivate* elePriv;
186 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
187 if (SUCCEEDED(hr)) {
188 Element* ele;
189 hr = elePriv->coreElement((void**)&ele);
190 elePriv->Release();
191 if (SUCCEEDED(hr) && ele && ele->hasTagName(formTag))
192 return static_cast<HTMLFormElement*>(ele);
193 }
194 return 0;
195 }
196
inputElementFromDOMElement(IDOMElement * element)197 static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element)
198 {
199 if (!element)
200 return 0;
201
202 IDOMElementPrivate* elePriv;
203 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
204 if (SUCCEEDED(hr)) {
205 Element* ele;
206 hr = elePriv->coreElement((void**)&ele);
207 elePriv->Release();
208 if (SUCCEEDED(hr) && ele && ele->hasTagName(inputTag))
209 return static_cast<HTMLInputElement*>(ele);
210 }
211 return 0;
212 }
213
214 // WebFramePrivate ------------------------------------------------------------
215
216 class WebFrame::WebFramePrivate {
217 public:
WebFramePrivate()218 WebFramePrivate()
219 : frame(0)
220 , webView(0)
221 , m_policyFunction(0)
222 {
223 }
224
~WebFramePrivate()225 ~WebFramePrivate() { }
frameView()226 FrameView* frameView() { return frame ? frame->view() : 0; }
227
228 Frame* frame;
229 WebView* webView;
230 FramePolicyFunction m_policyFunction;
231 COMPtr<WebFramePolicyListener> m_policyListener;
232 };
233
234 // WebFrame ----------------------------------------------------------------
235
WebFrame()236 WebFrame::WebFrame()
237 : WebFrameLoaderClient(this)
238 , m_refCount(0)
239 , d(new WebFrame::WebFramePrivate)
240 , m_quickRedirectComing(false)
241 , m_inPrintingMode(false)
242 , m_pageHeight(0)
243 {
244 WebFrameCount++;
245 gClassCount++;
246 gClassNameCount.add("WebFrame");
247 }
248
~WebFrame()249 WebFrame::~WebFrame()
250 {
251 delete d;
252 WebFrameCount--;
253 gClassCount--;
254 gClassNameCount.remove("WebFrame");
255 }
256
createInstance()257 WebFrame* WebFrame::createInstance()
258 {
259 WebFrame* instance = new WebFrame();
260 instance->AddRef();
261 return instance;
262 }
263
setAllowsScrolling(BOOL flag)264 HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling(
265 /* [in] */ BOOL flag)
266 {
267 if (Frame* frame = core(this))
268 if (FrameView* view = frame->view())
269 view->setCanHaveScrollbars(!!flag);
270
271 return S_OK;
272 }
273
allowsScrolling(BOOL * flag)274 HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling(
275 /* [retval][out] */ BOOL *flag)
276 {
277 if (flag)
278 if (Frame* frame = core(this))
279 if (FrameView* view = frame->view())
280 *flag = view->canHaveScrollbars();
281
282 return S_OK;
283 }
284
setIsDisconnected(BOOL flag)285 HRESULT STDMETHODCALLTYPE WebFrame::setIsDisconnected(
286 /* [in] */ BOOL flag)
287 {
288 if (Frame* frame = core(this)) {
289 frame->setIsDisconnected(flag);
290 return S_OK;
291 }
292
293 return E_FAIL;
294 }
295
setExcludeFromTextSearch(BOOL flag)296 HRESULT STDMETHODCALLTYPE WebFrame::setExcludeFromTextSearch(
297 /* [in] */ BOOL flag)
298 {
299 if (Frame* frame = core(this)) {
300 frame->setExcludeFromTextSearch(flag);
301 return S_OK;
302 }
303
304 return E_FAIL;
305 }
306
paintDocumentRectToContext(RECT rect,OLE_HANDLE deviceContext)307 HRESULT STDMETHODCALLTYPE WebFrame::paintDocumentRectToContext(
308 /* [in] */ RECT rect,
309 /* [in] */ OLE_HANDLE deviceContext)
310 {
311 Frame* coreFrame = core(this);
312 if (!coreFrame)
313 return E_FAIL;
314
315 FrameView* view = coreFrame->view();
316 if (!view)
317 return E_FAIL;
318
319 // We can't paint with a layout still pending.
320 view->layoutIfNeededRecursive();
321
322 HDC dc = (HDC)(ULONG64)deviceContext;
323 GraphicsContext gc(dc);
324 gc.setShouldIncludeChildWindows(true);
325 gc.save();
326 LONG width = rect.right - rect.left;
327 LONG height = rect.bottom - rect.top;
328 FloatRect dirtyRect;
329 dirtyRect.setWidth(width);
330 dirtyRect.setHeight(height);
331 gc.clip(dirtyRect);
332 gc.translate(-rect.left, -rect.top);
333 view->paintContents(&gc, rect);
334 gc.restore();
335
336 return S_OK;
337 }
338
339 // IUnknown -------------------------------------------------------------------
340
QueryInterface(REFIID riid,void ** ppvObject)341 HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
342 {
343 *ppvObject = 0;
344 if (IsEqualGUID(riid, __uuidof(WebFrame)))
345 *ppvObject = this;
346 else if (IsEqualGUID(riid, IID_IUnknown))
347 *ppvObject = static_cast<IWebFrame*>(this);
348 else if (IsEqualGUID(riid, IID_IWebFrame))
349 *ppvObject = static_cast<IWebFrame*>(this);
350 else if (IsEqualGUID(riid, IID_IWebFramePrivate))
351 *ppvObject = static_cast<IWebFramePrivate*>(this);
352 else if (IsEqualGUID(riid, IID_IWebDocumentText))
353 *ppvObject = static_cast<IWebDocumentText*>(this);
354 else
355 return E_NOINTERFACE;
356
357 AddRef();
358 return S_OK;
359 }
360
AddRef(void)361 ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
362 {
363 return ++m_refCount;
364 }
365
Release(void)366 ULONG STDMETHODCALLTYPE WebFrame::Release(void)
367 {
368 ULONG newRef = --m_refCount;
369 if (!newRef)
370 delete(this);
371
372 return newRef;
373 }
374
375 // IWebFrame -------------------------------------------------------------------
376
name(BSTR * frameName)377 HRESULT STDMETHODCALLTYPE WebFrame::name(
378 /* [retval][out] */ BSTR* frameName)
379 {
380 if (!frameName) {
381 ASSERT_NOT_REACHED();
382 return E_POINTER;
383 }
384
385 *frameName = 0;
386
387 Frame* coreFrame = core(this);
388 if (!coreFrame)
389 return E_FAIL;
390
391 *frameName = BString(coreFrame->tree()->name()).release();
392 return S_OK;
393 }
394
webView(IWebView ** view)395 HRESULT STDMETHODCALLTYPE WebFrame::webView(
396 /* [retval][out] */ IWebView** view)
397 {
398 *view = 0;
399 if (!d->webView)
400 return E_FAIL;
401 *view = d->webView;
402 (*view)->AddRef();
403 return S_OK;
404 }
405
frameView(IWebFrameView **)406 HRESULT STDMETHODCALLTYPE WebFrame::frameView(
407 /* [retval][out] */ IWebFrameView** /*view*/)
408 {
409 ASSERT_NOT_REACHED();
410 return E_NOTIMPL;
411 }
412
DOMDocument(IDOMDocument ** result)413 HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument(
414 /* [retval][out] */ IDOMDocument** result)
415 {
416 if (!result) {
417 ASSERT_NOT_REACHED();
418 return E_POINTER;
419 }
420
421 *result = 0;
422
423 if (Frame* coreFrame = core(this))
424 if (Document* document = coreFrame->document())
425 *result = DOMDocument::createInstance(document);
426
427 return *result ? S_OK : E_FAIL;
428 }
429
frameElement(IDOMHTMLElement ** frameElement)430 HRESULT STDMETHODCALLTYPE WebFrame::frameElement(
431 /* [retval][out] */ IDOMHTMLElement** frameElement)
432 {
433 if (!frameElement)
434 return E_POINTER;
435
436 *frameElement = 0;
437 Frame* coreFrame = core(this);
438 if (!coreFrame)
439 return E_FAIL;
440
441 COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(coreFrame->ownerElement()));
442 COMPtr<IDOMHTMLElement> htmlElement(Query, domElement);
443 if (!htmlElement)
444 return E_FAIL;
445 return htmlElement.copyRefTo(frameElement);
446 }
447
currentForm(IDOMElement ** currentForm)448 HRESULT STDMETHODCALLTYPE WebFrame::currentForm(
449 /* [retval][out] */ IDOMElement **currentForm)
450 {
451 if (!currentForm) {
452 ASSERT_NOT_REACHED();
453 return E_POINTER;
454 }
455
456 *currentForm = 0;
457
458 if (Frame* coreFrame = core(this))
459 if (HTMLFormElement* formElement = coreFrame->currentForm())
460 *currentForm = DOMElement::createInstance(formElement);
461
462 return *currentForm ? S_OK : E_FAIL;
463 }
464
globalContext()465 JSGlobalContextRef STDMETHODCALLTYPE WebFrame::globalContext()
466 {
467 Frame* coreFrame = core(this);
468 if (!coreFrame)
469 return 0;
470
471 return toGlobalRef(coreFrame->script()->globalObject()->globalExec());
472 }
473
loadRequest(IWebURLRequest * request)474 HRESULT STDMETHODCALLTYPE WebFrame::loadRequest(
475 /* [in] */ IWebURLRequest* request)
476 {
477 COMPtr<WebMutableURLRequest> requestImpl;
478
479 HRESULT hr = request->QueryInterface(&requestImpl);
480 if (FAILED(hr))
481 return hr;
482
483 Frame* coreFrame = core(this);
484 if (!coreFrame)
485 return E_FAIL;
486
487 coreFrame->loader()->load(requestImpl->resourceRequest(), false);
488 return S_OK;
489 }
490
loadData(PassRefPtr<WebCore::SharedBuffer> data,BSTR mimeType,BSTR textEncodingName,BSTR baseURL,BSTR failingURL)491 void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL)
492 {
493 String mimeTypeString(mimeType, SysStringLen(mimeType));
494 if (!mimeType)
495 mimeTypeString = "text/html";
496
497 String encodingString(textEncodingName, SysStringLen(textEncodingName));
498
499 // FIXME: We should really be using MarshallingHelpers::BSTRToKURL here,
500 // but that would turn a null BSTR into a null KURL, and we crash inside of
501 // WebCore if we use a null KURL in constructing the ResourceRequest.
502 KURL baseKURL = KURL(KURL(), String(baseURL ? baseURL : L"", SysStringLen(baseURL)));
503
504 KURL failingKURL = MarshallingHelpers::BSTRToKURL(failingURL);
505
506 ResourceRequest request(baseKURL);
507 SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL);
508
509 // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null.
510 if (Frame* coreFrame = core(this))
511 coreFrame->loader()->load(request, substituteData, false);
512 }
513
514
loadData(IStream * data,BSTR mimeType,BSTR textEncodingName,BSTR url)515 HRESULT STDMETHODCALLTYPE WebFrame::loadData(
516 /* [in] */ IStream* data,
517 /* [in] */ BSTR mimeType,
518 /* [in] */ BSTR textEncodingName,
519 /* [in] */ BSTR url)
520 {
521 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create();
522
523 STATSTG stat;
524 if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) {
525 if (!stat.cbSize.HighPart && stat.cbSize.LowPart) {
526 Vector<char> dataBuffer(stat.cbSize.LowPart);
527 ULONG read;
528 // FIXME: this does a needless copy, would be better to read right into the SharedBuffer
529 // or adopt the Vector or something.
530 if (SUCCEEDED(data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read)))
531 sharedBuffer->append(dataBuffer.data(), static_cast<int>(dataBuffer.size()));
532 }
533 }
534
535 loadData(sharedBuffer, mimeType, textEncodingName, url, 0);
536 return S_OK;
537 }
538
loadHTMLString(BSTR string,BSTR baseURL,BSTR unreachableURL)539 void WebFrame::loadHTMLString(BSTR string, BSTR baseURL, BSTR unreachableURL)
540 {
541 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
542 BString utf16Encoding(TEXT("utf-16"), 6);
543 loadData(sharedBuffer.release(), 0, utf16Encoding, baseURL, unreachableURL);
544 }
545
loadHTMLString(BSTR string,BSTR baseURL)546 HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString(
547 /* [in] */ BSTR string,
548 /* [in] */ BSTR baseURL)
549 {
550 loadHTMLString(string, baseURL, 0);
551 return S_OK;
552 }
553
loadAlternateHTMLString(BSTR str,BSTR baseURL,BSTR unreachableURL)554 HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString(
555 /* [in] */ BSTR str,
556 /* [in] */ BSTR baseURL,
557 /* [in] */ BSTR unreachableURL)
558 {
559 loadHTMLString(str, baseURL, unreachableURL);
560 return S_OK;
561 }
562
loadArchive(IWebArchive *)563 HRESULT STDMETHODCALLTYPE WebFrame::loadArchive(
564 /* [in] */ IWebArchive* /*archive*/)
565 {
566 ASSERT_NOT_REACHED();
567 return E_NOTIMPL;
568 }
569
getWebDataSource(DocumentLoader * loader)570 static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
571 {
572 return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
573 }
574
dataSource(IWebDataSource ** source)575 HRESULT STDMETHODCALLTYPE WebFrame::dataSource(
576 /* [retval][out] */ IWebDataSource** source)
577 {
578 if (!source) {
579 ASSERT_NOT_REACHED();
580 return E_POINTER;
581 }
582
583 *source = 0;
584
585 Frame* coreFrame = core(this);
586 if (!coreFrame)
587 return E_FAIL;
588
589 WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->documentLoader());
590
591 *source = webDataSource;
592
593 if (webDataSource)
594 webDataSource->AddRef();
595
596 return *source ? S_OK : E_FAIL;
597 }
598
provisionalDataSource(IWebDataSource ** source)599 HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource(
600 /* [retval][out] */ IWebDataSource** source)
601 {
602 if (!source) {
603 ASSERT_NOT_REACHED();
604 return E_POINTER;
605 }
606
607 *source = 0;
608
609 Frame* coreFrame = core(this);
610 if (!coreFrame)
611 return E_FAIL;
612
613 WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->provisionalDocumentLoader());
614
615 *source = webDataSource;
616
617 if (webDataSource)
618 webDataSource->AddRef();
619
620 return *source ? S_OK : E_FAIL;
621 }
622
url() const623 KURL WebFrame::url() const
624 {
625 Frame* coreFrame = core(this);
626 if (!coreFrame)
627 return KURL();
628
629 return coreFrame->loader()->url();
630 }
631
stopLoading(void)632 HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
633 {
634 if (Frame* coreFrame = core(this))
635 coreFrame->loader()->stopAllLoaders();
636 return S_OK;
637 }
638
reload(void)639 HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
640 {
641 Frame* coreFrame = core(this);
642 if (!coreFrame)
643 return E_FAIL;
644
645 coreFrame->loader()->reload();
646 return S_OK;
647 }
648
findFrameNamed(BSTR name,IWebFrame ** frame)649 HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed(
650 /* [in] */ BSTR name,
651 /* [retval][out] */ IWebFrame** frame)
652 {
653 if (!frame) {
654 ASSERT_NOT_REACHED();
655 return E_POINTER;
656 }
657
658 *frame = 0;
659
660 Frame* coreFrame = core(this);
661 if (!coreFrame)
662 return E_FAIL;
663
664 Frame* foundFrame = coreFrame->tree()->find(AtomicString(name, SysStringLen(name)));
665 if (!foundFrame)
666 return S_OK;
667
668 WebFrame* foundWebFrame = kit(foundFrame);
669 if (!foundWebFrame)
670 return E_FAIL;
671
672 return foundWebFrame->QueryInterface(IID_IWebFrame, (void**)frame);
673 }
674
parentFrame(IWebFrame ** frame)675 HRESULT STDMETHODCALLTYPE WebFrame::parentFrame(
676 /* [retval][out] */ IWebFrame** frame)
677 {
678 HRESULT hr = S_OK;
679 *frame = 0;
680 if (Frame* coreFrame = core(this))
681 if (WebFrame* webFrame = kit(coreFrame->tree()->parent()))
682 hr = webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
683
684 return hr;
685 }
686
687 class EnumChildFrames : public IEnumVARIANT
688 {
689 public:
EnumChildFrames(Frame * f)690 EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree()->firstChild() : 0) { }
691
QueryInterface(REFIID riid,void ** ppvObject)692 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
693 {
694 *ppvObject = 0;
695 if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
696 *ppvObject = this;
697 else
698 return E_NOINTERFACE;
699
700 AddRef();
701 return S_OK;
702 }
703
AddRef(void)704 virtual ULONG STDMETHODCALLTYPE AddRef(void)
705 {
706 return ++m_refCount;
707 }
708
Release(void)709 virtual ULONG STDMETHODCALLTYPE Release(void)
710 {
711 ULONG newRef = --m_refCount;
712 if (!newRef)
713 delete(this);
714 return newRef;
715 }
716
Next(ULONG celt,VARIANT * rgVar,ULONG * pCeltFetched)717 virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
718 {
719 if (pCeltFetched)
720 *pCeltFetched = 0;
721 if (!rgVar)
722 return E_POINTER;
723 VariantInit(rgVar);
724 if (!celt || celt > 1)
725 return S_FALSE;
726 if (!m_frame || !m_curChild)
727 return S_FALSE;
728
729 WebFrame* webFrame = kit(m_curChild);
730 IUnknown* unknown;
731 HRESULT hr = webFrame->QueryInterface(IID_IUnknown, (void**)&unknown);
732 if (FAILED(hr))
733 return hr;
734
735 V_VT(rgVar) = VT_UNKNOWN;
736 V_UNKNOWN(rgVar) = unknown;
737
738 m_curChild = m_curChild->tree()->nextSibling();
739 if (pCeltFetched)
740 *pCeltFetched = 1;
741 return S_OK;
742 }
743
Skip(ULONG celt)744 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
745 {
746 if (!m_frame)
747 return S_FALSE;
748 for (unsigned i = 0; i < celt && m_curChild; i++)
749 m_curChild = m_curChild->tree()->nextSibling();
750 return m_curChild ? S_OK : S_FALSE;
751 }
752
Reset(void)753 virtual HRESULT STDMETHODCALLTYPE Reset(void)
754 {
755 if (!m_frame)
756 return S_FALSE;
757 m_curChild = m_frame->tree()->firstChild();
758 return S_OK;
759 }
760
Clone(IEnumVARIANT **)761 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**)
762 {
763 return E_NOTIMPL;
764 }
765
766 private:
767 ULONG m_refCount;
768 Frame* m_frame;
769 Frame* m_curChild;
770 };
771
childFrames(IEnumVARIANT ** enumFrames)772 HRESULT STDMETHODCALLTYPE WebFrame::childFrames(
773 /* [retval][out] */ IEnumVARIANT **enumFrames)
774 {
775 if (!enumFrames)
776 return E_POINTER;
777
778 *enumFrames = new EnumChildFrames(core(this));
779 return S_OK;
780 }
781
782 // IWebFramePrivate ------------------------------------------------------
783
renderTreeAsExternalRepresentation(BSTR * result)784 HRESULT STDMETHODCALLTYPE WebFrame::renderTreeAsExternalRepresentation(
785 /* [retval][out] */ BSTR *result)
786 {
787 if (!result)
788 return E_POINTER;
789
790 Frame* coreFrame = core(this);
791 if (!coreFrame)
792 return E_FAIL;
793
794 *result = BString(externalRepresentation(coreFrame->contentRenderer())).release();
795 return S_OK;
796 }
797
scrollOffset(SIZE * offset)798 HRESULT STDMETHODCALLTYPE WebFrame::scrollOffset(
799 /* [retval][out] */ SIZE* offset)
800 {
801 if (!offset) {
802 ASSERT_NOT_REACHED();
803 return E_POINTER;
804 }
805
806 Frame* coreFrame = core(this);
807 if (!coreFrame)
808 return E_FAIL;
809
810 FrameView* view = coreFrame->view();
811 if (!view)
812 return E_FAIL;
813
814 *offset = view->scrollOffset();
815 return S_OK;
816 }
817
layout()818 HRESULT STDMETHODCALLTYPE WebFrame::layout()
819 {
820 Frame* coreFrame = core(this);
821 if (!coreFrame)
822 return E_FAIL;
823
824 FrameView* view = coreFrame->view();
825 if (!view)
826 return E_FAIL;
827
828 view->layout();
829 return S_OK;
830 }
831
firstLayoutDone(BOOL * result)832 HRESULT STDMETHODCALLTYPE WebFrame::firstLayoutDone(
833 /* [retval][out] */ BOOL* result)
834 {
835 if (!result) {
836 ASSERT_NOT_REACHED();
837 return E_POINTER;
838 }
839
840 *result = 0;
841
842 Frame* coreFrame = core(this);
843 if (!coreFrame)
844 return E_FAIL;
845
846 *result = coreFrame->loader()->firstLayoutDone();
847 return S_OK;
848 }
849
loadType(WebFrameLoadType * type)850 HRESULT STDMETHODCALLTYPE WebFrame::loadType(
851 /* [retval][out] */ WebFrameLoadType* type)
852 {
853 if (!type) {
854 ASSERT_NOT_REACHED();
855 return E_POINTER;
856 }
857
858 *type = (WebFrameLoadType)0;
859
860 Frame* coreFrame = core(this);
861 if (!coreFrame)
862 return E_FAIL;
863
864 *type = (WebFrameLoadType)coreFrame->loader()->loadType();
865 return S_OK;
866 }
867
pendingFrameUnloadEventCount(UINT * result)868 HRESULT STDMETHODCALLTYPE WebFrame::pendingFrameUnloadEventCount(
869 /* [retval][out] */ UINT* result)
870 {
871 if (!result) {
872 ASSERT_NOT_REACHED();
873 return E_POINTER;
874 }
875
876 *result = 0;
877
878 Frame* coreFrame = core(this);
879 if (!coreFrame)
880 return E_FAIL;
881
882 *result = coreFrame->domWindow()->pendingUnloadEventListeners();
883 return S_OK;
884 }
885
fetchApplicationIcon(IWebIconFetcherDelegate * delegate,IWebIconFetcher ** result)886 HRESULT STDMETHODCALLTYPE WebFrame::fetchApplicationIcon(
887 /* [in] */ IWebIconFetcherDelegate *delegate,
888 /* [retval][out] */ IWebIconFetcher **result)
889 {
890 if (!result)
891 return E_POINTER;
892
893 *result = 0;
894
895 if (!delegate)
896 return E_FAIL;
897
898 Frame* coreFrame = core(this);
899 if (!coreFrame)
900 return E_FAIL;
901
902 *result = WebIconFetcher::fetchApplicationIcon(coreFrame, delegate);
903 if (!*result)
904 return E_FAIL;
905
906 return S_OK;
907 }
908
909 // IWebDocumentText -----------------------------------------------------------
910
supportsTextEncoding(BOOL * result)911 HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding(
912 /* [retval][out] */ BOOL* result)
913 {
914 *result = FALSE;
915 return E_NOTIMPL;
916 }
917
selectedString(BSTR * result)918 HRESULT STDMETHODCALLTYPE WebFrame::selectedString(
919 /* [retval][out] */ BSTR* result)
920 {
921 *result = 0;
922
923 Frame* coreFrame = core(this);
924 if (!coreFrame)
925 return E_FAIL;
926
927 String text = coreFrame->displayStringModifiedByEncoding(coreFrame->selectedText());
928
929 *result = BString(text).release();
930 return S_OK;
931 }
932
selectAll()933 HRESULT STDMETHODCALLTYPE WebFrame::selectAll()
934 {
935 return E_NOTIMPL;
936 }
937
deselectAll()938 HRESULT STDMETHODCALLTYPE WebFrame::deselectAll()
939 {
940 return E_NOTIMPL;
941 }
942
943 // WebFrame ---------------------------------------------------------------
944
init(IWebView * webView,Page * page,HTMLFrameOwnerElement * ownerElement)945 PassRefPtr<Frame> WebFrame::init(IWebView* webView, Page* page, HTMLFrameOwnerElement* ownerElement)
946 {
947 webView->QueryInterface(&d->webView);
948 d->webView->Release(); // don't hold the extra ref
949
950 HWND viewWindow;
951 d->webView->viewWindow((OLE_HANDLE*)&viewWindow);
952
953 this->AddRef(); // We release this ref in frameLoaderDestroyed()
954 RefPtr<Frame> frame = Frame::create(page, ownerElement, this);
955 d->frame = frame.get();
956 return frame.release();
957 }
958
impl()959 Frame* WebFrame::impl()
960 {
961 return d->frame;
962 }
963
invalidate()964 void WebFrame::invalidate()
965 {
966 Frame* coreFrame = core(this);
967 ASSERT(coreFrame);
968
969 if (Document* document = coreFrame->document())
970 document->recalcStyle(Node::Force);
971 }
972
setTextSizeMultiplier(float multiplier)973 void WebFrame::setTextSizeMultiplier(float multiplier)
974 {
975 Frame* coreFrame = core(this);
976 ASSERT(coreFrame);
977 coreFrame->setZoomFactor(multiplier, true);
978 }
979
inViewSourceMode(BOOL * flag)980 HRESULT WebFrame::inViewSourceMode(BOOL* flag)
981 {
982 if (!flag) {
983 ASSERT_NOT_REACHED();
984 return E_POINTER;
985 }
986
987 *flag = FALSE;
988
989 Frame* coreFrame = core(this);
990 if (!coreFrame)
991 return E_FAIL;
992
993 *flag = coreFrame->inViewSourceMode() ? TRUE : FALSE;
994 return S_OK;
995 }
996
setInViewSourceMode(BOOL flag)997 HRESULT WebFrame::setInViewSourceMode(BOOL flag)
998 {
999 Frame* coreFrame = core(this);
1000 if (!coreFrame)
1001 return E_FAIL;
1002
1003 coreFrame->setInViewSourceMode(!!flag);
1004 return S_OK;
1005 }
1006
elementWithName(BSTR name,IDOMElement * form,IDOMElement ** element)1007 HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** element)
1008 {
1009 if (!form)
1010 return E_INVALIDARG;
1011
1012 HTMLFormElement *formElement = formElementFromDOMElement(form);
1013 if (formElement) {
1014 Vector<HTMLFormControlElement*>& elements = formElement->formElements;
1015 AtomicString targetName((UChar*)name, SysStringLen(name));
1016 for (unsigned int i = 0; i < elements.size(); i++) {
1017 HTMLFormControlElement *elt = elements[i];
1018 // Skip option elements, other duds
1019 if (elt->name() == targetName) {
1020 *element = DOMElement::createInstance(elt);
1021 return S_OK;
1022 }
1023 }
1024 }
1025 return E_FAIL;
1026 }
1027
formForElement(IDOMElement * element,IDOMElement ** form)1028 HRESULT WebFrame::formForElement(IDOMElement* element, IDOMElement** form)
1029 {
1030 if (!element)
1031 return E_INVALIDARG;
1032
1033 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1034 if (!inputElement)
1035 return E_FAIL;
1036
1037 HTMLFormElement *formElement = inputElement->form();
1038 if (!formElement)
1039 return E_FAIL;
1040
1041 *form = DOMElement::createInstance(formElement);
1042 return S_OK;
1043 }
1044
elementDoesAutoComplete(IDOMElement * element,BOOL * result)1045 HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, BOOL *result)
1046 {
1047 *result = false;
1048 if (!element)
1049 return E_INVALIDARG;
1050
1051 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1052 if (!inputElement)
1053 *result = false;
1054 else
1055 *result = (inputElement->inputType() == HTMLInputElement::TEXT && inputElement->autoComplete());
1056
1057 return S_OK;
1058 }
1059
pauseAnimation(BSTR animationName,IDOMNode * node,double secondsFromNow,BOOL * animationWasRunning)1060 HRESULT WebFrame::pauseAnimation(BSTR animationName, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
1061 {
1062 if (!node || !animationWasRunning)
1063 return E_POINTER;
1064
1065 *animationWasRunning = FALSE;
1066
1067 Frame* frame = core(this);
1068 if (!frame)
1069 return E_FAIL;
1070
1071 AnimationController* controller = frame->animation();
1072 if (!controller)
1073 return E_FAIL;
1074
1075 COMPtr<DOMNode> domNode(Query, node);
1076 if (!domNode)
1077 return E_FAIL;
1078
1079 *animationWasRunning = controller->pauseAnimationAtTime(domNode->node()->renderer(), String(animationName, SysStringLen(animationName)), secondsFromNow);
1080 return S_OK;
1081 }
1082
pauseTransition(BSTR propertyName,IDOMNode * node,double secondsFromNow,BOOL * transitionWasRunning)1083 HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double secondsFromNow, BOOL* transitionWasRunning)
1084 {
1085 if (!node || !transitionWasRunning)
1086 return E_POINTER;
1087
1088 *transitionWasRunning = FALSE;
1089
1090 Frame* frame = core(this);
1091 if (!frame)
1092 return E_FAIL;
1093
1094 AnimationController* controller = frame->animation();
1095 if (!controller)
1096 return E_FAIL;
1097
1098 COMPtr<DOMNode> domNode(Query, node);
1099 if (!domNode)
1100 return E_FAIL;
1101
1102 *transitionWasRunning = controller->pauseTransitionAtTime(domNode->node()->renderer(), String(propertyName, SysStringLen(propertyName)), secondsFromNow);
1103 return S_OK;
1104 }
1105
numberOfActiveAnimations(UINT * number)1106 HRESULT WebFrame::numberOfActiveAnimations(UINT* number)
1107 {
1108 if (!number)
1109 return E_POINTER;
1110
1111 *number = 0;
1112
1113 Frame* frame = core(this);
1114 if (!frame)
1115 return E_FAIL;
1116
1117 AnimationController* controller = frame->animation();
1118 if (!controller)
1119 return E_FAIL;
1120
1121 *number = controller->numberOfActiveAnimations();
1122 return S_OK;
1123 }
1124
isDisplayingStandaloneImage(BOOL * result)1125 HRESULT WebFrame::isDisplayingStandaloneImage(BOOL* result)
1126 {
1127 if (!result)
1128 return E_POINTER;
1129
1130 *result = FALSE;
1131
1132 Frame* frame = core(this);
1133 if (!frame)
1134 return E_FAIL;
1135
1136 Document* document = frame->document();
1137 *result = document && document->isImageDocument();
1138 return S_OK;
1139 }
1140
controlsInForm(IDOMElement * form,IDOMElement ** controls,int * cControls)1141 HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls)
1142 {
1143 if (!form)
1144 return E_INVALIDARG;
1145
1146 HTMLFormElement *formElement = formElementFromDOMElement(form);
1147 if (!formElement)
1148 return E_FAIL;
1149
1150 int inCount = *cControls;
1151 int count = (int) formElement->formElements.size();
1152 *cControls = count;
1153 if (!controls)
1154 return S_OK;
1155 if (inCount < count)
1156 return E_FAIL;
1157
1158 *cControls = 0;
1159 Vector<HTMLFormControlElement*>& elements = formElement->formElements;
1160 for (int i = 0; i < count; i++) {
1161 if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1162 controls[*cControls] = DOMElement::createInstance(elements.at(i));
1163 (*cControls)++;
1164 }
1165 }
1166 return S_OK;
1167 }
1168
elementIsPassword(IDOMElement * element,bool * result)1169 HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result)
1170 {
1171 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1172 *result = inputElement != 0
1173 && inputElement->inputType() == HTMLInputElement::PASSWORD;
1174 return S_OK;
1175 }
1176
searchForLabelsBeforeElement(const BSTR * labels,int cLabels,IDOMElement * beforeElement,BSTR * result)1177 HRESULT WebFrame::searchForLabelsBeforeElement(const BSTR* labels, int cLabels, IDOMElement* beforeElement, BSTR* result)
1178 {
1179 if (!result) {
1180 ASSERT_NOT_REACHED();
1181 return E_POINTER;
1182 }
1183
1184 *result = 0;
1185
1186 if (!cLabels)
1187 return S_OK;
1188 if (cLabels < 1)
1189 return E_INVALIDARG;
1190
1191 Frame* coreFrame = core(this);
1192 if (!coreFrame)
1193 return E_FAIL;
1194
1195 Vector<String> labelStrings(cLabels);
1196 for (int i=0; i<cLabels; i++)
1197 labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1198 Element *coreElement = elementFromDOMElement(beforeElement);
1199 if (!coreElement)
1200 return E_FAIL;
1201
1202 String label = coreFrame->searchForLabelsBeforeElement(labelStrings, coreElement);
1203
1204 *result = SysAllocStringLen(label.characters(), label.length());
1205 if (label.length() && !*result)
1206 return E_OUTOFMEMORY;
1207 return S_OK;
1208 }
1209
matchLabelsAgainstElement(const BSTR * labels,int cLabels,IDOMElement * againstElement,BSTR * result)1210 HRESULT WebFrame::matchLabelsAgainstElement(const BSTR* labels, int cLabels, IDOMElement* againstElement, BSTR* result)
1211 {
1212 if (!result) {
1213 ASSERT_NOT_REACHED();
1214 return E_POINTER;
1215 }
1216
1217 *result = 0;
1218
1219 if (!cLabels)
1220 return S_OK;
1221 if (cLabels < 1)
1222 return E_INVALIDARG;
1223
1224 Frame* coreFrame = core(this);
1225 if (!coreFrame)
1226 return E_FAIL;
1227
1228 Vector<String> labelStrings(cLabels);
1229 for (int i=0; i<cLabels; i++)
1230 labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1231 Element *coreElement = elementFromDOMElement(againstElement);
1232 if (!coreElement)
1233 return E_FAIL;
1234
1235 String label = coreFrame->matchLabelsAgainstElement(labelStrings, coreElement);
1236
1237 *result = SysAllocStringLen(label.characters(), label.length());
1238 if (label.length() && !*result)
1239 return E_OUTOFMEMORY;
1240 return S_OK;
1241 }
1242
canProvideDocumentSource(bool * result)1243 HRESULT WebFrame::canProvideDocumentSource(bool* result)
1244 {
1245 HRESULT hr = S_OK;
1246 *result = false;
1247
1248 COMPtr<IWebDataSource> dataSource;
1249 hr = WebFrame::dataSource(&dataSource);
1250 if (FAILED(hr))
1251 return hr;
1252
1253 COMPtr<IWebURLResponse> urlResponse;
1254 hr = dataSource->response(&urlResponse);
1255 if (SUCCEEDED(hr) && urlResponse) {
1256 BSTR mimeTypeBStr;
1257 if (SUCCEEDED(urlResponse->MIMEType(&mimeTypeBStr))) {
1258 String mimeType(mimeTypeBStr, SysStringLen(mimeTypeBStr));
1259 *result = mimeType == "text/html" || WebCore::DOMImplementation::isXMLMIMEType(mimeType);
1260 SysFreeString(mimeTypeBStr);
1261 }
1262 }
1263 return hr;
1264 }
1265
frameLoaderDestroyed()1266 void WebFrame::frameLoaderDestroyed()
1267 {
1268 // The FrameLoader going away is equivalent to the Frame going away,
1269 // so we now need to clear our frame pointer.
1270 d->frame = 0;
1271
1272 this->Release();
1273 }
1274
makeRepresentation(DocumentLoader *)1275 void WebFrame::makeRepresentation(DocumentLoader*)
1276 {
1277 notImplemented();
1278 }
1279
forceLayoutForNonHTML()1280 void WebFrame::forceLayoutForNonHTML()
1281 {
1282 notImplemented();
1283 }
1284
setCopiesOnScroll()1285 void WebFrame::setCopiesOnScroll()
1286 {
1287 notImplemented();
1288 }
1289
detachedFromParent2()1290 void WebFrame::detachedFromParent2()
1291 {
1292 notImplemented();
1293 }
1294
detachedFromParent3()1295 void WebFrame::detachedFromParent3()
1296 {
1297 notImplemented();
1298 }
1299
cancelPolicyCheck()1300 void WebFrame::cancelPolicyCheck()
1301 {
1302 if (d->m_policyListener) {
1303 d->m_policyListener->invalidate();
1304 d->m_policyListener = 0;
1305 }
1306
1307 d->m_policyFunction = 0;
1308 }
1309
dispatchWillSubmitForm(FramePolicyFunction function,PassRefPtr<FormState> formState)1310 void WebFrame::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
1311 {
1312 Frame* coreFrame = core(this);
1313 ASSERT(coreFrame);
1314
1315 COMPtr<IWebFormDelegate> formDelegate;
1316
1317 if (FAILED(d->webView->formDelegate(&formDelegate))) {
1318 (coreFrame->loader()->*function)(PolicyUse);
1319 return;
1320 }
1321
1322 COMPtr<IDOMElement> formElement(AdoptCOM, DOMElement::createInstance(formState->form()));
1323
1324 HashMap<String, String> formValuesMap;
1325 const StringPairVector& textFieldValues = formState->textFieldValues();
1326 size_t size = textFieldValues.size();
1327 for (size_t i = 0; i < size; ++i)
1328 formValuesMap.add(textFieldValues[i].first, textFieldValues[i].second);
1329
1330 COMPtr<IPropertyBag> formValuesPropertyBag(AdoptCOM, COMPropertyBag<String>::createInstance(formValuesMap));
1331
1332 COMPtr<WebFrame> sourceFrame(kit(formState->sourceFrame()));
1333 if (SUCCEEDED(formDelegate->willSubmitForm(this, sourceFrame.get(), formElement.get(), formValuesPropertyBag.get(), setUpPolicyListener(function).get())))
1334 return;
1335
1336 // FIXME: Add a sane default implementation
1337 (coreFrame->loader()->*function)(PolicyUse);
1338 }
1339
revertToProvisionalState(DocumentLoader *)1340 void WebFrame::revertToProvisionalState(DocumentLoader*)
1341 {
1342 notImplemented();
1343 }
1344
setMainFrameDocumentReady(bool)1345 void WebFrame::setMainFrameDocumentReady(bool)
1346 {
1347 notImplemented();
1348 }
1349
willChangeTitle(DocumentLoader *)1350 void WebFrame::willChangeTitle(DocumentLoader*)
1351 {
1352 notImplemented();
1353 }
1354
didChangeTitle(DocumentLoader *)1355 void WebFrame::didChangeTitle(DocumentLoader*)
1356 {
1357 notImplemented();
1358 }
1359
canHandleRequest(const ResourceRequest & request) const1360 bool WebFrame::canHandleRequest(const ResourceRequest& request) const
1361 {
1362 return WebView::canHandleRequest(request);
1363 }
1364
canShowMIMEType(const String &) const1365 bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const
1366 {
1367 notImplemented();
1368 return true;
1369 }
1370
representationExistsForURLScheme(const String &) const1371 bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const
1372 {
1373 notImplemented();
1374 return false;
1375 }
1376
generatedMIMETypeForURLScheme(const String &) const1377 String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1378 {
1379 notImplemented();
1380 ASSERT_NOT_REACHED();
1381 return String();
1382 }
1383
frameLoadCompleted()1384 void WebFrame::frameLoadCompleted()
1385 {
1386 }
1387
restoreViewState()1388 void WebFrame::restoreViewState()
1389 {
1390 }
1391
provisionalLoadStarted()1392 void WebFrame::provisionalLoadStarted()
1393 {
1394 notImplemented();
1395 }
1396
shouldTreatURLAsSameAsCurrent(const KURL &) const1397 bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const
1398 {
1399 notImplemented();
1400 return false;
1401 }
1402
addHistoryItemForFragmentScroll()1403 void WebFrame::addHistoryItemForFragmentScroll()
1404 {
1405 notImplemented();
1406 }
1407
didFinishLoad()1408 void WebFrame::didFinishLoad()
1409 {
1410 notImplemented();
1411 }
1412
prepareForDataSourceReplacement()1413 void WebFrame::prepareForDataSourceReplacement()
1414 {
1415 notImplemented();
1416 }
1417
userAgent(const KURL & url)1418 String WebFrame::userAgent(const KURL& url)
1419 {
1420 return d->webView->userAgentForKURL(url);
1421 }
1422
saveViewStateToItem(HistoryItem *)1423 void WebFrame::saveViewStateToItem(HistoryItem*)
1424 {
1425 }
1426
cancelledError(const ResourceRequest & request)1427 ResourceError WebFrame::cancelledError(const ResourceRequest& request)
1428 {
1429 // FIXME: Need ChickenCat to include CFNetwork/CFURLError.h to get these values
1430 // Alternatively, we could create our own error domain/codes.
1431 return ResourceError(String(WebURLErrorDomain), -999, request.url().string(), String());
1432 }
1433
blockedError(const ResourceRequest & request)1434 ResourceError WebFrame::blockedError(const ResourceRequest& request)
1435 {
1436 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1437 return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotUseRestrictedPort, request.url().string(), String());
1438 }
1439
cannotShowURLError(const ResourceRequest & request)1440 ResourceError WebFrame::cannotShowURLError(const ResourceRequest& request)
1441 {
1442 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1443 return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotShowURL, request.url().string(), String());
1444 }
1445
interruptForPolicyChangeError(const ResourceRequest & request)1446 ResourceError WebFrame::interruptForPolicyChangeError(const ResourceRequest& request)
1447 {
1448 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1449 return ResourceError(String(WebKitErrorDomain), WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), String());
1450 }
1451
cannotShowMIMETypeError(const ResourceResponse &)1452 ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&)
1453 {
1454 notImplemented();
1455 return ResourceError();
1456 }
1457
fileDoesNotExistError(const ResourceResponse &)1458 ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&)
1459 {
1460 notImplemented();
1461 return ResourceError();
1462 }
1463
pluginWillHandleLoadError(const ResourceResponse & response)1464 ResourceError WebFrame::pluginWillHandleLoadError(const ResourceResponse& response)
1465 {
1466 return ResourceError(String(WebKitErrorDomain), WebKitErrorPlugInWillHandleLoad, response.url().string(), String());
1467 }
1468
shouldFallBack(const ResourceError & error)1469 bool WebFrame::shouldFallBack(const ResourceError& error)
1470 {
1471 return error.errorCode() != WebURLErrorCancelled;
1472 }
1473
setUpPolicyListener(WebCore::FramePolicyFunction function)1474 COMPtr<WebFramePolicyListener> WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction function)
1475 {
1476 // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1477
1478 if (d->m_policyListener)
1479 d->m_policyListener->invalidate();
1480
1481 Frame* coreFrame = core(this);
1482 ASSERT(coreFrame);
1483
1484 d->m_policyListener.adoptRef(WebFramePolicyListener::createInstance(coreFrame));
1485 d->m_policyFunction = function;
1486
1487 return d->m_policyListener;
1488 }
1489
receivedPolicyDecision(PolicyAction action)1490 void WebFrame::receivedPolicyDecision(PolicyAction action)
1491 {
1492 ASSERT(d->m_policyListener);
1493 ASSERT(d->m_policyFunction);
1494
1495 FramePolicyFunction function = d->m_policyFunction;
1496
1497 d->m_policyListener = 0;
1498 d->m_policyFunction = 0;
1499
1500 Frame* coreFrame = core(this);
1501 ASSERT(coreFrame);
1502
1503 (coreFrame->loader()->*function)(action);
1504 }
1505
dispatchDecidePolicyForMIMEType(FramePolicyFunction function,const String & mimeType,const ResourceRequest & request)1506 void WebFrame::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const String& mimeType, const ResourceRequest& request)
1507 {
1508 Frame* coreFrame = core(this);
1509 ASSERT(coreFrame);
1510
1511 COMPtr<IWebPolicyDelegate> policyDelegate;
1512 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1513 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1514
1515 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1516
1517 if (SUCCEEDED(policyDelegate->decidePolicyForMIMEType(d->webView, BString(mimeType), urlRequest.get(), this, setUpPolicyListener(function).get())))
1518 return;
1519
1520 (coreFrame->loader()->*function)(PolicyUse);
1521 }
1522
dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,const NavigationAction & action,const ResourceRequest & request,PassRefPtr<FormState> formState,const String & frameName)1523 void WebFrame::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
1524 {
1525 Frame* coreFrame = core(this);
1526 ASSERT(coreFrame);
1527
1528 COMPtr<IWebPolicyDelegate> policyDelegate;
1529 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1530 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1531
1532 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1533 COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
1534
1535 if (SUCCEEDED(policyDelegate->decidePolicyForNewWindowAction(d->webView, actionInformation.get(), urlRequest.get(), BString(frameName), setUpPolicyListener(function).get())))
1536 return;
1537
1538 (coreFrame->loader()->*function)(PolicyUse);
1539 }
1540
dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,const NavigationAction & action,const ResourceRequest & request,PassRefPtr<FormState> formState)1541 void WebFrame::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
1542 {
1543 Frame* coreFrame = core(this);
1544 ASSERT(coreFrame);
1545
1546 COMPtr<IWebPolicyDelegate> policyDelegate;
1547 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1548 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1549
1550 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1551 COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
1552
1553 if (SUCCEEDED(policyDelegate->decidePolicyForNavigationAction(d->webView, actionInformation.get(), urlRequest.get(), this, setUpPolicyListener(function).get())))
1554 return;
1555
1556 (coreFrame->loader()->*function)(PolicyUse);
1557 }
1558
dispatchUnableToImplementPolicy(const ResourceError & error)1559 void WebFrame::dispatchUnableToImplementPolicy(const ResourceError& error)
1560 {
1561 COMPtr<IWebPolicyDelegate> policyDelegate;
1562 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1563 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1564
1565 COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error));
1566 policyDelegate->unableToImplementPolicyWithError(d->webView, webError.get(), this);
1567 }
1568
download(ResourceHandle * handle,const ResourceRequest & request,const ResourceRequest &,const ResourceResponse & response)1569 void WebFrame::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1570 {
1571 COMPtr<IWebDownloadDelegate> downloadDelegate;
1572 COMPtr<IWebView> webView;
1573 if (SUCCEEDED(this->webView(&webView))) {
1574 if (FAILED(webView->downloadDelegate(&downloadDelegate))) {
1575 // If the WebView doesn't successfully provide a download delegate we'll pass a null one
1576 // into the WebDownload - which may or may not decide to use a DefaultDownloadDelegate
1577 LOG_ERROR("Failed to get downloadDelegate from WebView");
1578 downloadDelegate = 0;
1579 }
1580 }
1581
1582 // Its the delegate's job to ref the WebDownload to keep it alive - otherwise it will be destroyed
1583 // when this method returns
1584 COMPtr<WebDownload> download;
1585 download.adoptRef(WebDownload::createInstance(handle, request, response, downloadDelegate.get()));
1586 }
1587
dispatchDidLoadResourceFromMemoryCache(DocumentLoader *,const ResourceRequest &,const ResourceResponse &,int)1588 bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
1589 {
1590 notImplemented();
1591 return false;
1592 }
1593
dispatchDidFailProvisionalLoad(const ResourceError & error)1594 void WebFrame::dispatchDidFailProvisionalLoad(const ResourceError& error)
1595 {
1596 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1597 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
1598 COMPtr<IWebError> webError;
1599 webError.adoptRef(WebError::createInstance(error));
1600 frameLoadDelegate->didFailProvisionalLoadWithError(d->webView, webError.get(), this);
1601 }
1602 }
1603
dispatchDidFailLoad(const ResourceError & error)1604 void WebFrame::dispatchDidFailLoad(const ResourceError& error)
1605 {
1606 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1607 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
1608 COMPtr<IWebError> webError;
1609 webError.adoptRef(WebError::createInstance(error));
1610 frameLoadDelegate->didFailLoadWithError(d->webView, webError.get(), this);
1611 }
1612 }
1613
startDownload(const ResourceRequest & request)1614 void WebFrame::startDownload(const ResourceRequest& request)
1615 {
1616 d->webView->downloadURL(request.url());
1617 }
1618
createJavaAppletWidget(const IntSize & pluginSize,HTMLAppletElement * element,const KURL &,const Vector<String> & paramNames,const Vector<String> & paramValues)1619 PassRefPtr<Widget> WebFrame::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues)
1620 {
1621 RefPtr<PluginView> pluginView = PluginView::create(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false);
1622
1623 // Check if the plugin can be loaded successfully
1624 if (pluginView->plugin() && pluginView->plugin()->load())
1625 return pluginView;
1626
1627 COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
1628 if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
1629 return pluginView;
1630
1631 COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance());
1632
1633 ResourceError resourceError(String(WebKitErrorDomain), WebKitErrorJavaUnavailable, String(), String());
1634 COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
1635
1636 resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader()));
1637
1638 return pluginView;
1639 }
1640
objectContentType(const KURL & url,const String & mimeTypeIn)1641 ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeTypeIn)
1642 {
1643 String mimeType = mimeTypeIn;
1644 if (mimeType.isEmpty())
1645 mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().substring(url.path().reverseFind('.') + 1));
1646
1647 if (mimeType.isEmpty())
1648 return ObjectContentFrame; // Go ahead and hope that we can display the content.
1649
1650 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1651 return WebCore::ObjectContentImage;
1652
1653 if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
1654 return WebCore::ObjectContentNetscapePlugin;
1655
1656 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1657 return WebCore::ObjectContentFrame;
1658
1659 return WebCore::ObjectContentNone;
1660 }
1661
overrideMediaType() const1662 String WebFrame::overrideMediaType() const
1663 {
1664 notImplemented();
1665 return String();
1666 }
1667
windowObjectCleared()1668 void WebFrame::windowObjectCleared()
1669 {
1670 Frame* coreFrame = core(this);
1671 ASSERT(coreFrame);
1672
1673 Settings* settings = coreFrame->settings();
1674 if (!settings || !settings->isJavaScriptEnabled())
1675 return;
1676
1677 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1678 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
1679 JSContextRef context = toRef(coreFrame->script()->globalObject()->globalExec());
1680 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject());
1681 ASSERT(windowObject);
1682
1683 if (FAILED(frameLoadDelegate->didClearWindowObject(d->webView, context, windowObject, this)))
1684 frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject);
1685 }
1686 }
1687
documentElementAvailable()1688 void WebFrame::documentElementAvailable()
1689 {
1690 }
1691
didPerformFirstNavigation() const1692 void WebFrame::didPerformFirstNavigation() const
1693 {
1694 COMPtr<IWebPreferences> preferences;
1695 if (FAILED(d->webView->preferences(&preferences)))
1696 return;
1697
1698 COMPtr<IWebPreferencesPrivate> preferencesPrivate(Query, preferences);
1699 if (!preferencesPrivate)
1700 return;
1701 BOOL automaticallyDetectsCacheModel;
1702 if (FAILED(preferencesPrivate->automaticallyDetectsCacheModel(&automaticallyDetectsCacheModel)))
1703 return;
1704
1705 WebCacheModel cacheModel;
1706 if (FAILED(preferences->cacheModel(&cacheModel)))
1707 return;
1708
1709 if (automaticallyDetectsCacheModel && cacheModel < WebCacheModelDocumentBrowser)
1710 preferences->setCacheModel(WebCacheModelDocumentBrowser);
1711 }
1712
registerForIconNotification(bool listen)1713 void WebFrame::registerForIconNotification(bool listen)
1714 {
1715 d->webView->registerForIconNotification(listen);
1716 }
1717
printerRect(HDC printDC)1718 static IntRect printerRect(HDC printDC)
1719 {
1720 return IntRect(0, 0,
1721 GetDeviceCaps(printDC, PHYSICALWIDTH) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETX),
1722 GetDeviceCaps(printDC, PHYSICALHEIGHT) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETY));
1723 }
1724
setPrinting(bool printing,float minPageWidth,float maxPageWidth,bool adjustViewSize)1725 void WebFrame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
1726 {
1727 Frame* coreFrame = core(this);
1728 ASSERT(coreFrame);
1729 coreFrame->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
1730 }
1731
setInPrintingMode(BOOL value,HDC printDC)1732 HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode(
1733 /* [in] */ BOOL value,
1734 /* [in] */ HDC printDC)
1735 {
1736 if (m_inPrintingMode == !!value)
1737 return S_OK;
1738
1739 Frame* coreFrame = core(this);
1740 if (!coreFrame || !coreFrame->document())
1741 return E_FAIL;
1742
1743 m_inPrintingMode = !!value;
1744
1745 // If we are a frameset just print with the layout we have onscreen, otherwise relayout
1746 // according to the paper size
1747 float minLayoutWidth = 0.0f;
1748 float maxLayoutWidth = 0.0f;
1749 if (m_inPrintingMode && !coreFrame->document()->isFrameSet()) {
1750 if (!printDC) {
1751 ASSERT_NOT_REACHED();
1752 return E_POINTER;
1753 }
1754
1755 const int desiredHorizontalPixelsPerInch = 72;
1756 int paperHorizontalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSX);
1757 int paperWidth = printerRect(printDC).width() * desiredHorizontalPixelsPerInch / paperHorizontalPixelsPerInch;
1758 minLayoutWidth = paperWidth * PrintingMinimumShrinkFactor;
1759 maxLayoutWidth = paperWidth * PrintingMaximumShrinkFactor;
1760 }
1761
1762 setPrinting(m_inPrintingMode, minLayoutWidth, maxLayoutWidth, true);
1763
1764 if (!m_inPrintingMode)
1765 m_pageRects.clear();
1766
1767 return S_OK;
1768 }
1769
headerAndFooterHeights(float * headerHeight,float * footerHeight)1770 void WebFrame::headerAndFooterHeights(float* headerHeight, float* footerHeight)
1771 {
1772 if (headerHeight)
1773 *headerHeight = 0;
1774 if (footerHeight)
1775 *footerHeight = 0;
1776 float height = 0;
1777 COMPtr<IWebUIDelegate> ui;
1778 if (FAILED(d->webView->uiDelegate(&ui)))
1779 return;
1780 if (headerHeight && SUCCEEDED(ui->webViewHeaderHeight(d->webView, &height)))
1781 *headerHeight = height;
1782 if (footerHeight && SUCCEEDED(ui->webViewFooterHeight(d->webView, &height)))
1783 *footerHeight = height;
1784 }
1785
printerMarginRect(HDC printDC)1786 IntRect WebFrame::printerMarginRect(HDC printDC)
1787 {
1788 IntRect emptyRect(0, 0, 0, 0);
1789
1790 COMPtr<IWebUIDelegate> ui;
1791 if (FAILED(d->webView->uiDelegate(&ui)))
1792 return emptyRect;
1793
1794 RECT rect;
1795 if (FAILED(ui->webViewPrintingMarginRect(d->webView, &rect)))
1796 return emptyRect;
1797
1798 rect.left = MulDiv(rect.left, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
1799 rect.top = MulDiv(rect.top, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
1800 rect.right = MulDiv(rect.right, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
1801 rect.bottom = MulDiv(rect.bottom, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
1802
1803 return IntRect(rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top);
1804 }
1805
computePageRects(HDC printDC)1806 const Vector<WebCore::IntRect>& WebFrame::computePageRects(HDC printDC)
1807 {
1808 ASSERT(m_inPrintingMode);
1809
1810 Frame* coreFrame = core(this);
1811 ASSERT(coreFrame);
1812 ASSERT(coreFrame->document());
1813
1814 if (!printDC)
1815 return m_pageRects;
1816
1817 // adjust the page rect by the header and footer
1818 float headerHeight = 0, footerHeight = 0;
1819 headerAndFooterHeights(&headerHeight, &footerHeight);
1820 IntRect pageRect = printerRect(printDC);
1821 IntRect marginRect = printerMarginRect(printDC);
1822 IntRect adjustedRect = IntRect(
1823 pageRect.x() + marginRect.x(),
1824 pageRect.y() + marginRect.y(),
1825 pageRect.width() - marginRect.x() - marginRect.right(),
1826 pageRect.height() - marginRect.y() - marginRect.bottom());
1827
1828 computePageRectsForFrame(coreFrame, adjustedRect, headerHeight, footerHeight, 1.0,m_pageRects, m_pageHeight);
1829
1830 return m_pageRects;
1831 }
1832
getPrintedPageCount(HDC printDC,UINT * pageCount)1833 HRESULT STDMETHODCALLTYPE WebFrame::getPrintedPageCount(
1834 /* [in] */ HDC printDC,
1835 /* [retval][out] */ UINT *pageCount)
1836 {
1837 if (!pageCount || !printDC) {
1838 ASSERT_NOT_REACHED();
1839 return E_POINTER;
1840 }
1841
1842 *pageCount = 0;
1843
1844 if (!m_inPrintingMode) {
1845 ASSERT_NOT_REACHED();
1846 return E_FAIL;
1847 }
1848
1849 Frame* coreFrame = core(this);
1850 if (!coreFrame || !coreFrame->document())
1851 return E_FAIL;
1852
1853 const Vector<IntRect>& pages = computePageRects(printDC);
1854 *pageCount = (UINT) pages.size();
1855
1856 return S_OK;
1857 }
1858
drawHeader(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,float headerHeight)1859 void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
1860 {
1861 int x = pageRect.x();
1862 int y = 0;
1863 RECT headerRect = {x, y, x+pageRect.width(), y+static_cast<int>(headerHeight)};
1864 ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)));
1865 }
1866
drawFooter(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,UINT page,UINT pageCount,float headerHeight,float footerHeight)1867 void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
1868 {
1869 int x = pageRect.x();
1870 int y = max((int)headerHeight+pageRect.height(), m_pageHeight-static_cast<int>(footerHeight));
1871 RECT footerRect = {x, y, x+pageRect.width(), y+static_cast<int>(footerHeight)};
1872 ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)), page+1, pageCount);
1873 }
1874
1875 #if PLATFORM(CG)
spoolPage(PlatformGraphicsContext * pctx,GraphicsContext * spoolCtx,HDC printDC,IWebUIDelegate * ui,float headerHeight,float footerHeight,UINT page,UINT pageCount)1876 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
1877 {
1878 Frame* coreFrame = core(this);
1879
1880 IntRect pageRect = m_pageRects[page];
1881
1882 CGContextSaveGState(pctx);
1883
1884 IntRect printRect = printerRect(printDC);
1885 CGRect mediaBox = CGRectMake(CGFloat(0),
1886 CGFloat(0),
1887 CGFloat(printRect.width()),
1888 CGFloat(printRect.height()));
1889
1890 CGContextBeginPage(pctx, &mediaBox);
1891
1892 // FIXME: Could some of this coordinate space manipulation be shared with Cairo?
1893 CGFloat scale = static_cast<float>(mediaBox.size.width)/static_cast<float>(pageRect.width());
1894 CGAffineTransform ctm = CGContextGetBaseCTM(pctx);
1895 ctm = CGAffineTransformScale(ctm, -scale, -scale);
1896 ctm = CGAffineTransformTranslate(ctm, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
1897 CGContextScaleCTM(pctx, scale, scale);
1898 CGContextTranslateCTM(pctx, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
1899 CGContextSetBaseCTM(pctx, ctm);
1900
1901 coreFrame->view()->paintContents(spoolCtx, pageRect);
1902
1903 CGContextTranslateCTM(pctx, CGFloat(pageRect.x()), CGFloat(pageRect.y())-headerHeight);
1904
1905 if (headerHeight)
1906 drawHeader(pctx, ui, pageRect, headerHeight);
1907
1908 if (footerHeight)
1909 drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
1910
1911 CGContextEndPage(pctx);
1912 CGContextRestoreGState(pctx);
1913 }
1914 #elif PLATFORM(CAIRO)
spoolPage(PlatformGraphicsContext * pctx,GraphicsContext * spoolCtx,HDC printDC,IWebUIDelegate * ui,float headerHeight,float footerHeight,UINT page,UINT pageCount)1915 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
1916 {
1917 Frame* coreFrame = core(this);
1918
1919 IntRect pageRect = m_pageRects[page];
1920
1921 cairo_save(pctx);
1922
1923 IntRect printRect = printerRect(printDC);
1924 IntRect mediaBox(0, 0, printRect.width(), printRect.height());
1925
1926 ::StartPage(printDC);
1927
1928 // FIXME: Could some of this coordinate space manipulation be shared with CG?
1929 float scale = static_cast<float>(mediaBox.size().width())/static_cast<float>(pageRect.width());
1930 cairo_scale(pctx, -scale, -scale);
1931 cairo_translate(pctx, -pageRect.x(), -pageRect.y()+headerHeight);
1932 cairo_scale(pctx, scale, scale);
1933 cairo_translate(pctx, -pageRect.x(), -pageRect.y()+headerHeight); // reserves space for header
1934
1935 coreFrame->view()->paintContents(spoolCtx, pageRect);
1936
1937 cairo_translate(pctx, pageRect.x(), pageRect.y()-headerHeight);
1938
1939 if (headerHeight)
1940 drawHeader(pctx, ui, pageRect, headerHeight);
1941
1942 if (footerHeight)
1943 drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
1944
1945 cairo_show_page(pctx);
1946 ::EndPage(printDC);
1947 cairo_restore(pctx);
1948 }
1949 #endif
1950
spoolPages(HDC printDC,UINT startPage,UINT endPage,void * ctx)1951 HRESULT STDMETHODCALLTYPE WebFrame::spoolPages(
1952 /* [in] */ HDC printDC,
1953 /* [in] */ UINT startPage,
1954 /* [in] */ UINT endPage,
1955 /* [retval][out] */ void* ctx)
1956 {
1957 if (!printDC || !ctx) {
1958 ASSERT_NOT_REACHED();
1959 return E_POINTER;
1960 }
1961
1962 if (!m_inPrintingMode) {
1963 ASSERT_NOT_REACHED();
1964 return E_FAIL;
1965 }
1966
1967 Frame* coreFrame = core(this);
1968 if (!coreFrame || !coreFrame->document())
1969 return E_FAIL;
1970
1971 UINT pageCount = (UINT) m_pageRects.size();
1972 PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx;
1973
1974 if (!pageCount || startPage > pageCount) {
1975 ASSERT_NOT_REACHED();
1976 return E_FAIL;
1977 }
1978
1979 if (startPage > 0)
1980 startPage--;
1981
1982 if (endPage == 0)
1983 endPage = pageCount;
1984
1985 COMPtr<IWebUIDelegate> ui;
1986 if (FAILED(d->webView->uiDelegate(&ui)))
1987 return E_FAIL;
1988
1989 float headerHeight = 0, footerHeight = 0;
1990 headerAndFooterHeights(&headerHeight, &footerHeight);
1991 GraphicsContext spoolCtx(pctx);
1992 spoolCtx.setShouldIncludeChildWindows(true);
1993
1994 for (UINT ii = startPage; ii < endPage; ii++)
1995 spoolPage(pctx, &spoolCtx, printDC, ui.get(), headerHeight, footerHeight, ii, pageCount);
1996
1997 return S_OK;
1998 }
1999
isFrameSet(BOOL * result)2000 HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet(
2001 /* [retval][out] */ BOOL* result)
2002 {
2003 *result = FALSE;
2004
2005 Frame* coreFrame = core(this);
2006 if (!coreFrame || !coreFrame->document())
2007 return E_FAIL;
2008
2009 *result = coreFrame->document()->isFrameSet() ? TRUE : FALSE;
2010 return S_OK;
2011 }
2012
string(BSTR * result)2013 HRESULT STDMETHODCALLTYPE WebFrame::string(
2014 /* [retval][out] */ BSTR *result)
2015 {
2016 *result = 0;
2017
2018 Frame* coreFrame = core(this);
2019 if (!coreFrame)
2020 return E_FAIL;
2021
2022 RefPtr<Range> allRange(rangeOfContents(coreFrame->document()));
2023 String allString = plainText(allRange.get());
2024 *result = BString(allString).release();
2025 return S_OK;
2026 }
2027
size(SIZE * size)2028 HRESULT STDMETHODCALLTYPE WebFrame::size(
2029 /* [retval][out] */ SIZE *size)
2030 {
2031 if (!size)
2032 return E_POINTER;
2033 size->cx = size->cy = 0;
2034
2035 Frame* coreFrame = core(this);
2036 if (!coreFrame)
2037 return E_FAIL;
2038 FrameView* view = coreFrame->view();
2039 if (!view)
2040 return E_FAIL;
2041 size->cx = view->width();
2042 size->cy = view->height();
2043 return S_OK;
2044 }
2045
hasScrollBars(BOOL * result)2046 HRESULT STDMETHODCALLTYPE WebFrame::hasScrollBars(
2047 /* [retval][out] */ BOOL *result)
2048 {
2049 if (!result)
2050 return E_POINTER;
2051 *result = FALSE;
2052
2053 Frame* coreFrame = core(this);
2054 if (!coreFrame)
2055 return E_FAIL;
2056
2057 FrameView* view = coreFrame->view();
2058 if (!view)
2059 return E_FAIL;
2060
2061 if (view->horizontalScrollbar() || view->verticalScrollbar())
2062 *result = TRUE;
2063
2064 return S_OK;
2065 }
2066
contentBounds(RECT * result)2067 HRESULT STDMETHODCALLTYPE WebFrame::contentBounds(
2068 /* [retval][out] */ RECT *result)
2069 {
2070 if (!result)
2071 return E_POINTER;
2072 ::SetRectEmpty(result);
2073
2074 Frame* coreFrame = core(this);
2075 if (!coreFrame)
2076 return E_FAIL;
2077
2078 FrameView* view = coreFrame->view();
2079 if (!view)
2080 return E_FAIL;
2081
2082 result->bottom = view->contentsHeight();
2083 result->right = view->contentsWidth();
2084 return S_OK;
2085 }
2086
frameBounds(RECT * result)2087 HRESULT STDMETHODCALLTYPE WebFrame::frameBounds(
2088 /* [retval][out] */ RECT *result)
2089 {
2090 if (!result)
2091 return E_POINTER;
2092 ::SetRectEmpty(result);
2093
2094 Frame* coreFrame = core(this);
2095 if (!coreFrame)
2096 return E_FAIL;
2097
2098 FrameView* view = coreFrame->view();
2099 if (!view)
2100 return E_FAIL;
2101
2102 FloatRect bounds = view->visibleContentRect(true);
2103 result->bottom = (LONG) bounds.height();
2104 result->right = (LONG) bounds.width();
2105 return S_OK;
2106 }
2107
isDescendantOfFrame(IWebFrame * ancestor,BOOL * result)2108 HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame(
2109 /* [in] */ IWebFrame *ancestor,
2110 /* [retval][out] */ BOOL *result)
2111 {
2112 if (!result)
2113 return E_POINTER;
2114 *result = FALSE;
2115
2116 Frame* coreFrame = core(this);
2117 COMPtr<WebFrame> ancestorWebFrame(Query, ancestor);
2118 if (!ancestorWebFrame)
2119 return S_OK;
2120
2121 *result = (coreFrame && coreFrame->tree()->isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE;
2122 return S_OK;
2123 }
2124
unmarkAllMisspellings()2125 void WebFrame::unmarkAllMisspellings()
2126 {
2127 Frame* coreFrame = core(this);
2128 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2129 Document *doc = frame->document();
2130 if (!doc)
2131 return;
2132
2133 doc->removeMarkers(DocumentMarker::Spelling);
2134 }
2135 }
2136
unmarkAllBadGrammar()2137 void WebFrame::unmarkAllBadGrammar()
2138 {
2139 Frame* coreFrame = core(this);
2140 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2141 Document *doc = frame->document();
2142 if (!doc)
2143 return;
2144
2145 doc->removeMarkers(DocumentMarker::Grammar);
2146 }
2147 }
2148
webView() const2149 WebView* WebFrame::webView() const
2150 {
2151 return d->webView;
2152 }
2153
accessible() const2154 COMPtr<IAccessible> WebFrame::accessible() const
2155 {
2156 Frame* coreFrame = core(this);
2157 ASSERT(coreFrame);
2158
2159 Document* currentDocument = coreFrame->document();
2160 if (!currentDocument)
2161 m_accessible = 0;
2162 else if (!m_accessible || m_accessible->document() != currentDocument) {
2163 // Either we've never had a wrapper for this frame's top-level Document,
2164 // the Document renderer was destroyed and its wrapper was detached, or
2165 // the previous Document is in the page cache, and the current document
2166 // needs to be wrapped.
2167 m_accessible = new AccessibleDocument(currentDocument);
2168 }
2169 return m_accessible.get();
2170 }
2171
updateBackground()2172 void WebFrame::updateBackground()
2173 {
2174 Color backgroundColor = webView()->transparent() ? Color::transparent : Color::white;
2175 Frame* coreFrame = core(this);
2176
2177 if (!coreFrame || !coreFrame->view())
2178 return;
2179
2180 coreFrame->view()->updateBackgroundRecursively(backgroundColor, webView()->transparent());
2181 }
2182