diff options
Diffstat (limited to 'Source/WebCore/plugins')
-rw-r--r-- | Source/WebCore/plugins/IFrameShimSupport.cpp | 167 | ||||
-rw-r--r-- | Source/WebCore/plugins/IFrameShimSupport.h | 34 | ||||
-rw-r--r-- | Source/WebCore/plugins/gtk/PluginPackageGtk.cpp | 25 | ||||
-rw-r--r-- | Source/WebCore/plugins/gtk/gtk2xtbin.c | 2 | ||||
-rw-r--r-- | Source/WebCore/plugins/gtk/gtk2xtbin.h | 3 | ||||
-rw-r--r-- | Source/WebCore/plugins/qt/PluginViewQt.cpp | 14 | ||||
-rw-r--r-- | Source/WebCore/plugins/symbian/PluginPackageSymbian.cpp | 4 | ||||
-rw-r--r-- | Source/WebCore/plugins/win/PluginPackageWin.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/plugins/win/PluginViewWin.cpp | 8 |
9 files changed, 252 insertions, 7 deletions
diff --git a/Source/WebCore/plugins/IFrameShimSupport.cpp b/Source/WebCore/plugins/IFrameShimSupport.cpp new file mode 100644 index 0000000..3deaf09 --- /dev/null +++ b/Source/WebCore/plugins/IFrameShimSupport.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2011 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 "IFrameShimSupport.h" + +#include "Element.h" +#include "FrameView.h" +#include "HTMLElement.h" +#include "HTMLFrameOwnerElement.h" +#include "HTMLNames.h" +#include "RenderBox.h" +#include "RenderObject.h" +#include "Widget.h" + +#include <wtf/HashSet.h> + +// This file provides plugin-related utility functions for iframe shims and is shared by platforms that inherit +// from PluginView (e.g. Qt) and those that do not (e.g. Chromium). + +namespace WebCore { + +static void getObjectStack(const RenderObject* ro, Vector<const RenderObject*>* roStack) +{ + roStack->clear(); + while (ro) { + roStack->append(ro); + ro = ro->parent(); + } +} + +// Returns true if stack1 is at or above stack2 +static bool iframeIsAbovePlugin(const Vector<const RenderObject*>& iframeZstack, const Vector<const RenderObject*>& pluginZstack) +{ + for (size_t i = 0; i < iframeZstack.size() && i < pluginZstack.size(); i++) { + // The root is at the end of these stacks. We want to iterate + // root-downwards so we index backwards from the end. + const RenderObject* ro1 = iframeZstack[iframeZstack.size() - 1 - i]; + const RenderObject* ro2 = pluginZstack[pluginZstack.size() - 1 - i]; + + if (ro1 != ro2) { + // When we find nodes in the stack that are not the same, then + // we've found the nodes just below the lowest comment ancestor. + // Determine which should be on top. + + // See if z-index determines an order. + if (ro1->style() && ro2->style()) { + int z1 = ro1->style()->zIndex(); + int z2 = ro2->style()->zIndex(); + if (z1 > z2) + return true; + if (z1 < z2) + return false; + } + + // If the plugin does not have an explicit z-index it stacks behind the iframe. + // This is for maintaining compatibility with IE. + if (ro2->style()->position() == StaticPosition) { + // The 0'th elements of these RenderObject arrays represent the plugin node and + // the iframe. + const RenderObject* pluginRenderObject = pluginZstack[0]; + const RenderObject* iframeRenderObject = iframeZstack[0]; + + if (pluginRenderObject->style() && iframeRenderObject->style()) { + if (pluginRenderObject->style()->zIndex() > iframeRenderObject->style()->zIndex()) + return false; + } + return true; + } + + // Inspect the document order. Later order means higher stacking. + const RenderObject* parent = ro1->parent(); + if (!parent) + return false; + ASSERT(parent == ro2->parent()); + + for (const RenderObject* ro = parent->firstChild(); ro; ro = ro->nextSibling()) { + if (ro == ro1) + return false; + if (ro == ro2) + return true; + } + ASSERT(false); // We should have seen ro1 and ro2 by now. + return false; + } + } + return true; +} + +// Return a set of rectangles that should not be overdrawn by the +// plugin ("cutouts"). This helps implement the "iframe shim" +// technique of overlaying a windowed plugin with content from the +// page. In a nutshell, iframe elements should occlude plugins when +// they occur higher in the stacking order. +void getPluginOcclusions(Element* element, Widget* parentWidget, const IntRect& frameRect, Vector<IntRect>& occlusions) +{ + RenderObject* pluginNode = element->renderer(); + ASSERT(pluginNode); + if (!pluginNode->style()) + return; + Vector<const RenderObject*> pluginZstack; + Vector<const RenderObject*> iframeZstack; + getObjectStack(pluginNode, &pluginZstack); + + if (!parentWidget->isFrameView()) + return; + + FrameView* parentFrameView = static_cast<FrameView*>(parentWidget); + + const HashSet<RefPtr<Widget> >* children = parentFrameView->children(); + for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != children->end(); ++it) { + // We only care about FrameView's because iframes show up as FrameViews. + if (!(*it)->isFrameView()) + continue; + + const FrameView* frameView = static_cast<const FrameView*>((*it).get()); + // Check to make sure we can get both the element and the RenderObject + // for this FrameView, if we can't just move on to the next object. + if (!frameView->frame() || !frameView->frame()->ownerElement() + || !frameView->frame()->ownerElement()->renderer()) + continue; + + HTMLElement* element = frameView->frame()->ownerElement(); + RenderObject* iframeRenderer = element->renderer(); + + if (element->hasTagName(HTMLNames::iframeTag) + && iframeRenderer->absoluteBoundingBoxRect().intersects(frameRect) + && (!iframeRenderer->style() || iframeRenderer->style()->visibility() == VISIBLE)) { + getObjectStack(iframeRenderer, &iframeZstack); + if (iframeIsAbovePlugin(iframeZstack, pluginZstack)) { + IntPoint point = roundedIntPoint(iframeRenderer->localToAbsolute()); + RenderBox* rbox = toRenderBox(iframeRenderer); + IntSize size(rbox->width(), rbox->height()); + occlusions.append(IntRect(point, size)); + } + } + } +} + +} // namespace WebCore diff --git a/Source/WebCore/plugins/IFrameShimSupport.h b/Source/WebCore/plugins/IFrameShimSupport.h new file mode 100644 index 0000000..6e55126 --- /dev/null +++ b/Source/WebCore/plugins/IFrameShimSupport.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2011 Robert Hogan <robert@roberthogan.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef IFrameShimSupport_h +#define IFrameShimSupport_h + +#include <wtf/Vector.h> + +namespace WebCore { +class Element; +class Widget; +class IntRect; + +void getPluginOcclusions(Element*, Widget* parentWidget, const IntRect& frameRect, Vector<IntRect>& occlusions); + +} // namespace WebCore + +#endif // IFrameShimSupport_h diff --git a/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp b/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp index a702296..26409a7 100644 --- a/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp +++ b/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp @@ -104,6 +104,22 @@ bool PluginPackage::fetchInfo() #endif } +#if defined(XP_UNIX) +static int webkitgtkXError(Display* xdisplay, XErrorEvent* error) +{ + gchar errorMessage[64]; + XGetErrorText(xdisplay, error->error_code, errorMessage, 63); + g_warning("The program '%s' received an X Window System error.\n" + "This probably reflects a bug in the Adobe Flash plugin.\n" + "The error was '%s'.\n" + " (Details: serial %ld error_code %d request_code %d minor_code %d)\n", + g_get_prgname(), errorMessage, + error->serial, error->error_code, + error->request_code, error->minor_code); + return 0; +} +#endif + bool PluginPackage::load() { if (m_isLoaded) { @@ -137,6 +153,15 @@ bool PluginPackage::load() m_isLoaded = true; +#if defined(XP_UNIX) + if (!g_strcmp0(baseName.get(), "libflashplayer.so")) { + // Flash plugin can produce X errors that are handled by the GDK X error handler, which + // exits the process. Since we don't want to crash due to flash bugs, we install a + // custom error handler to show a warning when a X error happens without aborting. + XSetErrorHandler(webkitgtkXError); + } +#endif + NP_InitializeFuncPtr NP_Initialize = 0; m_NPP_Shutdown = 0; diff --git a/Source/WebCore/plugins/gtk/gtk2xtbin.c b/Source/WebCore/plugins/gtk/gtk2xtbin.c index e03fad3..605e42c 100644 --- a/Source/WebCore/plugins/gtk/gtk2xtbin.c +++ b/Source/WebCore/plugins/gtk/gtk2xtbin.c @@ -46,7 +46,9 @@ #include "xembed.h" #include "gtk2xtbin.h" #include <gtk/gtk.h> +#ifdef GTK_API_VERSION_2 #include <gdk/gdkx.h> +#endif #include <glib.h> #include <assert.h> #include <sys/time.h> diff --git a/Source/WebCore/plugins/gtk/gtk2xtbin.h b/Source/WebCore/plugins/gtk/gtk2xtbin.h index 11f6e06..937cd77 100644 --- a/Source/WebCore/plugins/gtk/gtk2xtbin.h +++ b/Source/WebCore/plugins/gtk/gtk2xtbin.h @@ -41,6 +41,9 @@ #define __GTK_XTBIN_H__ #include <gtk/gtk.h> +#ifndef GTK_API_VERSION_2 +#include <gtk/gtkx.h> +#endif #include <X11/Intrinsic.h> #include <X11/Xutil.h> #include <X11/Xlib.h> diff --git a/Source/WebCore/plugins/qt/PluginViewQt.cpp b/Source/WebCore/plugins/qt/PluginViewQt.cpp index 579f77d..4dc4e15 100644 --- a/Source/WebCore/plugins/qt/PluginViewQt.cpp +++ b/Source/WebCore/plugins/qt/PluginViewQt.cpp @@ -47,6 +47,7 @@ #include "HTMLNames.h" #include "HTMLPlugInElement.h" #include "HostWindow.h" +#include "IFrameShimSupport.h" #include "Image.h" #if USE(JSC) #include "JSDOMBinding.h" @@ -627,10 +628,19 @@ void PluginView::setNPWindowIfNeeded() if (m_isWindowed) { platformPluginWidget()->setGeometry(m_windowRect); + + // Cut out areas of the plugin occluded by iframe shims + Vector<IntRect> cutOutRects; + QRegion clipRegion = QRegion(m_clipRect); + getPluginOcclusions(m_element, this->parent(), frameRect(), cutOutRects); + for (size_t i = 0; i < cutOutRects.size(); i++) { + cutOutRects[i].move(-frameRect().x(), -frameRect().y()); + clipRegion = clipRegion.subtracted(QRegion(cutOutRects[i])); + } // if setMask is set with an empty QRegion, no clipping will // be performed, so in that case we hide the plugin view - platformPluginWidget()->setVisible(!m_clipRect.isEmpty()); - platformPluginWidget()->setMask(QRegion(m_clipRect)); + platformPluginWidget()->setVisible(!clipRegion.isEmpty()); + platformPluginWidget()->setMask(clipRegion); m_npWindow.x = m_windowRect.x(); m_npWindow.y = m_windowRect.y(); diff --git a/Source/WebCore/plugins/symbian/PluginPackageSymbian.cpp b/Source/WebCore/plugins/symbian/PluginPackageSymbian.cpp index a14ac20..34aec4c 100644 --- a/Source/WebCore/plugins/symbian/PluginPackageSymbian.cpp +++ b/Source/WebCore/plugins/symbian/PluginPackageSymbian.cpp @@ -29,6 +29,7 @@ namespace WebCore { +#if ENABLE(NETSCAPE_PLUGIN_API) bool PluginPackage::fetchInfo() { if (!load()) @@ -169,6 +170,7 @@ bool PluginPackage::load() m_loadCount++; return true; } +#endif void PluginPackage::unload() { @@ -186,9 +188,11 @@ void PluginPackage::unload() m_pluginLoader = 0; } +#if ENABLE(NETSCAPE_PLUGIN_API) uint16_t PluginPackage::NPVersion() const { return NP_VERSION_MINOR; } +#endif } diff --git a/Source/WebCore/plugins/win/PluginPackageWin.cpp b/Source/WebCore/plugins/win/PluginPackageWin.cpp index 74bd2a9..e06d1f4 100644 --- a/Source/WebCore/plugins/win/PluginPackageWin.cpp +++ b/Source/WebCore/plugins/win/PluginPackageWin.cpp @@ -168,7 +168,7 @@ bool PluginPackage::fetchInfo() if (versionInfoSize == 0) return false; - OwnArrayPtr<char> versionInfoData(new char[versionInfoSize]); + OwnArrayPtr<char> versionInfoData = adoptArrayPtr(new char[versionInfoSize]); if (!GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()), 0, versionInfoSize, versionInfoData.get())) diff --git a/Source/WebCore/plugins/win/PluginViewWin.cpp b/Source/WebCore/plugins/win/PluginViewWin.cpp index 3cd1902..208121e 100644 --- a/Source/WebCore/plugins/win/PluginViewWin.cpp +++ b/Source/WebCore/plugins/win/PluginViewWin.cpp @@ -448,7 +448,7 @@ void PluginView::updatePluginWidget() rgn = ::CreateRectRgn(0, 0, 0, 0); ::SetWindowRgn(platformPluginWidget(), rgn, FALSE); } else { - rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom()); + rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.maxX(), m_clipRect.maxY()); ::SetWindowRgn(platformPluginWidget(), rgn, TRUE); } @@ -456,7 +456,7 @@ void PluginView::updatePluginWidget() ::MoveWindow(platformPluginWidget(), m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), TRUE); if (clipToZeroRect) { - rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom()); + rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.maxX(), m_clipRect.maxY()); ::SetWindowRgn(platformPluginWidget(), rgn, TRUE); } @@ -896,7 +896,7 @@ bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* re void PluginView::invalidateRect(const IntRect& rect) { if (m_isWindowed) { - RECT invalidRect = { rect.x(), rect.y(), rect.right(), rect.bottom() }; + RECT invalidRect = { rect.x(), rect.y(), rect.maxX(), rect.maxY() }; ::InvalidateRect(platformPluginWidget(), &invalidRect, false); return; } @@ -914,7 +914,7 @@ void PluginView::invalidateRect(NPRect* rect) IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); if (m_isWindowed) { - RECT invalidRect = { r.x(), r.y(), r.right(), r.bottom() }; + RECT invalidRect = { r.x(), r.y(), r.maxX(), r.maxY() }; InvalidateRect(platformPluginWidget(), &invalidRect, FALSE); } else { if (m_plugin->quirks().contains(PluginQuirkThrottleInvalidate)) { |