1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "WebKitDLL.h"
29 #include "WebFrame.h"
30
31 #include "CFDictionaryPropertyBag.h"
32 #include "COMPropertyBag.h"
33 #include "DOMCoreClasses.h"
34 #include "DefaultPolicyDelegate.h"
35 #include "HTMLFrameOwnerElement.h"
36 #include "MarshallingHelpers.h"
37 #include "WebActionPropertyBag.h"
38 #include "WebChromeClient.h"
39 #include "WebDataSource.h"
40 #include "WebDocumentLoader.h"
41 #include "WebDownload.h"
42 #include "WebEditorClient.h"
43 #include "WebError.h"
44 #include "WebFrameNetworkingContext.h"
45 #include "WebFramePolicyListener.h"
46 #include "WebHistory.h"
47 #include "WebHistoryItem.h"
48 #include "WebKit.h"
49 #include "WebKitStatisticsPrivate.h"
50 #include "WebMutableURLRequest.h"
51 #include "WebNotificationCenter.h"
52 #include "WebScriptWorld.h"
53 #include "WebURLResponse.h"
54 #include "WebView.h"
55 #include <WebCore/BString.h>
56 #include <WebCore/COMPtr.h>
57 #include <WebCore/MemoryCache.h>
58 #include <WebCore/Document.h>
59 #include <WebCore/DocumentLoader.h>
60 #include <WebCore/DocumentMarkerController.h>
61 #include <WebCore/DOMImplementation.h>
62 #include <WebCore/DOMWindow.h>
63 #include <WebCore/Event.h>
64 #include <WebCore/EventHandler.h>
65 #include <WebCore/FormState.h>
66 #include <WebCore/FrameLoader.h>
67 #include <WebCore/FrameLoadRequest.h>
68 #include <WebCore/FrameTree.h>
69 #include <WebCore/FrameView.h>
70 #include <WebCore/FrameWin.h>
71 #include <WebCore/GDIObjectCounter.h>
72 #include <WebCore/GraphicsContext.h>
73 #include <WebCore/HistoryItem.h>
74 #include <WebCore/HTMLAppletElement.h>
75 #include <WebCore/HTMLFormElement.h>
76 #include <WebCore/HTMLFormControlElement.h>
77 #include <WebCore/HTMLInputElement.h>
78 #include <WebCore/HTMLNames.h>
79 #include <WebCore/HTMLPlugInElement.h>
80 #include <WebCore/JSDOMWindow.h>
81 #include <WebCore/KeyboardEvent.h>
82 #include <WebCore/MouseRelatedEvent.h>
83 #include <WebCore/NotImplemented.h>
84 #include <WebCore/Page.h>
85 #include <WebCore/PlatformKeyboardEvent.h>
86 #include <WebCore/PluginData.h>
87 #include <WebCore/PluginDatabase.h>
88 #include <WebCore/PluginView.h>
89 #include <WebCore/PrintContext.h>
90 #include <WebCore/ResourceHandle.h>
91 #include <WebCore/ResourceRequest.h>
92 #include <WebCore/RenderView.h>
93 #include <WebCore/RenderTreeAsText.h>
94 #include <WebCore/Settings.h>
95 #include <WebCore/SVGDocumentExtensions.h>
96 #include <WebCore/SVGSMILElement.h>
97 #include <WebCore/TextIterator.h>
98 #include <WebCore/JSDOMBinding.h>
99 #include <WebCore/ScriptController.h>
100 #include <WebCore/SecurityOrigin.h>
101 #include <JavaScriptCore/APICast.h>
102 #include <JavaScriptCore/JSLock.h>
103 #include <JavaScriptCore/JSObject.h>
104 #include <JavaScriptCore/JSValue.h>
105 #include <wtf/MathExtras.h>
106
107 #if USE(CG)
108 #include <CoreGraphics/CoreGraphics.h>
109 #elif USE(CAIRO)
110 #include "PlatformContextCairo.h"
111 #include <cairo-win32.h>
112 #endif
113
114 #if USE(CG)
115 // CG SPI used for printing
116 extern "C" {
117 CGAffineTransform CGContextGetBaseCTM(CGContextRef c);
118 void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m);
119 }
120 #endif
121
122 using namespace WebCore;
123 using namespace HTMLNames;
124 using namespace std;
125
126 using JSC::JSGlobalObject;
127 using JSC::JSLock;
128 using JSC::JSValue;
129 using JSC::SilenceAssertionsOnly;
130
131 #define FLASH_REDRAW 0
132
133
134 // By imaging to a width a little wider than the available pixels,
135 // thin pages will be scaled down a little, matching the way they
136 // print in IE and Camino. This lets them use fewer sheets than they
137 // would otherwise, which is presumably why other browsers do this.
138 // Wide pages will be scaled down more than this.
139 const float PrintingMinimumShrinkFactor = 1.25f;
140
141 // This number determines how small we are willing to reduce the page content
142 // in order to accommodate the widest line. If the page would have to be
143 // reduced smaller to make the widest line fit, we just clip instead (this
144 // behavior matches MacIE and Mozilla, at least)
145 const float PrintingMaximumShrinkFactor = 2.0f;
146
147 //-----------------------------------------------------------------------------
148 // Helpers to convert from WebCore to WebKit type
kit(Frame * frame)149 WebFrame* kit(Frame* frame)
150 {
151 if (!frame)
152 return 0;
153
154 FrameLoaderClient* frameLoaderClient = frame->loader()->client();
155 if (frameLoaderClient)
156 return static_cast<WebFrame*>(frameLoaderClient); // eek, is there a better way than static cast?
157 return 0;
158 }
159
core(WebFrame * webFrame)160 Frame* core(WebFrame* webFrame)
161 {
162 if (!webFrame)
163 return 0;
164 return webFrame->impl();
165 }
166
167 // 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)168 Frame* core(const WebFrame* webFrame)
169 {
170 if (!webFrame)
171 return 0;
172 return const_cast<WebFrame*>(webFrame)->impl();
173 }
174
175 //-----------------------------------------------------------------------------
176
elementFromDOMElement(IDOMElement * element)177 static Element *elementFromDOMElement(IDOMElement *element)
178 {
179 if (!element)
180 return 0;
181
182 COMPtr<IDOMElementPrivate> elePriv;
183 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
184 if (SUCCEEDED(hr)) {
185 Element* ele;
186 hr = elePriv->coreElement((void**)&ele);
187 if (SUCCEEDED(hr))
188 return ele;
189 }
190 return 0;
191 }
192
formElementFromDOMElement(IDOMElement * element)193 static HTMLFormElement *formElementFromDOMElement(IDOMElement *element)
194 {
195 if (!element)
196 return 0;
197
198 IDOMElementPrivate* elePriv;
199 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
200 if (SUCCEEDED(hr)) {
201 Element* ele;
202 hr = elePriv->coreElement((void**)&ele);
203 elePriv->Release();
204 if (SUCCEEDED(hr) && ele && ele->hasTagName(formTag))
205 return static_cast<HTMLFormElement*>(ele);
206 }
207 return 0;
208 }
209
inputElementFromDOMElement(IDOMElement * element)210 static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element)
211 {
212 if (!element)
213 return 0;
214
215 IDOMElementPrivate* elePriv;
216 HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv);
217 if (SUCCEEDED(hr)) {
218 Element* ele;
219 hr = elePriv->coreElement((void**)&ele);
220 elePriv->Release();
221 if (SUCCEEDED(hr) && ele && ele->hasTagName(inputTag))
222 return static_cast<HTMLInputElement*>(ele);
223 }
224 return 0;
225 }
226
227 // WebFramePrivate ------------------------------------------------------------
228
229 class WebFrame::WebFramePrivate {
230 public:
WebFramePrivate()231 WebFramePrivate()
232 : frame(0)
233 , webView(0)
234 , m_policyFunction(0)
235 {
236 }
237
~WebFramePrivate()238 ~WebFramePrivate() { }
frameView()239 FrameView* frameView() { return frame ? frame->view() : 0; }
240
241 Frame* frame;
242 WebView* webView;
243 FramePolicyFunction m_policyFunction;
244 COMPtr<WebFramePolicyListener> m_policyListener;
245 };
246
247 // WebFrame ----------------------------------------------------------------
248
WebFrame()249 WebFrame::WebFrame()
250 : WebFrameLoaderClient(this)
251 , m_refCount(0)
252 , d(new WebFrame::WebFramePrivate)
253 , m_quickRedirectComing(false)
254 , m_inPrintingMode(false)
255 , m_pageHeight(0)
256 {
257 WebFrameCount++;
258 gClassCount++;
259 gClassNameCount.add("WebFrame");
260 }
261
~WebFrame()262 WebFrame::~WebFrame()
263 {
264 delete d;
265 WebFrameCount--;
266 gClassCount--;
267 gClassNameCount.remove("WebFrame");
268 }
269
createInstance()270 WebFrame* WebFrame::createInstance()
271 {
272 WebFrame* instance = new WebFrame();
273 instance->AddRef();
274 return instance;
275 }
276
setAllowsScrolling(BOOL flag)277 HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling(
278 /* [in] */ BOOL flag)
279 {
280 if (Frame* frame = core(this))
281 if (FrameView* view = frame->view())
282 view->setCanHaveScrollbars(!!flag);
283
284 return S_OK;
285 }
286
allowsScrolling(BOOL * flag)287 HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling(
288 /* [retval][out] */ BOOL *flag)
289 {
290 if (flag)
291 if (Frame* frame = core(this))
292 if (FrameView* view = frame->view())
293 *flag = view->canHaveScrollbars();
294
295 return S_OK;
296 }
297
setIsDisconnected(BOOL flag)298 HRESULT STDMETHODCALLTYPE WebFrame::setIsDisconnected(
299 /* [in] */ BOOL flag)
300 {
301 if (Frame* frame = core(this)) {
302 frame->setIsDisconnected(flag);
303 return S_OK;
304 }
305
306 return E_FAIL;
307 }
308
setExcludeFromTextSearch(BOOL flag)309 HRESULT STDMETHODCALLTYPE WebFrame::setExcludeFromTextSearch(
310 /* [in] */ BOOL flag)
311 {
312 if (Frame* frame = core(this)) {
313 frame->setExcludeFromTextSearch(flag);
314 return S_OK;
315 }
316
317 return E_FAIL;
318 }
319
reloadFromOrigin()320 HRESULT WebFrame::reloadFromOrigin()
321 {
322 Frame* coreFrame = core(this);
323 if (!coreFrame)
324 return E_FAIL;
325
326 coreFrame->loader()->reload(true);
327 return S_OK;
328 }
329
paintDocumentRectToContext(RECT rect,OLE_HANDLE deviceContext)330 HRESULT STDMETHODCALLTYPE WebFrame::paintDocumentRectToContext(
331 /* [in] */ RECT rect,
332 /* [in] */ OLE_HANDLE deviceContext)
333 {
334 Frame* coreFrame = core(this);
335 if (!coreFrame)
336 return E_FAIL;
337
338 FrameView* view = coreFrame->view();
339 if (!view)
340 return E_FAIL;
341
342 // We can't paint with a layout still pending.
343 view->updateLayoutAndStyleIfNeededRecursive();
344
345 HDC dc = reinterpret_cast<HDC>(static_cast<ULONG64>(deviceContext));
346 GraphicsContext gc(dc);
347 gc.setShouldIncludeChildWindows(true);
348 gc.save();
349 LONG width = rect.right - rect.left;
350 LONG height = rect.bottom - rect.top;
351 FloatRect dirtyRect;
352 dirtyRect.setWidth(width);
353 dirtyRect.setHeight(height);
354 gc.clip(dirtyRect);
355 gc.translate(-rect.left, -rect.top);
356 view->paintContents(&gc, rect);
357 gc.restore();
358
359 return S_OK;
360 }
361
paintScrollViewRectToContextAtPoint(RECT rect,POINT pt,OLE_HANDLE deviceContext)362 HRESULT STDMETHODCALLTYPE WebFrame::paintScrollViewRectToContextAtPoint(
363 /* [in] */ RECT rect,
364 /* [in] */ POINT pt,
365 /* [in] */ OLE_HANDLE deviceContext)
366 {
367 Frame* coreFrame = core(this);
368 if (!coreFrame)
369 return E_FAIL;
370
371 FrameView* view = coreFrame->view();
372 if (!view)
373 return E_FAIL;
374
375 // We can't paint with a layout still pending.
376 view->updateLayoutAndStyleIfNeededRecursive();
377
378 HDC dc = reinterpret_cast<HDC>(static_cast<ULONG64>(deviceContext));
379 GraphicsContext gc(dc);
380 gc.setShouldIncludeChildWindows(true);
381 gc.save();
382 IntRect dirtyRect(rect);
383 dirtyRect.move(-pt.x, -pt.y);
384 view->paint(&gc, dirtyRect);
385 gc.restore();
386
387 return S_OK;
388 }
389
390 // IUnknown -------------------------------------------------------------------
391
QueryInterface(REFIID riid,void ** ppvObject)392 HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject)
393 {
394 *ppvObject = 0;
395 if (IsEqualGUID(riid, __uuidof(WebFrame)))
396 *ppvObject = this;
397 else if (IsEqualGUID(riid, IID_IUnknown))
398 *ppvObject = static_cast<IWebFrame*>(this);
399 else if (IsEqualGUID(riid, IID_IWebFrame))
400 *ppvObject = static_cast<IWebFrame*>(this);
401 else if (IsEqualGUID(riid, IID_IWebFramePrivate))
402 *ppvObject = static_cast<IWebFramePrivate*>(this);
403 else if (IsEqualGUID(riid, IID_IWebDocumentText))
404 *ppvObject = static_cast<IWebDocumentText*>(this);
405 else
406 return E_NOINTERFACE;
407
408 AddRef();
409 return S_OK;
410 }
411
AddRef(void)412 ULONG STDMETHODCALLTYPE WebFrame::AddRef(void)
413 {
414 return ++m_refCount;
415 }
416
Release(void)417 ULONG STDMETHODCALLTYPE WebFrame::Release(void)
418 {
419 ULONG newRef = --m_refCount;
420 if (!newRef)
421 delete(this);
422
423 return newRef;
424 }
425
426 // IWebFrame -------------------------------------------------------------------
427
name(BSTR * frameName)428 HRESULT STDMETHODCALLTYPE WebFrame::name(
429 /* [retval][out] */ BSTR* frameName)
430 {
431 if (!frameName) {
432 ASSERT_NOT_REACHED();
433 return E_POINTER;
434 }
435
436 *frameName = 0;
437
438 Frame* coreFrame = core(this);
439 if (!coreFrame)
440 return E_FAIL;
441
442 *frameName = BString(coreFrame->tree()->uniqueName()).release();
443 return S_OK;
444 }
445
webView(IWebView ** view)446 HRESULT STDMETHODCALLTYPE WebFrame::webView(
447 /* [retval][out] */ IWebView** view)
448 {
449 *view = 0;
450 if (!d->webView)
451 return E_FAIL;
452 *view = d->webView;
453 (*view)->AddRef();
454 return S_OK;
455 }
456
frameView(IWebFrameView **)457 HRESULT STDMETHODCALLTYPE WebFrame::frameView(
458 /* [retval][out] */ IWebFrameView** /*view*/)
459 {
460 ASSERT_NOT_REACHED();
461 return E_NOTIMPL;
462 }
463
DOMDocument(IDOMDocument ** result)464 HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument(
465 /* [retval][out] */ IDOMDocument** result)
466 {
467 if (!result) {
468 ASSERT_NOT_REACHED();
469 return E_POINTER;
470 }
471
472 *result = 0;
473
474 if (Frame* coreFrame = core(this))
475 if (Document* document = coreFrame->document())
476 *result = DOMDocument::createInstance(document);
477
478 return *result ? S_OK : E_FAIL;
479 }
480
frameElement(IDOMHTMLElement ** frameElement)481 HRESULT STDMETHODCALLTYPE WebFrame::frameElement(
482 /* [retval][out] */ IDOMHTMLElement** frameElement)
483 {
484 if (!frameElement)
485 return E_POINTER;
486
487 *frameElement = 0;
488 Frame* coreFrame = core(this);
489 if (!coreFrame)
490 return E_FAIL;
491
492 COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(coreFrame->ownerElement()));
493 COMPtr<IDOMHTMLElement> htmlElement(Query, domElement);
494 if (!htmlElement)
495 return E_FAIL;
496 return htmlElement.copyRefTo(frameElement);
497 }
498
currentForm(IDOMElement ** currentForm)499 HRESULT STDMETHODCALLTYPE WebFrame::currentForm(
500 /* [retval][out] */ IDOMElement **currentForm)
501 {
502 if (!currentForm) {
503 ASSERT_NOT_REACHED();
504 return E_POINTER;
505 }
506
507 *currentForm = 0;
508
509 if (Frame* coreFrame = core(this)) {
510 if (HTMLFormElement* formElement = coreFrame->selection()->currentForm())
511 *currentForm = DOMElement::createInstance(formElement);
512 }
513
514 return *currentForm ? S_OK : E_FAIL;
515 }
516
globalContext()517 JSGlobalContextRef STDMETHODCALLTYPE WebFrame::globalContext()
518 {
519 Frame* coreFrame = core(this);
520 if (!coreFrame)
521 return 0;
522
523 return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
524 }
525
globalContextForScriptWorld(IWebScriptWorld * iWorld)526 JSGlobalContextRef WebFrame::globalContextForScriptWorld(IWebScriptWorld* iWorld)
527 {
528 Frame* coreFrame = core(this);
529 if (!coreFrame)
530 return 0;
531
532 COMPtr<WebScriptWorld> world(Query, iWorld);
533 if (!world)
534 return 0;
535
536 return toGlobalRef(coreFrame->script()->globalObject(world->world())->globalExec());
537 }
538
loadRequest(IWebURLRequest * request)539 HRESULT STDMETHODCALLTYPE WebFrame::loadRequest(
540 /* [in] */ IWebURLRequest* request)
541 {
542 COMPtr<WebMutableURLRequest> requestImpl;
543
544 HRESULT hr = request->QueryInterface(&requestImpl);
545 if (FAILED(hr))
546 return hr;
547
548 Frame* coreFrame = core(this);
549 if (!coreFrame)
550 return E_FAIL;
551
552 coreFrame->loader()->load(requestImpl->resourceRequest(), false);
553 return S_OK;
554 }
555
loadData(PassRefPtr<WebCore::SharedBuffer> data,BSTR mimeType,BSTR textEncodingName,BSTR baseURL,BSTR failingURL)556 void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL)
557 {
558 String mimeTypeString(mimeType, SysStringLen(mimeType));
559 if (!mimeType)
560 mimeTypeString = "text/html";
561
562 String encodingString(textEncodingName, SysStringLen(textEncodingName));
563
564 // FIXME: We should really be using MarshallingHelpers::BSTRToKURL here,
565 // but that would turn a null BSTR into a null KURL, and we crash inside of
566 // WebCore if we use a null KURL in constructing the ResourceRequest.
567 KURL baseKURL = KURL(KURL(), String(baseURL ? baseURL : L"", SysStringLen(baseURL)));
568
569 KURL failingKURL = MarshallingHelpers::BSTRToKURL(failingURL);
570
571 ResourceRequest request(baseKURL);
572 SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL);
573
574 // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null.
575 if (Frame* coreFrame = core(this))
576 coreFrame->loader()->load(request, substituteData, false);
577 }
578
579
loadData(IStream * data,BSTR mimeType,BSTR textEncodingName,BSTR url)580 HRESULT STDMETHODCALLTYPE WebFrame::loadData(
581 /* [in] */ IStream* data,
582 /* [in] */ BSTR mimeType,
583 /* [in] */ BSTR textEncodingName,
584 /* [in] */ BSTR url)
585 {
586 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create();
587
588 STATSTG stat;
589 if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) {
590 if (!stat.cbSize.HighPart && stat.cbSize.LowPart) {
591 Vector<char> dataBuffer(stat.cbSize.LowPart);
592 ULONG read;
593 // FIXME: this does a needless copy, would be better to read right into the SharedBuffer
594 // or adopt the Vector or something.
595 if (SUCCEEDED(data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read)))
596 sharedBuffer->append(dataBuffer.data(), static_cast<int>(dataBuffer.size()));
597 }
598 }
599
600 loadData(sharedBuffer, mimeType, textEncodingName, url, 0);
601 return S_OK;
602 }
603
loadPlainTextString(BSTR string,BSTR url)604 HRESULT WebFrame::loadPlainTextString(
605 /* [in] */ BSTR string,
606 /* [in] */ BSTR url)
607 {
608 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
609 BString plainTextMimeType(TEXT("text/plain"), 10);
610 BString utf16Encoding(TEXT("utf-16"), 6);
611 loadData(sharedBuffer.release(), plainTextMimeType, utf16Encoding, url, 0);
612 return S_OK;
613 }
614
loadHTMLString(BSTR string,BSTR baseURL,BSTR unreachableURL)615 void WebFrame::loadHTMLString(BSTR string, BSTR baseURL, BSTR unreachableURL)
616 {
617 RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<char*>(string), sizeof(UChar) * SysStringLen(string));
618 BString utf16Encoding(TEXT("utf-16"), 6);
619 loadData(sharedBuffer.release(), 0, utf16Encoding, baseURL, unreachableURL);
620 }
621
loadHTMLString(BSTR string,BSTR baseURL)622 HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString(
623 /* [in] */ BSTR string,
624 /* [in] */ BSTR baseURL)
625 {
626 loadHTMLString(string, baseURL, 0);
627 return S_OK;
628 }
629
loadAlternateHTMLString(BSTR str,BSTR baseURL,BSTR unreachableURL)630 HRESULT STDMETHODCALLTYPE WebFrame::loadAlternateHTMLString(
631 /* [in] */ BSTR str,
632 /* [in] */ BSTR baseURL,
633 /* [in] */ BSTR unreachableURL)
634 {
635 loadHTMLString(str, baseURL, unreachableURL);
636 return S_OK;
637 }
638
loadArchive(IWebArchive *)639 HRESULT STDMETHODCALLTYPE WebFrame::loadArchive(
640 /* [in] */ IWebArchive* /*archive*/)
641 {
642 ASSERT_NOT_REACHED();
643 return E_NOTIMPL;
644 }
645
getWebDataSource(DocumentLoader * loader)646 static inline WebDataSource *getWebDataSource(DocumentLoader* loader)
647 {
648 return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
649 }
650
dataSource(IWebDataSource ** source)651 HRESULT STDMETHODCALLTYPE WebFrame::dataSource(
652 /* [retval][out] */ IWebDataSource** source)
653 {
654 if (!source) {
655 ASSERT_NOT_REACHED();
656 return E_POINTER;
657 }
658
659 *source = 0;
660
661 Frame* coreFrame = core(this);
662 if (!coreFrame)
663 return E_FAIL;
664
665 WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->documentLoader());
666
667 *source = webDataSource;
668
669 if (webDataSource)
670 webDataSource->AddRef();
671
672 return *source ? S_OK : E_FAIL;
673 }
674
provisionalDataSource(IWebDataSource ** source)675 HRESULT STDMETHODCALLTYPE WebFrame::provisionalDataSource(
676 /* [retval][out] */ IWebDataSource** source)
677 {
678 if (!source) {
679 ASSERT_NOT_REACHED();
680 return E_POINTER;
681 }
682
683 *source = 0;
684
685 Frame* coreFrame = core(this);
686 if (!coreFrame)
687 return E_FAIL;
688
689 WebDataSource* webDataSource = getWebDataSource(coreFrame->loader()->provisionalDocumentLoader());
690
691 *source = webDataSource;
692
693 if (webDataSource)
694 webDataSource->AddRef();
695
696 return *source ? S_OK : E_FAIL;
697 }
698
url() const699 KURL WebFrame::url() const
700 {
701 Frame* coreFrame = core(this);
702 if (!coreFrame)
703 return KURL();
704
705 return coreFrame->document()->url();
706 }
707
stopLoading(void)708 HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void)
709 {
710 if (Frame* coreFrame = core(this))
711 coreFrame->loader()->stopAllLoaders();
712 return S_OK;
713 }
714
reload(void)715 HRESULT STDMETHODCALLTYPE WebFrame::reload( void)
716 {
717 Frame* coreFrame = core(this);
718 if (!coreFrame)
719 return E_FAIL;
720
721 coreFrame->loader()->reload();
722 return S_OK;
723 }
724
findFrameNamed(BSTR name,IWebFrame ** frame)725 HRESULT STDMETHODCALLTYPE WebFrame::findFrameNamed(
726 /* [in] */ BSTR name,
727 /* [retval][out] */ IWebFrame** frame)
728 {
729 if (!frame) {
730 ASSERT_NOT_REACHED();
731 return E_POINTER;
732 }
733
734 *frame = 0;
735
736 Frame* coreFrame = core(this);
737 if (!coreFrame)
738 return E_FAIL;
739
740 Frame* foundFrame = coreFrame->tree()->find(AtomicString(name, SysStringLen(name)));
741 if (!foundFrame)
742 return S_OK;
743
744 WebFrame* foundWebFrame = kit(foundFrame);
745 if (!foundWebFrame)
746 return E_FAIL;
747
748 return foundWebFrame->QueryInterface(IID_IWebFrame, (void**)frame);
749 }
750
parentFrame(IWebFrame ** frame)751 HRESULT STDMETHODCALLTYPE WebFrame::parentFrame(
752 /* [retval][out] */ IWebFrame** frame)
753 {
754 HRESULT hr = S_OK;
755 *frame = 0;
756 if (Frame* coreFrame = core(this))
757 if (WebFrame* webFrame = kit(coreFrame->tree()->parent()))
758 hr = webFrame->QueryInterface(IID_IWebFrame, (void**) frame);
759
760 return hr;
761 }
762
763 class EnumChildFrames : public IEnumVARIANT
764 {
765 public:
EnumChildFrames(Frame * f)766 EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree()->firstChild() : 0) { }
767
QueryInterface(REFIID riid,void ** ppvObject)768 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
769 {
770 *ppvObject = 0;
771 if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
772 *ppvObject = this;
773 else
774 return E_NOINTERFACE;
775
776 AddRef();
777 return S_OK;
778 }
779
AddRef(void)780 virtual ULONG STDMETHODCALLTYPE AddRef(void)
781 {
782 return ++m_refCount;
783 }
784
Release(void)785 virtual ULONG STDMETHODCALLTYPE Release(void)
786 {
787 ULONG newRef = --m_refCount;
788 if (!newRef)
789 delete(this);
790 return newRef;
791 }
792
Next(ULONG celt,VARIANT * rgVar,ULONG * pCeltFetched)793 virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
794 {
795 if (pCeltFetched)
796 *pCeltFetched = 0;
797 if (!rgVar)
798 return E_POINTER;
799 VariantInit(rgVar);
800 if (!celt || celt > 1)
801 return S_FALSE;
802 if (!m_frame || !m_curChild)
803 return S_FALSE;
804
805 WebFrame* webFrame = kit(m_curChild);
806 IUnknown* unknown;
807 HRESULT hr = webFrame->QueryInterface(IID_IUnknown, (void**)&unknown);
808 if (FAILED(hr))
809 return hr;
810
811 V_VT(rgVar) = VT_UNKNOWN;
812 V_UNKNOWN(rgVar) = unknown;
813
814 m_curChild = m_curChild->tree()->nextSibling();
815 if (pCeltFetched)
816 *pCeltFetched = 1;
817 return S_OK;
818 }
819
Skip(ULONG celt)820 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
821 {
822 if (!m_frame)
823 return S_FALSE;
824 for (unsigned i = 0; i < celt && m_curChild; i++)
825 m_curChild = m_curChild->tree()->nextSibling();
826 return m_curChild ? S_OK : S_FALSE;
827 }
828
Reset(void)829 virtual HRESULT STDMETHODCALLTYPE Reset(void)
830 {
831 if (!m_frame)
832 return S_FALSE;
833 m_curChild = m_frame->tree()->firstChild();
834 return S_OK;
835 }
836
Clone(IEnumVARIANT **)837 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**)
838 {
839 return E_NOTIMPL;
840 }
841
842 private:
843 ULONG m_refCount;
844 Frame* m_frame;
845 Frame* m_curChild;
846 };
847
childFrames(IEnumVARIANT ** enumFrames)848 HRESULT STDMETHODCALLTYPE WebFrame::childFrames(
849 /* [retval][out] */ IEnumVARIANT **enumFrames)
850 {
851 if (!enumFrames)
852 return E_POINTER;
853
854 *enumFrames = new EnumChildFrames(core(this));
855 return S_OK;
856 }
857
858 // IWebFramePrivate ------------------------------------------------------
859
renderTreeAsExternalRepresentation(BOOL forPrinting,BSTR * result)860 HRESULT WebFrame::renderTreeAsExternalRepresentation(BOOL forPrinting, BSTR *result)
861 {
862 if (!result)
863 return E_POINTER;
864
865 Frame* coreFrame = core(this);
866 if (!coreFrame)
867 return E_FAIL;
868
869 *result = BString(externalRepresentation(coreFrame, forPrinting ? RenderAsTextPrintingMode : RenderAsTextBehaviorNormal)).release();
870 return S_OK;
871 }
872
counterValueForElementById(BSTR id,BSTR * result)873 HRESULT STDMETHODCALLTYPE WebFrame::counterValueForElementById(
874 /* [in] */ BSTR id, /* [retval][out] */ BSTR *result)
875 {
876 if (!result)
877 return E_POINTER;
878
879 Frame* coreFrame = core(this);
880 if (!coreFrame)
881 return E_FAIL;
882
883 String coreId = String(id, SysStringLen(id));
884
885 Element* element = coreFrame->document()->getElementById(coreId);
886 if (!element)
887 return E_FAIL;
888 *result = BString(counterValueForElement(element)).release();
889 return S_OK;
890 }
891
pageNumberForElementById(BSTR id,float pageWidthInPixels,float pageHeightInPixels,int * result)892 HRESULT STDMETHODCALLTYPE WebFrame::pageNumberForElementById(
893 /* [in] */ BSTR id,
894 /* [in] */ float pageWidthInPixels,
895 /* [in] */ float pageHeightInPixels,
896 /* [retval][out] */ int* result)
897 {
898 if (!result)
899 return E_POINTER;
900
901 Frame* coreFrame = core(this);
902 if (!coreFrame)
903 return E_FAIL;
904
905 String coreId = String(id, SysStringLen(id));
906
907 Element* element = coreFrame->document()->getElementById(coreId);
908 if (!element)
909 return E_FAIL;
910 *result = PrintContext::pageNumberForElement(element, FloatSize(pageWidthInPixels, pageHeightInPixels));
911 return S_OK;
912 }
913
numberOfPages(float pageWidthInPixels,float pageHeightInPixels,int * result)914 HRESULT STDMETHODCALLTYPE WebFrame::numberOfPages(
915 /* [in] */ float pageWidthInPixels,
916 /* [in] */ float pageHeightInPixels,
917 /* [retval][out] */ int* result)
918 {
919 if (!result)
920 return E_POINTER;
921
922 Frame* coreFrame = core(this);
923 if (!coreFrame)
924 return E_FAIL;
925
926 *result = PrintContext::numberOfPages(coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels));
927 return S_OK;
928 }
929
scrollOffset(SIZE * offset)930 HRESULT STDMETHODCALLTYPE WebFrame::scrollOffset(
931 /* [retval][out] */ SIZE* offset)
932 {
933 if (!offset) {
934 ASSERT_NOT_REACHED();
935 return E_POINTER;
936 }
937
938 Frame* coreFrame = core(this);
939 if (!coreFrame)
940 return E_FAIL;
941
942 FrameView* view = coreFrame->view();
943 if (!view)
944 return E_FAIL;
945
946 *offset = view->scrollOffset();
947 return S_OK;
948 }
949
layout()950 HRESULT STDMETHODCALLTYPE WebFrame::layout()
951 {
952 Frame* coreFrame = core(this);
953 if (!coreFrame)
954 return E_FAIL;
955
956 FrameView* view = coreFrame->view();
957 if (!view)
958 return E_FAIL;
959
960 view->layout();
961 return S_OK;
962 }
963
firstLayoutDone(BOOL * result)964 HRESULT STDMETHODCALLTYPE WebFrame::firstLayoutDone(
965 /* [retval][out] */ BOOL* result)
966 {
967 if (!result) {
968 ASSERT_NOT_REACHED();
969 return E_POINTER;
970 }
971
972 *result = 0;
973
974 Frame* coreFrame = core(this);
975 if (!coreFrame)
976 return E_FAIL;
977
978 *result = coreFrame->loader()->stateMachine()->firstLayoutDone();
979 return S_OK;
980 }
981
loadType(WebFrameLoadType * type)982 HRESULT STDMETHODCALLTYPE WebFrame::loadType(
983 /* [retval][out] */ WebFrameLoadType* type)
984 {
985 if (!type) {
986 ASSERT_NOT_REACHED();
987 return E_POINTER;
988 }
989
990 *type = (WebFrameLoadType)0;
991
992 Frame* coreFrame = core(this);
993 if (!coreFrame)
994 return E_FAIL;
995
996 *type = (WebFrameLoadType)coreFrame->loader()->loadType();
997 return S_OK;
998 }
999
pendingFrameUnloadEventCount(UINT * result)1000 HRESULT STDMETHODCALLTYPE WebFrame::pendingFrameUnloadEventCount(
1001 /* [retval][out] */ UINT* result)
1002 {
1003 if (!result) {
1004 ASSERT_NOT_REACHED();
1005 return E_POINTER;
1006 }
1007
1008 *result = 0;
1009
1010 Frame* coreFrame = core(this);
1011 if (!coreFrame)
1012 return E_FAIL;
1013
1014 *result = coreFrame->domWindow()->pendingUnloadEventListeners();
1015 return S_OK;
1016 }
1017
unused2()1018 HRESULT STDMETHODCALLTYPE WebFrame::unused2()
1019 {
1020 return E_NOTIMPL;
1021 }
1022
hasSpellingMarker(UINT from,UINT length,BOOL * result)1023 HRESULT STDMETHODCALLTYPE WebFrame::hasSpellingMarker(
1024 /* [in] */ UINT from,
1025 /* [in] */ UINT length,
1026 /* [retval][out] */ BOOL* result)
1027 {
1028 Frame* coreFrame = core(this);
1029 if (!coreFrame)
1030 return E_FAIL;
1031 *result = coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1032 return S_OK;
1033 }
1034
clearOpener()1035 HRESULT STDMETHODCALLTYPE WebFrame::clearOpener()
1036 {
1037 HRESULT hr = S_OK;
1038 if (Frame* coreFrame = core(this))
1039 coreFrame->loader()->setOpener(0);
1040
1041 return hr;
1042 }
1043
1044 // IWebDocumentText -----------------------------------------------------------
1045
supportsTextEncoding(BOOL * result)1046 HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding(
1047 /* [retval][out] */ BOOL* result)
1048 {
1049 *result = FALSE;
1050 return E_NOTIMPL;
1051 }
1052
selectedString(BSTR * result)1053 HRESULT STDMETHODCALLTYPE WebFrame::selectedString(
1054 /* [retval][out] */ BSTR* result)
1055 {
1056 *result = 0;
1057
1058 Frame* coreFrame = core(this);
1059 if (!coreFrame)
1060 return E_FAIL;
1061
1062 String text = coreFrame->displayStringModifiedByEncoding(coreFrame->editor()->selectedText());
1063
1064 *result = BString(text).release();
1065 return S_OK;
1066 }
1067
selectAll()1068 HRESULT STDMETHODCALLTYPE WebFrame::selectAll()
1069 {
1070 Frame* coreFrame = core(this);
1071 if (!coreFrame)
1072 return E_FAIL;
1073
1074 if (!coreFrame->editor()->command("SelectAll").execute())
1075 return E_FAIL;
1076
1077 return S_OK;
1078 }
1079
deselectAll()1080 HRESULT STDMETHODCALLTYPE WebFrame::deselectAll()
1081 {
1082 return E_NOTIMPL;
1083 }
1084
1085 // WebFrame ---------------------------------------------------------------
1086
init(IWebView * webView,Page * page,HTMLFrameOwnerElement * ownerElement)1087 PassRefPtr<Frame> WebFrame::init(IWebView* webView, Page* page, HTMLFrameOwnerElement* ownerElement)
1088 {
1089 webView->QueryInterface(&d->webView);
1090 d->webView->Release(); // don't hold the extra ref
1091
1092 HWND viewWindow;
1093 d->webView->viewWindow((OLE_HANDLE*)&viewWindow);
1094
1095 this->AddRef(); // We release this ref in frameLoaderDestroyed()
1096 RefPtr<Frame> frame = Frame::create(page, ownerElement, this);
1097 d->frame = frame.get();
1098 return frame.release();
1099 }
1100
impl()1101 Frame* WebFrame::impl()
1102 {
1103 return d->frame;
1104 }
1105
invalidate()1106 void WebFrame::invalidate()
1107 {
1108 Frame* coreFrame = core(this);
1109 ASSERT(coreFrame);
1110
1111 if (Document* document = coreFrame->document())
1112 document->recalcStyle(Node::Force);
1113 }
1114
inViewSourceMode(BOOL * flag)1115 HRESULT WebFrame::inViewSourceMode(BOOL* flag)
1116 {
1117 if (!flag) {
1118 ASSERT_NOT_REACHED();
1119 return E_POINTER;
1120 }
1121
1122 *flag = FALSE;
1123
1124 Frame* coreFrame = core(this);
1125 if (!coreFrame)
1126 return E_FAIL;
1127
1128 *flag = coreFrame->inViewSourceMode() ? TRUE : FALSE;
1129 return S_OK;
1130 }
1131
setInViewSourceMode(BOOL flag)1132 HRESULT WebFrame::setInViewSourceMode(BOOL flag)
1133 {
1134 Frame* coreFrame = core(this);
1135 if (!coreFrame)
1136 return E_FAIL;
1137
1138 coreFrame->setInViewSourceMode(!!flag);
1139 return S_OK;
1140 }
1141
elementWithName(BSTR name,IDOMElement * form,IDOMElement ** element)1142 HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** element)
1143 {
1144 if (!form)
1145 return E_INVALIDARG;
1146
1147 HTMLFormElement* formElement = formElementFromDOMElement(form);
1148 if (formElement) {
1149 const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
1150 AtomicString targetName((UChar*)name, SysStringLen(name));
1151 for (unsigned int i = 0; i < elements.size(); i++) {
1152 if (!elements[i]->isFormControlElement())
1153 continue;
1154 HTMLFormControlElement* elt = static_cast<HTMLFormControlElement*>(elements[i]);
1155 // Skip option elements, other duds
1156 if (elt->name() == targetName) {
1157 *element = DOMElement::createInstance(elt);
1158 return S_OK;
1159 }
1160 }
1161 }
1162 return E_FAIL;
1163 }
1164
formForElement(IDOMElement * element,IDOMElement ** form)1165 HRESULT WebFrame::formForElement(IDOMElement* element, IDOMElement** form)
1166 {
1167 if (!element)
1168 return E_INVALIDARG;
1169
1170 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1171 if (!inputElement)
1172 return E_FAIL;
1173
1174 HTMLFormElement *formElement = inputElement->form();
1175 if (!formElement)
1176 return E_FAIL;
1177
1178 *form = DOMElement::createInstance(formElement);
1179 return S_OK;
1180 }
1181
elementDoesAutoComplete(IDOMElement * element,BOOL * result)1182 HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, BOOL *result)
1183 {
1184 *result = false;
1185 if (!element)
1186 return E_INVALIDARG;
1187
1188 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1189 if (!inputElement)
1190 *result = false;
1191 else
1192 *result = inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->autoComplete();
1193
1194 return S_OK;
1195 }
1196
pauseAnimation(BSTR animationName,IDOMNode * node,double secondsFromNow,BOOL * animationWasRunning)1197 HRESULT WebFrame::pauseAnimation(BSTR animationName, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
1198 {
1199 if (!node || !animationWasRunning)
1200 return E_POINTER;
1201
1202 *animationWasRunning = FALSE;
1203
1204 Frame* frame = core(this);
1205 if (!frame)
1206 return E_FAIL;
1207
1208 AnimationController* controller = frame->animation();
1209 if (!controller)
1210 return E_FAIL;
1211
1212 COMPtr<DOMNode> domNode(Query, node);
1213 if (!domNode)
1214 return E_FAIL;
1215
1216 *animationWasRunning = controller->pauseAnimationAtTime(domNode->node()->renderer(), String(animationName, SysStringLen(animationName)), secondsFromNow);
1217 return S_OK;
1218 }
1219
pauseTransition(BSTR propertyName,IDOMNode * node,double secondsFromNow,BOOL * transitionWasRunning)1220 HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double secondsFromNow, BOOL* transitionWasRunning)
1221 {
1222 if (!node || !transitionWasRunning)
1223 return E_POINTER;
1224
1225 *transitionWasRunning = FALSE;
1226
1227 Frame* frame = core(this);
1228 if (!frame)
1229 return E_FAIL;
1230
1231 AnimationController* controller = frame->animation();
1232 if (!controller)
1233 return E_FAIL;
1234
1235 COMPtr<DOMNode> domNode(Query, node);
1236 if (!domNode)
1237 return E_FAIL;
1238
1239 *transitionWasRunning = controller->pauseTransitionAtTime(domNode->node()->renderer(), String(propertyName, SysStringLen(propertyName)), secondsFromNow);
1240 return S_OK;
1241 }
1242
pauseSVGAnimation(BSTR elementId,IDOMNode * node,double secondsFromNow,BOOL * animationWasRunning)1243 HRESULT WebFrame::pauseSVGAnimation(BSTR elementId, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning)
1244 {
1245 if (!node || !animationWasRunning)
1246 return E_POINTER;
1247
1248 *animationWasRunning = FALSE;
1249
1250 Frame* frame = core(this);
1251 if (!frame)
1252 return E_FAIL;
1253
1254 Document* document = frame->document();
1255 if (!document || !document->svgExtensions())
1256 return E_FAIL;
1257
1258 COMPtr<DOMNode> domNode(Query, node);
1259 if (!domNode || !SVGSMILElement::isSMILElement(domNode->node()))
1260 return E_FAIL;
1261
1262 #if ENABLE(SVG)
1263 *animationWasRunning = document->accessSVGExtensions()->sampleAnimationAtTime(String(elementId, SysStringLen(elementId)), static_cast<SVGSMILElement*>(domNode->node()), secondsFromNow);
1264 #else
1265 *animationWasRunning = FALSE;
1266 #endif
1267
1268 return S_OK;
1269 }
1270
visibleContentRect(RECT * rect)1271 HRESULT WebFrame::visibleContentRect(RECT* rect)
1272 {
1273 if (!rect)
1274 return E_POINTER;
1275 SetRectEmpty(rect);
1276
1277 Frame* frame = core(this);
1278 if (!frame)
1279 return E_FAIL;
1280
1281 FrameView* view = frame->view();
1282 if (!view)
1283 return E_FAIL;
1284
1285 *rect = view->visibleContentRect(false);
1286 return S_OK;
1287 }
1288
numberOfActiveAnimations(UINT * number)1289 HRESULT WebFrame::numberOfActiveAnimations(UINT* number)
1290 {
1291 if (!number)
1292 return E_POINTER;
1293
1294 *number = 0;
1295
1296 Frame* frame = core(this);
1297 if (!frame)
1298 return E_FAIL;
1299
1300 AnimationController* controller = frame->animation();
1301 if (!controller)
1302 return E_FAIL;
1303
1304 *number = controller->numberOfActiveAnimations();
1305 return S_OK;
1306 }
1307
suspendAnimations()1308 HRESULT WebFrame::suspendAnimations()
1309 {
1310 Frame* frame = core(this);
1311 if (!frame)
1312 return E_FAIL;
1313
1314 frame->animation()->suspendAnimations();
1315 return S_OK;
1316 }
1317
resumeAnimations()1318 HRESULT WebFrame::resumeAnimations()
1319 {
1320 Frame* frame = core(this);
1321 if (!frame)
1322 return E_FAIL;
1323
1324 frame->animation()->resumeAnimations();
1325 return S_OK;
1326 }
1327
isDisplayingStandaloneImage(BOOL * result)1328 HRESULT WebFrame::isDisplayingStandaloneImage(BOOL* result)
1329 {
1330 if (!result)
1331 return E_POINTER;
1332
1333 *result = FALSE;
1334
1335 Frame* frame = core(this);
1336 if (!frame)
1337 return E_FAIL;
1338
1339 Document* document = frame->document();
1340 *result = document && document->isImageDocument();
1341 return S_OK;
1342 }
1343
allowsFollowingLink(BSTR url,BOOL * result)1344 HRESULT WebFrame::allowsFollowingLink(BSTR url, BOOL* result)
1345 {
1346 if (!result)
1347 return E_POINTER;
1348
1349 *result = TRUE;
1350
1351 Frame* frame = core(this);
1352 if (!frame)
1353 return E_FAIL;
1354
1355 *result = frame->document()->securityOrigin()->canDisplay(MarshallingHelpers::BSTRToKURL(url));
1356 return S_OK;
1357 }
1358
controlsInForm(IDOMElement * form,IDOMElement ** controls,int * cControls)1359 HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls)
1360 {
1361 if (!form)
1362 return E_INVALIDARG;
1363
1364 HTMLFormElement* formElement = formElementFromDOMElement(form);
1365 if (!formElement)
1366 return E_FAIL;
1367
1368 int inCount = *cControls;
1369 int count = (int) formElement->associatedElements().size();
1370 *cControls = count;
1371 if (!controls)
1372 return S_OK;
1373 if (inCount < count)
1374 return E_FAIL;
1375
1376 *cControls = 0;
1377 const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
1378 for (int i = 0; i < count; i++) {
1379 if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1380 controls[*cControls] = DOMElement::createInstance(toHTMLElement(elements.at(i)));
1381 (*cControls)++;
1382 }
1383 }
1384 return S_OK;
1385 }
1386
elementIsPassword(IDOMElement * element,bool * result)1387 HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result)
1388 {
1389 HTMLInputElement* inputElement = inputElementFromDOMElement(element);
1390 *result = inputElement && inputElement->isPasswordField();
1391 return S_OK;
1392 }
1393
searchForLabelsBeforeElement(const BSTR * labels,unsigned cLabels,IDOMElement * beforeElement,unsigned * outResultDistance,BOOL * outResultIsInCellAbove,BSTR * result)1394 HRESULT WebFrame::searchForLabelsBeforeElement(const BSTR* labels, unsigned cLabels, IDOMElement* beforeElement, unsigned* outResultDistance, BOOL* outResultIsInCellAbove, BSTR* result)
1395 {
1396 if (!result) {
1397 ASSERT_NOT_REACHED();
1398 return E_POINTER;
1399 }
1400
1401 if (outResultDistance)
1402 *outResultDistance = 0;
1403 if (outResultIsInCellAbove)
1404 *outResultIsInCellAbove = FALSE;
1405 *result = 0;
1406
1407 if (!cLabels)
1408 return S_OK;
1409 if (cLabels < 1)
1410 return E_INVALIDARG;
1411
1412 Frame* coreFrame = core(this);
1413 if (!coreFrame)
1414 return E_FAIL;
1415
1416 Vector<String> labelStrings(cLabels);
1417 for (int i=0; i<cLabels; i++)
1418 labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1419 Element *coreElement = elementFromDOMElement(beforeElement);
1420 if (!coreElement)
1421 return E_FAIL;
1422
1423 size_t resultDistance;
1424 bool resultIsInCellAbove;
1425 String label = coreFrame->searchForLabelsBeforeElement(labelStrings, coreElement, &resultDistance, &resultIsInCellAbove);
1426
1427 *result = SysAllocStringLen(label.characters(), label.length());
1428 if (label.length() && !*result)
1429 return E_OUTOFMEMORY;
1430 if (outResultDistance)
1431 *outResultDistance = resultDistance;
1432 if (outResultIsInCellAbove)
1433 *outResultIsInCellAbove = resultIsInCellAbove;
1434
1435 return S_OK;
1436 }
1437
matchLabelsAgainstElement(const BSTR * labels,int cLabels,IDOMElement * againstElement,BSTR * result)1438 HRESULT WebFrame::matchLabelsAgainstElement(const BSTR* labels, int cLabels, IDOMElement* againstElement, BSTR* result)
1439 {
1440 if (!result) {
1441 ASSERT_NOT_REACHED();
1442 return E_POINTER;
1443 }
1444
1445 *result = 0;
1446
1447 if (!cLabels)
1448 return S_OK;
1449 if (cLabels < 1)
1450 return E_INVALIDARG;
1451
1452 Frame* coreFrame = core(this);
1453 if (!coreFrame)
1454 return E_FAIL;
1455
1456 Vector<String> labelStrings(cLabels);
1457 for (int i=0; i<cLabels; i++)
1458 labelStrings[i] = String(labels[i], SysStringLen(labels[i]));
1459 Element *coreElement = elementFromDOMElement(againstElement);
1460 if (!coreElement)
1461 return E_FAIL;
1462
1463 String label = coreFrame->matchLabelsAgainstElement(labelStrings, coreElement);
1464
1465 *result = SysAllocStringLen(label.characters(), label.length());
1466 if (label.length() && !*result)
1467 return E_OUTOFMEMORY;
1468 return S_OK;
1469 }
1470
canProvideDocumentSource(bool * result)1471 HRESULT WebFrame::canProvideDocumentSource(bool* result)
1472 {
1473 HRESULT hr = S_OK;
1474 *result = false;
1475
1476 COMPtr<IWebDataSource> dataSource;
1477 hr = WebFrame::dataSource(&dataSource);
1478 if (FAILED(hr))
1479 return hr;
1480
1481 COMPtr<IWebURLResponse> urlResponse;
1482 hr = dataSource->response(&urlResponse);
1483 if (SUCCEEDED(hr) && urlResponse) {
1484 BSTR mimeTypeBStr;
1485 if (SUCCEEDED(urlResponse->MIMEType(&mimeTypeBStr))) {
1486 String mimeType(mimeTypeBStr, SysStringLen(mimeTypeBStr));
1487 *result = mimeType == "text/html" || WebCore::DOMImplementation::isXMLMIMEType(mimeType);
1488 SysFreeString(mimeTypeBStr);
1489 }
1490 }
1491 return hr;
1492 }
1493
layerTreeAsText(BSTR * result)1494 HRESULT STDMETHODCALLTYPE WebFrame::layerTreeAsText(BSTR* result)
1495 {
1496 if (!result)
1497 return E_POINTER;
1498 *result = 0;
1499
1500 Frame* frame = core(this);
1501 if (!frame)
1502 return E_FAIL;
1503
1504 String text = frame->layerTreeAsText();
1505 *result = BString(text).release();
1506 return S_OK;
1507 }
1508
frameLoaderDestroyed()1509 void WebFrame::frameLoaderDestroyed()
1510 {
1511 // The FrameLoader going away is equivalent to the Frame going away,
1512 // so we now need to clear our frame pointer.
1513 d->frame = 0;
1514
1515 this->Release();
1516 }
1517
makeRepresentation(DocumentLoader *)1518 void WebFrame::makeRepresentation(DocumentLoader*)
1519 {
1520 notImplemented();
1521 }
1522
forceLayoutForNonHTML()1523 void WebFrame::forceLayoutForNonHTML()
1524 {
1525 notImplemented();
1526 }
1527
setCopiesOnScroll()1528 void WebFrame::setCopiesOnScroll()
1529 {
1530 notImplemented();
1531 }
1532
detachedFromParent2()1533 void WebFrame::detachedFromParent2()
1534 {
1535 notImplemented();
1536 }
1537
detachedFromParent3()1538 void WebFrame::detachedFromParent3()
1539 {
1540 notImplemented();
1541 }
1542
cancelPolicyCheck()1543 void WebFrame::cancelPolicyCheck()
1544 {
1545 if (d->m_policyListener) {
1546 d->m_policyListener->invalidate();
1547 d->m_policyListener = 0;
1548 }
1549
1550 d->m_policyFunction = 0;
1551 }
1552
dispatchWillSubmitForm(FramePolicyFunction function,PassRefPtr<FormState> formState)1553 void WebFrame::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
1554 {
1555 Frame* coreFrame = core(this);
1556 ASSERT(coreFrame);
1557
1558 COMPtr<IWebFormDelegate> formDelegate;
1559
1560 if (FAILED(d->webView->formDelegate(&formDelegate))) {
1561 (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
1562 return;
1563 }
1564
1565 COMPtr<IDOMElement> formElement(AdoptCOM, DOMElement::createInstance(formState->form()));
1566
1567 HashMap<String, String> formValuesMap;
1568 const StringPairVector& textFieldValues = formState->textFieldValues();
1569 size_t size = textFieldValues.size();
1570 for (size_t i = 0; i < size; ++i)
1571 formValuesMap.add(textFieldValues[i].first, textFieldValues[i].second);
1572
1573 COMPtr<IPropertyBag> formValuesPropertyBag(AdoptCOM, COMPropertyBag<String>::createInstance(formValuesMap));
1574
1575 COMPtr<WebFrame> sourceFrame(kit(formState->sourceFrame()));
1576 if (SUCCEEDED(formDelegate->willSubmitForm(this, sourceFrame.get(), formElement.get(), formValuesPropertyBag.get(), setUpPolicyListener(function).get())))
1577 return;
1578
1579 // FIXME: Add a sane default implementation
1580 (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
1581 }
1582
revertToProvisionalState(DocumentLoader *)1583 void WebFrame::revertToProvisionalState(DocumentLoader*)
1584 {
1585 notImplemented();
1586 }
1587
setMainFrameDocumentReady(bool)1588 void WebFrame::setMainFrameDocumentReady(bool)
1589 {
1590 notImplemented();
1591 }
1592
willChangeTitle(DocumentLoader *)1593 void WebFrame::willChangeTitle(DocumentLoader*)
1594 {
1595 notImplemented();
1596 }
1597
didChangeTitle(DocumentLoader *)1598 void WebFrame::didChangeTitle(DocumentLoader*)
1599 {
1600 notImplemented();
1601 }
1602
didChangeIcons(DocumentLoader *)1603 void WebFrame::didChangeIcons(DocumentLoader*)
1604 {
1605 notImplemented();
1606 }
1607
canHandleRequest(const ResourceRequest & request) const1608 bool WebFrame::canHandleRequest(const ResourceRequest& request) const
1609 {
1610 return WebView::canHandleRequest(request);
1611 }
1612
canShowMIMETypeAsHTML(const String &) const1613 bool WebFrame::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1614 {
1615 notImplemented();
1616 return true;
1617 }
1618
canShowMIMEType(const String &) const1619 bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const
1620 {
1621 notImplemented();
1622 return true;
1623 }
1624
representationExistsForURLScheme(const String &) const1625 bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const
1626 {
1627 notImplemented();
1628 return false;
1629 }
1630
generatedMIMETypeForURLScheme(const String &) const1631 String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1632 {
1633 notImplemented();
1634 ASSERT_NOT_REACHED();
1635 return String();
1636 }
1637
frameLoadCompleted()1638 void WebFrame::frameLoadCompleted()
1639 {
1640 }
1641
restoreViewState()1642 void WebFrame::restoreViewState()
1643 {
1644 }
1645
provisionalLoadStarted()1646 void WebFrame::provisionalLoadStarted()
1647 {
1648 notImplemented();
1649 }
1650
shouldTreatURLAsSameAsCurrent(const KURL &) const1651 bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const
1652 {
1653 notImplemented();
1654 return false;
1655 }
1656
addHistoryItemForFragmentScroll()1657 void WebFrame::addHistoryItemForFragmentScroll()
1658 {
1659 notImplemented();
1660 }
1661
didFinishLoad()1662 void WebFrame::didFinishLoad()
1663 {
1664 notImplemented();
1665 }
1666
prepareForDataSourceReplacement()1667 void WebFrame::prepareForDataSourceReplacement()
1668 {
1669 notImplemented();
1670 }
1671
userAgent(const KURL & url)1672 String WebFrame::userAgent(const KURL& url)
1673 {
1674 return d->webView->userAgentForKURL(url);
1675 }
1676
saveViewStateToItem(HistoryItem *)1677 void WebFrame::saveViewStateToItem(HistoryItem*)
1678 {
1679 }
1680
cancelledError(const ResourceRequest & request)1681 ResourceError WebFrame::cancelledError(const ResourceRequest& request)
1682 {
1683 // FIXME: Need ChickenCat to include CFNetwork/CFURLError.h to get these values
1684 // Alternatively, we could create our own error domain/codes.
1685 return ResourceError(String(WebURLErrorDomain), -999, request.url().string(), String());
1686 }
1687
blockedError(const ResourceRequest & request)1688 ResourceError WebFrame::blockedError(const ResourceRequest& request)
1689 {
1690 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1691 return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotUseRestrictedPort, request.url().string(), String());
1692 }
1693
cannotShowURLError(const ResourceRequest & request)1694 ResourceError WebFrame::cannotShowURLError(const ResourceRequest& request)
1695 {
1696 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1697 return ResourceError(String(WebKitErrorDomain), WebKitErrorCannotShowURL, request.url().string(), String());
1698 }
1699
interruptForPolicyChangeError(const ResourceRequest & request)1700 ResourceError WebFrame::interruptForPolicyChangeError(const ResourceRequest& request)
1701 {
1702 // FIXME: Need to implement the String descriptions for errors in the WebKitErrorDomain and have them localized
1703 return ResourceError(String(WebKitErrorDomain), WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), String());
1704 }
1705
cannotShowMIMETypeError(const ResourceResponse &)1706 ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&)
1707 {
1708 notImplemented();
1709 return ResourceError();
1710 }
1711
fileDoesNotExistError(const ResourceResponse &)1712 ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&)
1713 {
1714 notImplemented();
1715 return ResourceError();
1716 }
1717
pluginWillHandleLoadError(const ResourceResponse & response)1718 ResourceError WebFrame::pluginWillHandleLoadError(const ResourceResponse& response)
1719 {
1720 return ResourceError(String(WebKitErrorDomain), WebKitErrorPlugInWillHandleLoad, response.url().string(), String());
1721 }
1722
shouldFallBack(const ResourceError & error)1723 bool WebFrame::shouldFallBack(const ResourceError& error)
1724 {
1725 if (error.errorCode() == WebURLErrorCancelled && error.domain() == String(WebURLErrorDomain))
1726 return false;
1727
1728 if (error.errorCode() == WebKitErrorPlugInWillHandleLoad && error.domain() == String(WebKitErrorDomain))
1729 return false;
1730
1731 return true;
1732 }
1733
setUpPolicyListener(WebCore::FramePolicyFunction function)1734 COMPtr<WebFramePolicyListener> WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction function)
1735 {
1736 // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1737
1738 if (d->m_policyListener)
1739 d->m_policyListener->invalidate();
1740
1741 Frame* coreFrame = core(this);
1742 ASSERT(coreFrame);
1743
1744 d->m_policyListener.adoptRef(WebFramePolicyListener::createInstance(coreFrame));
1745 d->m_policyFunction = function;
1746
1747 return d->m_policyListener;
1748 }
1749
receivedPolicyDecision(PolicyAction action)1750 void WebFrame::receivedPolicyDecision(PolicyAction action)
1751 {
1752 ASSERT(d->m_policyListener);
1753 ASSERT(d->m_policyFunction);
1754
1755 FramePolicyFunction function = d->m_policyFunction;
1756
1757 d->m_policyListener = 0;
1758 d->m_policyFunction = 0;
1759
1760 Frame* coreFrame = core(this);
1761 ASSERT(coreFrame);
1762
1763 (coreFrame->loader()->policyChecker()->*function)(action);
1764 }
1765
dispatchDecidePolicyForResponse(FramePolicyFunction function,const ResourceResponse & response,const ResourceRequest & request)1766 void WebFrame::dispatchDecidePolicyForResponse(FramePolicyFunction function, const ResourceResponse& response, const ResourceRequest& request)
1767 {
1768 Frame* coreFrame = core(this);
1769 ASSERT(coreFrame);
1770
1771 COMPtr<IWebPolicyDelegate> policyDelegate;
1772 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1773 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1774
1775 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1776
1777 if (SUCCEEDED(policyDelegate->decidePolicyForMIMEType(d->webView, BString(response.mimeType()), urlRequest.get(), this, setUpPolicyListener(function).get())))
1778 return;
1779
1780 (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
1781 }
1782
dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,const NavigationAction & action,const ResourceRequest & request,PassRefPtr<FormState> formState,const String & frameName)1783 void WebFrame::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
1784 {
1785 Frame* coreFrame = core(this);
1786 ASSERT(coreFrame);
1787
1788 COMPtr<IWebPolicyDelegate> policyDelegate;
1789 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1790 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1791
1792 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1793 COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
1794
1795 if (SUCCEEDED(policyDelegate->decidePolicyForNewWindowAction(d->webView, actionInformation.get(), urlRequest.get(), BString(frameName), setUpPolicyListener(function).get())))
1796 return;
1797
1798 (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
1799 }
1800
dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,const NavigationAction & action,const ResourceRequest & request,PassRefPtr<FormState> formState)1801 void WebFrame::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
1802 {
1803 Frame* coreFrame = core(this);
1804 ASSERT(coreFrame);
1805
1806 COMPtr<IWebPolicyDelegate> policyDelegate;
1807 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1808 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1809
1810 COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
1811 COMPtr<WebActionPropertyBag> actionInformation(AdoptCOM, WebActionPropertyBag::createInstance(action, formState ? formState->form() : 0, coreFrame));
1812
1813 if (SUCCEEDED(policyDelegate->decidePolicyForNavigationAction(d->webView, actionInformation.get(), urlRequest.get(), this, setUpPolicyListener(function).get())))
1814 return;
1815
1816 (coreFrame->loader()->policyChecker()->*function)(PolicyUse);
1817 }
1818
dispatchUnableToImplementPolicy(const ResourceError & error)1819 void WebFrame::dispatchUnableToImplementPolicy(const ResourceError& error)
1820 {
1821 COMPtr<IWebPolicyDelegate> policyDelegate;
1822 if (FAILED(d->webView->policyDelegate(&policyDelegate)))
1823 policyDelegate = DefaultPolicyDelegate::sharedInstance();
1824
1825 COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error));
1826 policyDelegate->unableToImplementPolicyWithError(d->webView, webError.get(), this);
1827 }
1828
download(ResourceHandle * handle,const ResourceRequest & request,const ResourceRequest &,const ResourceResponse & response)1829 void WebFrame::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1830 {
1831 COMPtr<IWebDownloadDelegate> downloadDelegate;
1832 COMPtr<IWebView> webView;
1833 if (SUCCEEDED(this->webView(&webView))) {
1834 if (FAILED(webView->downloadDelegate(&downloadDelegate))) {
1835 // If the WebView doesn't successfully provide a download delegate we'll pass a null one
1836 // into the WebDownload - which may or may not decide to use a DefaultDownloadDelegate
1837 LOG_ERROR("Failed to get downloadDelegate from WebView");
1838 downloadDelegate = 0;
1839 }
1840 }
1841
1842 // Its the delegate's job to ref the WebDownload to keep it alive - otherwise it will be destroyed
1843 // when this method returns
1844 COMPtr<WebDownload> download;
1845 download.adoptRef(WebDownload::createInstance(handle, request, response, downloadDelegate.get()));
1846 }
1847
dispatchDidLoadResourceFromMemoryCache(DocumentLoader *,const ResourceRequest &,const ResourceResponse &,int)1848 bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
1849 {
1850 notImplemented();
1851 return false;
1852 }
1853
dispatchDidFailProvisionalLoad(const ResourceError & error)1854 void WebFrame::dispatchDidFailProvisionalLoad(const ResourceError& error)
1855 {
1856 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1857 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
1858 COMPtr<IWebError> webError;
1859 webError.adoptRef(WebError::createInstance(error));
1860 frameLoadDelegate->didFailProvisionalLoadWithError(d->webView, webError.get(), this);
1861 }
1862 }
1863
dispatchDidFailLoad(const ResourceError & error)1864 void WebFrame::dispatchDidFailLoad(const ResourceError& error)
1865 {
1866 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1867 if (SUCCEEDED(d->webView->frameLoadDelegate(&frameLoadDelegate))) {
1868 COMPtr<IWebError> webError;
1869 webError.adoptRef(WebError::createInstance(error));
1870 frameLoadDelegate->didFailLoadWithError(d->webView, webError.get(), this);
1871 }
1872 }
1873
startDownload(const ResourceRequest & request)1874 void WebFrame::startDownload(const ResourceRequest& request)
1875 {
1876 d->webView->downloadURL(request.url());
1877 }
1878
createJavaAppletWidget(const IntSize & pluginSize,HTMLAppletElement * element,const KURL &,const Vector<String> & paramNames,const Vector<String> & paramValues)1879 PassRefPtr<Widget> WebFrame::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues)
1880 {
1881 RefPtr<PluginView> pluginView = PluginView::create(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false);
1882
1883 // Check if the plugin can be loaded successfully
1884 if (pluginView->plugin() && pluginView->plugin()->load())
1885 return pluginView;
1886
1887 COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
1888 if (FAILED(d->webView->resourceLoadDelegate(&resourceLoadDelegate)))
1889 return pluginView;
1890
1891 COMPtr<CFDictionaryPropertyBag> userInfoBag = CFDictionaryPropertyBag::createInstance();
1892
1893 ResourceError resourceError(String(WebKitErrorDomain), WebKitErrorJavaUnavailable, String(), String());
1894 COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
1895
1896 resourceLoadDelegate->plugInFailedWithError(d->webView, error.get(), getWebDataSource(d->frame->loader()->documentLoader()));
1897
1898 return pluginView;
1899 }
1900
objectContentType(const KURL & url,const String & mimeType,bool shouldPreferPlugInsForImages)1901 ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
1902 {
1903 return WebCore::FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages);
1904 }
1905
overrideMediaType() const1906 String WebFrame::overrideMediaType() const
1907 {
1908 notImplemented();
1909 return String();
1910 }
1911
dispatchDidClearWindowObjectInWorld(DOMWrapperWorld * world)1912 void WebFrame::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
1913 {
1914 Frame* coreFrame = core(this);
1915 ASSERT(coreFrame);
1916
1917 Settings* settings = coreFrame->settings();
1918 if (!settings || !settings->isJavaScriptEnabled())
1919 return;
1920
1921 COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
1922 if (FAILED(d->webView->frameLoadDelegate(&frameLoadDelegate)))
1923 return;
1924
1925 COMPtr<IWebFrameLoadDelegatePrivate2> delegatePrivate(Query, frameLoadDelegate);
1926 if (delegatePrivate && delegatePrivate->didClearWindowObjectForFrameInScriptWorld(d->webView, this, WebScriptWorld::findOrCreateWorld(world).get()) != E_NOTIMPL)
1927 return;
1928
1929 if (world != mainThreadNormalWorld())
1930 return;
1931
1932 JSContextRef context = toRef(coreFrame->script()->globalObject(world)->globalExec());
1933 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(world));
1934 ASSERT(windowObject);
1935
1936 if (FAILED(frameLoadDelegate->didClearWindowObject(d->webView, context, windowObject, this)))
1937 frameLoadDelegate->windowScriptObjectAvailable(d->webView, context, windowObject);
1938 }
1939
documentElementAvailable()1940 void WebFrame::documentElementAvailable()
1941 {
1942 }
1943
didPerformFirstNavigation() const1944 void WebFrame::didPerformFirstNavigation() const
1945 {
1946 COMPtr<IWebPreferences> preferences;
1947 if (FAILED(d->webView->preferences(&preferences)))
1948 return;
1949
1950 COMPtr<IWebPreferencesPrivate> preferencesPrivate(Query, preferences);
1951 if (!preferencesPrivate)
1952 return;
1953 BOOL automaticallyDetectsCacheModel;
1954 if (FAILED(preferencesPrivate->automaticallyDetectsCacheModel(&automaticallyDetectsCacheModel)))
1955 return;
1956
1957 WebCacheModel cacheModel;
1958 if (FAILED(preferences->cacheModel(&cacheModel)))
1959 return;
1960
1961 if (automaticallyDetectsCacheModel && cacheModel < WebCacheModelDocumentBrowser)
1962 preferences->setCacheModel(WebCacheModelDocumentBrowser);
1963 }
1964
registerForIconNotification(bool listen)1965 void WebFrame::registerForIconNotification(bool listen)
1966 {
1967 d->webView->registerForIconNotification(listen);
1968 }
1969
printerRect(HDC printDC)1970 static IntRect printerRect(HDC printDC)
1971 {
1972 return IntRect(0, 0,
1973 GetDeviceCaps(printDC, PHYSICALWIDTH) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETX),
1974 GetDeviceCaps(printDC, PHYSICALHEIGHT) - 2 * GetDeviceCaps(printDC, PHYSICALOFFSETY));
1975 }
1976
setPrinting(bool printing,float minPageWidth,float maxPageWidth,float minPageHeight,bool adjustViewSize)1977 void WebFrame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, float minPageHeight, bool adjustViewSize)
1978 {
1979 Frame* coreFrame = core(this);
1980 ASSERT(coreFrame);
1981 coreFrame->setPrinting(printing, FloatSize(minPageWidth, minPageHeight), maxPageWidth / minPageWidth, adjustViewSize ? Frame::AdjustViewSize : Frame::DoNotAdjustViewSize);
1982 }
1983
setInPrintingMode(BOOL value,HDC printDC)1984 HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode(
1985 /* [in] */ BOOL value,
1986 /* [in] */ HDC printDC)
1987 {
1988 if (m_inPrintingMode == !!value)
1989 return S_OK;
1990
1991 Frame* coreFrame = core(this);
1992 if (!coreFrame || !coreFrame->document())
1993 return E_FAIL;
1994
1995 m_inPrintingMode = !!value;
1996
1997 // If we are a frameset just print with the layout we have onscreen, otherwise relayout
1998 // according to the paper size
1999 float minLayoutWidth = 0.0f;
2000 float maxLayoutWidth = 0.0f;
2001 float minLayoutHeight = 0.0f;
2002 if (m_inPrintingMode && !coreFrame->document()->isFrameSet()) {
2003 if (!printDC) {
2004 ASSERT_NOT_REACHED();
2005 return E_POINTER;
2006 }
2007
2008 const int desiredPixelsPerInch = 72;
2009 IntRect printRect = printerRect(printDC);
2010 int paperHorizontalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSX);
2011 int paperWidth = printRect.width() * desiredPixelsPerInch / paperHorizontalPixelsPerInch;
2012 int paperVerticalPixelsPerInch = ::GetDeviceCaps(printDC, LOGPIXELSY);
2013 int paperHeight = printRect.height() * desiredPixelsPerInch / paperVerticalPixelsPerInch;
2014 minLayoutWidth = paperWidth * PrintingMinimumShrinkFactor;
2015 maxLayoutWidth = paperWidth * PrintingMaximumShrinkFactor;
2016 minLayoutHeight = paperHeight * PrintingMinimumShrinkFactor;
2017 }
2018
2019 setPrinting(m_inPrintingMode, minLayoutWidth, maxLayoutWidth, minLayoutHeight, true);
2020
2021 if (!m_inPrintingMode)
2022 m_pageRects.clear();
2023
2024 return S_OK;
2025 }
2026
headerAndFooterHeights(float * headerHeight,float * footerHeight)2027 void WebFrame::headerAndFooterHeights(float* headerHeight, float* footerHeight)
2028 {
2029 if (headerHeight)
2030 *headerHeight = 0;
2031 if (footerHeight)
2032 *footerHeight = 0;
2033 float height = 0;
2034 COMPtr<IWebUIDelegate> ui;
2035 if (FAILED(d->webView->uiDelegate(&ui)))
2036 return;
2037 if (headerHeight && SUCCEEDED(ui->webViewHeaderHeight(d->webView, &height)))
2038 *headerHeight = height;
2039 if (footerHeight && SUCCEEDED(ui->webViewFooterHeight(d->webView, &height)))
2040 *footerHeight = height;
2041 }
2042
printerMarginRect(HDC printDC)2043 IntRect WebFrame::printerMarginRect(HDC printDC)
2044 {
2045 IntRect emptyRect(0, 0, 0, 0);
2046
2047 COMPtr<IWebUIDelegate> ui;
2048 if (FAILED(d->webView->uiDelegate(&ui)))
2049 return emptyRect;
2050
2051 RECT rect;
2052 if (FAILED(ui->webViewPrintingMarginRect(d->webView, &rect)))
2053 return emptyRect;
2054
2055 rect.left = MulDiv(rect.left, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
2056 rect.top = MulDiv(rect.top, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
2057 rect.right = MulDiv(rect.right, ::GetDeviceCaps(printDC, LOGPIXELSX), 1000);
2058 rect.bottom = MulDiv(rect.bottom, ::GetDeviceCaps(printDC, LOGPIXELSY), 1000);
2059
2060 return IntRect(rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top);
2061 }
2062
computePageRects(HDC printDC)2063 const Vector<WebCore::IntRect>& WebFrame::computePageRects(HDC printDC)
2064 {
2065 ASSERT(m_inPrintingMode);
2066
2067 Frame* coreFrame = core(this);
2068 ASSERT(coreFrame);
2069 ASSERT(coreFrame->document());
2070
2071 if (!printDC)
2072 return m_pageRects;
2073
2074 // adjust the page rect by the header and footer
2075 float headerHeight = 0, footerHeight = 0;
2076 headerAndFooterHeights(&headerHeight, &footerHeight);
2077 IntRect pageRect = printerRect(printDC);
2078 IntRect marginRect = printerMarginRect(printDC);
2079 IntRect adjustedRect = IntRect(
2080 pageRect.x() + marginRect.x(),
2081 pageRect.y() + marginRect.y(),
2082 pageRect.width() - marginRect.x() - marginRect.maxX(),
2083 pageRect.height() - marginRect.y() - marginRect.maxY());
2084
2085 computePageRectsForFrame(coreFrame, adjustedRect, headerHeight, footerHeight, 1.0,m_pageRects, m_pageHeight);
2086
2087 return m_pageRects;
2088 }
2089
getPrintedPageCount(HDC printDC,UINT * pageCount)2090 HRESULT STDMETHODCALLTYPE WebFrame::getPrintedPageCount(
2091 /* [in] */ HDC printDC,
2092 /* [retval][out] */ UINT *pageCount)
2093 {
2094 if (!pageCount || !printDC) {
2095 ASSERT_NOT_REACHED();
2096 return E_POINTER;
2097 }
2098
2099 *pageCount = 0;
2100
2101 if (!m_inPrintingMode) {
2102 ASSERT_NOT_REACHED();
2103 return E_FAIL;
2104 }
2105
2106 Frame* coreFrame = core(this);
2107 if (!coreFrame || !coreFrame->document())
2108 return E_FAIL;
2109
2110 const Vector<IntRect>& pages = computePageRects(printDC);
2111 *pageCount = (UINT) pages.size();
2112
2113 return S_OK;
2114 }
2115
2116 #if USE(CG)
drawHeader(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,float headerHeight)2117 void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
2118 {
2119 int x = pageRect.x();
2120 int y = 0;
2121 RECT headerRect = {x, y, x+pageRect.width(), y+static_cast<int>(headerHeight)};
2122 ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)));
2123 }
2124
drawFooter(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,UINT page,UINT pageCount,float headerHeight,float footerHeight)2125 void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
2126 {
2127 int x = pageRect.x();
2128 int y = max((int)headerHeight+pageRect.height(), m_pageHeight-static_cast<int>(footerHeight));
2129 RECT footerRect = {x, y, x+pageRect.width(), y+static_cast<int>(footerHeight)};
2130 ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(pctx)), page+1, pageCount);
2131 }
2132
spoolPage(PlatformGraphicsContext * pctx,GraphicsContext * spoolCtx,HDC printDC,IWebUIDelegate * ui,float headerHeight,float footerHeight,UINT page,UINT pageCount)2133 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
2134 {
2135 Frame* coreFrame = core(this);
2136
2137 IntRect pageRect = m_pageRects[page];
2138
2139 CGContextSaveGState(pctx);
2140
2141 IntRect printRect = printerRect(printDC);
2142 CGRect mediaBox = CGRectMake(CGFloat(0),
2143 CGFloat(0),
2144 CGFloat(printRect.width()),
2145 CGFloat(printRect.height()));
2146
2147 CGContextBeginPage(pctx, &mediaBox);
2148
2149 CGFloat scale = static_cast<float>(mediaBox.size.width)/static_cast<float>(pageRect.width());
2150 CGAffineTransform ctm = CGContextGetBaseCTM(pctx);
2151 ctm = CGAffineTransformScale(ctm, -scale, -scale);
2152 ctm = CGAffineTransformTranslate(ctm, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
2153 CGContextScaleCTM(pctx, scale, scale);
2154 CGContextTranslateCTM(pctx, CGFloat(-pageRect.x()), CGFloat(-pageRect.y()+headerHeight)); // reserves space for header
2155 CGContextSetBaseCTM(pctx, ctm);
2156
2157 coreFrame->view()->paintContents(spoolCtx, pageRect);
2158
2159 CGContextTranslateCTM(pctx, CGFloat(pageRect.x()), CGFloat(pageRect.y())-headerHeight);
2160
2161 if (headerHeight)
2162 drawHeader(pctx, ui, pageRect, headerHeight);
2163
2164 if (footerHeight)
2165 drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
2166
2167 CGContextEndPage(pctx);
2168 CGContextRestoreGState(pctx);
2169 }
2170 #elif USE(CAIRO)
scaleFactor(HDC printDC,const IntRect & marginRect,const IntRect & pageRect)2171 static float scaleFactor(HDC printDC, const IntRect& marginRect, const IntRect& pageRect)
2172 {
2173 const IntRect& printRect = printerRect(printDC);
2174
2175 IntRect adjustedRect = IntRect(
2176 printRect.x() + marginRect.x(),
2177 printRect.y() + marginRect.y(),
2178 printRect.width() - marginRect.x() - marginRect.maxX(),
2179 printRect.height() - marginRect.y() - marginRect.maxY());
2180
2181 float scale = static_cast<float>(adjustedRect.width()) / static_cast<float>(pageRect.width());
2182 if (!scale)
2183 scale = 1.0;
2184
2185 return scale;
2186 }
2187
hdcFromContext(PlatformGraphicsContext * pctx)2188 static HDC hdcFromContext(PlatformGraphicsContext* pctx)
2189 {
2190 return cairo_win32_surface_get_dc(cairo_get_target(pctx->cr()));
2191 }
2192
drawHeader(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,float headerHeight)2193 void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight)
2194 {
2195 HDC hdc = hdcFromContext(pctx);
2196
2197 int x = pageRect.x();
2198 int y = 0;
2199 RECT headerRect = {x, y, x + pageRect.width(), y + static_cast<int>(headerHeight)};
2200
2201 ui->drawHeaderInRect(d->webView, &headerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc)));
2202 }
2203
drawFooter(PlatformGraphicsContext * pctx,IWebUIDelegate * ui,const IntRect & pageRect,UINT page,UINT pageCount,float headerHeight,float footerHeight)2204 void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight)
2205 {
2206 HDC hdc = hdcFromContext(pctx);
2207
2208 int x = pageRect.x();
2209 int y = max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight -static_cast<int>(footerHeight));
2210 RECT footerRect = {x, y, x + pageRect.width(), y + static_cast<int>(footerHeight)};
2211
2212 ui->drawFooterInRect(d->webView, &footerRect, static_cast<OLE_HANDLE>(reinterpret_cast<LONG64>(hdc)), page+1, pageCount);
2213 }
2214
buildXFORMFromCairo(HDC targetDC,cairo_t * previewContext)2215 static XFORM buildXFORMFromCairo(HDC targetDC, cairo_t* previewContext)
2216 {
2217 XFORM scaled;
2218 GetWorldTransform(targetDC, &scaled);
2219
2220 cairo_matrix_t ctm;
2221 cairo_get_matrix(previewContext, &ctm);
2222
2223 // Scale to the preview screen bounds
2224 scaled.eM11 = ctm.xx;
2225 scaled.eM22 = ctm.yy;
2226
2227 return scaled;
2228 }
2229
spoolPage(PlatformGraphicsContext * pctx,GraphicsContext * spoolCtx,HDC printDC,IWebUIDelegate * ui,float headerHeight,float footerHeight,UINT page,UINT pageCount)2230 void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCtx, HDC printDC, IWebUIDelegate* ui, float headerHeight, float footerHeight, UINT page, UINT pageCount)
2231 {
2232 Frame* coreFrame = core(this);
2233
2234 const IntRect& pageRect = m_pageRects[page];
2235 const IntRect& marginRect = printerMarginRect(printDC);
2236
2237 // In preview, the printDC is a placeholder, so just always use the HDC backing the graphics context.
2238 HDC hdc = hdcFromContext(pctx);
2239
2240 spoolCtx->save();
2241
2242 XFORM original, scaled;
2243 GetWorldTransform(hdc, &original);
2244
2245 cairo_t* cr = pctx->cr();
2246 bool preview = (hdc != printDC);
2247 if (preview) {
2248 // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo will
2249 // draw correctly. We need to retain the correct preview scale here for use when the Cairo
2250 // drawing completes so that we can scale our GDI-based header/footer calls. This is a
2251 // workaround for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
2252 scaled = buildXFORMFromCairo(hdc, cr);
2253 }
2254
2255 float scale = scaleFactor(printDC, marginRect, pageRect);
2256
2257 IntRect cairoMarginRect(marginRect);
2258 cairoMarginRect.scale(1 / scale);
2259
2260 // We cannot scale the display HDC because the print surface also scales fonts,
2261 // resulting in invalid printing (and print preview)
2262 cairo_scale(cr, scale, scale);
2263 cairo_translate(cr, cairoMarginRect.x(), cairoMarginRect.y() + headerHeight);
2264
2265 // Modify Cairo (only) to account for page position.
2266 cairo_translate(cr, -pageRect.x(), -pageRect.y());
2267 coreFrame->view()->paintContents(spoolCtx, pageRect);
2268 cairo_translate(cr, pageRect.x(), pageRect.y());
2269
2270 if (preview) {
2271 // If this is a preview, the Windows HDC was set to a non-scaled state so that Cairo would
2272 // draw correctly. We need to rescale the HDC to the correct preview scale so our GDI-based
2273 // header/footer calls will draw properly. This is a workaround for a bug in Cairo.
2274 // (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
2275 SetWorldTransform(hdc, &scaled);
2276 }
2277
2278 XFORM xform = TransformationMatrix().translate(marginRect.x(), marginRect.y()).scale(scale);
2279 ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
2280
2281 if (headerHeight)
2282 drawHeader(pctx, ui, pageRect, headerHeight);
2283
2284 if (footerHeight)
2285 drawFooter(pctx, ui, pageRect, page, pageCount, headerHeight, footerHeight);
2286
2287 SetWorldTransform(hdc, &original);
2288
2289 cairo_show_page(cr);
2290 ASSERT(!cairo_status(cr));
2291 spoolCtx->restore();
2292 }
2293
setCairoTransformToPreviewHDC(cairo_t * previewCtx,HDC previewDC)2294 static void setCairoTransformToPreviewHDC(cairo_t* previewCtx, HDC previewDC)
2295 {
2296 XFORM passedCTM;
2297 GetWorldTransform(previewDC, &passedCTM);
2298
2299 // Reset HDC WorldTransform to unscaled state. Scaling must be
2300 // done in Cairo to avoid drawing errors.
2301 XFORM unscaledCTM = passedCTM;
2302 unscaledCTM.eM11 = 1.0;
2303 unscaledCTM.eM22 = 1.0;
2304
2305 SetWorldTransform(previewDC, &unscaledCTM);
2306
2307 // Make the Cairo transform match the information passed to WebKit
2308 // in the HDC's WorldTransform.
2309 cairo_matrix_t ctm = { passedCTM.eM11, passedCTM.eM12, passedCTM.eM21,
2310 passedCTM.eM22, passedCTM.eDx, passedCTM.eDy };
2311
2312 cairo_set_matrix(previewCtx, &ctm);
2313 }
2314
2315 #endif
2316
spoolPages(HDC printDC,UINT startPage,UINT endPage,void * ctx)2317 HRESULT STDMETHODCALLTYPE WebFrame::spoolPages(
2318 /* [in] */ HDC printDC,
2319 /* [in] */ UINT startPage,
2320 /* [in] */ UINT endPage,
2321 /* [retval][out] */ void* ctx)
2322 {
2323 #if USE(CG)
2324 if (!printDC || !ctx) {
2325 ASSERT_NOT_REACHED();
2326 return E_POINTER;
2327 }
2328 #elif USE(CAIRO)
2329 if (!printDC) {
2330 ASSERT_NOT_REACHED();
2331 return E_POINTER;
2332 }
2333
2334 HDC targetDC = (ctx) ? (HDC)ctx : printDC;
2335
2336 cairo_surface_t* printSurface = 0;
2337 if (ctx)
2338 printSurface = cairo_win32_surface_create(targetDC); // in-memory
2339 else
2340 printSurface = cairo_win32_printing_surface_create(targetDC); // metafile
2341
2342 cairo_t* cr = cairo_create(printSurface);
2343 if (!cr) {
2344 cairo_surface_destroy(printSurface);
2345 return E_FAIL;
2346 }
2347
2348 PlatformContextCairo platformContext(cr);
2349 PlatformGraphicsContext* pctx = &platformContext;
2350 cairo_destroy(cr);
2351
2352 if (ctx) {
2353 // If this is a preview, the Windows HDC was sent with scaling information.
2354 // Retrieve it and reset it so that it draws properly. This is a workaround
2355 // for a bug in Cairo (see https://bugs.freedesktop.org/show_bug.cgi?id=28161)
2356 setCairoTransformToPreviewHDC(cr, targetDC);
2357 }
2358
2359 cairo_surface_set_fallback_resolution(printSurface, 72.0, 72.0);
2360 #endif
2361
2362 if (!m_inPrintingMode) {
2363 ASSERT_NOT_REACHED();
2364 return E_FAIL;
2365 }
2366
2367 Frame* coreFrame = core(this);
2368 if (!coreFrame || !coreFrame->document())
2369 return E_FAIL;
2370
2371 UINT pageCount = (UINT) m_pageRects.size();
2372 #if USE(CG)
2373 PlatformGraphicsContext* pctx = (PlatformGraphicsContext*)ctx;
2374 #endif
2375
2376 if (!pageCount || startPage > pageCount) {
2377 ASSERT_NOT_REACHED();
2378 return E_FAIL;
2379 }
2380
2381 if (startPage > 0)
2382 startPage--;
2383
2384 if (endPage == 0)
2385 endPage = pageCount;
2386
2387 COMPtr<IWebUIDelegate> ui;
2388 if (FAILED(d->webView->uiDelegate(&ui)))
2389 return E_FAIL;
2390
2391 float headerHeight = 0, footerHeight = 0;
2392 headerAndFooterHeights(&headerHeight, &footerHeight);
2393 GraphicsContext spoolCtx(pctx);
2394 spoolCtx.setShouldIncludeChildWindows(true);
2395
2396 for (UINT ii = startPage; ii < endPage; ii++)
2397 spoolPage(pctx, &spoolCtx, printDC, ui.get(), headerHeight, footerHeight, ii, pageCount);
2398
2399 #if USE(CAIRO)
2400 cairo_surface_finish(printSurface);
2401 ASSERT(!cairo_surface_status(printSurface));
2402 cairo_surface_destroy(printSurface);
2403 #endif
2404
2405 return S_OK;
2406 }
2407
isFrameSet(BOOL * result)2408 HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet(
2409 /* [retval][out] */ BOOL* result)
2410 {
2411 *result = FALSE;
2412
2413 Frame* coreFrame = core(this);
2414 if (!coreFrame || !coreFrame->document())
2415 return E_FAIL;
2416
2417 *result = coreFrame->document()->isFrameSet() ? TRUE : FALSE;
2418 return S_OK;
2419 }
2420
string(BSTR * result)2421 HRESULT STDMETHODCALLTYPE WebFrame::string(
2422 /* [retval][out] */ BSTR *result)
2423 {
2424 *result = 0;
2425
2426 Frame* coreFrame = core(this);
2427 if (!coreFrame)
2428 return E_FAIL;
2429
2430 RefPtr<Range> allRange(rangeOfContents(coreFrame->document()));
2431 String allString = plainText(allRange.get());
2432 *result = BString(allString).release();
2433 return S_OK;
2434 }
2435
size(SIZE * size)2436 HRESULT STDMETHODCALLTYPE WebFrame::size(
2437 /* [retval][out] */ SIZE *size)
2438 {
2439 if (!size)
2440 return E_POINTER;
2441 size->cx = size->cy = 0;
2442
2443 Frame* coreFrame = core(this);
2444 if (!coreFrame)
2445 return E_FAIL;
2446 FrameView* view = coreFrame->view();
2447 if (!view)
2448 return E_FAIL;
2449 size->cx = view->width();
2450 size->cy = view->height();
2451 return S_OK;
2452 }
2453
hasScrollBars(BOOL * result)2454 HRESULT STDMETHODCALLTYPE WebFrame::hasScrollBars(
2455 /* [retval][out] */ BOOL *result)
2456 {
2457 if (!result)
2458 return E_POINTER;
2459 *result = FALSE;
2460
2461 Frame* coreFrame = core(this);
2462 if (!coreFrame)
2463 return E_FAIL;
2464
2465 FrameView* view = coreFrame->view();
2466 if (!view)
2467 return E_FAIL;
2468
2469 if (view->horizontalScrollbar() || view->verticalScrollbar())
2470 *result = TRUE;
2471
2472 return S_OK;
2473 }
2474
contentBounds(RECT * result)2475 HRESULT STDMETHODCALLTYPE WebFrame::contentBounds(
2476 /* [retval][out] */ RECT *result)
2477 {
2478 if (!result)
2479 return E_POINTER;
2480 ::SetRectEmpty(result);
2481
2482 Frame* coreFrame = core(this);
2483 if (!coreFrame)
2484 return E_FAIL;
2485
2486 FrameView* view = coreFrame->view();
2487 if (!view)
2488 return E_FAIL;
2489
2490 result->bottom = view->contentsHeight();
2491 result->right = view->contentsWidth();
2492 return S_OK;
2493 }
2494
frameBounds(RECT * result)2495 HRESULT STDMETHODCALLTYPE WebFrame::frameBounds(
2496 /* [retval][out] */ RECT *result)
2497 {
2498 if (!result)
2499 return E_POINTER;
2500 ::SetRectEmpty(result);
2501
2502 Frame* coreFrame = core(this);
2503 if (!coreFrame)
2504 return E_FAIL;
2505
2506 FrameView* view = coreFrame->view();
2507 if (!view)
2508 return E_FAIL;
2509
2510 FloatRect bounds = view->visibleContentRect(true);
2511 result->bottom = (LONG) bounds.height();
2512 result->right = (LONG) bounds.width();
2513 return S_OK;
2514 }
2515
isDescendantOfFrame(IWebFrame * ancestor,BOOL * result)2516 HRESULT STDMETHODCALLTYPE WebFrame::isDescendantOfFrame(
2517 /* [in] */ IWebFrame *ancestor,
2518 /* [retval][out] */ BOOL *result)
2519 {
2520 if (!result)
2521 return E_POINTER;
2522 *result = FALSE;
2523
2524 Frame* coreFrame = core(this);
2525 COMPtr<WebFrame> ancestorWebFrame(Query, ancestor);
2526 if (!ancestorWebFrame)
2527 return S_OK;
2528
2529 *result = (coreFrame && coreFrame->tree()->isDescendantOf(core(ancestorWebFrame.get()))) ? TRUE : FALSE;
2530 return S_OK;
2531 }
2532
stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld * iWorld,JSObjectRef globalObjectRef,BSTR script,BSTR * evaluationResult)2533 HRESULT WebFrame::stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld* iWorld, JSObjectRef globalObjectRef, BSTR script, BSTR* evaluationResult)
2534 {
2535 if (!evaluationResult)
2536 return E_POINTER;
2537 *evaluationResult = 0;
2538
2539 if (!iWorld)
2540 return E_POINTER;
2541
2542 COMPtr<WebScriptWorld> world(Query, iWorld);
2543 if (!world)
2544 return E_INVALIDARG;
2545
2546 Frame* coreFrame = core(this);
2547 String string = String(script, SysStringLen(script));
2548
2549 // Start off with some guess at a frame and a global object, we'll try to do better...!
2550 JSDOMWindow* anyWorldGlobalObject = coreFrame->script()->globalObject(mainThreadNormalWorld());
2551
2552 // The global object is probably a shell object? - if so, we know how to use this!
2553 JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
2554 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
2555 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
2556
2557 // Get the frame frome the global object we've settled on.
2558 Frame* frame = anyWorldGlobalObject->impl()->frame();
2559 ASSERT(frame->document());
2560 JSValue result = frame->script()->executeScriptInWorld(world->world(), string, true).jsValue();
2561
2562 if (!frame) // In case the script removed our frame from the page.
2563 return S_OK;
2564
2565 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
2566 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
2567 // JSEvaluateScript instead, since they have less surprising semantics.
2568 if (!result || !result.isBoolean() && !result.isString() && !result.isNumber())
2569 return S_OK;
2570
2571 JSLock lock(SilenceAssertionsOnly);
2572 String resultString = ustringToString(result.toString(anyWorldGlobalObject->globalExec()));
2573 *evaluationResult = BString(resultString).release();
2574
2575 return S_OK;
2576 }
2577
unmarkAllMisspellings()2578 void WebFrame::unmarkAllMisspellings()
2579 {
2580 Frame* coreFrame = core(this);
2581 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2582 Document *doc = frame->document();
2583 if (!doc)
2584 return;
2585
2586 doc->markers()->removeMarkers(DocumentMarker::Spelling);
2587 }
2588 }
2589
unmarkAllBadGrammar()2590 void WebFrame::unmarkAllBadGrammar()
2591 {
2592 Frame* coreFrame = core(this);
2593 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
2594 Document *doc = frame->document();
2595 if (!doc)
2596 return;
2597
2598 doc->markers()->removeMarkers(DocumentMarker::Grammar);
2599 }
2600 }
2601
webView() const2602 WebView* WebFrame::webView() const
2603 {
2604 return d->webView;
2605 }
2606
setWebView(WebView * webView)2607 void WebFrame::setWebView(WebView* webView)
2608 {
2609 d->webView = webView;
2610 }
2611
accessible() const2612 COMPtr<IAccessible> WebFrame::accessible() const
2613 {
2614 Frame* coreFrame = core(this);
2615 ASSERT(coreFrame);
2616
2617 Document* currentDocument = coreFrame->document();
2618 if (!currentDocument)
2619 m_accessible = 0;
2620 else if (!m_accessible || m_accessible->document() != currentDocument) {
2621 // Either we've never had a wrapper for this frame's top-level Document,
2622 // the Document renderer was destroyed and its wrapper was detached, or
2623 // the previous Document is in the page cache, and the current document
2624 // needs to be wrapped.
2625 m_accessible = new AccessibleDocument(currentDocument);
2626 }
2627 return m_accessible.get();
2628 }
2629
updateBackground()2630 void WebFrame::updateBackground()
2631 {
2632 Color backgroundColor = webView()->transparent() ? Color::transparent : Color::white;
2633 Frame* coreFrame = core(this);
2634
2635 if (!coreFrame || !coreFrame->view())
2636 return;
2637
2638 coreFrame->view()->updateBackgroundRecursively(backgroundColor, webView()->transparent());
2639 }
2640
createNetworkingContext()2641 PassRefPtr<FrameNetworkingContext> WebFrame::createNetworkingContext()
2642 {
2643 return WebFrameNetworkingContext::create(core(this), userAgent(url()));
2644 }
2645