Home | History | Annotate | Download | only in plugins
      1 /*
      2  * Copyright 2009, The Android Open Source Project
      3  * Copyright (C) 2008 Google Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "PluginTimer.h"
     29 #include "RefPtr.h"
     30 
     31 namespace WebCore {
     32 
     33     static uint32_t gTimerID;
     34 
     35     PluginTimer::PluginTimer(PluginTimer** list, NPP instance, bool repeat,
     36                              void (*timerFunc)(NPP npp, uint32_t timerID))
     37                 : m_list(list),
     38                   m_instance(instance),
     39                   m_timerFunc(timerFunc),
     40                   m_repeat(repeat),
     41                   m_unscheduled(false)
     42     {
     43         m_timerID = ++gTimerID;
     44 
     45         m_next = *list;
     46         if (m_next) {
     47             m_next->m_prev = this;
     48         }
     49         m_prev = 0;
     50         *list = this;
     51         relaxAdoptionRequirement();
     52     }
     53 
     54     PluginTimer::~PluginTimer()
     55     {
     56         if (m_next) {
     57             m_next->m_prev = m_prev;
     58         }
     59         if (m_prev) {
     60             m_prev->m_next = m_next;
     61         } else {
     62             *m_list = m_next;
     63         }
     64     }
     65 
     66     void PluginTimer::fired()
     67     {
     68         // ensure the timer cannot be deleted until this method completes
     69         RefPtr<PluginTimer> protector(this);
     70 
     71         if (!m_unscheduled)
     72             m_timerFunc(m_instance, m_timerID);
     73 
     74         // remove the timer if it is a one-shot timer (!m_repeat) or if is a
     75         // repeating timer that has been unscheduled. In either case we must
     76         // ensure that the refcount is 2 or greater since the PluginTimerList
     77         // could have been deleted by the timerFunc and we must ensure that we
     78         // do not double delete.
     79         if ((!m_repeat || m_unscheduled) && refCount() > 1)
     80             deref(); // mark the timer for deletion as it is no longer needed
     81     }
     82 
     83     // may return null if timerID is not found
     84     PluginTimer* PluginTimer::Find(PluginTimer* list, uint32_t timerID)
     85     {
     86         PluginTimer* curr = list;
     87         while (curr) {
     88             if (curr->m_timerID == timerID) {
     89                 break;
     90             }
     91             curr = curr->m_next;
     92         }
     93         return curr;
     94     }
     95 
     96     ///////////////////////////////////////////////////////////////////////////
     97 
     98     PluginTimerList::~PluginTimerList()
     99     {
    100         PluginTimer* curr = m_list;
    101         PluginTimer* next;
    102         while (curr) {
    103             next = curr->next();
    104             curr->deref();
    105             curr = next;
    106         }
    107     }
    108 
    109     uint32_t PluginTimerList::schedule(NPP instance, uint32_t interval, bool repeat,
    110                                      void (*proc)(NPP npp, uint32_t timerID))
    111     {
    112         PluginTimer* timer = new PluginTimer(&m_list, instance, repeat, proc);
    113 
    114         double dinterval = interval * 0.001;    // milliseconds to seconds
    115         if (repeat) {
    116             timer->startRepeating(dinterval);
    117         } else {
    118             timer->startOneShot(dinterval);
    119         }
    120         return timer->timerID();
    121     }
    122 
    123     void PluginTimerList::unschedule(NPP instance, uint32_t timerID)
    124     {
    125         // Although it looks like simply deleting the timer would work here
    126         // (stop() will be executed by the dtor), we cannot do this, as
    127         // the plugin can call us while we are in the fired() method,
    128         // (when we execute the timerFunc callback). Deleting the object
    129         // we are in would then be a rather bad move...
    130         PluginTimer* timer = PluginTimer::Find(m_list, timerID);
    131         if (timer)
    132             timer->unschedule();
    133     }
    134 
    135 } // namespace WebCore
    136