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