WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
ah.
136197.11.patch (text/plain), 15.84 KB, created by
Gavin Barraclough
on 2014-09-10 13:37:38 PDT
(
hide
)
Description:
ah.
Filename:
MIME Type:
Creator:
Gavin Barraclough
Created:
2014-09-10 13:37:38 PDT
Size:
15.84 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 173476) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,48 @@ >+2014-09-03 Gavin Barraclough <barraclough@apple.com> >+ >+ DOM timer throttling for hidden plugins >+ https://bugs.webkit.org/show_bug.cgi?id=136197 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ For non-visible web pages we slow timers (since they can't be driving animations, etc). >+ We should do the same for plugins. >+ >+ There are a few steps to this: >+ - JSPluginElementFunctions notifies DOMTimer when script interacts with a plugin. >+ - DOMTimerFireState keeps a record of events that occur while a timer is firing. >+ - DOMTimer::fired detects timers that interact with invisible/inaudible plugins, and flags itself for throtting. >+ - DOMTimer::intervalClampedToMinimum sets timer intervals appropriately. >+ >+ * bindings/js/JSPluginElementFunctions.cpp: >+ (WebCore::pluginScriptObject): >+ - notify DOMTimer when script interacts with a plugin. >+ * html/HTMLPlugInElement.cpp: >+ (WebCore::HTMLPlugInElement::isDetectable): >+ * html/HTMLPlugInElement.h: >+ - added isDetectable, to check for visible / audible plugins. >+ * page/DOMTimer.cpp: >+ (WebCore::DOMTimerFireState::DOMTimerFireState): >+ (WebCore::DOMTimerFireState::~DOMTimerFireState): >+ - track current DOMTimerFireState. >+ (WebCore::DOMTimer::DOMTimer): >+ - initialize m_throttleState. >+ (WebCore::DOMTimer::scriptDidInteractWithPlugin): >+ - if interaction with a plugin occurs while a timer is firing, record on the DOMTimerFireState. >+ (WebCore::DOMTimer::fired): >+ - set DOMTimerFireState, and update m_throttleState accordingly. >+ (WebCore::DOMTimer::updateTimerIntervalIfNecessary): >+ - remove redundant check of maxTimerNestingLevel (covered by intervalClampedToMinimum). >+ (WebCore::DOMTimer::intervalClampedToMinimum): >+ - Also take m_throttleState into account when throttling. >+ * page/DOMTimer.h: >+ - added scriptDidInteractWithPlugin, m_throttleState. >+ * platform/audio/AudioHardwareListener.h: >+ - enum -> enum class. >+ * plugins/PluginViewBase.h: >+ (WebCore::PluginViewBase::audioHardwareActivity): >+ - expose audioHardwareActivity on PluginViewBase (previously available in subclass). >+ > 2014-09-10 Myles C. Maxfield <mmaxfield@apple.com> > > Laying out a TextRun using an SVG font is O(n^2) >Index: Source/WebCore/bindings/js/JSPluginElementFunctions.cpp >=================================================================== >--- Source/WebCore/bindings/js/JSPluginElementFunctions.cpp (revision 173476) >+++ Source/WebCore/bindings/js/JSPluginElementFunctions.cpp (working copy) >@@ -82,6 +82,9 @@ JSObject* pluginScriptObject(ExecState* > > HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element); > >+ // Choke point for script/plugin interaction; notify DOMTimer of the event. >+ DOMTimer::scriptDidInteractWithPlugin(pluginElement); >+ > // First, see if the element has a plug-in replacement with a script. > if (JSObject* scriptObject = pluginElement.scriptObjectForPluginReplacement()) > return scriptObject; >Index: Source/WebCore/html/HTMLPlugInElement.cpp >=================================================================== >--- Source/WebCore/html/HTMLPlugInElement.cpp (revision 173476) >+++ Source/WebCore/html/HTMLPlugInElement.cpp (working copy) >@@ -253,6 +253,23 @@ bool HTMLPlugInElement::isPluginElement( > return true; > } > >+bool HTMLPlugInElement::isUserObservable() const >+{ >+ // No widget - can't be anything to see or hear here. >+ Widget* widget = pluginWidget(); >+ if (!widget || !widget->isPluginViewBase()) >+ return false; >+ >+ PluginViewBase* pluginView = toPluginViewBase(widget); >+ >+ // If audio is playing (or might be) then the plugin is detectable. >+ if (pluginView->audioHardwareActivity() != AudioHardwareActivityType::IsInactive) >+ return true; >+ >+ // If the plugin is visible and not vanishingly small in either dimension it is detectable. >+ return pluginView->isVisible() && widget->width() > 2 && widget->height() > 2; >+} >+ > bool HTMLPlugInElement::supportsFocus() const > { > if (HTMLFrameOwnerElement::supportsFocus()) >Index: Source/WebCore/html/HTMLPlugInElement.h >=================================================================== >--- Source/WebCore/html/HTMLPlugInElement.h (revision 173476) >+++ Source/WebCore/html/HTMLPlugInElement.h (working copy) >@@ -88,6 +88,8 @@ public: > > virtual bool isPlugInImageElement() const { return false; } > >+ bool isUserObservable() const; >+ > protected: > HTMLPlugInElement(const QualifiedName& tagName, Document&); > >Index: Source/WebCore/page/DOMTimer.cpp >=================================================================== >--- Source/WebCore/page/DOMTimer.cpp (revision 173476) >+++ Source/WebCore/page/DOMTimer.cpp (working copy) >@@ -27,7 +27,9 @@ > #include "config.h" > #include "DOMTimer.h" > >+#include "HTMLPlugInElement.h" > #include "InspectorInstrumentation.h" >+#include "PluginViewBase.h" > #include "ScheduledAction.h" > #include "ScriptExecutionContext.h" > #include "UserGestureIndicator.h" >@@ -46,9 +48,42 @@ > namespace WebCore { > > static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko. >+static const int minIntervalForNonUserObservablePluginScriptTimers = 1000; // Empirically determined to maximize battery life. > static const int maxTimerNestingLevel = 5; > static const double oneMillisecond = 0.001; > >+struct DOMTimerFireState { >+ DOMTimerFireState(ScriptExecutionContext* context) >+ : scriptDidInteractWithNonUserObservablePlugin(false) >+ , scriptDidInteractWithUserObservablePlugin(false) >+ , shouldSetCurrent(context->isDocument()) >+ { >+ // For worker threads, don't update the current DOMTimerFireState. >+ // Setting this from workers would not be thread-safe, and its not relevant to current uses. >+ if (shouldSetCurrent) { >+ previous = current; >+ current = this; >+ } >+ } >+ >+ ~DOMTimerFireState() >+ { >+ if (shouldSetCurrent) >+ current = previous; >+ } >+ >+ static DOMTimerFireState* current; >+ >+ bool scriptDidInteractWithNonUserObservablePlugin; >+ bool scriptDidInteractWithUserObservablePlugin; >+ >+private: >+ bool shouldSetCurrent; >+ DOMTimerFireState* previous; >+}; >+ >+DOMTimerFireState* DOMTimerFireState::current = nullptr; >+ > static inline bool shouldForwardUserGesture(int interval, int nestingLevel) > { > return UserGestureIndicator::processingUserGesture() >@@ -61,6 +96,7 @@ DOMTimer::DOMTimer(ScriptExecutionContex > , m_nestingLevel(context->timerNestingLevel()) > , m_action(WTF::move(action)) > , m_originalInterval(interval) >+ , m_throttleState(Undetermined) > , m_currentTimerInterval(intervalClampedToMinimum()) > , m_shouldForwardUserGesture(shouldForwardUserGesture(interval, m_nestingLevel)) > { >@@ -112,6 +148,17 @@ void DOMTimer::removeById(ScriptExecutio > context->removeTimeout(timeoutId); > } > >+void DOMTimer::scriptDidInteractWithPlugin(HTMLPlugInElement& pluginElement) >+{ >+ if (!DOMTimerFireState::current) >+ return; >+ >+ if (pluginElement.isUserObservable()) >+ DOMTimerFireState::current->scriptDidInteractWithUserObservablePlugin = true; >+ else >+ DOMTimerFireState::current->scriptDidInteractWithNonUserObservablePlugin = true; >+} >+ > void DOMTimer::fired() > { > // Retain this - if the timer is cancelled while this function is on the stack (implicitly and always >@@ -121,6 +168,9 @@ void DOMTimer::fired() > > ScriptExecutionContext* context = scriptExecutionContext(); > ASSERT(context); >+ >+ DOMTimerFireState fireState(context); >+ > #if PLATFORM(IOS) > Document* document = nullptr; > if (context->isDocument()) { >@@ -149,6 +199,14 @@ void DOMTimer::fired() > > InspectorInstrumentation::didFireTimer(cookie); > >+ if (fireState.scriptDidInteractWithUserObservablePlugin && m_throttleState != ShouldNotThrottle) { >+ m_throttleState = ShouldNotThrottle; >+ updateTimerIntervalIfNecessary(); >+ } else if (fireState.scriptDidInteractWithNonUserObservablePlugin && m_throttleState == Undetermined) { >+ m_throttleState = ShouldThrottle; >+ updateTimerIntervalIfNecessary(); >+ } >+ > return; > } > >@@ -199,8 +257,6 @@ void DOMTimer::didStop() > void DOMTimer::updateTimerIntervalIfNecessary() > { > ASSERT(m_nestingLevel <= maxTimerNestingLevel); >- if (m_nestingLevel < maxTimerNestingLevel) >- return; > > double previousInterval = m_currentTimerInterval; > m_currentTimerInterval = intervalClampedToMinimum(); >@@ -220,12 +276,17 @@ double DOMTimer::intervalClampedToMinimu > ASSERT(scriptExecutionContext()); > ASSERT(m_nestingLevel <= maxTimerNestingLevel); > >- double minimumTimerInterval = scriptExecutionContext()->minimumTimerInterval(); >- double intervalMilliseconds = std::max(oneMillisecond, m_originalInterval * oneMillisecond); >+ double intervalInSeconds = std::max(oneMillisecond, m_originalInterval * oneMillisecond); >+ >+ // Only apply throttling to repeating timers. >+ if (m_nestingLevel < maxTimerNestingLevel) >+ return intervalInSeconds; > >- if (intervalMilliseconds < minimumTimerInterval && m_nestingLevel == maxTimerNestingLevel) >- intervalMilliseconds = minimumTimerInterval; >- return intervalMilliseconds; >+ // Apply two throttles - the global (per Page) minimum, and also a per-timer throttle. >+ intervalInSeconds = std::max(intervalInSeconds, scriptExecutionContext()->minimumTimerInterval()); >+ if (m_throttleState == ShouldThrottle) >+ intervalInSeconds = std::max(intervalInSeconds, minIntervalForNonUserObservablePluginScriptTimers * oneMillisecond); >+ return intervalInSeconds; > } > > double DOMTimer::alignedFireTime(double fireTime) const >Index: Source/WebCore/page/DOMTimer.h >=================================================================== >--- Source/WebCore/page/DOMTimer.h (revision 173476) >+++ Source/WebCore/page/DOMTimer.h (working copy) >@@ -33,6 +33,7 @@ > > namespace WebCore { > >+ class HTMLPlugInElement; > class ScheduledAction; > > class DOMTimer final : public RefCounted<DOMTimer>, public SuspendableTimer { >@@ -48,6 +49,8 @@ namespace WebCore { > // setting for the context has changed). > void updateTimerIntervalIfNecessary(); > >+ static void scriptDidInteractWithPlugin(HTMLPlugInElement&); >+ > private: > DOMTimer(ScriptExecutionContext*, std::unique_ptr<ScheduledAction>, int interval, bool singleShot); > double intervalClampedToMinimum() const; >@@ -57,10 +60,17 @@ namespace WebCore { > virtual void didStop() override; > virtual double alignedFireTime(double) const override; > >+ enum TimerThrottleState { >+ Undetermined, >+ ShouldThrottle, >+ ShouldNotThrottle >+ }; >+ > int m_timeoutId; > int m_nestingLevel; > std::unique_ptr<ScheduledAction> m_action; > int m_originalInterval; >+ TimerThrottleState m_throttleState; > double m_currentTimerInterval; > bool m_shouldForwardUserGesture; > }; >Index: Source/WebCore/plugins/PluginViewBase.h >=================================================================== >--- Source/WebCore/plugins/PluginViewBase.h (revision 173476) >+++ Source/WebCore/plugins/PluginViewBase.h (working copy) >@@ -25,6 +25,7 @@ > #ifndef PluginWidget_h > #define PluginWidget_h > >+#include "AudioHardwareListener.h" > #include "PlatformLayer.h" > #include "ScrollTypes.h" > #include "Widget.h" >@@ -74,6 +75,8 @@ public: > virtual bool isPluginViewBase() const { return true; } > virtual bool shouldNotAddLayer() const { return false; } > >+ virtual AudioHardwareActivityType audioHardwareActivity() const { return AudioHardwareActivityType::Unknown; } >+ > protected: > explicit PluginViewBase(PlatformWidget widget = 0) : Widget(widget) { } > }; >Index: Source/WebKit2/ChangeLog >=================================================================== >--- Source/WebKit2/ChangeLog (revision 173476) >+++ Source/WebKit2/ChangeLog (working copy) >@@ -1,3 +1,19 @@ >+2014-09-03 Gavin Barraclough <barraclough@apple.com> >+ >+ DOM timer throttling for hidden plugins >+ https://bugs.webkit.org/show_bug.cgi?id=136197 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ For non-visible web pages we slow timers (since they can't be driving animations, etc). >+ We should do the same for plugins. >+ >+ * PluginProcess/WebProcessConnection.cpp: >+ * WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp: >+ - remove now redundant includes. >+ * WebProcess/Plugins/PluginView.h: >+ - audioHardwareActivity is now virtual, override. >+ > 2014-09-10 Antti Koivisto <antti@apple.com> > > NetworkResourceLoader cleanups >Index: Source/WebKit2/PluginProcess/WebProcessConnection.cpp >=================================================================== >--- Source/WebKit2/PluginProcess/WebProcessConnection.cpp (revision 173476) >+++ Source/WebKit2/PluginProcess/WebProcessConnection.cpp (working copy) >@@ -39,7 +39,6 @@ > #include "PluginProcessConnectionMessages.h" > #include "PluginProxyMessages.h" > #include "WebProcessConnectionMessages.h" >-#include <WebCore/AudioHardwareListener.h> > #include <unistd.h> > #include <wtf/RunLoop.h> > >Index: Source/WebKit2/WebProcess/Plugins/PluginView.cpp >=================================================================== >--- Source/WebKit2/WebProcess/Plugins/PluginView.cpp (revision 173476) >+++ Source/WebKit2/WebProcess/Plugins/PluginView.cpp (working copy) >@@ -514,6 +514,18 @@ void PluginView::viewStateDidChange(View > m_plugin->windowFocusChanged(m_webPage->windowIsFocused()); > } > >+WebCore::AudioHardwareActivityType PluginView::audioHardwareActivity() const >+{ >+ if (!m_isInitialized || !m_plugin) >+ return AudioHardwareActivityType::IsInactive; >+ >+#if PLATFORM(COCOA) >+ return m_plugin->audioHardwareActivity(); >+#else >+ return AudioHardwareActivityType::Unknown; >+#endif >+} >+ > #if PLATFORM(COCOA) > void PluginView::setDeviceScaleFactor(float scaleFactor) > { >@@ -543,11 +555,6 @@ bool PluginView::sendComplexTextInput(ui > return true; > } > >-WebCore::AudioHardwareActivityType PluginView::audioHardwareActivity() const >-{ >- return m_plugin->audioHardwareActivity(); >-} >- > NSObject *PluginView::accessibilityObject() const > { > if (!m_isInitialized || !m_plugin) >Index: Source/WebKit2/WebProcess/Plugins/PluginView.h >=================================================================== >--- Source/WebKit2/WebProcess/Plugins/PluginView.h (revision 173476) >+++ Source/WebKit2/WebProcess/Plugins/PluginView.h (working copy) >@@ -109,7 +109,7 @@ public: > > PassRefPtr<WebCore::SharedBuffer> liveResourceData() const; > bool performDictionaryLookupAtLocation(const WebCore::FloatPoint&); >- WebCore::AudioHardwareActivityType audioHardwareActivity() const; >+ virtual WebCore::AudioHardwareActivityType audioHardwareActivity() const override; > > private: > PluginView(PassRefPtr<WebCore::HTMLPlugInElement>, PassRefPtr<Plugin>, const Plugin::Parameters& parameters); >Index: Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp >=================================================================== >--- Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp (revision 173476) >+++ Source/WebKit2/WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp (working copy) >@@ -39,7 +39,6 @@ > #include <JavaScriptCore/SourceCode.h> > #include <JavaScriptCore/Strong.h> > #include <JavaScriptCore/StrongInlines.h> >-#include <WebCore/AudioHardwareListener.h> > #include <WebCore/DOMWrapperWorld.h> > #include <WebCore/Frame.h> > #include <WebCore/Page.h>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 136197
:
237044
|
237585
|
237598
|
237614
|
237618
|
237726
|
237794
|
237813
|
237897
| 237903