Home | History | Annotate | Download | only in page
      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