Title: [145421] trunk/Source/WebCore
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)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to