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 116extern "C" { 117 CGAffineTransform CGContextGetBaseCTM(CGContextRef c); 118 void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m); 119} 120#endif 121 122using namespace WebCore; 123using namespace HTMLNames; 124using namespace std; 125 126using JSC::JSGlobalObject; 127using JSC::JSLock; 128using JSC::JSValue; 129using 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. 139const 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) 145const float PrintingMaximumShrinkFactor = 2.0f; 146 147//----------------------------------------------------------------------------- 148// Helpers to convert from WebCore to WebKit type 149WebFrame* 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 160Frame* 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 168Frame* core(const WebFrame* webFrame) 169{ 170 if (!webFrame) 171 return 0; 172 return const_cast<WebFrame*>(webFrame)->impl(); 173} 174 175//----------------------------------------------------------------------------- 176 177static 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 193static 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 210static 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 229class WebFrame::WebFramePrivate { 230public: 231 WebFramePrivate() 232 : frame(0) 233 , webView(0) 234 , m_policyFunction(0) 235 { 236 } 237 238 ~WebFramePrivate() { } 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 249WebFrame::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 262WebFrame::~WebFrame() 263{ 264 delete d; 265 WebFrameCount--; 266 gClassCount--; 267 gClassNameCount.remove("WebFrame"); 268} 269 270WebFrame* WebFrame::createInstance() 271{ 272 WebFrame* instance = new WebFrame(); 273 instance->AddRef(); 274 return instance; 275} 276 277HRESULT 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 287HRESULT 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 298HRESULT 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 309HRESULT 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 320HRESULT 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 330HRESULT 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 362HRESULT 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 392HRESULT 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 412ULONG STDMETHODCALLTYPE WebFrame::AddRef(void) 413{ 414 return ++m_refCount; 415} 416 417ULONG 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 428HRESULT 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 446HRESULT 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 457HRESULT STDMETHODCALLTYPE WebFrame::frameView( 458 /* [retval][out] */ IWebFrameView** /*view*/) 459{ 460 ASSERT_NOT_REACHED(); 461 return E_NOTIMPL; 462} 463 464HRESULT 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 481HRESULT 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 499HRESULT 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 517JSGlobalContextRef 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 526JSGlobalContextRef 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 539HRESULT 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 556void 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 580HRESULT 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 604HRESULT 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 615void 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 622HRESULT STDMETHODCALLTYPE WebFrame::loadHTMLString( 623 /* [in] */ BSTR string, 624 /* [in] */ BSTR baseURL) 625{ 626 loadHTMLString(string, baseURL, 0); 627 return S_OK; 628} 629 630HRESULT 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 639HRESULT STDMETHODCALLTYPE WebFrame::loadArchive( 640 /* [in] */ IWebArchive* /*archive*/) 641{ 642 ASSERT_NOT_REACHED(); 643 return E_NOTIMPL; 644} 645 646static inline WebDataSource *getWebDataSource(DocumentLoader* loader) 647{ 648 return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0; 649} 650 651HRESULT 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 675HRESULT 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 699KURL WebFrame::url() const 700{ 701 Frame* coreFrame = core(this); 702 if (!coreFrame) 703 return KURL(); 704 705 return coreFrame->document()->url(); 706} 707 708HRESULT STDMETHODCALLTYPE WebFrame::stopLoading( void) 709{ 710 if (Frame* coreFrame = core(this)) 711 coreFrame->loader()->stopAllLoaders(); 712 return S_OK; 713} 714 715HRESULT 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 725HRESULT 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 751HRESULT 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 763class EnumChildFrames : public IEnumVARIANT 764{ 765public: 766 EnumChildFrames(Frame* f) : m_refCount(1), m_frame(f), m_curChild(f ? f->tree()->firstChild() : 0) { } 767 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 780 virtual ULONG STDMETHODCALLTYPE AddRef(void) 781 { 782 return ++m_refCount; 783 } 784 785 virtual ULONG STDMETHODCALLTYPE Release(void) 786 { 787 ULONG newRef = --m_refCount; 788 if (!newRef) 789 delete(this); 790 return newRef; 791 } 792 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 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 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 837 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**) 838 { 839 return E_NOTIMPL; 840 } 841 842private: 843 ULONG m_refCount; 844 Frame* m_frame; 845 Frame* m_curChild; 846}; 847 848HRESULT 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 860HRESULT 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 873HRESULT 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 892HRESULT 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 914HRESULT 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 930HRESULT 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 950HRESULT 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 964HRESULT 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 982HRESULT 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 1000HRESULT 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 1018HRESULT STDMETHODCALLTYPE WebFrame::unused2() 1019{ 1020 return E_NOTIMPL; 1021} 1022 1023HRESULT 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 1035HRESULT 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 1046HRESULT STDMETHODCALLTYPE WebFrame::supportsTextEncoding( 1047 /* [retval][out] */ BOOL* result) 1048{ 1049 *result = FALSE; 1050 return E_NOTIMPL; 1051} 1052 1053HRESULT 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 1068HRESULT 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 1080HRESULT STDMETHODCALLTYPE WebFrame::deselectAll() 1081{ 1082 return E_NOTIMPL; 1083} 1084 1085// WebFrame --------------------------------------------------------------- 1086 1087PassRefPtr<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 1101Frame* WebFrame::impl() 1102{ 1103 return d->frame; 1104} 1105 1106void 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 1115HRESULT 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 1132HRESULT 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 1142HRESULT 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 1165HRESULT 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 1182HRESULT 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 1197HRESULT 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 1220HRESULT 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 1243HRESULT 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 1271HRESULT 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 1289HRESULT 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 1308HRESULT 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 1318HRESULT 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 1328HRESULT 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 1344HRESULT 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 1359HRESULT 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 1387HRESULT WebFrame::elementIsPassword(IDOMElement *element, bool *result) 1388{ 1389 HTMLInputElement* inputElement = inputElementFromDOMElement(element); 1390 *result = inputElement && inputElement->isPasswordField(); 1391 return S_OK; 1392} 1393 1394HRESULT 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 1438HRESULT 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 1471HRESULT 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 1494HRESULT 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 1509void 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 1518void WebFrame::makeRepresentation(DocumentLoader*) 1519{ 1520 notImplemented(); 1521} 1522 1523void WebFrame::forceLayoutForNonHTML() 1524{ 1525 notImplemented(); 1526} 1527 1528void WebFrame::setCopiesOnScroll() 1529{ 1530 notImplemented(); 1531} 1532 1533void WebFrame::detachedFromParent2() 1534{ 1535 notImplemented(); 1536} 1537 1538void WebFrame::detachedFromParent3() 1539{ 1540 notImplemented(); 1541} 1542 1543void 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 1553void 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 1583void WebFrame::revertToProvisionalState(DocumentLoader*) 1584{ 1585 notImplemented(); 1586} 1587 1588void WebFrame::setMainFrameDocumentReady(bool) 1589{ 1590 notImplemented(); 1591} 1592 1593void WebFrame::willChangeTitle(DocumentLoader*) 1594{ 1595 notImplemented(); 1596} 1597 1598void WebFrame::didChangeTitle(DocumentLoader*) 1599{ 1600 notImplemented(); 1601} 1602 1603void WebFrame::didChangeIcons(DocumentLoader*) 1604{ 1605 notImplemented(); 1606} 1607 1608bool WebFrame::canHandleRequest(const ResourceRequest& request) const 1609{ 1610 return WebView::canHandleRequest(request); 1611} 1612 1613bool WebFrame::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const 1614{ 1615 notImplemented(); 1616 return true; 1617} 1618 1619bool WebFrame::canShowMIMEType(const String& /*MIMEType*/) const 1620{ 1621 notImplemented(); 1622 return true; 1623} 1624 1625bool WebFrame::representationExistsForURLScheme(const String& /*URLScheme*/) const 1626{ 1627 notImplemented(); 1628 return false; 1629} 1630 1631String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const 1632{ 1633 notImplemented(); 1634 ASSERT_NOT_REACHED(); 1635 return String(); 1636} 1637 1638void WebFrame::frameLoadCompleted() 1639{ 1640} 1641 1642void WebFrame::restoreViewState() 1643{ 1644} 1645 1646void WebFrame::provisionalLoadStarted() 1647{ 1648 notImplemented(); 1649} 1650 1651bool WebFrame::shouldTreatURLAsSameAsCurrent(const KURL&) const 1652{ 1653 notImplemented(); 1654 return false; 1655} 1656 1657void WebFrame::addHistoryItemForFragmentScroll() 1658{ 1659 notImplemented(); 1660} 1661 1662void WebFrame::didFinishLoad() 1663{ 1664 notImplemented(); 1665} 1666 1667void WebFrame::prepareForDataSourceReplacement() 1668{ 1669 notImplemented(); 1670} 1671 1672String WebFrame::userAgent(const KURL& url) 1673{ 1674 return d->webView->userAgentForKURL(url); 1675} 1676 1677void WebFrame::saveViewStateToItem(HistoryItem*) 1678{ 1679} 1680 1681ResourceError 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 1688ResourceError 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 1694ResourceError 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 1700ResourceError 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 1706ResourceError WebFrame::cannotShowMIMETypeError(const ResourceResponse&) 1707{ 1708 notImplemented(); 1709 return ResourceError(); 1710} 1711 1712ResourceError WebFrame::fileDoesNotExistError(const ResourceResponse&) 1713{ 1714 notImplemented(); 1715 return ResourceError(); 1716} 1717 1718ResourceError WebFrame::pluginWillHandleLoadError(const ResourceResponse& response) 1719{ 1720 return ResourceError(String(WebKitErrorDomain), WebKitErrorPlugInWillHandleLoad, response.url().string(), String()); 1721} 1722 1723bool 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 1734COMPtr<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 1750void 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 1766void 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 1783void 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 1801void 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 1819void 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 1829void 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 1848bool WebFrame::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/) 1849{ 1850 notImplemented(); 1851 return false; 1852} 1853 1854void 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 1864void 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 1874void WebFrame::startDownload(const ResourceRequest& request) 1875{ 1876 d->webView->downloadURL(request.url()); 1877} 1878 1879PassRefPtr<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 1901ObjectContentType WebFrame::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages) 1902{ 1903 return WebCore::FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages); 1904} 1905 1906String WebFrame::overrideMediaType() const 1907{ 1908 notImplemented(); 1909 return String(); 1910} 1911 1912void 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 1940void WebFrame::documentElementAvailable() 1941{ 1942} 1943 1944void 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 1965void WebFrame::registerForIconNotification(bool listen) 1966{ 1967 d->webView->registerForIconNotification(listen); 1968} 1969 1970static 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 1977void 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 1984HRESULT 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 2027void 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 2043IntRect 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 2063const 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 2090HRESULT 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) 2117void 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 2125void 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 2133void 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) 2171static 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 2188static HDC hdcFromContext(PlatformGraphicsContext* pctx) 2189{ 2190 return cairo_win32_surface_get_dc(cairo_get_target(pctx->cr())); 2191} 2192 2193void 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 2204void 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 2215static 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 2230void 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 2294static 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 2317HRESULT 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 2408HRESULT 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 2421HRESULT 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 2436HRESULT 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 2454HRESULT 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 2475HRESULT 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 2495HRESULT 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 2516HRESULT 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 2533HRESULT 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 2578void 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 2590void 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 2602WebView* WebFrame::webView() const 2603{ 2604 return d->webView; 2605} 2606 2607void WebFrame::setWebView(WebView* webView) 2608{ 2609 d->webView = webView; 2610} 2611 2612COMPtr<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 2630void 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 2641PassRefPtr<FrameNetworkingContext> WebFrame::createNetworkingContext() 2642{ 2643 return WebFrameNetworkingContext::create(core(this), userAgent(url())); 2644} 2645