| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "core/plugins/PluginOcclusionSupport.h" | 32 #include "core/plugins/PluginOcclusionSupport.h" |
| 33 | 33 |
| 34 #include "core/HTMLNames.h" | 34 #include "core/HTMLNames.h" |
| 35 #include "core/dom/Element.h" | 35 #include "core/dom/Element.h" |
| 36 #include "core/frame/FrameView.h" | 36 #include "core/frame/FrameView.h" |
| 37 #include "core/frame/LocalFrame.h" | 37 #include "core/frame/LocalFrame.h" |
| 38 #include "core/html/HTMLElement.h" | 38 #include "core/html/HTMLElement.h" |
| 39 #include "core/html/HTMLFrameOwnerElement.h" | 39 #include "core/html/HTMLFrameOwnerElement.h" |
| 40 #include "core/layout/LayoutObject.h" |
| 40 #include "core/rendering/RenderBox.h" | 41 #include "core/rendering/RenderBox.h" |
| 41 #include "core/rendering/RenderObject.h" | |
| 42 #include "platform/Widget.h" | 42 #include "platform/Widget.h" |
| 43 #include "wtf/HashSet.h" | 43 #include "wtf/HashSet.h" |
| 44 | 44 |
| 45 // This file provides a utility function to support rendering certain elements a
bove plugins. | 45 // This file provides a utility function to support rendering certain elements a
bove plugins. |
| 46 | 46 |
| 47 namespace blink { | 47 namespace blink { |
| 48 | 48 |
| 49 static void getObjectStack(const RenderObject* ro, Vector<const RenderObject*>*
roStack) | 49 static void getObjectStack(const LayoutObject* ro, Vector<const LayoutObject*>*
roStack) |
| 50 { | 50 { |
| 51 roStack->clear(); | 51 roStack->clear(); |
| 52 while (ro) { | 52 while (ro) { |
| 53 roStack->append(ro); | 53 roStack->append(ro); |
| 54 ro = ro->parent(); | 54 ro = ro->parent(); |
| 55 } | 55 } |
| 56 } | 56 } |
| 57 | 57 |
| 58 // Returns true if stack1 is at or above stack2 | 58 // Returns true if stack1 is at or above stack2 |
| 59 static bool iframeIsAbovePlugin(const Vector<const RenderObject*>& iframeZstack,
const Vector<const RenderObject*>& pluginZstack) | 59 static bool iframeIsAbovePlugin(const Vector<const LayoutObject*>& iframeZstack,
const Vector<const LayoutObject*>& pluginZstack) |
| 60 { | 60 { |
| 61 for (size_t i = 0; i < iframeZstack.size() && i < pluginZstack.size(); i++)
{ | 61 for (size_t i = 0; i < iframeZstack.size() && i < pluginZstack.size(); i++)
{ |
| 62 // The root is at the end of these stacks. We want to iterate | 62 // The root is at the end of these stacks. We want to iterate |
| 63 // root-downwards so we index backwards from the end. | 63 // root-downwards so we index backwards from the end. |
| 64 const RenderObject* ro1 = iframeZstack[iframeZstack.size() - 1 - i]; | 64 const LayoutObject* ro1 = iframeZstack[iframeZstack.size() - 1 - i]; |
| 65 const RenderObject* ro2 = pluginZstack[pluginZstack.size() - 1 - i]; | 65 const LayoutObject* ro2 = pluginZstack[pluginZstack.size() - 1 - i]; |
| 66 | 66 |
| 67 if (ro1 != ro2) { | 67 if (ro1 != ro2) { |
| 68 // When we find nodes in the stack that are not the same, then | 68 // When we find nodes in the stack that are not the same, then |
| 69 // we've found the nodes just below the lowest comment ancestor. | 69 // we've found the nodes just below the lowest comment ancestor. |
| 70 // Determine which should be on top. | 70 // Determine which should be on top. |
| 71 | 71 |
| 72 // See if z-index determines an order. | 72 // See if z-index determines an order. |
| 73 if (ro1->style() && ro2->style()) { | 73 if (ro1->style() && ro2->style()) { |
| 74 int z1 = ro1->style()->zIndex(); | 74 int z1 = ro1->style()->zIndex(); |
| 75 int z2 = ro2->style()->zIndex(); | 75 int z2 = ro2->style()->zIndex(); |
| 76 if (z1 > z2) | 76 if (z1 > z2) |
| 77 return true; | 77 return true; |
| 78 if (z1 < z2) | 78 if (z1 < z2) |
| 79 return false; | 79 return false; |
| 80 } | 80 } |
| 81 | 81 |
| 82 // If the plugin does not have an explicit z-index it stacks behind
the iframe. | 82 // If the plugin does not have an explicit z-index it stacks behind
the iframe. |
| 83 // This is for maintaining compatibility with IE. | 83 // This is for maintaining compatibility with IE. |
| 84 if (ro2->style()->position() == StaticPosition) { | 84 if (ro2->style()->position() == StaticPosition) { |
| 85 // The 0'th elements of these RenderObject arrays represent the
plugin node and | 85 // The 0'th elements of these LayoutObject arrays represent the
plugin node and |
| 86 // the iframe. | 86 // the iframe. |
| 87 const RenderObject* pluginRenderObject = pluginZstack[0]; | 87 const LayoutObject* pluginLayoutObject = pluginZstack[0]; |
| 88 const RenderObject* iframeRenderObject = iframeZstack[0]; | 88 const LayoutObject* iframeLayoutObject = iframeZstack[0]; |
| 89 | 89 |
| 90 if (pluginRenderObject->style() && iframeRenderObject->style())
{ | 90 if (pluginLayoutObject->style() && iframeLayoutObject->style())
{ |
| 91 if (pluginRenderObject->style()->zIndex() > iframeRenderObje
ct->style()->zIndex()) | 91 if (pluginLayoutObject->style()->zIndex() > iframeLayoutObje
ct->style()->zIndex()) |
| 92 return false; | 92 return false; |
| 93 } | 93 } |
| 94 return true; | 94 return true; |
| 95 } | 95 } |
| 96 | 96 |
| 97 // Inspect the document order. Later order means higher stacking. | 97 // Inspect the document order. Later order means higher stacking. |
| 98 const RenderObject* parent = ro1->parent(); | 98 const LayoutObject* parent = ro1->parent(); |
| 99 if (!parent) | 99 if (!parent) |
| 100 return false; | 100 return false; |
| 101 ASSERT(parent == ro2->parent()); | 101 ASSERT(parent == ro2->parent()); |
| 102 | 102 |
| 103 for (const RenderObject* ro = parent->slowFirstChild(); ro; ro = ro-
>nextSibling()) { | 103 for (const LayoutObject* ro = parent->slowFirstChild(); ro; ro = ro-
>nextSibling()) { |
| 104 if (ro == ro1) | 104 if (ro == ro1) |
| 105 return false; | 105 return false; |
| 106 if (ro == ro2) | 106 if (ro == ro2) |
| 107 return true; | 107 return true; |
| 108 } | 108 } |
| 109 ASSERT(false); // We should have seen ro1 and ro2 by now. | 109 ASSERT(false); // We should have seen ro1 and ro2 by now. |
| 110 return false; | 110 return false; |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 return true; | 113 return true; |
| 114 } | 114 } |
| 115 | 115 |
| 116 static bool intersectsRect(const RenderObject* renderer, const IntRect& rect) | 116 static bool intersectsRect(const LayoutObject* renderer, const IntRect& rect) |
| 117 { | 117 { |
| 118 return renderer->absoluteBoundingBoxRectIgnoringTransforms().intersects(rect
) | 118 return renderer->absoluteBoundingBoxRectIgnoringTransforms().intersects(rect
) |
| 119 && (!renderer->style() || renderer->style()->visibility() == VISIBLE); | 119 && (!renderer->style() || renderer->style()->visibility() == VISIBLE); |
| 120 } | 120 } |
| 121 | 121 |
| 122 static void addToOcclusions(const RenderBox* renderer, Vector<IntRect>& occlusio
ns) | 122 static void addToOcclusions(const RenderBox* renderer, Vector<IntRect>& occlusio
ns) |
| 123 { | 123 { |
| 124 occlusions.append(IntRect( | 124 occlusions.append(IntRect( |
| 125 roundedIntPoint(renderer->localToAbsolute()), | 125 roundedIntPoint(renderer->localToAbsolute()), |
| 126 flooredIntSize(renderer->size()))); | 126 flooredIntSize(renderer->size()))); |
| 127 } | 127 } |
| 128 | 128 |
| 129 static void addTreeToOcclusions(const RenderObject* renderer, const IntRect& fra
meRect, Vector<IntRect>& occlusions) | 129 static void addTreeToOcclusions(const LayoutObject* renderer, const IntRect& fra
meRect, Vector<IntRect>& occlusions) |
| 130 { | 130 { |
| 131 if (!renderer) | 131 if (!renderer) |
| 132 return; | 132 return; |
| 133 if (renderer->isBox() && intersectsRect(renderer, frameRect)) | 133 if (renderer->isBox() && intersectsRect(renderer, frameRect)) |
| 134 addToOcclusions(toRenderBox(renderer), occlusions); | 134 addToOcclusions(toRenderBox(renderer), occlusions); |
| 135 for (RenderObject* child = renderer->slowFirstChild(); child; child = child-
>nextSibling()) | 135 for (LayoutObject* child = renderer->slowFirstChild(); child; child = child-
>nextSibling()) |
| 136 addTreeToOcclusions(child, frameRect, occlusions); | 136 addTreeToOcclusions(child, frameRect, occlusions); |
| 137 } | 137 } |
| 138 | 138 |
| 139 static const Element* topLayerAncestor(const Element* element) | 139 static const Element* topLayerAncestor(const Element* element) |
| 140 { | 140 { |
| 141 while (element && !element->isInTopLayer()) | 141 while (element && !element->isInTopLayer()) |
| 142 element = element->parentOrShadowHostElement(); | 142 element = element->parentOrShadowHostElement(); |
| 143 return element; | 143 return element; |
| 144 } | 144 } |
| 145 | 145 |
| 146 // Return a set of rectangles that should not be overdrawn by the | 146 // Return a set of rectangles that should not be overdrawn by the |
| 147 // plugin ("cutouts"). This helps implement the "iframe shim" | 147 // plugin ("cutouts"). This helps implement the "iframe shim" |
| 148 // technique of overlaying a windowed plugin with content from the | 148 // technique of overlaying a windowed plugin with content from the |
| 149 // page. In a nutshell, iframe elements should occlude plugins when | 149 // page. In a nutshell, iframe elements should occlude plugins when |
| 150 // they occur higher in the stacking order. | 150 // they occur higher in the stacking order. |
| 151 void getPluginOcclusions(Element* element, Widget* parentWidget, const IntRect&
frameRect, Vector<IntRect>& occlusions) | 151 void getPluginOcclusions(Element* element, Widget* parentWidget, const IntRect&
frameRect, Vector<IntRect>& occlusions) |
| 152 { | 152 { |
| 153 RenderObject* pluginNode = element->renderer(); | 153 LayoutObject* pluginNode = element->renderer(); |
| 154 ASSERT(pluginNode); | 154 ASSERT(pluginNode); |
| 155 if (!pluginNode->style()) | 155 if (!pluginNode->style()) |
| 156 return; | 156 return; |
| 157 Vector<const RenderObject*> pluginZstack; | 157 Vector<const LayoutObject*> pluginZstack; |
| 158 Vector<const RenderObject*> iframeZstack; | 158 Vector<const LayoutObject*> iframeZstack; |
| 159 getObjectStack(pluginNode, &pluginZstack); | 159 getObjectStack(pluginNode, &pluginZstack); |
| 160 | 160 |
| 161 if (!parentWidget->isFrameView()) | 161 if (!parentWidget->isFrameView()) |
| 162 return; | 162 return; |
| 163 | 163 |
| 164 FrameView* parentFrameView = toFrameView(parentWidget); | 164 FrameView* parentFrameView = toFrameView(parentWidget); |
| 165 | 165 |
| 166 // Occlusions by iframes. | 166 // Occlusions by iframes. |
| 167 const FrameView::ChildrenWidgetSet* children = parentFrameView->children(); | 167 const FrameView::ChildrenWidgetSet* children = parentFrameView->children(); |
| 168 for (FrameView::ChildrenWidgetSet::const_iterator it = children->begin(); it
!= children->end(); ++it) { | 168 for (FrameView::ChildrenWidgetSet::const_iterator it = children->begin(); it
!= children->end(); ++it) { |
| 169 // We only care about FrameView's because iframes show up as FrameViews. | 169 // We only care about FrameView's because iframes show up as FrameViews. |
| 170 if (!(*it)->isFrameView()) | 170 if (!(*it)->isFrameView()) |
| 171 continue; | 171 continue; |
| 172 | 172 |
| 173 const FrameView* frameView = toFrameView(it->get()); | 173 const FrameView* frameView = toFrameView(it->get()); |
| 174 // Check to make sure we can get both the element and the RenderObject | 174 // Check to make sure we can get both the element and the LayoutObject |
| 175 // for this FrameView, if we can't just move on to the next object. | 175 // for this FrameView, if we can't just move on to the next object. |
| 176 // FIXME: Plugin occlusion by remote frames is probably broken. | 176 // FIXME: Plugin occlusion by remote frames is probably broken. |
| 177 HTMLElement* element = frameView->frame().deprecatedLocalOwner(); | 177 HTMLElement* element = frameView->frame().deprecatedLocalOwner(); |
| 178 if (!element || !element->renderer()) | 178 if (!element || !element->renderer()) |
| 179 continue; | 179 continue; |
| 180 | 180 |
| 181 RenderObject* iframeRenderer = element->renderer(); | 181 LayoutObject* iframeRenderer = element->renderer(); |
| 182 | 182 |
| 183 if (isHTMLIFrameElement(*element) && intersectsRect(iframeRenderer, fram
eRect)) { | 183 if (isHTMLIFrameElement(*element) && intersectsRect(iframeRenderer, fram
eRect)) { |
| 184 getObjectStack(iframeRenderer, &iframeZstack); | 184 getObjectStack(iframeRenderer, &iframeZstack); |
| 185 if (iframeIsAbovePlugin(iframeZstack, pluginZstack)) | 185 if (iframeIsAbovePlugin(iframeZstack, pluginZstack)) |
| 186 addToOcclusions(toRenderBox(iframeRenderer), occlusions); | 186 addToOcclusions(toRenderBox(iframeRenderer), occlusions); |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 | 189 |
| 190 // Occlusions by top layer elements. | 190 // Occlusions by top layer elements. |
| 191 // FIXME: There's no handling yet for the interaction between top layer and | 191 // FIXME: There's no handling yet for the interaction between top layer and |
| 192 // iframes. For example, a plugin in the top layer will be occluded by an | 192 // iframes. For example, a plugin in the top layer will be occluded by an |
| 193 // iframe. And a plugin inside an iframe in the top layer won't be respected | 193 // iframe. And a plugin inside an iframe in the top layer won't be respected |
| 194 // as being in the top layer. | 194 // as being in the top layer. |
| 195 const Element* ancestor = topLayerAncestor(element); | 195 const Element* ancestor = topLayerAncestor(element); |
| 196 Document* document = parentFrameView->frame().document(); | 196 Document* document = parentFrameView->frame().document(); |
| 197 const WillBeHeapVector<RefPtrWillBeMember<Element> >& elements = document->t
opLayerElements(); | 197 const WillBeHeapVector<RefPtrWillBeMember<Element> >& elements = document->t
opLayerElements(); |
| 198 size_t start = ancestor ? elements.find(ancestor) + 1 : 0; | 198 size_t start = ancestor ? elements.find(ancestor) + 1 : 0; |
| 199 for (size_t i = start; i < elements.size(); ++i) | 199 for (size_t i = start; i < elements.size(); ++i) |
| 200 addTreeToOcclusions(elements[i]->renderer(), frameRect, occlusions); | 200 addTreeToOcclusions(elements[i]->renderer(), frameRect, occlusions); |
| 201 } | 201 } |
| 202 | 202 |
| 203 } // namespace blink | 203 } // namespace blink |
| OLD | NEW |