/* * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "PluginHalter.h" #include "HaltablePlugin.h" #include "PlatformString.h" #include <wtf/CurrentTime.h> #include <wtf/Vector.h> using namespace std; namespace WebCore { PluginHalter::PluginHalter(PluginHalterClient* client) : m_client(client) , m_timer(this, &PluginHalter::timerFired) , m_pluginAllowedRunTime(numeric_limits<unsigned>::max()) { ASSERT_ARG(client, client); } void PluginHalter::didStartPlugin(HaltablePlugin* obj) { ASSERT_ARG(obj, obj); ASSERT_ARG(obj, !m_plugins.contains(obj)); if (!m_client->enabled()) return; double currentTime = WTF::currentTime(); m_plugins.add(obj, currentTime); if (m_plugins.size() == 1) m_oldestStartTime = currentTime; startTimerIfNecessary(); } void PluginHalter::didStopPlugin(HaltablePlugin* obj) { if (!m_client->enabled()) return; m_plugins.remove(obj); } void PluginHalter::timerFired(Timer<PluginHalter>*) { if (m_plugins.isEmpty()) return; Vector<HaltablePlugin*> plugins; copyKeysToVector(m_plugins, plugins); // Plug-ins older than this are candidates to be halted. double pluginCutOffTime = WTF::currentTime() - m_pluginAllowedRunTime; m_oldestStartTime = numeric_limits<double>::max(); for (size_t i = 0; i < plugins.size(); ++i) { double thisStartTime = m_plugins.get(plugins[i]); if (thisStartTime > pluginCutOffTime) { // This plug-in is too young to be halted. We find the oldest // plug-in that is not old enough to be halted and use it to set // the timer's next fire time. if (thisStartTime < m_oldestStartTime) m_oldestStartTime = thisStartTime; continue; } if (m_client->shouldHaltPlugin(plugins[i]->node(), plugins[i]->isWindowed(), plugins[i]->pluginName())) plugins[i]->halt(); m_plugins.remove(plugins[i]); } startTimerIfNecessary(); } void PluginHalter::startTimerIfNecessary() { if (m_timer.isActive()) return; if (m_plugins.isEmpty()) return; double nextFireInterval = static_cast<double>(m_pluginAllowedRunTime) - (currentTime() - m_oldestStartTime); m_timer.startOneShot(nextFireInterval < 0 ? 0 : nextFireInterval); } } // namespace WebCore