Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved.
      3  * Copyright (C) 2008 Collabora, Ltd. 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  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. 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 APPLE INC. ``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 APPLE INC. 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 "PluginMessageThrottlerWin.h"
     29 
     30 #include "PluginView.h"
     31 #include <wtf/ASCIICType.h>
     32 #include <wtf/CurrentTime.h>
     33 
     34 using namespace WTF;
     35 
     36 namespace WebCore {
     37 
     38 // Set a timer to make sure we process any queued messages at least every 16ms.
     39 // This value allows Flash 60 messages/second, which should be enough for video
     40 // playback, and also gets us over the limit for kicking into high-resolution
     41 // timer mode (see SharedTimerWin.cpp).
     42 static const double MessageThrottleTimeInterval = 0.016;
     43 
     44 // During a continuous stream of messages, process one every 5ms.
     45 static const double MessageDirectProcessingInterval = 0.005;
     46 
     47 PluginMessageThrottlerWin::PluginMessageThrottlerWin(PluginView* pluginView)
     48     : m_pluginView(pluginView)
     49     , m_back(0)
     50     , m_front(0)
     51     , m_messageThrottleTimer(this, &PluginMessageThrottlerWin::messageThrottleTimerFired)
     52     , m_lastMessageTime(0)
     53 {
     54     // Initialize the free list with our inline messages
     55     for (unsigned i = 0; i < NumInlineMessages - 1; i++)
     56         m_inlineMessages[i].next = &m_inlineMessages[i + 1];
     57     m_inlineMessages[NumInlineMessages - 1].next = 0;
     58     m_freeInlineMessages = &m_inlineMessages[0];
     59 }
     60 
     61 PluginMessageThrottlerWin::~PluginMessageThrottlerWin()
     62 {
     63     PluginMessage* next;
     64 
     65     for (PluginMessage* message = m_front; message; message = next) {
     66         next = message->next;
     67         freeMessage(message);
     68     }
     69 }
     70 
     71 void PluginMessageThrottlerWin::appendMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
     72 {
     73     PluginMessage* message = allocateMessage();
     74 
     75     message->hWnd = hWnd;
     76     message->msg = msg;
     77     message->wParam = wParam;
     78     message->lParam = lParam;
     79     message->next = 0;
     80 
     81     if (m_back)
     82         m_back->next = message;
     83     m_back = message;
     84     if (!m_front)
     85         m_front = message;
     86 
     87     // If it has been more than MessageDirectProcessingInterval between throttled messages,
     88     // go ahead and process a message directly.
     89     double currentTime = WTF::currentTime();
     90     if (currentTime - m_lastMessageTime > MessageDirectProcessingInterval) {
     91         processQueuedMessage();
     92         m_lastMessageTime = currentTime;
     93         if (!m_front)
     94             return;
     95     }
     96 
     97     if (!m_messageThrottleTimer.isActive())
     98         m_messageThrottleTimer.startOneShot(MessageThrottleTimeInterval);
     99 }
    100 
    101 void PluginMessageThrottlerWin::processQueuedMessage()
    102 {
    103     PluginMessage* message = m_front;
    104     m_front = m_front->next;
    105     if (message == m_back)
    106         m_back = 0;
    107 
    108     // Protect the PluginView from destruction while calling its window proc.
    109     // <rdar://problem/6930280>
    110     RefPtr<PluginView> protect(m_pluginView);
    111     ::CallWindowProc(m_pluginView->pluginWndProc(), message->hWnd, message->msg, message->wParam, message->lParam);
    112 
    113     freeMessage(message);
    114 }
    115 
    116 void PluginMessageThrottlerWin::messageThrottleTimerFired(Timer<PluginMessageThrottlerWin>*)
    117 {
    118     processQueuedMessage();
    119 
    120     if (m_front)
    121         m_messageThrottleTimer.startOneShot(MessageThrottleTimeInterval);
    122 }
    123 
    124 PluginMessage* PluginMessageThrottlerWin::allocateMessage()
    125 {
    126     PluginMessage *message;
    127 
    128     if (m_freeInlineMessages) {
    129         message = m_freeInlineMessages;
    130         m_freeInlineMessages = message->next;
    131     } else
    132         message = new PluginMessage;
    133 
    134     return message;
    135 }
    136 
    137 bool PluginMessageThrottlerWin::isInlineMessage(PluginMessage* message)
    138 {
    139     return message >= &m_inlineMessages[0] && message <= &m_inlineMessages[NumInlineMessages - 1];
    140 }
    141 
    142 void PluginMessageThrottlerWin::freeMessage(PluginMessage* message)
    143 {
    144     if (isInlineMessage(message)) {
    145         message->next = m_freeInlineMessages;
    146         m_freeInlineMessages = message;
    147     } else
    148         delete message;
    149 }
    150 
    151 } // namespace WebCore
    152