diff -r 000000000000 -r 4f2f89ce4247 WebCore/plugins/win/PluginMessageThrottlerWin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebCore/plugins/win/PluginMessageThrottlerWin.cpp Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 Collabora, Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``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 APPLE INC. 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 "PluginMessageThrottlerWin.h" + +#include "PluginView.h" +#include +#include + +using namespace WTF; + +namespace WebCore { + +// Set a timer to make sure we process any queued messages at least every 16ms. +// This value allows Flash 60 messages/second, which should be enough for video +// playback, and also gets us over the limit for kicking into high-resolution +// timer mode (see SharedTimerWin.cpp). +static const double MessageThrottleTimeInterval = 0.016; + +// During a continuous stream of messages, process one every 5ms. +static const double MessageDirectProcessingInterval = 0.005; + +PluginMessageThrottlerWin::PluginMessageThrottlerWin(PluginView* pluginView) + : m_pluginView(pluginView) + , m_back(0) + , m_front(0) + , m_lastMessageTime(0) + , m_messageThrottleTimer(this, &PluginMessageThrottlerWin::messageThrottleTimerFired) +{ + // Initialize the free list with our inline messages + for (unsigned i = 0; i < NumInlineMessages - 1; i++) + m_inlineMessages[i].next = &m_inlineMessages[i + 1]; + m_inlineMessages[NumInlineMessages - 1].next = 0; + m_freeInlineMessages = &m_inlineMessages[0]; +} + +PluginMessageThrottlerWin::~PluginMessageThrottlerWin() +{ + PluginMessage* next; + + for (PluginMessage* message = m_front; message; message = next) { + next = message->next; + freeMessage(message); + } +} + +void PluginMessageThrottlerWin::appendMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PluginMessage* message = allocateMessage(); + + message->hWnd = hWnd; + message->msg = msg; + message->wParam = wParam; + message->lParam = lParam; + message->next = 0; + + if (m_back) + m_back->next = message; + m_back = message; + if (!m_front) + m_front = message; + + // If it has been more than MessageDirectProcessingInterval between throttled messages, + // go ahead and process a message directly. + double currentTime = WTF::currentTime(); + if (currentTime - m_lastMessageTime > MessageDirectProcessingInterval) { + processQueuedMessage(); + m_lastMessageTime = currentTime; + if (!m_front) + return; + } + + if (!m_messageThrottleTimer.isActive()) + m_messageThrottleTimer.startOneShot(MessageThrottleTimeInterval); +} + +void PluginMessageThrottlerWin::processQueuedMessage() +{ + PluginMessage* message = m_front; + m_front = m_front->next; + if (message == m_back) + m_back = 0; + + // Protect the PluginView from destruction while calling its window proc. + // + RefPtr protect(m_pluginView); + ::CallWindowProc(m_pluginView->pluginWndProc(), message->hWnd, message->msg, message->wParam, message->lParam); + + freeMessage(message); +} + +void PluginMessageThrottlerWin::messageThrottleTimerFired(Timer*) +{ + processQueuedMessage(); + + if (m_front) + m_messageThrottleTimer.startOneShot(MessageThrottleTimeInterval); +} + +PluginMessage* PluginMessageThrottlerWin::allocateMessage() +{ + PluginMessage *message; + + if (m_freeInlineMessages) { + message = m_freeInlineMessages; + m_freeInlineMessages = message->next; + } else + message = new PluginMessage; + + return message; +} + +bool PluginMessageThrottlerWin::isInlineMessage(PluginMessage* message) +{ + return message >= &m_inlineMessages[0] && message <= &m_inlineMessages[NumInlineMessages - 1]; +} + +void PluginMessageThrottlerWin::freeMessage(PluginMessage* message) +{ + if (isInlineMessage(message)) { + message->next = m_freeInlineMessages; + m_freeInlineMessages = message; + } else + delete message; +} + +} // namespace WebCore