diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/Plugins/PluginView.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/Plugins/PluginView.cpp | 501 |
1 files changed, 300 insertions, 201 deletions
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp index 00cb367f5..6efd32ce9 100644 --- a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp +++ b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2012, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +31,7 @@ #include "ShareableBitmap.h" #include "WebCoreArgumentCoders.h" #include "WebEvent.h" +#include "WebLoaderStrategy.h" #include "WebPage.h" #include "WebPageProxyMessages.h" #include "WebProcess.h" @@ -41,6 +42,7 @@ #include <WebCore/CredentialStorage.h> #include <WebCore/DocumentLoader.h> #include <WebCore/EventHandler.h> +#include <WebCore/EventNames.h> #include <WebCore/FocusController.h> #include <WebCore/FrameLoadRequest.h> #include <WebCore/FrameLoader.h> @@ -49,6 +51,7 @@ #include <WebCore/GraphicsContext.h> #include <WebCore/HTMLPlugInElement.h> #include <WebCore/HTMLPlugInImageElement.h> +#include <WebCore/HTTPHeaderNames.h> #include <WebCore/HostWindow.h> #include <WebCore/MIMETypeRegistry.h> #include <WebCore/MainFrame.h> @@ -56,12 +59,10 @@ #include <WebCore/NetscapePlugInStreamLoader.h> #include <WebCore/NetworkingContext.h> #include <WebCore/Page.h> -#include <WebCore/PageThrottler.h> #include <WebCore/PlatformMouseEvent.h> #include <WebCore/ProtectionSpace.h> #include <WebCore/ProxyServer.h> #include <WebCore/RenderEmbeddedObject.h> -#include <WebCore/ResourceLoadScheduler.h> #include <WebCore/ScriptController.h> #include <WebCore/ScrollView.h> #include <WebCore/SecurityOrigin.h> @@ -71,19 +72,23 @@ #include <bindings/ScriptValue.h> #include <wtf/text/StringBuilder.h> +#if PLUGIN_ARCHITECTURE(X11) +#include <WebCore/PlatformDisplay.h> +#endif + using namespace JSC; using namespace WebCore; namespace WebKit { // This simulated mouse click delay in HTMLPlugInImageElement.cpp should generally be the same or shorter than this delay. -static const double pluginSnapshotTimerDelay = 1.1; +static const auto pluginSnapshotTimerDelay = std::chrono::milliseconds { 1100 }; class PluginView::URLRequest : public RefCounted<URLRequest> { public: - static PassRefPtr<PluginView::URLRequest> create(uint64_t requestID, const FrameLoadRequest& request, bool allowPopups) + static Ref<PluginView::URLRequest> create(uint64_t requestID, const FrameLoadRequest& request, bool allowPopups) { - return adoptRef(new URLRequest(requestID, request, allowPopups)); + return adoptRef(*new URLRequest(requestID, request, allowPopups)); } uint64_t requestID() const { return m_requestID; } @@ -106,14 +111,15 @@ private: class PluginView::Stream : public RefCounted<PluginView::Stream>, NetscapePlugInStreamLoaderClient { public: - static PassRefPtr<Stream> create(PluginView* pluginView, uint64_t streamID, const ResourceRequest& request) + static Ref<Stream> create(PluginView* pluginView, uint64_t streamID, const ResourceRequest& request) { - return adoptRef(new Stream(pluginView, streamID, request)); + return adoptRef(*new Stream(pluginView, streamID, request)); } ~Stream(); void start(); void cancel(); + void continueLoad(); uint64_t streamID() const { return m_streamID; } @@ -127,15 +133,17 @@ private: } // NetscapePluginStreamLoaderClient - virtual void didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse&); - virtual void didReceiveData(NetscapePlugInStreamLoader*, const char*, int); - virtual void didFail(NetscapePlugInStreamLoader*, const ResourceError&); - virtual void didFinishLoading(NetscapePlugInStreamLoader*); + void willSendRequest(NetscapePlugInStreamLoader*, ResourceRequest&&, const ResourceResponse& redirectResponse, std::function<void (ResourceRequest&&)>&&) override; + void didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse&) override; + void didReceiveData(NetscapePlugInStreamLoader*, const char*, int) override; + void didFail(NetscapePlugInStreamLoader*, const ResourceError&) override; + void didFinishLoading(NetscapePlugInStreamLoader*) override; PluginView* m_pluginView; uint64_t m_streamID; - const ResourceRequest m_request; - + ResourceRequest m_request; + std::function<void (ResourceRequest)> m_loadCallback; + // True if the stream was explicitly cancelled by calling cancel(). // (As opposed to being cancelled by the user hitting the stop button for example. bool m_streamWasCancelled; @@ -156,7 +164,7 @@ void PluginView::Stream::start() Frame* frame = m_pluginView->m_pluginElement->document().frame(); ASSERT(frame); - m_loader = resourceLoadScheduler()->schedulePluginStreamLoad(frame, this, m_request); + m_loader = WebProcess::singleton().webLoaderStrategy().schedulePluginStreamLoad(*frame, *this, m_request); } void PluginView::Stream::cancel() @@ -165,7 +173,15 @@ void PluginView::Stream::cancel() m_streamWasCancelled = true; m_loader->cancel(m_loader->cancelledError()); - m_loader = 0; + m_loader = nullptr; +} + +void PluginView::Stream::continueLoad() +{ + ASSERT(m_pluginView->m_plugin); + ASSERT(m_loadCallback); + + m_loadCallback(m_request); } static String buildHTTPHeaders(const ResourceResponse& response, long long& expectedContentLength) @@ -173,40 +189,46 @@ static String buildHTTPHeaders(const ResourceResponse& response, long long& expe if (!response.isHTTP()) return String(); - StringBuilder stringBuilder; - - String statusLine = String::format("HTTP %d ", response.httpStatusCode()); - stringBuilder.append(statusLine); - stringBuilder.append(response.httpStatusText()); - stringBuilder.append('\n'); - - HTTPHeaderMap::const_iterator end = response.httpHeaderFields().end(); - for (HTTPHeaderMap::const_iterator it = response.httpHeaderFields().begin(); it != end; ++it) { - stringBuilder.append(it->key); - stringBuilder.appendLiteral(": "); - stringBuilder.append(it->value); - stringBuilder.append('\n'); + StringBuilder header; + header.appendLiteral("HTTP "); + header.appendNumber(response.httpStatusCode()); + header.append(' '); + header.append(response.httpStatusText()); + header.append('\n'); + for (auto& field : response.httpHeaderFields()) { + header.append(field.key); + header.appendLiteral(": "); + header.append(field.value); + header.append('\n'); } - - String headers = stringBuilder.toString(); - + // If the content is encoded (most likely compressed), then don't send its length to the plugin, // which is only interested in the decoded length, not yet known at the moment. // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic. - String contentEncoding = response.httpHeaderField("Content-Encoding"); + String contentEncoding = response.httpHeaderField(HTTPHeaderName::ContentEncoding); if (!contentEncoding.isNull() && contentEncoding != "identity") expectedContentLength = -1; - return headers; + return header.toString(); } -static uint32_t lastModifiedDate(const ResourceResponse& response) +static uint32_t lastModifiedDateMS(const ResourceResponse& response) { - double lastModified = response.lastModified(); - if (!std::isfinite(lastModified)) + auto lastModified = response.lastModified(); + if (!lastModified) return 0; - return lastModified * 1000; + return std::chrono::duration_cast<std::chrono::milliseconds>(lastModified.value().time_since_epoch()).count(); +} + +void PluginView::Stream::willSendRequest(NetscapePlugInStreamLoader*, ResourceRequest&& request, const ResourceResponse& redirectResponse, std::function<void (ResourceRequest&&)>&& decisionHandler) +{ + const URL& requestURL = request.url(); + const URL& redirectResponseURL = redirectResponse.url(); + + m_loadCallback = decisionHandler; + m_request = request; + m_pluginView->m_plugin->streamWillSendRequest(m_streamID, requestURL, redirectResponseURL, redirectResponse.httpStatusCode()); } void PluginView::Stream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response) @@ -222,7 +244,7 @@ void PluginView::Stream::didReceiveResponse(NetscapePlugInStreamLoader*, const R if (expectedContentLength > 0) streamLength = expectedContentLength; - m_pluginView->m_plugin->streamDidReceiveResponse(m_streamID, responseURL, streamLength, lastModifiedDate(response), mimeType, headers, response.suggestedFilename()); + m_pluginView->m_plugin->streamDidReceiveResponse(m_streamID, responseURL, streamLength, lastModifiedDateMS(response), mimeType, headers, response.suggestedFilename()); } void PluginView::Stream::didReceiveData(NetscapePlugInStreamLoader*, const char* bytes, int length) @@ -263,38 +285,26 @@ static inline WebPage* webPage(HTMLPlugInElement* pluginElement) Frame* frame = pluginElement->document().frame(); ASSERT(frame); - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader().client()); - WebPage* webPage = webFrameLoaderClient ? webFrameLoaderClient->webFrame()->page() : 0; - ASSERT(webPage); + WebFrame* webFrame = WebFrame::fromCoreFrame(*frame); + if (!webFrame) + return nullptr; - return webPage; + return webFrame->page(); } -PassRefPtr<PluginView> PluginView::create(PassRefPtr<HTMLPlugInElement> pluginElement, PassRefPtr<Plugin> plugin, const Plugin::Parameters& parameters) +Ref<PluginView> PluginView::create(HTMLPlugInElement& pluginElement, Ref<Plugin>&& plugin, const Plugin::Parameters& parameters) { - return adoptRef(new PluginView(pluginElement, plugin, parameters)); + return adoptRef(*new PluginView(pluginElement, WTFMove(plugin), parameters)); } -PluginView::PluginView(PassRefPtr<HTMLPlugInElement> pluginElement, PassRefPtr<Plugin> plugin, const Plugin::Parameters& parameters) +PluginView::PluginView(HTMLPlugInElement& pluginElement, Ref<Plugin>&& plugin, const Plugin::Parameters& parameters) : PluginViewBase(0) - , m_pluginElement(pluginElement) - , m_plugin(plugin) + , m_pluginElement(&pluginElement) + , m_plugin(WTFMove(plugin)) , m_webPage(webPage(m_pluginElement.get())) , m_parameters(parameters) - , m_isInitialized(false) - , m_isWaitingForSynchronousInitialization(false) - , m_isWaitingUntilMediaCanStart(false) - , m_isBeingDestroyed(false) - , m_pluginProcessHasCrashed(false) , m_pendingURLRequestsTimer(RunLoop::main(), this, &PluginView::pendingURLRequestsTimerFired) -#if ENABLE(NETSCAPE_PLUGIN_API) - , m_npRuntimeObjectMap(this) -#endif - , m_manualStreamState(StreamStateInitial) - , m_pluginSnapshotTimer(this, &PluginView::pluginSnapshotTimerFired, pluginSnapshotTimerDelay) - , m_countSnapshotRetries(0) - , m_didReceiveUserInteraction(false) - , m_pageScaleFactor(1) + , m_pluginSnapshotTimer(*this, &PluginView::pluginSnapshotTimerFired, pluginSnapshotTimerDelay) { m_webPage->addPluginView(this); } @@ -309,6 +319,8 @@ PluginView::~PluginView() if (m_isWaitingUntilMediaCanStart) m_pluginElement->document().removeMediaCanStartListener(this); + m_pluginElement->document().removeAudioProducer(this); + destroyPluginAndReset(); // Null out the plug-in element explicitly so we'll crash earlier if we try to use @@ -330,7 +342,7 @@ void PluginView::destroyPluginAndReset() m_pendingURLRequests.clear(); m_pendingURLRequestsTimer.stop(); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) if (m_webPage) pluginFocusOrWindowFocusChanged(false); #endif @@ -344,7 +356,7 @@ void PluginView::destroyPluginAndReset() cancelAllStreams(); } -void PluginView::recreateAndInitialize(PassRefPtr<Plugin> plugin) +void PluginView::recreateAndInitialize(Ref<Plugin>&& plugin) { if (m_plugin) { if (m_pluginSnapshotTimer.isActive()) @@ -352,13 +364,12 @@ void PluginView::recreateAndInitialize(PassRefPtr<Plugin> plugin) destroyPluginAndReset(); } - // Reset member variables to initial values. - m_plugin = plugin; + m_plugin = WTFMove(plugin); m_isInitialized = false; m_isWaitingForSynchronousInitialization = false; m_isWaitingUntilMediaCanStart = false; m_isBeingDestroyed = false; - m_manualStreamState = StreamStateInitial; + m_manualStreamState = ManualStreamState::Initial; m_transientPaintingSnapshot = nullptr; initializePlugin(); @@ -366,7 +377,7 @@ void PluginView::recreateAndInitialize(PassRefPtr<Plugin> plugin) void PluginView::setLayerHostingMode(LayerHostingMode layerHostingMode) { -#if HAVE(LAYER_HOSTING_IN_WINDOW_SERVER) +#if HAVE(OUT_OF_PROCESS_LAYER_HOSTING) if (!m_plugin) return; @@ -391,8 +402,8 @@ void PluginView::manualLoadDidReceiveResponse(const ResourceResponse& response) return; if (!m_isInitialized) { - ASSERT(m_manualStreamState == StreamStateInitial); - m_manualStreamState = StreamStateHasReceivedResponse; + ASSERT(m_manualStreamState == ManualStreamState::Initial); + m_manualStreamState = ManualStreamState::HasReceivedResponse; m_manualStreamResponse = response; return; } @@ -408,7 +419,7 @@ void PluginView::manualLoadDidReceiveResponse(const ResourceResponse& response) if (expectedContentLength > 0) streamLength = expectedContentLength; - m_plugin->manualStreamDidReceiveResponse(responseURL, streamLength, lastModifiedDate(response), mimeType, headers, response.suggestedFilename()); + m_plugin->manualStreamDidReceiveResponse(responseURL, streamLength, lastModifiedDateMS(response), mimeType, headers, response.suggestedFilename()); } void PluginView::manualLoadDidReceiveData(const char* bytes, int length) @@ -418,7 +429,7 @@ void PluginView::manualLoadDidReceiveData(const char* bytes, int length) return; if (!m_isInitialized) { - ASSERT(m_manualStreamState == StreamStateHasReceivedResponse); + ASSERT(m_manualStreamState == ManualStreamState::HasReceivedResponse); if (!m_manualStreamData) m_manualStreamData = SharedBuffer::create(); @@ -436,8 +447,8 @@ void PluginView::manualLoadDidFinishLoading() return; if (!m_isInitialized) { - ASSERT(m_manualStreamState == StreamStateHasReceivedResponse); - m_manualStreamState = StreamStateFinished; + ASSERT(m_manualStreamState == ManualStreamState::HasReceivedResponse); + m_manualStreamState = ManualStreamState::Finished; return; } @@ -451,7 +462,7 @@ void PluginView::manualLoadDidFail(const ResourceError& error) return; if (!m_isInitialized) { - m_manualStreamState = StreamStateFinished; + m_manualStreamState = ManualStreamState::Finished; m_manualStreamError = error; m_manualStreamData = nullptr; return; @@ -460,12 +471,12 @@ void PluginView::manualLoadDidFail(const ResourceError& error) m_plugin->manualStreamDidFail(error.isCancellation()); } -RenderBoxModelObject* PluginView::renderer() const +void PluginView::pageScaleFactorDidChange() { - return toRenderBoxModelObject(m_pluginElement->renderer()); + viewGeometryDidChange(); } -void PluginView::pageScaleFactorDidChange() +void PluginView::topContentInsetDidChange() { viewGeometryDidChange(); } @@ -473,8 +484,8 @@ void PluginView::pageScaleFactorDidChange() void PluginView::setPageScaleFactor(double scaleFactor, IntPoint) { m_pageScaleFactor = scaleFactor; - m_webPage->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor)); - m_webPage->send(Messages::WebPageProxy::PageZoomFactorDidChange(scaleFactor)); + m_webPage->send(Messages::WebPageProxy::PluginScaleFactorDidChange(scaleFactor)); + m_webPage->send(Messages::WebPageProxy::PluginZoomFactorDidChange(scaleFactor)); pageScaleFactorDidChange(); } @@ -491,30 +502,31 @@ bool PluginView::handlesPageScaleFactor() const return m_plugin->handlesPageScaleFactor(); } -void PluginView::webPageDestroyed() +bool PluginView::requiresUnifiedScaleFactor() const { - m_webPage = 0; + if (!m_plugin || !m_isInitialized) + return false; + + return m_plugin->requiresUnifiedScaleFactor(); } -void PluginView::viewStateDidChange(ViewState::Flags changed) +void PluginView::webPageDestroyed() { -#if PLATFORM(MAC) - platformViewStateDidChange(changed); -#endif + m_webPage = 0; } -#if PLATFORM(MAC) -void PluginView::platformViewStateDidChange(ViewState::Flags changed) +void PluginView::activityStateDidChange(ActivityState::Flags changed) { if (!m_plugin || !m_isInitialized) return; - if (changed & ViewState::IsVisible) - m_plugin->windowVisibilityChanged(m_webPage->isVisible()); - if (changed & ViewState::WindowIsActive) + if (changed & ActivityState::IsVisibleOrOccluded) + m_plugin->windowVisibilityChanged(m_webPage->isVisibleOrOccluded()); + if (changed & ActivityState::WindowIsActive) m_plugin->windowFocusChanged(m_webPage->windowIsFocused()); } +#if PLATFORM(COCOA) void PluginView::setDeviceScaleFactor(float scaleFactor) { if (!m_isInitialized || !m_plugin) @@ -542,7 +554,7 @@ bool PluginView::sendComplexTextInput(uint64_t pluginComplexTextInputIdentifier, m_plugin->sendComplexTextInput(textInput); return true; } - + NSObject *PluginView::accessibilityObject() const { if (!m_isInitialized || !m_plugin) @@ -577,6 +589,12 @@ void PluginView::initializePlugin() } } + m_pluginElement->document().addAudioProducer(this); + +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + HTMLPlugInImageElement& plugInImageElement = downcast<HTMLPlugInImageElement>(*m_pluginElement); + m_didPlugInStartOffScreen = !m_webPage->plugInIntersectsSearchRect(plugInImageElement); +#endif m_plugin->initialize(this, m_parameters); // Plug-in initialization continued in didFailToInitializePlugin() or didInitializePlugin(). @@ -584,7 +602,7 @@ void PluginView::initializePlugin() void PluginView::didFailToInitializePlugin() { - m_plugin = 0; + m_plugin = nullptr; #if ENABLE(NETSCAPE_PLUGIN_API) String frameURLString = frame()->loader().documentLoader()->responseURL().string(); @@ -597,7 +615,7 @@ void PluginView::didInitializePlugin() { m_isInitialized = true; -#if PLATFORM(MAC) +#if PLATFORM(COCOA) windowAndViewFramesChanged(m_webPage->windowFrameInScreenCoordinates(), m_webPage->viewFrameInWindowCoordinates()); #endif @@ -609,27 +627,28 @@ void PluginView::didInitializePlugin() redeliverManualStream(); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) if (m_pluginElement->displayState() < HTMLPlugInElement::Restarting) { if (m_plugin->pluginLayer() && frame()) { frame()->view()->enterCompositingMode(); - m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); + m_pluginElement->invalidateStyleAndLayerComposition(); } if (frame() && !frame()->settings().maximumPlugInSnapshotAttempts()) { - m_pluginElement->setDisplayState(HTMLPlugInElement::DisplayingSnapshot); + beginSnapshottingRunningPlugin(); return; } m_pluginSnapshotTimer.restart(); } else { if (m_plugin->pluginLayer() && frame()) { frame()->view()->enterCompositingMode(); - m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); + m_pluginElement->invalidateStyleAndLayerComposition(); } if (m_pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick) m_pluginElement->dispatchPendingMouseClick(); } - m_plugin->windowVisibilityChanged(m_webPage->isVisible()); + m_plugin->visibilityDidChange(isVisible()); + m_plugin->windowVisibilityChanged(m_webPage->isVisibleOrOccluded()); m_plugin->windowFocusChanged(m_webPage->windowIsFocused()); #endif @@ -639,9 +658,15 @@ void PluginView::didInitializePlugin() frameView->setNeedsLayout(); } } + + if (Frame* frame = m_pluginElement->document().frame()) { + auto* webFrame = WebFrame::fromCoreFrame(*frame); + if (webFrame->isMainFrame()) + webFrame->page()->send(Messages::WebPageProxy::MainFramePluginHandlesPageScaleGestureDidChange(handlesPageScaleFactor())); + } } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) PlatformLayer* PluginView::platformLayer() const { // The plug-in can be null here if it failed to initialize. @@ -685,7 +710,7 @@ void PluginView::storageBlockingStateChanged() if (!m_isInitialized || !m_plugin) return; - bool storageBlockingPolicy = !frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->document()->topOrigin()); + bool storageBlockingPolicy = !frame()->document()->securityOrigin().canAccessPluginStorage(frame()->document()->topOrigin()); m_plugin->storageBlockingStateChanged(storageBlockingPolicy); } @@ -750,13 +775,13 @@ void PluginView::setFrameRect(const WebCore::IntRect& rect) viewGeometryDidChange(); } -void PluginView::paint(GraphicsContext* context, const IntRect& /*dirtyRect*/) +void PluginView::paint(GraphicsContext& context, const IntRect& /*dirtyRect*/, Widget::SecurityOriginPaintPolicy) { if (!m_plugin || !m_isInitialized || m_pluginElement->displayState() < HTMLPlugInElement::Restarting) return; - if (context->paintingDisabled()) { - if (context->updatingControlTints()) + if (context.paintingDisabled()) { + if (context.updatingControlTints()) m_plugin->updateControlTints(context); return; } @@ -768,14 +793,14 @@ void PluginView::paint(GraphicsContext* context, const IntRect& /*dirtyRect*/) return; if (m_transientPaintingSnapshot) { - m_transientPaintingSnapshot->paint(*context, contentsScaleFactor(), frameRect().location(), m_transientPaintingSnapshot->bounds()); + m_transientPaintingSnapshot->paint(context, contentsScaleFactor(), frameRect().location(), m_transientPaintingSnapshot->bounds()); return; } - GraphicsContextStateSaver stateSaver(*context); + GraphicsContextStateSaver stateSaver(context); // Translate the coordinate system so that the origin is in the top-left corner of the plug-in. - context->translate(frameRect().location().x(), frameRect().location().y()); + context.translate(frameRect().location().x(), frameRect().location().y()); m_plugin->paint(context, paintRect); } @@ -823,7 +848,7 @@ String PluginView::getSelectionString() const return m_plugin->getSelectionString(); } -OwnPtr<WebEvent> PluginView::createWebEvent(MouseEvent* event) const +std::unique_ptr<WebEvent> PluginView::createWebEvent(MouseEvent* event) const { WebEvent::Type type = WebEvent::NoType; unsigned clickCount = 1; @@ -865,7 +890,7 @@ OwnPtr<WebEvent> PluginView::createWebEvent(MouseEvent* event) const if (event->metaKey()) modifiers |= WebEvent::MetaKey; - return adoptPtr(new WebMouseEvent(type, button, m_plugin->convertToRootView(IntPoint(event->offsetX(), event->offsetY())), event->screenLocation(), 0, 0, 0, clickCount, static_cast<WebEvent::Modifiers>(modifiers), 0)); + return std::make_unique<WebMouseEvent>(type, button, m_plugin->convertToRootView(IntPoint(event->offsetX(), event->offsetY())), event->screenLocation(), 0, 0, 0, clickCount, static_cast<WebEvent::Modifiers>(modifiers), 0, 0); } void PluginView::handleEvent(Event* event) @@ -874,9 +899,9 @@ void PluginView::handleEvent(Event* event) return; const WebEvent* currentEvent = WebPage::currentEvent(); - OwnPtr<WebEvent> simulatedWebEvent; - if (event->isMouseEvent() && toMouseEvent(event)->isSimulated()) { - simulatedWebEvent = createWebEvent(toMouseEvent(event)); + std::unique_ptr<WebEvent> simulatedWebEvent; + if (is<MouseEvent>(*event) && downcast<MouseEvent>(*event).isSimulated()) { + simulatedWebEvent = createWebEvent(downcast<MouseEvent>(event)); currentEvent = simulatedWebEvent.get(); } if (!currentEvent) @@ -897,7 +922,7 @@ void PluginView::handleEvent(Event* event) didHandleEvent = m_plugin->handleMouseEvent(static_cast<const WebMouseEvent&>(*currentEvent)); if (event->type() != eventNames().mousemoveEvent) pluginDidReceiveUserInteraction(); - } else if ((event->type() == eventNames().wheelEvent || event->type() == eventNames().mousewheelEvent) + } else if (eventNames().isWheelEventType(event->type()) && currentEvent->type() == WebEvent::Wheel && m_plugin->wantsWheelEvents()) { didHandleEvent = m_plugin->handleWheelEvent(static_cast<const WebWheelEvent&>(*currentEvent)); pluginDidReceiveUserInteraction(); @@ -955,7 +980,15 @@ bool PluginView::shouldNotAddLayer() const return m_pluginElement->displayState() < HTMLPlugInElement::Restarting && !m_plugin->supportsSnapshotting(); } -PassRefPtr<SharedBuffer> PluginView::liveResourceData() const +void PluginView::willDetatchRenderer() +{ + if (!m_isInitialized || !m_plugin) + return; + + m_plugin->willDetatchRenderer(); +} + +RefPtr<SharedBuffer> PluginView::liveResourceData() const { if (!m_isInitialized || !m_plugin) return 0; @@ -971,6 +1004,22 @@ bool PluginView::performDictionaryLookupAtLocation(const WebCore::FloatPoint& po return m_plugin->performDictionaryLookupAtLocation(point); } +String PluginView::getSelectionForWordAtPoint(const WebCore::FloatPoint& point) const +{ + if (!m_isInitialized || !m_plugin) + return String(); + + return m_plugin->getSelectionForWordAtPoint(point); +} + +bool PluginView::existingSelectionContainsPoint(const WebCore::FloatPoint& point) const +{ + if (!m_isInitialized || !m_plugin) + return false; + + return m_plugin->existingSelectionContainsPoint(point); +} + void PluginView::notifyWidget(WidgetNotification notification) { switch (notification) { @@ -1083,9 +1132,9 @@ void PluginView::focusPluginElement() ASSERT(frame()); if (Page* page = frame()->page()) - page->focusController().setFocusedElement(m_pluginElement.get(), frame()); + page->focusController().setFocusedElement(m_pluginElement.get(), *frame()); else - frame()->document()->setFocusedElement(m_pluginElement); + frame()->document()->setFocusedElement(m_pluginElement.get()); } void PluginView::pendingURLRequestsTimerFired() @@ -1131,19 +1180,19 @@ void PluginView::performFrameLoadURLRequest(URLRequest* request) if (!frame) return; - if (!m_pluginElement->document().securityOrigin()->canDisplay(request->request().url())) { + if (!m_pluginElement->document().securityOrigin().canDisplay(request->request().url())) { // We can't load the request, send back a reply to the plug-in. m_plugin->frameDidFail(request->requestID(), false); return; } - UserGestureIndicator gestureIndicator(request->allowPopups() ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); + UserGestureIndicator gestureIndicator(request->allowPopups() ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt); // First, try to find a target frame. Frame* targetFrame = frame->loader().findFrameForNavigation(request->target()); if (!targetFrame) { // We did not find a target frame. Ask our frame to load the page. This may or may not create a popup window. - FrameLoadRequest frameRequest(frame, request->request()); + FrameLoadRequest frameRequest(frame, request->request(), ShouldOpenExternalURLsPolicy::ShouldNotAllow); frameRequest.setFrameName(request->target()); frameRequest.setShouldCheckNewWindowPolicy(true); frame->loader().load(frameRequest); @@ -1155,10 +1204,9 @@ void PluginView::performFrameLoadURLRequest(URLRequest* request) } // Now ask the frame to load the request. - targetFrame->loader().load(FrameLoadRequest(targetFrame, request->request())); + targetFrame->loader().load(FrameLoadRequest(targetFrame, request->request(), ShouldOpenExternalURLsPolicy::ShouldNotAllow)); - WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(targetFrame->loader().client()); - WebFrame* targetWebFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + auto* targetWebFrame = WebFrame::fromCoreFrame(*targetFrame); ASSERT(targetWebFrame); if (WebFrame::LoadListener* loadListener = targetWebFrame->loadListener()) { @@ -1193,7 +1241,10 @@ void PluginView::performJavaScriptURLRequest(URLRequest* request) // Evaluate the JavaScript code. Note that running JavaScript here could cause the plug-in to be destroyed, so we // grab references to the plug-in here. RefPtr<Plugin> plugin = m_plugin; - Deprecated::ScriptValue result = frame->script().executeScript(jsString, request->allowPopups()); + auto result = frame->script().executeScript(jsString, request->allowPopups()); + + if (!result) + return; // Check if evaluating the JavaScript destroyed the plug-in. if (!plugin->controller()) @@ -1238,12 +1289,12 @@ void PluginView::cancelAllStreams() void PluginView::redeliverManualStream() { - if (m_manualStreamState == StreamStateInitial) { + if (m_manualStreamState == ManualStreamState::Initial) { // Nothing to do. return; } - if (m_manualStreamState == StreamStateFailed) { + if (m_manualStreamState == ManualStreamState::Failed) { manualLoadDidFail(m_manualStreamError); return; } @@ -1264,7 +1315,7 @@ void PluginView::redeliverManualStream() m_manualStreamData = nullptr; } - if (m_manualStreamState == StreamStateFinished) + if (m_manualStreamState == ManualStreamState::Finished) manualLoadDidFinishLoading(); } @@ -1273,7 +1324,7 @@ void PluginView::invalidateRect(const IntRect& dirtyRect) if (!parent() || !m_plugin || !m_isInitialized) return; -#if PLATFORM(MAC) +#if PLATFORM(COCOA) if (m_plugin->pluginLayer()) return; #endif @@ -1281,12 +1332,13 @@ void PluginView::invalidateRect(const IntRect& dirtyRect) if (m_pluginElement->displayState() < HTMLPlugInElement::Restarting) return; - RenderBoxModelObject* renderer = toRenderBoxModelObject(m_pluginElement->renderer()); - if (!renderer) + auto* renderer = m_pluginElement->renderer(); + if (!is<RenderEmbeddedObject>(renderer)) return; + auto& object = downcast<RenderEmbeddedObject>(*renderer); IntRect contentRect(dirtyRect); - contentRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop()); + contentRect.move(object.borderLeft() + object.paddingLeft(), object.borderTop() + object.paddingTop()); renderer->repaintRectangle(contentRect); } @@ -1300,7 +1352,7 @@ void PluginView::setFocus(bool hasFocus) m_plugin->setFocus(hasFocus); } -void PluginView::mediaCanStart() +void PluginView::mediaCanStart(WebCore::Document&) { ASSERT(m_isWaitingUntilMediaCanStart); m_isWaitingUntilMediaCanStart = false; @@ -1308,9 +1360,15 @@ void PluginView::mediaCanStart() initializePlugin(); } -bool PluginView::isPluginVisible() +void PluginView::pageMutedStateDidChange() { - return isVisible(); +#if ENABLE(NETSCAPE_PLUGIN_API) + // The plug-in can be null here if it failed to initialize. + if (!m_isInitialized || !m_plugin) + return; + + m_plugin->mutedStateChanged(isMuted()); +#endif } void PluginView::invalidate(const IntRect& dirtyRect) @@ -1327,14 +1385,18 @@ String PluginView::userAgent() return frame->loader().client().userAgent(URL()); } -void PluginView::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, - const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups) +void PluginView::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups) { - FrameLoadRequest frameLoadRequest(m_pluginElement->document().securityOrigin()); + FrameLoadRequest frameLoadRequest(m_pluginElement->document().securityOrigin(), LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow); frameLoadRequest.resourceRequest().setHTTPMethod(method); frameLoadRequest.resourceRequest().setURL(m_pluginElement->document().completeURL(urlString)); - frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields); - frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(httpBody.data(), httpBody.size())); + frameLoadRequest.resourceRequest().setHTTPHeaderFields(headerFields); + if (!httpBody.isEmpty()) { + frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(httpBody.data(), httpBody.size())); + if (frameLoadRequest.resourceRequest().httpContentType().isEmpty()) + frameLoadRequest.resourceRequest().setHTTPContentType("application/x-www-form-urlencoded"); + } + frameLoadRequest.setFrameName(target); String referrer = SecurityPolicy::generateReferrerHeader(frame()->document()->referrerPolicy(), frameLoadRequest.resourceRequest().url(), frame()->loader().outgoingReferrer()); @@ -1358,6 +1420,15 @@ void PluginView::cancelStreamLoad(uint64_t streamID) ASSERT(!m_streams.contains(streamID)); } +void PluginView::continueStreamLoad(uint64_t streamID) +{ + RefPtr<Stream> stream = m_streams.get(streamID); + if (!stream) + return; + + stream->continueLoad(); +} + void PluginView::cancelManualStreamLoad() { if (!frame()) @@ -1381,7 +1452,7 @@ NPObject* PluginView::windowScriptNPObject() return 0; } - return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld().vm(), frame()->script().windowShell(pluginWorld())->window()); + return m_npRuntimeObjectMap.getOrCreateNPObject(pluginWorld().vm(), frame()->script().windowShell(pluginWorld())->window()); } NPObject* PluginView::pluginElementNPObject() @@ -1397,7 +1468,7 @@ NPObject* PluginView::pluginElementNPObject() JSObject* object = frame()->script().jsObjectForPluginElement(m_pluginElement.get()); ASSERT(object); - return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld().vm(), object); + return m_npRuntimeObjectMap.getOrCreateNPObject(pluginWorld().vm(), object); } bool PluginView::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result, bool allowPopups) @@ -1410,9 +1481,26 @@ bool PluginView::evaluate(NPObject* npObject, const String& scriptString, NPVari // protect the plug-in view from destruction. NPRuntimeObjectMap::PluginProtector pluginProtector(&m_npRuntimeObjectMap); - UserGestureIndicator gestureIndicator(allowPopups ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); + UserGestureIndicator gestureIndicator(allowPopups ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt); return m_npRuntimeObjectMap.evaluate(npObject, scriptString, result); } + +void PluginView::setPluginIsPlayingAudio(bool pluginIsPlayingAudio) +{ + if (m_pluginIsPlayingAudio == pluginIsPlayingAudio) + return; + + m_pluginIsPlayingAudio = pluginIsPlayingAudio; + m_pluginElement->document().updateIsPlayingMedia(); +} + +bool PluginView::isMuted() const +{ + if (!frame() || !frame()->page()) + return false; + + return frame()->page()->isAudioMuted(); +} #endif void PluginView::setStatusbarText(const String& statusbarText) @@ -1424,7 +1512,7 @@ void PluginView::setStatusbarText(const String& statusbarText) if (!page) return; - page->chrome().setStatusbarText(frame(), statusbarText); + page->chrome().setStatusbarText(*frame(), statusbarText); } bool PluginView::isAcceleratedCompositingEnabled() @@ -1446,29 +1534,18 @@ void PluginView::pluginProcessCrashed() { m_pluginProcessHasCrashed = true; - if (!m_pluginElement->renderer()) + auto* renderer = m_pluginElement->renderer(); + if (!is<RenderEmbeddedObject>(renderer)) return; - if (!m_pluginElement->renderer()->isEmbeddedObject()) - return; + m_pluginElement->invalidateStyleAndLayerComposition(); - m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); + downcast<RenderEmbeddedObject>(*renderer).setPluginUnavailabilityReason(RenderEmbeddedObject::PluginCrashed); - RenderEmbeddedObject* renderer = toRenderEmbeddedObject(m_pluginElement->renderer()); - renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginCrashed); - Widget::invalidate(); } -void PluginView::willSendEventToPlugin() -{ - // If we're sending an event to a plug-in, we can't control how long the plug-in - // takes to process it (e.g. it may display a context menu), so we tell the UI process - // to stop the responsiveness timer in this case. - m_webPage->send(Messages::WebPageProxy::StopResponsivenessTimer()); -} - -#if PLATFORM(MAC) +#if PLATFORM(COCOA) void PluginView::pluginFocusOrWindowFocusChanged(bool pluginHasFocusAndWindowHasFocus) { if (m_webPage) @@ -1481,14 +1558,9 @@ void PluginView::setComplexTextInputState(PluginComplexTextInputState pluginComp m_webPage->send(Messages::WebPageProxy::SetPluginComplexTextInputState(m_plugin->pluginComplexTextInputIdentifier(), pluginComplexTextInputState)); } -mach_port_t PluginView::compositingRenderServerPort() +const MachSendRight& PluginView::compositingRenderServerPort() { - return WebProcess::shared().compositingRenderServerPort(); -} - -void PluginView::openPluginPreferencePane() -{ - ASSERT_NOT_REACHED(); + return WebProcess::singleton().compositingRenderServerPort(); } #endif @@ -1511,19 +1583,24 @@ String PluginView::proxiesForURL(const String& urlString) String PluginView::cookiesForURL(const String& urlString) { - return cookies(&m_pluginElement->document(), URL(URL(), urlString)); + return cookies(m_pluginElement->document(), URL(URL(), urlString)); } void PluginView::setCookiesForURL(const String& urlString, const String& cookieString) { - setCookies(&m_pluginElement->document(), URL(URL(), urlString), cookieString); + setCookies(m_pluginElement->document(), URL(URL(), urlString), cookieString); } bool PluginView::getAuthenticationInfo(const ProtectionSpace& protectionSpace, String& username, String& password) { - Credential credential = CredentialStorage::get(protectionSpace); + auto* contentDocument = m_pluginElement->contentDocument(); + if (!contentDocument) + return false; + + String partitionName = contentDocument->topDocument().securityOrigin().domainForCachePartition(); + Credential credential = CredentialStorage::defaultCredentialStorage().get(partitionName, protectionSpace); if (credential.isEmpty()) - credential = CredentialStorage::getFromPersistentStorage(protectionSpace); + credential = CredentialStorage::defaultCredentialStorage().getFromPersistentStorage(protectionSpace); if (!credential.hasPassword()) return false; @@ -1540,10 +1617,10 @@ bool PluginView::isPrivateBrowsingEnabled() if (!frame()) return true; - if (!frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->document()->topOrigin())) + if (!frame()->document()->securityOrigin().canAccessPluginStorage(frame()->document()->topOrigin())) return true; - return frame()->settings().privateBrowsingEnabled(); + return frame()->page()->usesEphemeralSession(); } bool PluginView::asynchronousPluginInitializationEnabled() const @@ -1567,11 +1644,6 @@ void PluginView::protectPluginFromDestruction() ref(); } -static void derefPluginView(PluginView* pluginView) -{ - pluginView->deref(); -} - void PluginView::unprotectPluginFromDestruction() { if (m_isBeingDestroyed) @@ -1582,10 +1654,13 @@ void PluginView::unprotectPluginFromDestruction() // for example, may crash if the plug-in is destroyed and we return to code for // the destroyed object higher on the stack. To prevent this, if the plug-in has // only one remaining reference, call deref() asynchronously. - if (hasOneRef()) - RunLoop::main()->dispatch(bind(derefPluginView, this)); - else - deref(); + if (hasOneRef()) { + RunLoop::main().dispatch([lastRef = adoptRef(*this)] { + }); + return; + } + + deref(); } void PluginView::didFinishLoad(WebFrame* webFrame) @@ -1610,7 +1685,8 @@ void PluginView::didFailLoad(WebFrame* webFrame, bool wasCancelled) uint64_t PluginView::createPluginContainer() { uint64_t windowID = 0; - m_webPage->sendSync(Messages::WebPageProxy::CreatePluginContainer(), Messages::WebPageProxy::CreatePluginContainer::Reply(windowID)); + if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) + m_webPage->sendSync(Messages::WebPageProxy::CreatePluginContainer(), Messages::WebPageProxy::CreatePluginContainer::Reply(windowID)); return windowID; } @@ -1625,10 +1701,10 @@ void PluginView::windowedPluginVisibilityDidChange(bool isVisible, uint64_t wind } #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) static bool isAlmostSolidColor(BitmapImage* bitmap) { - CGImageRef image = bitmap->getCGImageRef(); + CGImageRef image = bitmap->nativeImage().get(); ASSERT(CGImageGetBitsPerComponent(image) == 8); CGBitmapInfo imageInfo = CGImageGetBitmapInfo(image); @@ -1688,11 +1764,16 @@ static bool isAlmostSolidColor(BitmapImage* bitmap) } #endif -void PluginView::pluginSnapshotTimerFired(DeferrableOneShotTimer<PluginView>&) +void PluginView::pluginSnapshotTimerFired() { - ASSERT(m_plugin); +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + HTMLPlugInImageElement& plugInImageElement = downcast<HTMLPlugInImageElement>(*m_pluginElement); + bool isPlugInOnScreen = m_webPage->plugInIntersectsSearchRect(plugInImageElement); + bool plugInCameOnScreen = isPlugInOnScreen && m_didPlugInStartOffScreen; + bool snapshotFound = false; +#endif - if (m_plugin->supportsSnapshotting()) { + if (m_plugin && m_plugin->supportsSnapshotting()) { // Snapshot might be 0 if plugin size is 0x0. RefPtr<ShareableBitmap> snapshot = m_plugin->snapshot(); RefPtr<Image> snapshotImage; @@ -1700,18 +1781,33 @@ void PluginView::pluginSnapshotTimerFired(DeferrableOneShotTimer<PluginView>&) snapshotImage = snapshot->createImage(); m_pluginElement->updateSnapshot(snapshotImage.get()); -#if PLATFORM(MAC) - unsigned maximumSnapshotRetries = frame() ? frame()->settings().maximumPlugInSnapshotAttempts() : 0; - if (snapshotImage && isAlmostSolidColor(toBitmapImage(snapshotImage.get())) && m_countSnapshotRetries < maximumSnapshotRetries) { - ++m_countSnapshotRetries; - m_pluginSnapshotTimer.restart(); - return; - } + if (snapshotImage) { +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + bool snapshotIsAlmostSolidColor = isAlmostSolidColor(downcast<BitmapImage>(snapshotImage.get())); + snapshotFound = !snapshotIsAlmostSolidColor; +#endif + +#if PLATFORM(COCOA) + unsigned maximumSnapshotRetries = frame() ? frame()->settings().maximumPlugInSnapshotAttempts() : 0; + if (snapshotIsAlmostSolidColor && m_countSnapshotRetries < maximumSnapshotRetries && !plugInCameOnScreen) { + ++m_countSnapshotRetries; + m_pluginSnapshotTimer.restart(); + return; + } #endif + } } - // Even if there is no snapshot we still set the state to DisplayingSnapshot - // since we just want to display the default empty box. - m_pluginElement->setDisplayState(HTMLPlugInElement::DisplayingSnapshot); + +#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) + unsigned candidateArea = 0; + unsigned maximumSnapshotRetries = frame() ? frame()->settings().maximumPlugInSnapshotAttempts() : 0; + bool noSnapshotFoundAfterMaxRetries = m_countSnapshotRetries == maximumSnapshotRetries && !isPlugInOnScreen && !snapshotFound; + if (m_webPage->plugInIsPrimarySize(plugInImageElement, candidateArea) + && (noSnapshotFoundAfterMaxRetries || plugInCameOnScreen)) + m_pluginElement->setDisplayState(HTMLPlugInElement::Playing); + else +#endif + m_pluginElement->setDisplayState(HTMLPlugInElement::DisplayingSnapshot); } void PluginView::beginSnapshottingRunningPlugin() @@ -1740,12 +1836,12 @@ void PluginView::pluginDidReceiveUserInteraction() m_didReceiveUserInteraction = true; - WebCore::HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(m_pluginElement.get()); - String pageOrigin = plugInImageElement->document().page()->mainFrame().document()->baseURL().host(); - String pluginOrigin = plugInImageElement->loadedUrl().host(); - String mimeType = plugInImageElement->loadedMimeType(); + HTMLPlugInImageElement& plugInImageElement = downcast<HTMLPlugInImageElement>(*m_pluginElement); + String pageOrigin = plugInImageElement.document().page()->mainFrame().document()->baseURL().host(); + String pluginOrigin = plugInImageElement.loadedUrl().host(); + String mimeType = plugInImageElement.loadedMimeType(); - WebProcess::shared().plugInDidReceiveUserInteraction(pageOrigin, pluginOrigin, mimeType); + WebProcess::singleton().plugInDidReceiveUserInteraction(pageOrigin, pluginOrigin, mimeType, plugInImageElement.document().page()->sessionID()); } bool PluginView::shouldCreateTransientPaintingSnapshot() const @@ -1757,13 +1853,16 @@ bool PluginView::shouldCreateTransientPaintingSnapshot() const return false; if (FrameView* frameView = frame()->view()) { - if (frameView->paintBehavior() & (PaintBehaviorSelectionOnly | PaintBehaviorForceBlackText)) { + if (frameView->paintBehavior() & (PaintBehaviorSelectionOnly | PaintBehaviorSelectionAndBackgroundsOnly | PaintBehaviorForceBlackText)) { // This paint behavior is used when drawing the find indicator and there's no need to // snapshot plug-ins, because they can never be painted as part of the find indicator. return false; } } + if (!m_plugin->canCreateTransientPaintingSnapshot()) + return false; + return true; } |