Home | History | Annotate | Download | only in plugins
      1 /*
      2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "PluginMainThreadScheduler.h"
     28 #include <wtf/StdLibExtras.h>
     29 
     30 namespace WebCore {
     31 
     32 PluginMainThreadScheduler& PluginMainThreadScheduler::scheduler()
     33 {
     34     DEFINE_STATIC_LOCAL(PluginMainThreadScheduler, scheduler, ());
     35 
     36     return scheduler;
     37 }
     38 
     39 PluginMainThreadScheduler::PluginMainThreadScheduler()
     40     : m_callPending(false)
     41 {
     42 }
     43 
     44 void PluginMainThreadScheduler::scheduleCall(NPP npp, MainThreadFunction function, void* userData)
     45 {
     46     MutexLocker lock(m_queueMutex);
     47 
     48     CallQueueMap::iterator it = m_callQueueMap.find(npp);
     49     if (it == m_callQueueMap.end())
     50         return;
     51 
     52     it->second.append(Call(function, userData));
     53 
     54     if (!m_callPending) {
     55         callOnMainThread(mainThreadCallback, this);
     56         m_callPending = true;
     57     }
     58 }
     59 
     60 void PluginMainThreadScheduler::registerPlugin(NPP npp)
     61 {
     62     MutexLocker lock(m_queueMutex);
     63 
     64     ASSERT(!m_callQueueMap.contains(npp));
     65     m_callQueueMap.set(npp, Deque<Call>());
     66 }
     67 
     68 void PluginMainThreadScheduler::unregisterPlugin(NPP npp)
     69 {
     70     MutexLocker lock(m_queueMutex);
     71 
     72     ASSERT(m_callQueueMap.contains(npp));
     73     m_callQueueMap.remove(npp);
     74 }
     75 
     76 void PluginMainThreadScheduler::dispatchCallsForPlugin(NPP npp, const Deque<Call>& calls)
     77 {
     78     Deque<Call>::const_iterator end = calls.end();
     79     for (Deque<Call>::const_iterator it = calls.begin(); it != end; ++it) {
     80         // Check if the plug-in has been destroyed.
     81         {
     82             MutexLocker lock(m_queueMutex);
     83             if (!m_callQueueMap.contains(npp))
     84                 return;
     85         }
     86 
     87         (*it).performCall();
     88     }
     89 }
     90 
     91 void PluginMainThreadScheduler::dispatchCalls()
     92 {
     93     m_queueMutex.lock();
     94     CallQueueMap copy(m_callQueueMap);
     95 
     96     {
     97         // Empty all the queues in the original map
     98         CallQueueMap::iterator end = m_callQueueMap.end();
     99         for (CallQueueMap::iterator it = m_callQueueMap.begin(); it != end; ++it)
    100             it->second.clear();
    101     }
    102 
    103     m_callPending = false;
    104     m_queueMutex.unlock();
    105 
    106     CallQueueMap::iterator end = copy.end();
    107     for (CallQueueMap::iterator it = copy.begin(); it != end; ++it)
    108         dispatchCallsForPlugin(it->first, it->second);
    109 }
    110 
    111 void PluginMainThreadScheduler::mainThreadCallback(void* context)
    112 {
    113     static_cast<PluginMainThreadScheduler*>(context)->dispatchCalls();
    114 }
    115 
    116 } // namespace WebCore
    117