1 /* 2 * Copyright (C) 2009 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #include "PluginHalter.h" 29 30 #include "HaltablePlugin.h" 31 #include "PlatformString.h" 32 #include <wtf/CurrentTime.h> 33 #include <wtf/Vector.h> 34 35 using namespace std; 36 37 namespace WebCore { 38 39 PluginHalter::PluginHalter(PluginHalterClient* client) 40 : m_client(client) 41 , m_timer(this, &PluginHalter::timerFired) 42 , m_pluginAllowedRunTime(numeric_limits<unsigned>::max()) 43 { 44 ASSERT_ARG(client, client); 45 } 46 47 void PluginHalter::didStartPlugin(HaltablePlugin* obj) 48 { 49 ASSERT_ARG(obj, obj); 50 ASSERT_ARG(obj, !m_plugins.contains(obj)); 51 52 if (!m_client->enabled()) 53 return; 54 55 double currentTime = WTF::currentTime(); 56 57 m_plugins.add(obj, currentTime); 58 59 if (m_plugins.size() == 1) 60 m_oldestStartTime = currentTime; 61 62 startTimerIfNecessary(); 63 } 64 65 void PluginHalter::didStopPlugin(HaltablePlugin* obj) 66 { 67 if (!m_client->enabled()) 68 return; 69 70 m_plugins.remove(obj); 71 } 72 73 void PluginHalter::timerFired(Timer<PluginHalter>*) 74 { 75 if (m_plugins.isEmpty()) 76 return; 77 78 Vector<HaltablePlugin*> plugins; 79 copyKeysToVector(m_plugins, plugins); 80 81 // Plug-ins older than this are candidates to be halted. 82 double pluginCutOffTime = WTF::currentTime() - m_pluginAllowedRunTime; 83 84 m_oldestStartTime = numeric_limits<double>::max(); 85 86 for (size_t i = 0; i < plugins.size(); ++i) { 87 double thisStartTime = m_plugins.get(plugins[i]); 88 if (thisStartTime > pluginCutOffTime) { 89 // This plug-in is too young to be halted. We find the oldest 90 // plug-in that is not old enough to be halted and use it to set 91 // the timer's next fire time. 92 if (thisStartTime < m_oldestStartTime) 93 m_oldestStartTime = thisStartTime; 94 continue; 95 } 96 97 if (m_client->shouldHaltPlugin(plugins[i]->node(), plugins[i]->isWindowed(), plugins[i]->pluginName())) 98 plugins[i]->halt(); 99 100 m_plugins.remove(plugins[i]); 101 } 102 103 startTimerIfNecessary(); 104 } 105 106 void PluginHalter::startTimerIfNecessary() 107 { 108 if (m_timer.isActive()) 109 return; 110 111 if (m_plugins.isEmpty()) 112 return; 113 114 double nextFireInterval = static_cast<double>(m_pluginAllowedRunTime) - (currentTime() - m_oldestStartTime); 115 m_timer.startOneShot(nextFireInterval < 0 ? 0 : nextFireInterval); 116 } 117 118 } // namespace WebCore 119