diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebKit2/WebProcess/Plugins/PluginView.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebKit2/WebProcess/Plugins/PluginView.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/Plugins/PluginView.cpp | 364 |
1 files changed, 300 insertions, 64 deletions
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp index 6c74f4633..b8857017f 100644 --- a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp +++ b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp @@ -34,27 +34,35 @@ #include "WebPage.h" #include "WebPageProxyMessages.h" #include "WebProcess.h" +#include <WebCore/BitmapImage.h> #include <WebCore/Chrome.h> #include <WebCore/CookieJar.h> #include <WebCore/Credential.h> #include <WebCore/CredentialStorage.h> #include <WebCore/DocumentLoader.h> -#include <WebCore/MouseEvent.h> +#include <WebCore/EventHandler.h> #include <WebCore/FocusController.h> #include <WebCore/Frame.h> #include <WebCore/FrameLoadRequest.h> +#include <WebCore/FrameLoader.h> #include <WebCore/FrameLoaderClient.h> #include <WebCore/FrameView.h> #include <WebCore/GraphicsContext.h> #include <WebCore/HTMLPlugInElement.h> +#include <WebCore/HTMLPlugInImageElement.h> #include <WebCore/HostWindow.h> +#include <WebCore/MIMETypeRegistry.h> +#include <WebCore/MouseEvent.h> #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/ScriptValue.h> #include <WebCore/ScrollView.h> #include <WebCore/SecurityOrigin.h> @@ -142,6 +150,7 @@ PluginView::Stream::~Stream() void PluginView::Stream::start() { + ASSERT(m_pluginView->m_plugin); ASSERT(!m_loader); Frame* frame = m_pluginView->m_pluginElement->document()->frame(); @@ -245,7 +254,8 @@ static inline WebPage* webPage(HTMLPlugInElement* pluginElement) Frame* frame = pluginElement->document()->frame(); ASSERT(frame); - WebPage* webPage = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame()->page(); + WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame->loader()->client()); + WebPage* webPage = webFrameLoaderClient ? webFrameLoaderClient->webFrame()->page() : 0; ASSERT(webPage); return webPage; @@ -266,12 +276,15 @@ PluginView::PluginView(PassRefPtr<HTMLPlugInElement> pluginElement, PassRefPtr<P , 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_webPage->addPluginView(this); @@ -304,6 +317,10 @@ void PluginView::destroyPluginAndReset() m_isBeingDestroyed = true; m_plugin->destroyPlugin(); m_isBeingDestroyed = false; + + m_pendingURLRequests.clear(); + m_pendingURLRequestsTimer.stop(); + #if PLATFORM(MAC) if (m_webPage) pluginFocusOrWindowFocusChanged(false); @@ -433,14 +450,23 @@ void PluginView::setPageScaleFactor(double scaleFactor, IntPoint) { m_pageScaleFactor = scaleFactor; m_webPage->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor)); + m_webPage->send(Messages::WebPageProxy::PageZoomFactorDidChange(scaleFactor)); pageScaleFactorDidChange(); } -double PluginView::pageScaleFactor() +double PluginView::pageScaleFactor() const { return m_pageScaleFactor; } +bool PluginView::handlesPageScaleFactor() const +{ + if (!m_plugin || !m_isInitialized) + return false; + + return m_plugin->handlesPageScaleFactor(); +} + void PluginView::webPageDestroyed() { m_webPage = 0; @@ -471,12 +497,12 @@ void PluginView::setDeviceScaleFactor(float scaleFactor) m_plugin->contentsScaleFactorChanged(scaleFactor); } -void PluginView::windowAndViewFramesChanged(const IntRect& windowFrameInScreenCoordinates, const IntRect& viewFrameInWindowCoordinates) +void PluginView::windowAndViewFramesChanged(const FloatRect& windowFrameInScreenCoordinates, const FloatRect& viewFrameInWindowCoordinates) { if (!m_isInitialized || !m_plugin) return; - m_plugin->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates); + m_plugin->windowAndViewFramesChanged(enclosingIntRect(windowFrameInScreenCoordinates), enclosingIntRect(viewFrameInWindowCoordinates)); } bool PluginView::sendComplexTextInput(uint64_t pluginComplexTextInputIdentifier, const String& textInput) @@ -503,7 +529,14 @@ void PluginView::setLayerHostingMode(LayerHostingMode layerHostingMode) m_plugin->setLayerHostingMode(layerHostingMode); } - + +NSObject *PluginView::accessibilityObject() const +{ + if (!m_isInitialized || !m_plugin) + return 0; + + return m_plugin->accessibilityObject(); +} #endif void PluginView::initializePlugin() @@ -539,7 +572,10 @@ void PluginView::initializePlugin() void PluginView::didFailToInitializePlugin() { m_plugin = 0; - m_webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(m_parameters.mimeType)); + + String frameURLString = frame()->loader()->documentLoader()->responseURL().string(); + String pageURLString = m_webPage->corePage()->mainFrame()->loader()->documentLoader()->responseURL().string(); + m_webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(m_parameters.mimeType, frameURLString, pageURLString)); } void PluginView::didInitializePlugin() @@ -552,19 +588,28 @@ void PluginView::didInitializePlugin() viewGeometryDidChange(); + if (m_pluginElement->document()->focusedElement() == m_pluginElement) + m_plugin->setFocus(true); + redeliverManualStream(); #if PLATFORM(MAC) - if (m_pluginElement->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick) + if (m_pluginElement->displayState() < HTMLPlugInElement::Restarting) { + if (m_plugin->pluginLayer() && frame()) { + frame()->view()->enterCompositingMode(); + m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); + } + if (frame() && !frame()->settings()->maximumPlugInSnapshotAttempts()) { + m_pluginElement->setDisplayState(HTMLPlugInElement::DisplayingSnapshot); + return; + } m_pluginSnapshotTimer.restart(); - else { - if (m_plugin->pluginLayer()) { - if (frame()) { - frame()->view()->enterCompositingMode(); - m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); - } + } else { + if (m_plugin->pluginLayer() && frame()) { + frame()->view()->enterCompositingMode(); + m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); } - if (m_pluginElement->displayState() < HTMLPlugInElement::Playing) + if (m_pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick) m_pluginElement->dispatchPendingMouseClick(); } @@ -584,7 +629,7 @@ void PluginView::didInitializePlugin() PlatformLayer* PluginView::platformLayer() const { // The plug-in can be null here if it failed to initialize. - if (!m_isInitialized || !m_plugin) + if (!m_isInitialized || !m_plugin || m_pluginProcessHasCrashed) return 0; return m_plugin->pluginLayer(); @@ -624,7 +669,7 @@ void PluginView::storageBlockingStateChanged() if (!m_isInitialized || !m_plugin) return; - bool storageBlockingPolicy = !frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->tree()->top()->document()->securityOrigin()); + bool storageBlockingPolicy = !frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->document()->topOrigin()); m_plugin->storageBlockingStateChanged(storageBlockingPolicy); } @@ -691,7 +736,7 @@ void PluginView::setFrameRect(const WebCore::IntRect& rect) void PluginView::paint(GraphicsContext* context, const IntRect& /*dirtyRect*/) { - if (!m_plugin || !m_isInitialized || m_pluginElement->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick) + if (!m_plugin || !m_isInitialized || m_pluginElement->displayState() < HTMLPlugInElement::Restarting) return; if (context->paintingDisabled()) { @@ -725,6 +770,11 @@ void PluginView::frameRectsChanged() viewGeometryDidChange(); } +void PluginView::clipRectChanged() +{ + viewGeometryDidChange(); +} + void PluginView::setParent(ScrollView* scrollView) { Widget::setParent(scrollView); @@ -733,6 +783,30 @@ void PluginView::setParent(ScrollView* scrollView) initializePlugin(); } +unsigned PluginView::countFindMatches(const String& target, WebCore::FindOptions options, unsigned maxMatchCount) +{ + if (!m_isInitialized || !m_plugin) + return 0; + + return m_plugin->countFindMatches(target, options, maxMatchCount); +} + +bool PluginView::findString(const String& target, WebCore::FindOptions options, unsigned maxMatchCount) +{ + if (!m_isInitialized || !m_plugin) + return false; + + return m_plugin->findString(target, options, maxMatchCount); +} + +String PluginView::getSelectionString() const +{ + if (!m_isInitialized || !m_plugin) + return String(); + + return m_plugin->getSelectionString(); +} + PassOwnPtr<WebEvent> PluginView::createWebEvent(MouseEvent* event) const { WebEvent::Type type = WebEvent::NoType; @@ -797,8 +871,6 @@ void PluginView::handleEvent(Event* event) if ((event->type() == eventNames().mousemoveEvent && currentEvent->type() == WebEvent::MouseMove) || (event->type() == eventNames().mousedownEvent && currentEvent->type() == WebEvent::MouseDown) || (event->type() == eventNames().mouseupEvent && currentEvent->type() == WebEvent::MouseUp)) { - // We have a mouse event. - // FIXME: Clicking in a scroll bar should not change focus. if (currentEvent->type() == WebEvent::MouseDown) { focusPluginElement(); @@ -807,22 +879,22 @@ void PluginView::handleEvent(Event* event) frame()->eventHandler()->setCapturingMouseEventsNode(0); didHandleEvent = m_plugin->handleMouseEvent(static_cast<const WebMouseEvent&>(*currentEvent)); + if (event->type() != eventNames().mousemoveEvent) + pluginDidReceiveUserInteraction(); } else if (event->type() == eventNames().mousewheelEvent && currentEvent->type() == WebEvent::Wheel && m_plugin->wantsWheelEvents()) { - // We have a wheel event. didHandleEvent = m_plugin->handleWheelEvent(static_cast<const WebWheelEvent&>(*currentEvent)); - } else if (event->type() == eventNames().mouseoverEvent && currentEvent->type() == WebEvent::MouseMove) { - // We have a mouse enter event. + pluginDidReceiveUserInteraction(); + } else if (event->type() == eventNames().mouseoverEvent && currentEvent->type() == WebEvent::MouseMove) didHandleEvent = m_plugin->handleMouseEnterEvent(static_cast<const WebMouseEvent&>(*currentEvent)); - } else if (event->type() == eventNames().mouseoutEvent && currentEvent->type() == WebEvent::MouseMove) { - // We have a mouse leave event. + else if (event->type() == eventNames().mouseoutEvent && currentEvent->type() == WebEvent::MouseMove) didHandleEvent = m_plugin->handleMouseLeaveEvent(static_cast<const WebMouseEvent&>(*currentEvent)); - } else if (event->type() == eventNames().contextmenuEvent && currentEvent->type() == WebEvent::MouseDown) { - // We have a context menu event. + else if (event->type() == eventNames().contextmenuEvent && currentEvent->type() == WebEvent::MouseDown) { didHandleEvent = m_plugin->handleContextMenuEvent(static_cast<const WebMouseEvent&>(*currentEvent)); + pluginDidReceiveUserInteraction(); } else if ((event->type() == eventNames().keydownEvent && currentEvent->type() == WebEvent::KeyDown) || (event->type() == eventNames().keyupEvent && currentEvent->type() == WebEvent::KeyUp)) { - // We have a keyboard event. didHandleEvent = m_plugin->handleKeyboardEvent(static_cast<const WebKeyboardEvent&>(*currentEvent)); + pluginDidReceiveUserInteraction(); } if (didHandleEvent) @@ -853,11 +925,40 @@ bool PluginView::shouldAllowScripting() return m_plugin->shouldAllowScripting(); } +bool PluginView::shouldAllowNavigationFromDrags() const +{ + if (!m_isInitialized || !m_plugin) + return false; + + return m_plugin->shouldAllowNavigationFromDrags(); +} + +bool PluginView::shouldNotAddLayer() const +{ + return m_pluginElement->displayState() < HTMLPlugInElement::Restarting && !m_plugin->supportsSnapshotting(); +} + +PassRefPtr<SharedBuffer> PluginView::liveResourceData() const +{ + if (!m_isInitialized || !m_plugin) + return 0; + + return m_plugin->liveResourceData(); +} + +bool PluginView::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point) +{ + if (!m_isInitialized || !m_plugin) + return false; + + return m_plugin->performDictionaryLookupAtLocation(point); +} + void PluginView::notifyWidget(WidgetNotification notification) { switch (notification) { case WillPaintFlattened: - if (m_plugin && m_isInitialized) + if (shouldCreateTransientPaintingSnapshot()) m_transientPaintingSnapshot = m_plugin->snapshot(); break; case DidPaintFlattened: @@ -956,9 +1057,9 @@ void PluginView::focusPluginElement() ASSERT(frame()); if (Page* page = frame()->page()) - page->focusController()->setFocusedNode(m_pluginElement.get(), frame()); + page->focusController()->setFocusedElement(m_pluginElement.get(), frame()); else - frame()->document()->setFocusedNode(m_pluginElement); + frame()->document()->setFocusedElement(m_pluginElement); } void PluginView::pendingURLRequestsTimerFired() @@ -1010,6 +1111,8 @@ void PluginView::performFrameLoadURLRequest(URLRequest* request) return; } + UserGestureIndicator gestureIndicator(request->allowPopups() ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); + // First, try to find a target frame. Frame* targetFrame = frame->loader()->findFrameForNavigation(request->target()); if (!targetFrame) { @@ -1028,7 +1131,10 @@ void PluginView::performFrameLoadURLRequest(URLRequest* request) // Now ask the frame to load the request. targetFrame->loader()->load(FrameLoadRequest(targetFrame, request->request())); - WebFrame* targetWebFrame = static_cast<WebFrameLoaderClient*>(targetFrame->loader()->client())->webFrame(); + WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(targetFrame->loader()->client()); + WebFrame* targetWebFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0; + ASSERT(targetWebFrame); + if (WebFrame::LoadListener* loadListener = targetWebFrame->loadListener()) { // Check if another plug-in view or even this view is waiting for the frame to load. // If it is, tell it that the load was cancelled because it will be anyway. @@ -1094,7 +1200,7 @@ void PluginView::removeStream(Stream* stream) void PluginView::cancelAllStreams() { - Vector<RefPtr<Stream> > streams; + Vector<RefPtr<Stream>> streams; copyValuesToVector(m_streams, streams); for (size_t i = 0; i < streams.size(); ++i) @@ -1146,13 +1252,13 @@ void PluginView::invalidateRect(const IntRect& dirtyRect) return; #endif - if (m_pluginElement->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick) + if (m_pluginElement->displayState() < HTMLPlugInElement::Restarting) return; RenderBoxModelObject* renderer = toRenderBoxModelObject(m_pluginElement->renderer()); if (!renderer) return; - + IntRect contentRect(dirtyRect); contentRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop()); renderer->repaintRectangle(contentRect); @@ -1217,7 +1323,7 @@ void PluginView::cancelStreamLoad(uint64_t streamID) { // Keep a reference to the stream. Stream::cancel might remove the stream from the map, and thus // releasing its last reference. - RefPtr<Stream> stream = m_streams.get(streamID).get(); + RefPtr<Stream> stream = m_streams.get(streamID); if (!stream) return; @@ -1249,7 +1355,7 @@ NPObject* PluginView::windowScriptNPObject() return 0; } - return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld()->globalData(), frame()->script()->windowShell(pluginWorld())->window()); + return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld()->vm(), frame()->script()->windowShell(pluginWorld())->window()); } NPObject* PluginView::pluginElementNPObject() @@ -1265,7 +1371,7 @@ NPObject* PluginView::pluginElementNPObject() JSObject* object = frame()->script()->jsObjectForPluginElement(m_pluginElement.get()); ASSERT(object); - return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld()->globalData(), object); + return m_npRuntimeObjectMap.getOrCreateNPObject(*pluginWorld()->vm(), object); } bool PluginView::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result, bool allowPopups) @@ -1292,7 +1398,7 @@ void PluginView::setStatusbarText(const String& statusbarText) if (!page) return; - page->chrome()->setStatusbarText(frame(), statusbarText); + page->chrome().setStatusbarText(frame(), statusbarText); } bool PluginView::isAcceleratedCompositingEnabled() @@ -1304,20 +1410,29 @@ bool PluginView::isAcceleratedCompositingEnabled() if (!settings) return false; - if (m_pluginElement->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick) + // We know that some plug-ins can support snapshotting without needing + // accelerated compositing. Since we're trying to snapshot them anyway, + // put them into normal compositing mode. A side benefit is that this might + // allow the entire page to stay in that mode. + if (m_pluginElement->displayState() < HTMLPlugInElement::Restarting && m_parameters.mimeType == "application/x-shockwave-flash") return false; + return settings->acceleratedCompositingEnabled(); } void PluginView::pluginProcessCrashed() { + m_pluginProcessHasCrashed = true; + if (!m_pluginElement->renderer()) return; // FIXME: The renderer could also be a RenderApplet, we should handle that. if (!m_pluginElement->renderer()->isEmbeddedObject()) return; - + + m_pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); + RenderEmbeddedObject* renderer = toRenderEmbeddedObject(m_pluginElement->renderer()); renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginCrashed); @@ -1332,18 +1447,6 @@ void PluginView::willSendEventToPlugin() m_webPage->send(Messages::WebPageProxy::StopResponsivenessTimer()); } -#if PLATFORM(WIN) -HWND PluginView::nativeParentWindow() -{ - return m_webPage->nativeWindow(); -} - -void PluginView::scheduleWindowedPluginGeometryUpdate(const WindowGeometry& geometry) -{ - m_webPage->drawingArea()->scheduleChildWindowGeometryUpdate(geometry); -} -#endif - #if PLATFORM(MAC) void PluginView::pluginFocusOrWindowFocusChanged(bool pluginHasFocusAndWindowHasFocus) { @@ -1361,6 +1464,12 @@ mach_port_t PluginView::compositingRenderServerPort() { return WebProcess::shared().compositingRenderServerPort(); } + +void PluginView::openPluginPreferencePane() +{ + ASSERT_NOT_REACHED(); +} + #endif float PluginView::contentsScaleFactor() @@ -1410,7 +1519,7 @@ bool PluginView::isPrivateBrowsingEnabled() if (!frame()) return true; - if (!frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->tree()->top()->document()->securityOrigin())) + if (!frame()->document()->securityOrigin()->canAccessPluginStorage(frame()->document()->topOrigin())) return true; Settings* settings = frame()->settings(); @@ -1494,19 +1603,146 @@ void PluginView::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRe } #endif -void PluginView::pluginSnapshotTimerFired(DeferrableOneShotTimer<PluginView>* timer) +#if PLATFORM(MAC) +static bool isAlmostSolidColor(BitmapImage* bitmap) +{ + CGImageRef image = bitmap->getCGImageRef(); + ASSERT(CGImageGetBitsPerComponent(image) == 8); + + CGBitmapInfo imageInfo = CGImageGetBitmapInfo(image); + if (!(imageInfo & kCGBitmapByteOrder32Little) || (imageInfo & kCGBitmapAlphaInfoMask) != kCGImageAlphaPremultipliedFirst) { + // FIXME: Consider being able to handle other pixel formats. + ASSERT_NOT_REACHED(); + return false; + } + + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + size_t bytesPerRow = CGImageGetBytesPerRow(image); + + RetainPtr<CFDataRef> provider = adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(image))); + const UInt8* data = CFDataGetBytePtr(provider.get()); + + // Overlay a grid of sampling dots on top of a grayscale version of the image. + // For the interior points, calculate the difference in luminance among the sample point + // and its surrounds points, scaled by transparency. + const unsigned sampleRows = 7; + const unsigned sampleCols = 7; + // FIXME: Refine the proper number of samples, and accommodate different aspect ratios. + if (width < sampleCols || height < sampleRows) + return false; + + // Ensure that the last row/column land on the image perimeter. + const float strideWidth = static_cast<float>(width - 1) / (sampleCols - 1); + const float strideHeight = static_cast<float>(height - 1) / (sampleRows - 1); + float samples[sampleRows][sampleCols]; + + // Find the luminance of the sample points. + float y = 0; + const UInt8* row = data; + for (unsigned i = 0; i < sampleRows; ++i) { + float x = 0; + for (unsigned j = 0; j < sampleCols; ++j) { + const UInt8* p0 = row + (static_cast<int>(x + .5)) * 4; + // R G B A + samples[i][j] = (0.2125 * *p0 + 0.7154 * *(p0+1) + 0.0721 * *(p0+2)) * *(p0+3) / 255; + x += strideWidth; + } + y += strideHeight; + row = data + (static_cast<int>(y + .5)) * bytesPerRow; + } + + // Determine the image score. + float accumScore = 0; + for (unsigned i = 1; i < sampleRows - 1; ++i) { + for (unsigned j = 1; j < sampleCols - 1; ++j) { + float diff = samples[i - 1][j] + samples[i + 1][j] + samples[i][j - 1] + samples[i][j + 1] - 4 * samples[i][j]; + accumScore += diff * diff; + } + } + + // The score for a given sample can be within the range of 0 and 255^2. + return accumScore < 2500 * (sampleRows - 2) * (sampleCols - 2); +} +#endif + +void PluginView::pluginSnapshotTimerFired(DeferrableOneShotTimer<PluginView>*) { - ASSERT_UNUSED(timer, timer == &m_pluginSnapshotTimer); ASSERT(m_plugin); - // Snapshot might be 0 if plugin size is 0x0. - RefPtr<ShareableBitmap> snapshot = m_plugin->snapshot(); - RefPtr<Image> snapshotImage; - if (snapshot) - snapshotImage = snapshot->createImage(); - m_pluginElement->updateSnapshot(snapshotImage.release()); - destroyPluginAndReset(); - m_plugin = 0; + if (m_plugin->supportsSnapshotting()) { + // Snapshot might be 0 if plugin size is 0x0. + RefPtr<ShareableBitmap> snapshot = m_plugin->snapshot(); + RefPtr<Image> snapshotImage; + if (snapshot) + snapshotImage = snapshot->createImage(); + m_pluginElement->updateSnapshot(snapshotImage.get()); + +#if PLATFORM(MAC) + unsigned maximumSnapshotRetries = frame() ? frame()->settings()->maximumPlugInSnapshotAttempts() : 0; + if (snapshotImage && isAlmostSolidColor(static_cast<BitmapImage*>(snapshotImage.get())) && m_countSnapshotRetries < maximumSnapshotRetries) { + ++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); +} + +void PluginView::beginSnapshottingRunningPlugin() +{ + m_pluginSnapshotTimer.restart(); +} + +bool PluginView::shouldAlwaysAutoStart() const +{ + if (!m_plugin) + return PluginViewBase::shouldAlwaysAutoStart(); + + if (MIMETypeRegistry::isJavaAppletMIMEType(m_parameters.mimeType)) + return true; + + return m_plugin->shouldAlwaysAutoStart(); +} + +void PluginView::pluginDidReceiveUserInteraction() +{ + if (frame() && !frame()->settings()->plugInSnapshottingEnabled()) + return; + + if (m_didReceiveUserInteraction) + return; + + 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(); + + WebProcess::shared().plugInDidReceiveUserInteraction(pageOrigin, pluginOrigin, mimeType); +} + +bool PluginView::shouldCreateTransientPaintingSnapshot() const +{ + if (!m_plugin) + return false; + + if (!m_isInitialized) + return false; + + if (FrameView* frameView = frame()->view()) { + if (frameView->paintBehavior() & (PaintBehaviorSelectionOnly | 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; + } + } + + return true; } } // namespace WebKit |