Diff
Modified: trunk/Source/WebCore/ChangeLog (218912 => 218913)
--- trunk/Source/WebCore/ChangeLog 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/ChangeLog 2017-06-29 03:54:05 UTC (rev 218913)
@@ -1,3 +1,27 @@
+2017-06-28 Zalan Bujtas <[email protected]>
+
+ Move RenderEmbeddedObject::isReplacementObscured to HTMLPlugInElement
+ https://bugs.webkit.org/show_bug.cgi?id=173802
+ <rdar://problem/32884389>
+
+ Reviewed by Simon Fraser.
+
+ Hittesting could potentially destroy "this" renderer so calling it inside RenderEmbeddedObject
+ could leave the caller with a stale pointer.
+ This patch protects the plugin element from getting destroyed and checks if the renderer got
+ deleted during the hittest to avoid nullptr dereference.
+
+ Speculative fix.
+
+ * html/HTMLPlugInElement.cpp:
+ (WebCore::HTMLPlugInElement::isReplacementObscured):
+ * html/HTMLPlugInElement.h:
+ * rendering/RenderEmbeddedObject.cpp:
+ (WebCore::RenderEmbeddedObject::isReplacementObscured): Deleted.
+ * rendering/RenderEmbeddedObject.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::isPluginUnavailabilityIndicatorObscured):
+
2017-06-28 Chris Dumez <[email protected]>
Avoid copying statistics in ResourceLoadStatisticsStore::readDataFromDecoder()
Modified: trunk/Source/WebCore/html/HTMLPlugInElement.cpp (218912 => 218913)
--- trunk/Source/WebCore/html/HTMLPlugInElement.cpp 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/html/HTMLPlugInElement.cpp 2017-06-29 03:54:05 UTC (rev 218913)
@@ -32,6 +32,7 @@
#include "FrameLoader.h"
#include "FrameTree.h"
#include "HTMLNames.h"
+#include "HitTestResult.h"
#include "Logging.h"
#include "MIMETypeRegistry.h"
#include "Page.h"
@@ -39,7 +40,9 @@
#include "PluginReplacement.h"
#include "PluginViewBase.h"
#include "RenderEmbeddedObject.h"
+#include "RenderLayer.h"
#include "RenderSnapshottedPlugIn.h"
+#include "RenderView.h"
#include "RenderWidget.h"
#include "RuntimeEnabledFeatures.h"
#include "ScriptController.h"
@@ -396,4 +399,78 @@
return nullptr;
}
+// Return whether or not the replacement content for blocked plugins is accessible to the user.
+bool HTMLPlugInElement::isReplacementObscured(const String& unavailabilityDescription)
+{
+ if (!is<RenderEmbeddedObject>(renderer()))
+ return false;
+ Ref<HTMLPlugInElement> protectedThis(*this);
+ downcast<RenderEmbeddedObject>(*renderer()).setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription);
+ bool replacementIsObscured = isReplacementObscured();
+ // hittest in isReplacementObscured() method could destroy the renderer. Let's refetch it.
+ if (is<RenderEmbeddedObject>(renderer()))
+ downcast<RenderEmbeddedObject>(*renderer()).setUnavailablePluginIndicatorIsHidden(replacementIsObscured);
+ return replacementIsObscured;
}
+
+bool HTMLPlugInElement::isReplacementObscured()
+{
+ // We should always start hit testing a clean tree.
+ if (document().view())
+ document().view()->updateLayoutAndStyleIfNeededRecursive();
+ // Check if style recalc/layout destroyed the associated renderer.
+ auto* renderView = document().topDocument().renderView();
+ if (!document().view() || !renderView)
+ return false;
+ if (!renderer() || !is<RenderEmbeddedObject>(*renderer()))
+ return false;
+ auto& pluginRenderer = downcast<RenderEmbeddedObject>(*renderer());
+ // Check the opacity of each layer containing the element or its ancestors.
+ float opacity = 1.0;
+ for (auto* layer = pluginRenderer.enclosingLayer(); layer; layer = layer->parent()) {
+ opacity *= layer->renderer().style().opacity();
+ if (opacity < 0.1)
+ return true;
+ }
+ // Calculate the absolute rect for the blocked plugin replacement text.
+ LayoutPoint absoluteLocation(pluginRenderer.absoluteBoundingBoxRect().location());
+ LayoutRect rect = pluginRenderer.unavailablePluginIndicatorBounds(absoluteLocation);
+ if (rect.isEmpty())
+ return true;
+ auto viewRect = document().view()->convertToRootView(snappedIntRect(rect));
+ auto x = viewRect.x();
+ auto y = viewRect.y();
+ auto width = viewRect.width();
+ auto height = viewRect.height();
+ // Hit test the center and near the corners of the replacement text to ensure
+ // it is visible and is not masked by other elements.
+ HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
+ HitTestResult result;
+ HitTestLocation location = LayoutPoint(x + width / 2, y + height / 2);
+ bool hit = renderView->hitTest(request, location, result);
+ if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
+ return true;
+
+ location = LayoutPoint(x, y);
+ hit = renderView->hitTest(request, location, result);
+ if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
+ return true;
+
+ location = LayoutPoint(x + width, y);
+ hit = renderView->hitTest(request, location, result);
+ if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
+ return true;
+
+ location = LayoutPoint(x + width, y + height);
+ hit = renderView->hitTest(request, location, result);
+ if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
+ return true;
+
+ location = LayoutPoint(x, y + height);
+ hit = renderView->hitTest(request, location, result);
+ if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
+ return true;
+ return false;
+}
+
+}
Modified: trunk/Source/WebCore/html/HTMLPlugInElement.h (218912 => 218913)
--- trunk/Source/WebCore/html/HTMLPlugInElement.h 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/html/HTMLPlugInElement.h 2017-06-29 03:54:05 UTC (rev 218913)
@@ -81,7 +81,10 @@
virtual bool isPlugInImageElement() const { return false; }
bool isUserObservable() const;
-
+
+ WEBCORE_EXPORT bool isReplacementObscured(const String& unavailabilityDescription);
+ WEBCORE_EXPORT bool isReplacementObscured();
+
protected:
HTMLPlugInElement(const QualifiedName& tagName, Document&);
Modified: trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp (218912 => 218913)
--- trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp 2017-06-29 03:54:05 UTC (rev 218913)
@@ -49,7 +49,6 @@
#include "Path.h"
#include "PlatformMouseEvent.h"
#include "PluginViewBase.h"
-#include "RenderLayer.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "Settings.h"
@@ -400,74 +399,6 @@
return getReplacementTextGeometry(accumulatedOffset);
}
-bool RenderEmbeddedObject::isReplacementObscured() const
-{
- // Return whether or not the replacement content for blocked plugins is accessible to the user.
-
- // Check the opacity of each layer containing the element or its ancestors.
- float opacity = 1.0;
- for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) {
- opacity *= layer->renderer().style().opacity();
- if (opacity < 0.1)
- return true;
- }
-
- // Calculate the absolute rect for the blocked plugin replacement text.
- IntRect absoluteBoundingBox = absoluteBoundingBoxRect();
- LayoutPoint absoluteLocation(absoluteBoundingBox.location());
- LayoutRect rect = unavailablePluginIndicatorBounds(absoluteLocation);
- if (rect.isEmpty())
- return true;
-
- RenderView* rootRenderView = document().topDocument().renderView();
- ASSERT(rootRenderView);
- if (!rootRenderView)
- return true;
-
- // We should always start hit testing a clean tree.
- view().frameView().updateLayoutAndStyleIfNeededRecursive();
-
- HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
- HitTestResult result;
- HitTestLocation location;
-
- IntRect rootViewRect = view().frameView().convertToRootView(snappedIntRect(rect));
- LayoutUnit x = rootViewRect.x();
- LayoutUnit y = rootViewRect.y();
- LayoutUnit width = rootViewRect.width();
- LayoutUnit height = rootViewRect.height();
-
- // Hit test the center and near the corners of the replacement text to ensure
- // it is visible and is not masked by other elements.
- bool hit = false;
- location = LayoutPoint(x + width / 2, y + height / 2);
- hit = rootRenderView->hitTest(request, location, result);
- if (!hit || result.innerNode() != &frameOwnerElement())
- return true;
-
- location = LayoutPoint(x, y);
- hit = rootRenderView->hitTest(request, location, result);
- if (!hit || result.innerNode() != &frameOwnerElement())
- return true;
-
- location = LayoutPoint(x + width, y);
- hit = rootRenderView->hitTest(request, location, result);
- if (!hit || result.innerNode() != &frameOwnerElement())
- return true;
-
- location = LayoutPoint(x + width, y + height);
- hit = rootRenderView->hitTest(request, location, result);
- if (!hit || result.innerNode() != &frameOwnerElement())
- return true;
-
- location = LayoutPoint(x, y + height);
- hit = rootRenderView->hitTest(request, location, result);
- if (!hit || result.innerNode() != &frameOwnerElement())
- return true;
-
- return false;
-}
-
void RenderEmbeddedObject::layout()
{
StackStats::LayoutCheckPoint layoutCheckPoint;
Modified: trunk/Source/WebCore/rendering/RenderEmbeddedObject.h (218912 => 218913)
--- trunk/Source/WebCore/rendering/RenderEmbeddedObject.h 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/rendering/RenderEmbeddedObject.h 2017-06-29 03:54:05 UTC (rev 218913)
@@ -54,10 +54,9 @@
void handleUnavailablePluginIndicatorEvent(Event*);
- WEBCORE_EXPORT bool isReplacementObscured() const;
-
bool allowsAcceleratedCompositing() const;
+ LayoutRect unavailablePluginIndicatorBounds(const LayoutPoint& accumulatedOffset) const;
protected:
void paintReplaced(PaintInfo&, const LayoutPoint&) final;
void paint(PaintInfo&, const LayoutPoint&) override;
@@ -88,7 +87,6 @@
bool isInUnavailablePluginIndicator(const FloatPoint&) const;
void getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, FontCascade&, TextRun&, float& textWidth) const;
LayoutRect getReplacementTextGeometry(const LayoutPoint& accumulatedOffset) const;
- LayoutRect unavailablePluginIndicatorBounds(const LayoutPoint&) const;
bool canHaveChildren() const final;
virtual bool canHaveWidget() const { return true; }
Modified: trunk/Source/WebCore/testing/Internals.cpp (218912 => 218913)
--- trunk/Source/WebCore/testing/Internals.cpp 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebCore/testing/Internals.cpp 2017-06-29 03:54:05 UTC (rev 218913)
@@ -3196,10 +3196,10 @@
ExceptionOr<bool> Internals::isPluginUnavailabilityIndicatorObscured(Element& element)
{
auto* renderer = element.renderer();
- if (!is<RenderEmbeddedObject>(renderer))
+ if (!is<HTMLPlugInElement>(element) || !is<RenderEmbeddedObject>(renderer))
return Exception { INVALID_ACCESS_ERR };
- return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
+ return downcast<HTMLPlugInElement>(element).isReplacementObscured();
}
bool Internals::isPluginSnapshotted(Element& element)
Modified: trunk/Source/WebKit2/ChangeLog (218912 => 218913)
--- trunk/Source/WebKit2/ChangeLog 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebKit2/ChangeLog 2017-06-29 03:54:05 UTC (rev 218913)
@@ -1,3 +1,14 @@
+2017-06-29 Zalan Bujtas <[email protected]>
+
+ Move RenderEmbeddedObject::isReplacementObscured to HTMLPlugInElement
+ https://bugs.webkit.org/show_bug.cgi?id=173802
+ <rdar://problem/32884389>
+
+ Reviewed by Simon Fraser.
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::createPlugin):
+
2017-06-28 Ryosuke Niwa <[email protected]>
REGRESSION (r218842): com.apple.WebKit crash in WebKit::ProcessLauncher::launchProcess
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (218912 => 218913)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2017-06-29 03:28:47 UTC (rev 218912)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2017-06-29 03:54:05 UTC (rev 218913)
@@ -771,7 +771,6 @@
#endif
#if ENABLE(NETSCAPE_PLUGIN_API)
-
RefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters, String& newMIMEType)
{
String frameURLString = frame->coreFrame()->loader().documentLoader()->responseURL().string();
@@ -809,16 +808,7 @@
}
if (isBlockedPlugin) {
- bool replacementObscured = false;
- auto* renderer = pluginElement->renderer();
- if (is<RenderEmbeddedObject>(renderer)) {
- auto& renderObject = downcast<RenderEmbeddedObject>(*renderer);
- renderObject.setPluginUnavailabilityReasonWithDescription(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription);
- replacementObscured = renderObject.isReplacementObscured();
- renderObject.setUnavailablePluginIndicatorIsHidden(replacementObscured);
- }
-
- send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, replacementObscured));
+ send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, pluginElement->isReplacementObscured(unavailabilityDescription)));
return nullptr;
}
@@ -828,7 +818,6 @@
bool isRestartedProcess = (pluginElement->displayState() == HTMLPlugInElement::Restarting || pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick);
return PluginProxy::create(pluginProcessToken, isRestartedProcess);
}
-
#endif // ENABLE(NETSCAPE_PLUGIN_API)
#if ENABLE(WEBGL) && !PLATFORM(COCOA)