- Revision
- 145421
- Author
- [email protected]
- Date
- 2013-03-11 15:51:43 -0700 (Mon, 11 Mar 2013)
Log Message
Plugins created during user gestures (or soon after) should not be snapshotted
https://bugs.webkit.org/show_bug.cgi?id=111975
Reviewed by Tim Horton.
There are sites which create plugins in response to user actions, such as clicking
on an image that is acting like a poster frame. In those cases we should never snapshot.
There are some other sites which also create plugins in response to user actions,
but don't necessarily create the content themselves. Instead they run some script
that injects an iframe, and the frame loads a plugin. In order to make sure we don't
snapshot in those cases, we're adding the concept of a blessed plugin. Anything that
is created soon after a *handled* user gesture is not snapshotted. To do this we
mark a timestamp in the document when we've called an event listener for a user
gesture. The plugin element then compares its creation time with the most recent
user action time.
* dom/Document.cpp:
(WebCore::Document::Document): Initialise new timestamp.
(WebCore::Document::resetLastHandledUserGestureTimestamp): Sets the member variable
to the current time.
* dom/Document.h:
(WebCore::Document::lastHandledUserGestureTimestamp): Getter.
* dom/EventTarget.cpp:
(WebCore::EventTarget::fireEventListeners): If there were some event listeners and
we were processing a user gesture, then reset the timestamp in the document.
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement): Remember if we were created
during a user gesture.
(WebCore::HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn): Start the plugin
if we were created during a user gesture, or if we are close enough in time
to a listener that fired in relation to a user gesture.
* html/HTMLPlugInImageElement.h: New private member flag indicating if we were
in a user gesture when constructed.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (145420 => 145421)
--- trunk/Source/WebCore/ChangeLog 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/ChangeLog 2013-03-11 22:51:43 UTC (rev 145421)
@@ -1,3 +1,42 @@
+2013-03-11 Dean Jackson <[email protected]>
+
+ Plugins created during user gestures (or soon after) should not be snapshotted
+ https://bugs.webkit.org/show_bug.cgi?id=111975
+
+ Reviewed by Tim Horton.
+
+ There are sites which create plugins in response to user actions, such as clicking
+ on an image that is acting like a poster frame. In those cases we should never snapshot.
+
+ There are some other sites which also create plugins in response to user actions,
+ but don't necessarily create the content themselves. Instead they run some script
+ that injects an iframe, and the frame loads a plugin. In order to make sure we don't
+ snapshot in those cases, we're adding the concept of a blessed plugin. Anything that
+ is created soon after a *handled* user gesture is not snapshotted. To do this we
+ mark a timestamp in the document when we've called an event listener for a user
+ gesture. The plugin element then compares its creation time with the most recent
+ user action time.
+
+ * dom/Document.cpp:
+ (WebCore::Document::Document): Initialise new timestamp.
+ (WebCore::Document::resetLastHandledUserGestureTimestamp): Sets the member variable
+ to the current time.
+ * dom/Document.h:
+ (WebCore::Document::lastHandledUserGestureTimestamp): Getter.
+
+ * dom/EventTarget.cpp:
+ (WebCore::EventTarget::fireEventListeners): If there were some event listeners and
+ we were processing a user gesture, then reset the timestamp in the document.
+
+ * html/HTMLPlugInImageElement.cpp:
+ (WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement): Remember if we were created
+ during a user gesture.
+ (WebCore::HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn): Start the plugin
+ if we were created during a user gesture, or if we are close enough in time
+ to a listener that fired in relation to a user gesture.
+ * html/HTMLPlugInImageElement.h: New private member flag indicating if we were
+ in a user gesture when constructed.
+
2013-03-11 Jeffrey Pfau <[email protected]>
List cache partitions as units instead of as their contents
Modified: trunk/Source/WebCore/dom/Document.cpp (145420 => 145421)
--- trunk/Source/WebCore/dom/Document.cpp 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/dom/Document.cpp 2013-03-11 22:51:43 UTC (rev 145421)
@@ -476,6 +476,7 @@
, m_writeRecursionIsTooDeep(false)
, m_writeRecursionDepth(0)
, m_wheelEventHandlerCount(0)
+ , m_lastHandledUserGestureTimestamp(0)
, m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
, m_scheduledTasksAreSuspended(false)
, m_visualUpdatesAllowed(true)
@@ -5677,6 +5678,11 @@
}
#endif
+void Document::resetLastHandledUserGestureTimestamp()
+{
+ m_lastHandledUserGestureTimestamp = currentTime();
+}
+
HTMLIFrameElement* Document::seamlessParentIFrame() const
{
if (!shouldDisplaySeamlesslyWithParent())
Modified: trunk/Source/WebCore/dom/Document.h (145420 => 145421)
--- trunk/Source/WebCore/dom/Document.h 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/dom/Document.h 2013-03-11 22:51:43 UTC (rev 145421)
@@ -1101,6 +1101,9 @@
void didAddWheelEventHandler();
void didRemoveWheelEventHandler();
+ double lastHandledUserGestureTimestamp() const { return m_lastHandledUserGestureTimestamp; }
+ void resetLastHandledUserGestureTimestamp();
+
#if ENABLE(TOUCH_EVENTS)
bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; }
#else
@@ -1513,6 +1516,8 @@
OwnPtr<TouchEventTargetSet> m_touchEventTargets;
#endif
+ double m_lastHandledUserGestureTimestamp;
+
#if ENABLE(REQUEST_ANIMATION_FRAME)
RefPtr<ScriptedAnimationController> m_scriptedAnimationController;
#endif
Modified: trunk/Source/WebCore/dom/EventTarget.cpp (145420 => 145421)
--- trunk/Source/WebCore/dom/EventTarget.cpp 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/dom/EventTarget.cpp 2013-03-11 22:51:43 UTC (rev 145421)
@@ -232,6 +232,7 @@
// dispatch. Conveniently, all new event listeners will be added after 'end',
// so iterating to 'end' naturally excludes new event listeners.
+ bool userEventWasHandled = false;
size_t i = 0;
size_t end = entry.size();
if (!d->firingEventIterators)
@@ -254,9 +255,18 @@
// To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
// event listeners, even though that violates some versions of the DOM spec.
registeredListener.listener->handleEvent(context, event);
+ if (!userEventWasHandled && ScriptController::processingUserGesture())
+ userEventWasHandled = true;
InspectorInstrumentation::didHandleEvent(cookie);
}
d->firingEventIterators->removeLast();
+ if (userEventWasHandled) {
+ ScriptExecutionContext* context = scriptExecutionContext();
+ if (context && context->isDocument()) {
+ Document* document = static_cast<Document*>(context);
+ document->resetLastHandledUserGestureTimestamp();
+ }
+ }
}
const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
Modified: trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp (145420 => 145421)
--- trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp 2013-03-11 22:51:43 UTC (rev 145421)
@@ -58,6 +58,7 @@
static const int sizingMediumWidthThreshold = 450;
static const int sizingMediumHeightThreshold = 300;
static const float sizingFullPageAreaRatioThreshold = 0.96;
+static const float autostartSoonAfterUserGestureThreshold = 5.0;
// This delay should not exceed the snapshot delay in PluginView.cpp
static const double simulatedMouseClickTimerDelay = .75;
@@ -74,6 +75,7 @@
, m_isPrimarySnapshottedPlugIn(false)
, m_simulatedMouseClickTimer(this, &HTMLPlugInImageElement::simulatedMouseClickTimerFired, simulatedMouseClickTimerDelay)
, m_swapRendererTimer(this, &HTMLPlugInImageElement::swapRendererTimerFired)
+ , m_createdDuringUserGesture(ScriptController::processingUserGesture())
{
setHasCustomStyleCallbacks();
}
@@ -444,6 +446,19 @@
return;
}
+ if (m_createdDuringUserGesture) {
+ LOG(Plugins, "%p Plug-in was created when processing user gesture, set to play", this);
+ return;
+ }
+
+ double lastKnownUserGestureTimestamp = document()->lastHandledUserGestureTimestamp();
+ if (!inMainFrame && document()->page()->mainFrame() && document()->page()->mainFrame()->document())
+ lastKnownUserGestureTimestamp = std::max(lastKnownUserGestureTimestamp, document()->page()->mainFrame()->document()->lastHandledUserGestureTimestamp());
+ if (currentTime() - lastKnownUserGestureTimestamp < autostartSoonAfterUserGestureThreshold) {
+ LOG(Plugins, "%p Plug-in was created shortly after a user gesture, set to play", this);
+ return;
+ }
+
RenderBox* renderEmbeddedObject = toRenderBox(renderer());
Length styleWidth = renderEmbeddedObject->style()->width();
Length styleHeight = renderEmbeddedObject->style()->height();
Modified: trunk/Source/WebCore/html/HTMLPlugInImageElement.h (145420 => 145421)
--- trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2013-03-11 22:45:06 UTC (rev 145420)
+++ trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2013-03-11 22:51:43 UTC (rev 145421)
@@ -125,6 +125,7 @@
DeferrableOneShotTimer<HTMLPlugInImageElement> m_simulatedMouseClickTimer;
Timer<HTMLPlugInImageElement> m_swapRendererTimer;
RefPtr<Image> m_snapshotImage;
+ bool m_createdDuringUserGesture;
};
inline HTMLPlugInImageElement* toHTMLPlugInImageElement(Node* node)