• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PluginHalter(PluginHalterClient * client)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 
didStartPlugin(HaltablePlugin * obj)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 
didStopPlugin(HaltablePlugin * obj)65 void PluginHalter::didStopPlugin(HaltablePlugin* obj)
66 {
67     if (!m_client->enabled())
68         return;
69 
70     m_plugins.remove(obj);
71 }
72 
timerFired(Timer<PluginHalter> *)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 
startTimerIfNecessary()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