diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/WebFrame.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/WebPage/WebFrame.cpp | 304 |
1 files changed, 193 insertions, 111 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp index 4b9845d86..30203c647 100644 --- a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp +++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,14 +28,20 @@ #include "APIArray.h" #include "DownloadManager.h" +#include "FrameInfoData.h" +#include "InjectedBundleFileHandle.h" #include "InjectedBundleHitTestResult.h" #include "InjectedBundleNodeHandle.h" #include "InjectedBundleRangeHandle.h" #include "InjectedBundleScriptWorld.h" +#include "NetworkConnectionToWebProcessMessages.h" +#include "NetworkProcessConnection.h" #include "PluginView.h" #include "WKAPICast.h" #include "WKBundleAPICast.h" #include "WebChromeClient.h" +#include "WebCoreArgumentCoders.h" +#include "WebDocumentLoader.h" #include "WebPage.h" #include "WebPageProxyMessages.h" #include "WebProcess.h" @@ -44,18 +50,24 @@ #include <JavaScriptCore/JSLock.h> #include <JavaScriptCore/JSValueRef.h> #include <WebCore/ArchiveResource.h> +#include <WebCore/CertificateInfo.h> #include <WebCore/Chrome.h> #include <WebCore/DocumentLoader.h> #include <WebCore/EventHandler.h> +#include <WebCore/File.h> #include <WebCore/Frame.h> +#include <WebCore/FrameSnapshotting.h> #include <WebCore/FrameView.h> #include <WebCore/HTMLFormElement.h> #include <WebCore/HTMLFrameOwnerElement.h> #include <WebCore/HTMLInputElement.h> #include <WebCore/HTMLNames.h> +#include <WebCore/HTMLSelectElement.h> #include <WebCore/HTMLTextAreaElement.h> +#include <WebCore/ImageBuffer.h> #include <WebCore/JSCSSStyleDeclaration.h> #include <WebCore/JSElement.h> +#include <WebCore/JSFile.h> #include <WebCore/JSRange.h> #include <WebCore/MainFrame.h> #include <WebCore/NetworkingContext.h> @@ -63,24 +75,17 @@ #include <WebCore/Page.h> #include <WebCore/PluginDocument.h> #include <WebCore/RenderTreeAsText.h> -#include <WebCore/ResourceBuffer.h> -#include <WebCore/ResourceLoader.h> #include <WebCore/ScriptController.h> #include <WebCore/SecurityOrigin.h> +#include <WebCore/SubresourceLoader.h> #include <WebCore/TextIterator.h> #include <WebCore/TextResourceDecoder.h> #include <wtf/text/StringBuilder.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <WebCore/LegacyWebArchive.h> #endif -#if ENABLE(NETWORK_PROCESS) -#include "NetworkConnectionToWebProcessMessages.h" -#include "NetworkProcessConnection.h" -#include "WebCoreArgumentCoders.h" -#endif - #ifndef NDEBUG #include <wtf/RefCountedLeakCounter.h> #endif @@ -104,54 +109,51 @@ static uint64_t generateListenerID() return uniqueListenerID++; } -PassRefPtr<WebFrame> WebFrame::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame) +Ref<WebFrame> WebFrame::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame) { - RefPtr<WebFrame> frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client()))); - page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID())); + auto frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client()))); + page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()), page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply); frame->m_coreFrame = coreFrame; frame->m_coreFrame->tree().setName(String()); frame->m_coreFrame->init(); - return frame.release(); + return frame; } -PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement) +Ref<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement) { - RefPtr<WebFrame> frame = create(std::make_unique<WebFrameLoaderClient>()); - page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID())); + auto frame = create(std::make_unique<WebFrameLoaderClient>()); + page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()), page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply); + + auto coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get()); + frame->m_coreFrame = coreFrame.ptr(); - RefPtr<Frame> coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get()); - frame->m_coreFrame = coreFrame.get(); - frame->m_coreFrame->tree().setName(frameName); + coreFrame->tree().setName(frameName); if (ownerElement) { ASSERT(ownerElement->document().frame()); - ownerElement->document().frame()->tree().appendChild(coreFrame.release()); + ownerElement->document().frame()->tree().appendChild(coreFrame.get()); } - frame->m_coreFrame->init(); - return frame.release(); + coreFrame->init(); + + return frame; } -PassRefPtr<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient) +Ref<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient) { - RefPtr<WebFrame> frame = adoptRef(new WebFrame(std::move(frameLoaderClient))); + auto frame = adoptRef(*new WebFrame(WTFMove(frameLoaderClient))); // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed(). frame->ref(); - return frame.release(); + return frame; } WebFrame::WebFrame(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient) - : m_coreFrame(0) - , m_policyListenerID(0) - , m_policyFunction(0) - , m_policyDownloadID(0) - , m_frameLoaderClient(std::move(frameLoaderClient)) - , m_loadListener(0) + : m_frameLoaderClient(WTFMove(frameLoaderClient)) , m_frameID(generateFrameID()) { m_frameLoaderClient->setWebFrame(this); - WebProcess::shared().addWebFrame(m_frameID, this); + WebProcess::singleton().addWebFrame(m_frameID, this); #ifndef NDEBUG webFrameCounter.increment(); @@ -178,9 +180,31 @@ WebPage* WebFrame::page() const return 0; } +WebFrame* WebFrame::fromCoreFrame(Frame& frame) +{ + auto* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client()); + if (!webFrameLoaderClient) + return nullptr; + + return webFrameLoaderClient->webFrame(); +} + +FrameInfoData WebFrame::info() const +{ + FrameInfoData info; + + info.isMainFrame = isMainFrame(); + // FIXME: This should use the full request. + info.request = ResourceRequest(URL(URL(), url())); + info.securityOrigin = SecurityOriginData::fromFrame(m_coreFrame); + info.frameID = m_frameID; + + return info; +} + void WebFrame::invalidate() { - WebProcess::shared().removeWebFrame(m_frameID); + WebProcess::singleton().removeWebFrame(m_frameID); m_coreFrame = 0; } @@ -200,12 +224,12 @@ void WebFrame::invalidatePolicyListener() if (!m_policyListenerID) return; - m_policyDownloadID = 0; + m_policyDownloadID = { }; m_policyListenerID = 0; m_policyFunction = 0; } -void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t downloadID) +void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t navigationID, DownloadID downloadID) { if (!m_coreFrame) return; @@ -218,65 +242,54 @@ void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action ASSERT(m_policyFunction); - FramePolicyFunction function = std::move(m_policyFunction); + FramePolicyFunction function = WTFMove(m_policyFunction); invalidatePolicyListener(); m_policyDownloadID = downloadID; + if (navigationID) { + if (WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(m_coreFrame->loader().policyDocumentLoader())) + documentLoader->setNavigationID(navigationID); + } + function(action); } -void WebFrame::startDownload(const WebCore::ResourceRequest& request) +void WebFrame::startDownload(const WebCore::ResourceRequest& request, const String& suggestedName) { - ASSERT(m_policyDownloadID); - - uint64_t policyDownloadID = m_policyDownloadID; - m_policyDownloadID = 0; + ASSERT(m_policyDownloadID.downloadID()); -#if ENABLE(NETWORK_PROCESS) - if (WebProcess::shared().usesNetworkProcess()) { - WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::StartDownload(page()->sessionID(), policyDownloadID, request), 0); - return; - } -#endif + auto policyDownloadID = m_policyDownloadID; + m_policyDownloadID = { }; - WebProcess::shared().downloadManager().startDownload(policyDownloadID, request); + auto& webProcess = WebProcess::singleton(); + SessionID sessionID = page() ? page()->sessionID() : SessionID::defaultSessionID(); + webProcess.networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::StartDownload(sessionID, policyDownloadID, request, suggestedName), 0); } -void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response) +void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response) { - ASSERT(m_policyDownloadID); - - uint64_t policyDownloadID = m_policyDownloadID; - m_policyDownloadID = 0; + ASSERT(m_policyDownloadID.downloadID()); - ResourceLoader* mainResourceLoader = documentLoader->mainResourceLoader(); + auto policyDownloadID = m_policyDownloadID; + m_policyDownloadID = { }; -#if ENABLE(NETWORK_PROCESS) - if (WebProcess::shared().usesNetworkProcess()) { - // Use 0 to indicate that there is no main resource loader. - // This can happen if the main resource is in the WebCore memory cache. - uint64_t mainResourceLoadIdentifier; - if (mainResourceLoader) - mainResourceLoadIdentifier = mainResourceLoader->identifier(); - else - mainResourceLoadIdentifier = 0; + SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader(); - WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(mainResourceLoadIdentifier, policyDownloadID, request, response), 0); - return; - } -#endif - - if (!mainResourceLoader) { - // The main resource has already been loaded. Start a new download instead. - WebProcess::shared().downloadManager().startDownload(policyDownloadID, request); - return; - } + auto& webProcess = WebProcess::singleton(); + // Use 0 to indicate that the resource load can't be converted and a new download must be started. + // This can happen if there is no loader because the main resource is in the WebCore memory cache, + // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse(). + uint64_t mainResourceLoadIdentifier; + if (mainResourceLoader) + mainResourceLoadIdentifier = mainResourceLoader->identifier(); + else + mainResourceLoadIdentifier = 0; - WebProcess::shared().downloadManager().convertHandleToDownload(policyDownloadID, documentLoader->mainResourceLoader()->handle(), request, response); + webProcess.networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(sessionID, mainResourceLoadIdentifier, policyDownloadID, request, response), 0); } -String WebFrame::source() const +String WebFrame::source() const { if (!m_coreFrame) return String(); @@ -289,7 +302,7 @@ String WebFrame::source() const DocumentLoader* documentLoader = m_coreFrame->loader().activeDocumentLoader(); if (!documentLoader) return String(); - RefPtr<ResourceBuffer> mainResourceData = documentLoader->mainResourceData(); + RefPtr<SharedBuffer> mainResourceData = documentLoader->mainResourceData(); if (!mainResourceData) return String(); return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size()); @@ -306,8 +319,7 @@ String WebFrame::contentsAsString() const if (!builder.isEmpty()) builder.append(' '); - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(child->loader().client()); - WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + WebFrame* webFrame = WebFrame::fromCoreFrame(*child); ASSERT(webFrame); builder.append(webFrame->contentsAsString()); @@ -326,9 +338,7 @@ String WebFrame::contentsAsString() const RefPtr<Range> range = document->createRange(); - ExceptionCode ec = 0; - range->selectNode(documentElement.get(), ec); - if (ec) + if (range->selectNode(*documentElement).hasException()) return String(); return plainText(range.get()); @@ -393,6 +403,18 @@ String WebFrame::url() const return documentLoader->url().string(); } +CertificateInfo WebFrame::certificateInfo() const +{ + if (!m_coreFrame) + return { }; + + DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader(); + if (!documentLoader) + return { }; + + return valueOrCompute(documentLoader->response().certificateInfo(), [] { return CertificateInfo(); }); +} + String WebFrame::innerText() const { if (!m_coreFrame) @@ -409,11 +431,10 @@ WebFrame* WebFrame::parentFrame() const if (!m_coreFrame || !m_coreFrame->ownerElement()) return 0; - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(m_coreFrame->ownerElement()->document().frame()->loader().client()); - return webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + return WebFrame::fromCoreFrame(*m_coreFrame->ownerElement()->document().frame()); } -PassRefPtr<API::Array> WebFrame::childFrames() +Ref<API::Array> WebFrame::childFrames() { if (!m_coreFrame) return API::Array::create(); @@ -426,13 +447,12 @@ PassRefPtr<API::Array> WebFrame::childFrames() vector.reserveInitialCapacity(size); for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) { - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(child->loader().client()); - WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + WebFrame* webFrame = WebFrame::fromCoreFrame(*child); ASSERT(webFrame); vector.uncheckedAppend(webFrame); } - return API::Array::create(std::move(vector)); + return API::Array::create(WTFMove(vector)); } String WebFrame::layerTreeAsText() const @@ -456,7 +476,7 @@ bool WebFrame::allowsFollowingLink(const WebCore::URL& url) const if (!m_coreFrame) return true; - return m_coreFrame->document()->securityOrigin()->canDisplay(url); + return m_coreFrame->document()->securityOrigin().canDisplay(url); } JSGlobalContextRef WebFrame::jsContext() @@ -479,6 +499,35 @@ bool WebFrame::handlesPageScaleGesture() const return pluginView && pluginView->handlesPageScaleFactor(); } +bool WebFrame::requiresUnifiedScaleFactor() const +{ + if (!m_coreFrame->document()->isPluginDocument()) + return 0; + + PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document()); + PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget()); + return pluginView && pluginView->requiresUnifiedScaleFactor(); +} + +void WebFrame::setAccessibleName(const String& accessibleName) +{ + if (!AXObjectCache::accessibilityEnabled()) + return; + + if (!m_coreFrame) + return; + + auto* document = m_coreFrame->document(); + if (!document) + return; + + auto* rootObject = document->axObjectCache()->rootObject(); + if (!rootObject) + return; + + rootObject->setAccessibleName(accessibleName); +} + IntRect WebFrame::contentBounds() const { if (!m_coreFrame) @@ -526,7 +575,7 @@ IntSize WebFrame::scrollOffset() const if (!view) return IntSize(); - return view->scrollOffset(); + return toIntSize(view->scrollPosition()); } bool WebFrame::hasHorizontalScrollbar() const @@ -558,7 +607,7 @@ PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point) if (!m_coreFrame) return 0; - return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent)); + return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent)); } bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha) @@ -587,10 +636,10 @@ bool WebFrame::containsAnyFormElements() const if (!document) return false; - for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) { - if (!node->isElementNode()) + for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) { + if (!is<Element>(*node)) continue; - if (isHTMLFormElement(node)) + if (is<HTMLFormElement>(*node)) return true; } return false; @@ -605,10 +654,10 @@ bool WebFrame::containsAnyFormControls() const if (!document) return false; - for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) { - if (!node->isElementNode()) + for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) { + if (!is<Element>(*node)) continue; - if (isHTMLInputElement(node) || isHTMLSelectElement(node) || isHTMLTextAreaElement(node)) + if (is<HTMLInputElement>(*node) || is<HTMLSelectElement>(*node) || is<HTMLTextAreaElement>(*node)) return true; } return false; @@ -624,15 +673,12 @@ void WebFrame::stopLoading() WebFrame* WebFrame::frameForContext(JSContextRef context) { - JSObjectRef globalObjectRef = JSContextGetGlobalObject(context); - JSC::JSObject* globalObjectObj = toJS(globalObjectRef); - if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0) - return 0; - Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl().frame(); - - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(coreFrame->loader().client()); - return webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + JSC::JSGlobalObject* globalObjectObj = toJS(context)->lexicalGlobalObject(); + JSDOMWindow* window = jsDynamicDowncast<JSDOMWindow*>(globalObjectObj->vm(), globalObjectObj); + if (!window) + return nullptr; + return WebFrame::fromCoreFrame(*(window->wrapped().frame())); } JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world) @@ -659,12 +705,24 @@ JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, I return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange())); } +JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleFileHandle* fileHandle, InjectedBundleScriptWorld* world) +{ + if (!m_coreFrame) + return nullptr; + + JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld()); + ExecState* exec = globalObject->globalExec(); + + JSLockHolder lock(exec); + return toRef(exec, toJS(exec, globalObject, fileHandle->coreFile())); +} + String WebFrame::counterValue(JSObjectRef element) { - if (!toJS(element)->inherits(JSElement::info())) + if (!toJS(element)->inherits(*toJS(element)->vm(), JSElement::info())) return String(); - return counterValueForElement(&jsCast<JSElement*>(toJS(element))->impl()); + return counterValueForElement(&jsCast<JSElement*>(toJS(element))->wrapped()); } String WebFrame::provisionalURL() const @@ -734,15 +792,19 @@ void WebFrame::setTextDirection(const String& direction) m_coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection); } -#if PLATFORM(MAC) +void WebFrame::documentLoaderDetached(uint64_t navigationID) +{ + page()->send(Messages::WebPageProxy::DidDestroyNavigation(navigationID)); +} + +#if PLATFORM(COCOA) RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context) { - RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document(), [this, callback, context](Frame& frame) -> bool { + RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(*coreFrame()->document(), [this, callback, context](Frame& frame) -> bool { if (!callback) return true; - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client()); - WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + WebFrame* webFrame = WebFrame::fromCoreFrame(frame); ASSERT(webFrame); return callback(toAPI(this), toAPI(webFrame), context); @@ -754,5 +816,25 @@ RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void return archive->rawDataRepresentation(); } #endif + +PassRefPtr<ShareableBitmap> WebFrame::createSelectionSnapshot() const +{ + std::unique_ptr<ImageBuffer> snapshot = snapshotSelection(*coreFrame(), WebCore::SnapshotOptionsForceBlackText); + if (!snapshot) + return nullptr; + + auto sharedSnapshot = ShareableBitmap::createShareable(snapshot->internalSize(), ShareableBitmap::SupportsAlpha); + if (!sharedSnapshot) + return nullptr; + + // FIXME: We should consider providing a way to use subpixel antialiasing for the snapshot + // if we're compositing this image onto a solid color (e.g. the modern find indicator style). + auto graphicsContext = sharedSnapshot->createGraphicsContext(); + float deviceScaleFactor = coreFrame()->page()->deviceScaleFactor(); + graphicsContext->scale(deviceScaleFactor); + graphicsContext->drawConsumingImageBuffer(WTFMove(snapshot), FloatPoint()); + + return WTFMove(sharedSnapshot); +} } // namespace WebKit |