📄 webframe.cpp
字号:
/* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "WebKitDLL.h"#include "WebFrame.h"#include "CFDictionaryPropertyBag.h"#include "COMPtr.h"#include "COMPropertyBag.h"#include "DefaultPolicyDelegate.h"#include "DOMCoreClasses.h"#include "HTMLFrameOwnerElement.h"#include "MarshallingHelpers.h"#include "WebActionPropertyBag.h"#include "WebChromeClient.h"#include "WebDocumentLoader.h"#include "WebDownload.h"#include "WebError.h"#include "WebMutableURLRequest.h"#include "WebEditorClient.h"#include "WebFramePolicyListener.h"#include "WebHistory.h"#include "WebIconFetcher.h"#include "WebKit.h"#include "WebKitStatisticsPrivate.h"#include "WebNotificationCenter.h"#include "WebView.h"#include "WebDataSource.h"#include "WebHistoryItem.h"#include "WebURLResponse.h"#pragma warning( push, 0 )#include <WebCore/BString.h>#include <WebCore/Cache.h>#include <WebCore/Document.h>#include <WebCore/DocumentLoader.h>#include <WebCore/DOMImplementation.h>#include <WebCore/DOMWindow.h>#include <WebCore/Event.h>#include <WebCore/EventHandler.h>#include <WebCore/FormState.h>#include <WebCore/FrameLoader.h>#include <WebCore/FrameLoadRequest.h>#include <WebCore/FrameTree.h>#include <WebCore/FrameView.h>#include <WebCore/FrameWin.h>#include <WebCore/GDIObjectCounter.h>#include <WebCore/GraphicsContext.h>#include <WebCore/HistoryItem.h>#include <WebCore/HTMLAppletElement.h>#include <WebCore/HTMLFormElement.h>#include <WebCore/HTMLFormControlElement.h>#include <WebCore/HTMLInputElement.h>#include <WebCore/HTMLNames.h>#include <WebCore/HTMLPlugInElement.h>#include <WebCore/JSDOMWindow.h>#include <WebCore/KeyboardEvent.h>#include <WebCore/MIMETypeRegistry.h>#include <WebCore/MouseRelatedEvent.h>#include <WebCore/NotImplemented.h>#include <WebCore/Page.h>#include <WebCore/PlatformKeyboardEvent.h>#include <WebCore/PluginInfoStore.h>#include <WebCore/PluginDatabase.h>#include <WebCore/PluginView.h>#include <WebCore/ResourceHandle.h>#include <WebCore/ResourceHandleWin.h>#include <WebCore/ResourceRequest.h>#include <WebCore/RenderView.h>#include <WebCore/RenderTreeAsText.h>#include <WebCore/Settings.h>#include <WebCore/TextIterator.h>#include <WebCore/JSDOMBinding.h>#include <WebCore/ScriptController.h>#include <JavaScriptCore/APICast.h>#include <wtf/MathExtras.h>#pragma warning(pop)#include <CoreGraphics/CoreGraphics.h>// CG SPI used for printingextern "C" { CGAffineTransform CGContextGetBaseCTM(CGContextRef c); void CGContextSetBaseCTM(CGContextRef c, CGAffineTransform m); }using namespace WebCore;using namespace HTMLNames;#define FLASH_REDRAW 0// By imaging to a width a little wider than the available pixels,// thin pages will be scaled down a little, matching the way they// print in IE and Camino. This lets them use fewer sheets than they// would otherwise, which is presumably why other browsers do this.// Wide pages will be scaled down more than this.const float PrintingMinimumShrinkFactor = 1.25f;// This number determines how small we are willing to reduce the page content// in order to accommodate the widest line. If the page would have to be// reduced smaller to make the widest line fit, we just clip instead (this// behavior matches MacIE and Mozilla, at least)const float PrintingMaximumShrinkFactor = 2.0f;//-----------------------------------------------------------------------------// Helpers to convert from WebCore to WebKit typeWebFrame* kit(Frame* frame){ if (!frame) return 0; FrameLoaderClient* frameLoaderClient = frame->loader()->client(); if (frameLoaderClient) return static_cast<WebFrame*>(frameLoaderClient); // eek, is there a better way than static cast? return 0;}Frame* core(WebFrame* webFrame){ if (!webFrame) return 0; return webFrame->impl();}// 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 WebFrameFrame* core(const WebFrame* webFrame){ if (!webFrame) return 0; return const_cast<WebFrame*>(webFrame)->impl();}//-----------------------------------------------------------------------------static Element *elementFromDOMElement(IDOMElement *element){ if (!element) return 0; COMPtr<IDOMElementPrivate> elePriv; HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv); if (SUCCEEDED(hr)) { Element* ele; hr = elePriv->coreElement((void**)&ele); if (SUCCEEDED(hr)) return ele; } return 0;}static HTMLFormElement *formElementFromDOMElement(IDOMElement *element){ if (!element) return 0; IDOMElementPrivate* elePriv; HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv); if (SUCCEEDED(hr)) { Element* ele; hr = elePriv->coreElement((void**)&ele); elePriv->Release(); if (SUCCEEDED(hr) && ele && ele->hasTagName(formTag)) return static_cast<HTMLFormElement*>(ele); } return 0;}static HTMLInputElement* inputElementFromDOMElement(IDOMElement* element){ if (!element) return 0; IDOMElementPrivate* elePriv; HRESULT hr = element->QueryInterface(IID_IDOMElementPrivate, (void**) &elePriv); if (SUCCEEDED(hr)) { Element* ele; hr = elePriv->coreElement((void**)&ele); elePriv->Release(); if (SUCCEEDED(hr) && ele && ele->hasTagName(inputTag)) return static_cast<HTMLInputElement*>(ele); } return 0;}// WebFramePrivate ------------------------------------------------------------class WebFrame::WebFramePrivate {public: WebFramePrivate() : frame(0) , webView(0) , m_policyFunction(0) { } ~WebFramePrivate() { } FrameView* frameView() { return frame ? frame->view() : 0; } Frame* frame; WebView* webView; FramePolicyFunction m_policyFunction; COMPtr<WebFramePolicyListener> m_policyListener;};// WebFrame ----------------------------------------------------------------WebFrame::WebFrame() : WebFrameLoaderClient(this) , m_refCount(0) , d(new WebFrame::WebFramePrivate) , m_quickRedirectComing(false) , m_inPrintingMode(false) , m_pageHeight(0){ WebFrameCount++; gClassCount++; gClassNameCount.add("WebFrame");}WebFrame::~WebFrame(){ delete d; WebFrameCount--; gClassCount--; gClassNameCount.remove("WebFrame");}WebFrame* WebFrame::createInstance(){ WebFrame* instance = new WebFrame(); instance->AddRef(); return instance;}HRESULT STDMETHODCALLTYPE WebFrame::setAllowsScrolling( /* [in] */ BOOL flag){ if (Frame* frame = core(this)) if (FrameView* view = frame->view()) view->setCanHaveScrollbars(!!flag); return S_OK;}HRESULT STDMETHODCALLTYPE WebFrame::allowsScrolling( /* [retval][out] */ BOOL *flag){ if (flag) if (Frame* frame = core(this)) if (FrameView* view = frame->view()) *flag = view->canHaveScrollbars(); return S_OK;}HRESULT STDMETHODCALLTYPE WebFrame::setIsDisconnected( /* [in] */ BOOL flag){ if (Frame* frame = core(this)) { frame->setIsDisconnected(flag); return S_OK; } return E_FAIL;}HRESULT STDMETHODCALLTYPE WebFrame::setExcludeFromTextSearch( /* [in] */ BOOL flag){ if (Frame* frame = core(this)) { frame->setExcludeFromTextSearch(flag); return S_OK; } return E_FAIL;}HRESULT STDMETHODCALLTYPE WebFrame::paintDocumentRectToContext( /* [in] */ RECT rect, /* [in] */ OLE_HANDLE deviceContext){ Frame* coreFrame = core(this); if (!coreFrame) return E_FAIL; FrameView* view = coreFrame->view(); if (!view) return E_FAIL; // We can't paint with a layout still pending. view->layoutIfNeededRecursive(); HDC dc = (HDC)(ULONG64)deviceContext; GraphicsContext gc(dc); gc.setShouldIncludeChildWindows(true); gc.save(); LONG width = rect.right - rect.left; LONG height = rect.bottom - rect.top; FloatRect dirtyRect; dirtyRect.setWidth(width); dirtyRect.setHeight(height); gc.clip(dirtyRect); gc.translate(-rect.left, -rect.top); view->paintContents(&gc, rect); gc.restore(); return S_OK;}// IUnknown -------------------------------------------------------------------HRESULT STDMETHODCALLTYPE WebFrame::QueryInterface(REFIID riid, void** ppvObject){ *ppvObject = 0; if (IsEqualGUID(riid, __uuidof(WebFrame))) *ppvObject = this; else if (IsEqualGUID(riid, IID_IUnknown)) *ppvObject = static_cast<IWebFrame*>(this); else if (IsEqualGUID(riid, IID_IWebFrame)) *ppvObject = static_cast<IWebFrame*>(this); else if (IsEqualGUID(riid, IID_IWebFramePrivate)) *ppvObject = static_cast<IWebFramePrivate*>(this); else if (IsEqualGUID(riid, IID_IWebDocumentText)) *ppvObject = static_cast<IWebDocumentText*>(this); else return E_NOINTERFACE; AddRef(); return S_OK;}ULONG STDMETHODCALLTYPE WebFrame::AddRef(void){ return ++m_refCount;}ULONG STDMETHODCALLTYPE WebFrame::Release(void){ ULONG newRef = --m_refCount; if (!newRef) delete(this); return newRef;}// IWebFrame -------------------------------------------------------------------HRESULT STDMETHODCALLTYPE WebFrame::name( /* [retval][out] */ BSTR* frameName){ if (!frameName) { ASSERT_NOT_REACHED(); return E_POINTER; } *frameName = 0; Frame* coreFrame = core(this); if (!coreFrame) return E_FAIL; *frameName = BString(coreFrame->tree()->name()).release(); return S_OK;}HRESULT STDMETHODCALLTYPE WebFrame::webView( /* [retval][out] */ IWebView** view){ *view = 0; if (!d->webView) return E_FAIL; *view = d->webView; (*view)->AddRef(); return S_OK;}HRESULT STDMETHODCALLTYPE WebFrame::frameView( /* [retval][out] */ IWebFrameView** /*view*/){ ASSERT_NOT_REACHED(); return E_NOTIMPL;}HRESULT STDMETHODCALLTYPE WebFrame::DOMDocument( /* [retval][out] */ IDOMDocument** result){ if (!result) { ASSERT_NOT_REACHED(); return E_POINTER; } *result = 0; if (Frame* coreFrame = core(this)) if (Document* document = coreFrame->document()) *result = DOMDocument::createInstance(document); return *result ? S_OK : E_FAIL;}HRESULT STDMETHODCALLTYPE WebFrame::frameElement( /* [retval][out] */ IDOMHTMLElement** frameElement){ if (!frameElement) return E_POINTER; *frameElement = 0; Frame* coreFrame = core(this); if (!coreFrame) return E_FAIL; COMPtr<IDOMElement> domElement(AdoptCOM, DOMElement::createInstance(coreFrame->ownerElement())); COMPtr<IDOMHTMLElement> htmlElement(Query, domElement); if (!htmlElement) return E_FAIL; return htmlElement.copyRefTo(frameElement);}HRESULT STDMETHODCALLTYPE WebFrame::currentForm( /* [retval][out] */ IDOMElement **currentForm){ if (!currentForm) { ASSERT_NOT_REACHED(); return E_POINTER; } *currentForm = 0; if (Frame* coreFrame = core(this)) if (HTMLFormElement* formElement = coreFrame->currentForm()) *currentForm = DOMElement::createInstance(formElement); return *currentForm ? S_OK : E_FAIL;}JSGlobalContextRef STDMETHODCALLTYPE WebFrame::globalContext(){ Frame* coreFrame = core(this); if (!coreFrame) return 0; return toGlobalRef(coreFrame->script()->globalObject()->globalExec());}HRESULT STDMETHODCALLTYPE WebFrame::loadRequest( /* [in] */ IWebURLRequest* request){ COMPtr<WebMutableURLRequest> requestImpl; HRESULT hr = request->QueryInterface(&requestImpl); if (FAILED(hr)) return hr; Frame* coreFrame = core(this); if (!coreFrame) return E_FAIL; coreFrame->loader()->load(requestImpl->resourceRequest(), false); return S_OK;}void WebFrame::loadData(PassRefPtr<WebCore::SharedBuffer> data, BSTR mimeType, BSTR textEncodingName, BSTR baseURL, BSTR failingURL){ String mimeTypeString(mimeType, SysStringLen(mimeType)); if (!mimeType) mimeTypeString = "text/html"; String encodingString(textEncodingName, SysStringLen(textEncodingName)); // FIXME: We should really be using MarshallingHelpers::BSTRToKURL here, // but that would turn a null BSTR into a null KURL, and we crash inside of // WebCore if we use a null KURL in constructing the ResourceRequest. KURL baseKURL = KURL(KURL(), String(baseURL ? baseURL : L"", SysStringLen(baseURL))); KURL failingKURL = MarshallingHelpers::BSTRToKURL(failingURL); ResourceRequest request(baseKURL); SubstituteData substituteData(data, mimeTypeString, encodingString, failingKURL); // This method is only called from IWebFrame methods, so don't ASSERT that the Frame pointer isn't null. if (Frame* coreFrame = core(this)) coreFrame->loader()->load(request, substituteData, false);}HRESULT STDMETHODCALLTYPE WebFrame::loadData( /* [in] */ IStream* data, /* [in] */ BSTR mimeType, /* [in] */ BSTR textEncodingName, /* [in] */ BSTR url){ RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(); STATSTG stat; if (SUCCEEDED(data->Stat(&stat, STATFLAG_NONAME))) { if (!stat.cbSize.HighPart && stat.cbSize.LowPart) { Vector<char> dataBuffer(stat.cbSize.LowPart); ULONG read; // FIXME: this does a needless copy, would be better to read right into the SharedBuffer // or adopt the Vector or something. if (SUCCEEDED(data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read))) sharedBuffer->append(dataBuffer.data(), static_cast<int>(dataBuffer.size())); } } loadData(sharedBuffer, mimeType, textEncodingName, url, 0); return S_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -