18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright 2009, The Android Open Source Project
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Google Inc. All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
83298a7d84b96ade73c6b170671711a8f2792ae59Steve Block *  * Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
103298a7d84b96ade73c6b170671711a8f2792ae59Steve Block *  * Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
143298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
173298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
243298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PluginTimer.h"
297e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger#include "RefPtr.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
33c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch    static uint32_t gTimerID;
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PluginTimer::PluginTimer(PluginTimer** list, NPP instance, bool repeat,
36c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch                             void (*timerFunc)(NPP npp, uint32_t timerID))
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                : m_list(list),
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                  m_instance(instance),
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                  m_timerFunc(timerFunc),
4081b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard                  m_repeat(repeat),
4181b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard                  m_unscheduled(false)
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_timerID = ++gTimerID;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_next = *list;
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_next) {
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_next->m_prev = this;
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_prev = 0;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *list = this;
511a8ec29fc0211a6b5c53a8cd9ce20be5e630b005Patrick Scott        relaxAdoptionRequirement();
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PluginTimer::~PluginTimer()
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_next) {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_next->m_prev = m_prev;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_prev) {
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_prev->m_next = m_next;
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *m_list = m_next;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void PluginTimer::fired()
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
687e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger        // ensure the timer cannot be deleted until this method completes
697e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger        RefPtr<PluginTimer> protector(this);
707e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger
7181b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        if (!m_unscheduled)
7281b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard            m_timerFunc(m_instance, m_timerID);
7381b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard
74d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        // remove the timer if it is a one-shot timer (!m_repeat) or if is a
75d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        // repeating timer that has been unscheduled. In either case we must
76d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        // ensure that the refcount is 2 or greater since the PluginTimerList
77d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        // could have been deleted by the timerFunc and we must ensure that we
78d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        // do not double delete.
79d1f25a8a55bba56cdfbe6275a04028e5f85d6bdaDerek Sollenberger        if ((!m_repeat || m_unscheduled) && refCount() > 1)
807e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger            deref(); // mark the timer for deletion as it is no longer needed
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // may return null if timerID is not found
84c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch    PluginTimer* PluginTimer::Find(PluginTimer* list, uint32_t timerID)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        PluginTimer* curr = list;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (curr) {
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (curr->m_timerID == timerID) {
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            curr = curr->m_next;
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return curr;
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ///////////////////////////////////////////////////////////////////////////
977e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PluginTimerList::~PluginTimerList()
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1007e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger        PluginTimer* curr = m_list;
1017e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger        PluginTimer* next;
1027e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger        while (curr) {
1037e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger            next = curr->next();
1047e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger            curr->deref();
1057e336d32d9c3465ff9792faa8ccc8613b7849e4cDerek Sollenberger            curr = next;
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
109c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch    uint32_t PluginTimerList::schedule(NPP instance, uint32_t interval, bool repeat,
110c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch                                     void (*proc)(NPP npp, uint32_t timerID))
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        PluginTimer* timer = new PluginTimer(&m_list, instance, repeat, proc);
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        double dinterval = interval * 0.001;    // milliseconds to seconds
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (repeat) {
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timer->startRepeating(dinterval);
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timer->startOneShot(dinterval);
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return timer->timerID();
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
123c02eba192362e2ea83fdfbe0be51a08429ec4123Ben Murdoch    void PluginTimerList::unschedule(NPP instance, uint32_t timerID)
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
12581b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        // Although it looks like simply deleting the timer would work here
12681b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        // (stop() will be executed by the dtor), we cannot do this, as
12781b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        // the plugin can call us while we are in the fired() method,
12881b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        // (when we execute the timerFunc callback). Deleting the object
12981b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        // we are in would then be a rather bad move...
13081b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        PluginTimer* timer = PluginTimer::Find(m_list, timerID);
13181b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard        if (timer)
13281b3dad72dd3fbc96e1128fc3d011272c4c27b91Nicolas Roard            timer->unschedule();
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
136