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