• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PluginTimer(PluginTimer ** list,NPP instance,bool repeat,void (* timerFunc)(NPP npp,uint32_t timerID))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 
~PluginTimer()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 
fired()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
Find(PluginTimer * list,uint32_t timerID)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 
~PluginTimerList()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 
schedule(NPP instance,uint32_t interval,bool repeat,void (* proc)(NPP npp,uint32_t timerID))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 
unschedule(NPP instance,uint32_t timerID)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