/* * Copyright 2009, The Android Open Source Project * Copyright (C) 2008 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "PluginTimer.h" #include "RefPtr.h" namespace WebCore { static uint32_t gTimerID; PluginTimer::PluginTimer(PluginTimer** list, NPP instance, bool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) : m_list(list), m_instance(instance), m_timerFunc(timerFunc), m_repeat(repeat), m_unscheduled(false) { m_timerID = ++gTimerID; m_next = *list; if (m_next) { m_next->m_prev = this; } m_prev = 0; *list = this; relaxAdoptionRequirement(); } PluginTimer::~PluginTimer() { if (m_next) { m_next->m_prev = m_prev; } if (m_prev) { m_prev->m_next = m_next; } else { *m_list = m_next; } } void PluginTimer::fired() { // ensure the timer cannot be deleted until this method completes RefPtr protector(this); if (!m_unscheduled) m_timerFunc(m_instance, m_timerID); // remove the timer if it is a one-shot timer (!m_repeat) or if is a // repeating timer that has been unscheduled. In either case we must // ensure that the refcount is 2 or greater since the PluginTimerList // could have been deleted by the timerFunc and we must ensure that we // do not double delete. if ((!m_repeat || m_unscheduled) && refCount() > 1) deref(); // mark the timer for deletion as it is no longer needed } // may return null if timerID is not found PluginTimer* PluginTimer::Find(PluginTimer* list, uint32_t timerID) { PluginTimer* curr = list; while (curr) { if (curr->m_timerID == timerID) { break; } curr = curr->m_next; } return curr; } /////////////////////////////////////////////////////////////////////////// PluginTimerList::~PluginTimerList() { PluginTimer* curr = m_list; PluginTimer* next; while (curr) { next = curr->next(); curr->deref(); curr = next; } } uint32_t PluginTimerList::schedule(NPP instance, uint32_t interval, bool repeat, void (*proc)(NPP npp, uint32_t timerID)) { PluginTimer* timer = new PluginTimer(&m_list, instance, repeat, proc); double dinterval = interval * 0.001; // milliseconds to seconds if (repeat) { timer->startRepeating(dinterval); } else { timer->startOneShot(dinterval); } return timer->timerID(); } void PluginTimerList::unschedule(NPP instance, uint32_t timerID) { // Although it looks like simply deleting the timer would work here // (stop() will be executed by the dtor), we cannot do this, as // the plugin can call us while we are in the fired() method, // (when we execute the timerFunc callback). Deleting the object // we are in would then be a rather bad move... PluginTimer* timer = PluginTimer::Find(m_list, timerID); if (timer) timer->unschedule(); } } // namespace WebCore