RenderEmbeddedObject.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /*
  2. * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  3. * (C) 2000 Simon Hausmann <hausmann@kde.org>
  4. * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
  5. * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Library General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public License
  18. * along with this library; see the file COPYING.LIB. If not, write to
  19. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  20. * Boston, MA 02110-1301, USA.
  21. *
  22. */
  23. #include "config.h"
  24. #include "RenderEmbeddedObject.h"
  25. #include "CSSValueKeywords.h"
  26. #include "Chrome.h"
  27. #include "ChromeClient.h"
  28. #include "Cursor.h"
  29. #include "EventHandler.h"
  30. #include "Font.h"
  31. #include "FontSelector.h"
  32. #include "Frame.h"
  33. #include "FrameLoaderClient.h"
  34. #include "GraphicsContext.h"
  35. #include "HTMLEmbedElement.h"
  36. #include "HTMLIFrameElement.h"
  37. #include "HTMLNames.h"
  38. #include "HTMLObjectElement.h"
  39. #include "HTMLParamElement.h"
  40. #include "HTMLPlugInElement.h"
  41. #include "HitTestResult.h"
  42. #include "LocalizedStrings.h"
  43. #include "MIMETypeRegistry.h"
  44. #include "MouseEvent.h"
  45. #include "Page.h"
  46. #include "PaintInfo.h"
  47. #include "Path.h"
  48. #include "PlatformMouseEvent.h"
  49. #include "PluginViewBase.h"
  50. #include "RenderLayer.h"
  51. #include "RenderTheme.h"
  52. #include "RenderView.h"
  53. #include "RenderWidgetProtector.h"
  54. #include "Settings.h"
  55. #include "Text.h"
  56. #include "TextRun.h"
  57. #include <wtf/StackStats.h>
  58. #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
  59. #include "HTMLMediaElement.h"
  60. #endif
  61. namespace WebCore {
  62. using namespace HTMLNames;
  63. static const float replacementTextRoundedRectHeight = 22;
  64. static const float replacementTextRoundedRectLeftTextMargin = 10;
  65. static const float replacementTextRoundedRectRightTextMargin = 10;
  66. static const float replacementTextRoundedRectRightTextMarginWithArrow = 5;
  67. static const float replacementTextRoundedRectRadius = 11;
  68. static const float replacementArrowLeftMargin = -4;
  69. static const float replacementArrowPadding = 4;
  70. static const float replacementArrowCirclePadding = 3;
  71. static const Color& replacementTextRoundedRectPressedColor()
  72. {
  73. static const Color pressed(105, 105, 105, 242);
  74. return pressed;
  75. }
  76. static const Color& replacementTextRoundedRectColor()
  77. {
  78. static const Color standard(125, 125, 125, 242);
  79. return standard;
  80. }
  81. static const Color& replacementTextColor()
  82. {
  83. static const Color standard(240, 240, 240, 255);
  84. return standard;
  85. }
  86. static const Color& unavailablePluginBorderColor()
  87. {
  88. static const Color standard(255, 255, 255, 216);
  89. return standard;
  90. }
  91. RenderEmbeddedObject::RenderEmbeddedObject(Element* element)
  92. : RenderPart(element)
  93. , m_hasFallbackContent(false)
  94. , m_isPluginUnavailable(false)
  95. , m_isUnavailablePluginIndicatorHidden(false)
  96. , m_unavailablePluginIndicatorIsPressed(false)
  97. , m_mouseDownWasInUnavailablePluginIndicator(false)
  98. {
  99. view()->frameView()->setIsVisuallyNonEmpty();
  100. }
  101. RenderEmbeddedObject::~RenderEmbeddedObject()
  102. {
  103. if (frameView())
  104. frameView()->removeWidgetToUpdate(this);
  105. }
  106. #if USE(ACCELERATED_COMPOSITING)
  107. bool RenderEmbeddedObject::requiresLayer() const
  108. {
  109. if (RenderPart::requiresLayer())
  110. return true;
  111. return allowsAcceleratedCompositing();
  112. }
  113. bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
  114. {
  115. return widget() && widget()->isPluginViewBase() && toPluginViewBase(widget())->platformLayer();
  116. }
  117. #endif
  118. static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
  119. {
  120. switch (pluginUnavailabilityReason) {
  121. case RenderEmbeddedObject::PluginMissing:
  122. return missingPluginText();
  123. case RenderEmbeddedObject::PluginCrashed:
  124. return crashedPluginText();
  125. case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
  126. return blockedPluginByContentSecurityPolicyText();
  127. case RenderEmbeddedObject::InsecurePluginVersion:
  128. return insecurePluginVersionText();
  129. }
  130. ASSERT_NOT_REACHED();
  131. return String();
  132. }
  133. static bool shouldUnavailablePluginMessageBeButton(Document* document, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
  134. {
  135. Page* page = document->page();
  136. return page && page->chrome().client()->shouldUnavailablePluginMessageBeButton(pluginUnavailabilityReason);
  137. }
  138. void RenderEmbeddedObject::setPluginUnavailabilityReason(PluginUnavailabilityReason pluginUnavailabilityReason)
  139. {
  140. setPluginUnavailabilityReasonWithDescription(pluginUnavailabilityReason, unavailablePluginReplacementText(pluginUnavailabilityReason));
  141. }
  142. void RenderEmbeddedObject::setPluginUnavailabilityReasonWithDescription(PluginUnavailabilityReason pluginUnavailabilityReason, const String& description)
  143. {
  144. ASSERT(!m_isPluginUnavailable);
  145. m_isPluginUnavailable = true;
  146. m_pluginUnavailabilityReason = pluginUnavailabilityReason;
  147. if (description.isEmpty())
  148. m_unavailablePluginReplacementText = unavailablePluginReplacementText(pluginUnavailabilityReason);
  149. else
  150. m_unavailablePluginReplacementText = description;
  151. }
  152. void RenderEmbeddedObject::setUnavailablePluginIndicatorIsPressed(bool pressed)
  153. {
  154. if (m_unavailablePluginIndicatorIsPressed == pressed)
  155. return;
  156. m_unavailablePluginIndicatorIsPressed = pressed;
  157. repaint();
  158. }
  159. void RenderEmbeddedObject::paintSnapshotImage(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Image* image)
  160. {
  161. LayoutUnit cWidth = contentWidth();
  162. LayoutUnit cHeight = contentHeight();
  163. if (!cWidth || !cHeight)
  164. return;
  165. GraphicsContext* context = paintInfo.context;
  166. LayoutSize contentSize(cWidth, cHeight);
  167. LayoutPoint contentLocation = location() + paintOffset;
  168. contentLocation.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
  169. LayoutRect rect(contentLocation, contentSize);
  170. IntRect alignedRect = pixelSnappedIntRect(rect);
  171. if (alignedRect.width() <= 0 || alignedRect.height() <= 0)
  172. return;
  173. bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
  174. context->drawImage(image, style()->colorSpace(), alignedRect, CompositeSourceOver, shouldRespectImageOrientation(), useLowQualityScaling);
  175. }
  176. void RenderEmbeddedObject::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
  177. {
  178. Element* element = toElement(node());
  179. if (!element || !element->isPluginElement())
  180. return;
  181. HTMLPlugInElement* plugInElement = toHTMLPlugInElement(element);
  182. if (plugInElement->displayState() > HTMLPlugInElement::DisplayingSnapshot) {
  183. RenderPart::paintContents(paintInfo, paintOffset);
  184. if (!plugInElement->isRestartedPlugin())
  185. return;
  186. }
  187. if (!plugInElement->isPlugInImageElement())
  188. return;
  189. Image* snapshot = toHTMLPlugInImageElement(plugInElement)->snapshotImage();
  190. if (snapshot)
  191. paintSnapshotImage(paintInfo, paintOffset, snapshot);
  192. }
  193. void RenderEmbeddedObject::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
  194. {
  195. Page* page = 0;
  196. if (Frame* frame = this->frame())
  197. page = frame->page();
  198. if (isPluginUnavailable()) {
  199. if (page && paintInfo.phase == PaintPhaseForeground)
  200. page->addRelevantUnpaintedObject(this, visualOverflowRect());
  201. RenderReplaced::paint(paintInfo, paintOffset);
  202. return;
  203. }
  204. if (page && paintInfo.phase == PaintPhaseForeground)
  205. page->addRelevantRepaintedObject(this, visualOverflowRect());
  206. RenderPart::paint(paintInfo, paintOffset);
  207. }
  208. static void drawReplacementArrow(GraphicsContext* context, const FloatRect& insideRect)
  209. {
  210. GraphicsContextStateSaver stateSaver(*context);
  211. FloatRect rect(insideRect);
  212. rect.inflate(-replacementArrowPadding);
  213. FloatPoint center(rect.center());
  214. FloatPoint arrowTip(rect.maxX(), center.y());
  215. context->setStrokeThickness(2);
  216. context->setLineCap(RoundCap);
  217. context->setLineJoin(RoundJoin);
  218. Path path;
  219. path.moveTo(FloatPoint(rect.x(), center.y()));
  220. path.addLineTo(arrowTip);
  221. path.addLineTo(FloatPoint(center.x(), rect.y()));
  222. path.moveTo(arrowTip);
  223. path.addLineTo(FloatPoint(center.x(), rect.maxY()));
  224. context->strokePath(path);
  225. }
  226. void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
  227. {
  228. if (!showsUnavailablePluginIndicator())
  229. return;
  230. if (paintInfo.phase == PaintPhaseSelection)
  231. return;
  232. GraphicsContext* context = paintInfo.context;
  233. if (context->paintingDisabled())
  234. return;
  235. FloatRect contentRect;
  236. FloatRect indicatorRect;
  237. FloatRect replacementTextRect;
  238. FloatRect arrowRect;
  239. Font font;
  240. TextRun run("");
  241. float textWidth;
  242. if (!getReplacementTextGeometry(paintOffset, contentRect, indicatorRect, replacementTextRect, arrowRect, font, run, textWidth))
  243. return;
  244. Path background;
  245. background.addRoundedRect(indicatorRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius));
  246. GraphicsContextStateSaver stateSaver(*context);
  247. context->clip(contentRect);
  248. context->setFillColor(m_unavailablePluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : replacementTextRoundedRectColor(), style()->colorSpace());
  249. context->fillPath(background);
  250. Path strokePath;
  251. FloatRect strokeRect(indicatorRect);
  252. strokeRect.inflate(1);
  253. strokePath.addRoundedRect(strokeRect, FloatSize(replacementTextRoundedRectRadius + 1, replacementTextRoundedRectRadius + 1));
  254. context->setStrokeColor(unavailablePluginBorderColor(), style()->colorSpace());
  255. context->setStrokeThickness(2);
  256. context->strokePath(strokePath);
  257. const FontMetrics& fontMetrics = font.fontMetrics();
  258. float labelX = roundf(replacementTextRect.location().x() + replacementTextRoundedRectLeftTextMargin);
  259. float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent());
  260. context->setFillColor(replacementTextColor(), style()->colorSpace());
  261. context->drawBidiText(font, run, FloatPoint(labelX, labelY));
  262. if (shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason)) {
  263. arrowRect.inflate(-replacementArrowCirclePadding);
  264. context->beginTransparencyLayer(1.0);
  265. context->setFillColor(replacementTextColor(), style()->colorSpace());
  266. context->fillEllipse(arrowRect);
  267. context->setCompositeOperation(CompositeClear);
  268. drawReplacementArrow(context, arrowRect);
  269. context->endTransparencyLayer();
  270. }
  271. }
  272. void RenderEmbeddedObject::setUnavailablePluginIndicatorIsHidden(bool hidden)
  273. {
  274. m_isUnavailablePluginIndicatorHidden = hidden;
  275. repaint();
  276. }
  277. bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, Font& font, TextRun& run, float& textWidth) const
  278. {
  279. bool includesArrow = shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason);
  280. contentRect = contentBoxRect();
  281. contentRect.moveBy(roundedIntPoint(accumulatedOffset));
  282. FontDescription fontDescription;
  283. RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription);
  284. fontDescription.setWeight(FontWeightBold);
  285. Settings* settings = document()->settings();
  286. ASSERT(settings);
  287. if (!settings)
  288. return false;
  289. fontDescription.setRenderingMode(settings->fontRenderingMode());
  290. fontDescription.setComputedSize(12);
  291. font = Font(fontDescription, 0, 0);
  292. font.update(0);
  293. run = TextRun(m_unavailablePluginReplacementText);
  294. textWidth = font.width(run);
  295. replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftTextMargin + (includesArrow ? replacementTextRoundedRectRightTextMarginWithArrow : replacementTextRoundedRectRightTextMargin), replacementTextRoundedRectHeight));
  296. float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x();
  297. float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y();
  298. replacementTextRect.setLocation(FloatPoint(x, y));
  299. indicatorRect = replacementTextRect;
  300. // Expand the background rect to include the arrow, if it will be used.
  301. if (includesArrow) {
  302. arrowRect = indicatorRect;
  303. arrowRect.setX(ceilf(arrowRect.maxX() + replacementArrowLeftMargin));
  304. arrowRect.setWidth(arrowRect.height());
  305. indicatorRect.unite(arrowRect);
  306. }
  307. return true;
  308. }
  309. LayoutRect RenderEmbeddedObject::unavailablePluginIndicatorBounds(const LayoutPoint& accumulatedOffset) const
  310. {
  311. FloatRect contentRect;
  312. FloatRect indicatorRect;
  313. FloatRect replacementTextRect;
  314. FloatRect arrowRect;
  315. Font font;
  316. TextRun run("", 0);
  317. float textWidth;
  318. if (getReplacementTextGeometry(accumulatedOffset, contentRect, indicatorRect, replacementTextRect, arrowRect, font, run, textWidth))
  319. return LayoutRect(indicatorRect);
  320. return LayoutRect();
  321. }
  322. bool RenderEmbeddedObject::isReplacementObscured() const
  323. {
  324. // Return whether or not the replacement content for blocked plugins is accessible to the user.
  325. // Check the opacity of each layer containing the element or its ancestors.
  326. float opacity = 1.0;
  327. for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) {
  328. RenderLayerModelObject* renderer = layer->renderer();
  329. RenderStyle* style = renderer->style();
  330. opacity *= style->opacity();
  331. if (opacity < 0.1)
  332. return true;
  333. }
  334. // Calculate the absolute rect for the blocked plugin replacement text.
  335. IntRect absoluteBoundingBox = absoluteBoundingBoxRect();
  336. LayoutPoint absoluteLocation(absoluteBoundingBox.location());
  337. LayoutRect rect = unavailablePluginIndicatorBounds(absoluteLocation);
  338. if (rect.isEmpty())
  339. return true;
  340. RenderView* docRenderer = document()->renderView();
  341. ASSERT(docRenderer);
  342. if (!docRenderer)
  343. return true;
  344. HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
  345. HitTestResult result;
  346. HitTestLocation location;
  347. LayoutUnit x = rect.x();
  348. LayoutUnit y = rect.y();
  349. LayoutUnit width = rect.width();
  350. LayoutUnit height = rect.height();
  351. // Hit test the center and near the corners of the replacement text to ensure
  352. // it is visible and is not masked by other elements.
  353. bool hit = false;
  354. location = LayoutPoint(x + width / 2, y + height / 2);
  355. hit = docRenderer->hitTest(request, location, result);
  356. if (!hit || result.innerNode() != node())
  357. return true;
  358. location = LayoutPoint(x, y);
  359. hit = docRenderer->hitTest(request, location, result);
  360. if (!hit || result.innerNode() != node())
  361. return true;
  362. location = LayoutPoint(x + width, y);
  363. hit = docRenderer->hitTest(request, location, result);
  364. if (!hit || result.innerNode() != node())
  365. return true;
  366. location = LayoutPoint(x + width, y + height);
  367. hit = docRenderer->hitTest(request, location, result);
  368. if (!hit || result.innerNode() != node())
  369. return true;
  370. location = LayoutPoint(x, y + height);
  371. hit = docRenderer->hitTest(request, location, result);
  372. if (!hit || result.innerNode() != node())
  373. return true;
  374. return false;
  375. }
  376. void RenderEmbeddedObject::layout()
  377. {
  378. StackStats::LayoutCheckPoint layoutCheckPoint;
  379. ASSERT(needsLayout());
  380. LayoutSize oldSize = contentBoxRect().size();
  381. updateLogicalWidth();
  382. updateLogicalHeight();
  383. RenderPart::layout();
  384. m_overflow.clear();
  385. addVisualEffectOverflow();
  386. updateLayerTransform();
  387. bool wasMissingWidget = false;
  388. if (!widget() && frameView() && canHaveWidget()) {
  389. wasMissingWidget = true;
  390. frameView()->addWidgetToUpdate(this);
  391. }
  392. setNeedsLayout(false);
  393. LayoutSize newSize = contentBoxRect().size();
  394. if (!wasMissingWidget && newSize.width() >= oldSize.width() && newSize.height() >= oldSize.height()) {
  395. Element* element = toElement(node());
  396. if (element && element->isPluginElement() && toHTMLPlugInElement(element)->isPlugInImageElement()) {
  397. HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(element);
  398. if (plugInImageElement->displayState() > HTMLPlugInElement::DisplayingSnapshot && plugInImageElement->snapshotDecision() == HTMLPlugInImageElement::MaySnapshotWhenResized && document()->view()) {
  399. plugInImageElement->setNeedsCheckForSizeChange();
  400. document()->view()->addWidgetToUpdate(this);
  401. }
  402. }
  403. }
  404. if (!canHaveChildren())
  405. return;
  406. // This code copied from RenderMedia::layout().
  407. RenderObject* child = m_children.firstChild();
  408. if (!child)
  409. return;
  410. RenderBox* childBox = toRenderBox(child);
  411. if (!childBox)
  412. return;
  413. if (newSize == oldSize && !childBox->needsLayout())
  414. return;
  415. // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
  416. // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
  417. // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
  418. LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
  419. childBox->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
  420. childBox->style()->setHeight(Length(newSize.height(), Fixed));
  421. childBox->style()->setWidth(Length(newSize.width(), Fixed));
  422. childBox->setNeedsLayout(true, MarkOnlyThis);
  423. childBox->layout();
  424. setChildNeedsLayout(false);
  425. statePusher.pop();
  426. }
  427. void RenderEmbeddedObject::viewCleared()
  428. {
  429. // This is required for <object> elements whose contents are rendered by WebCore (e.g. src="foo.html").
  430. if (node() && widget() && widget()->isFrameView()) {
  431. FrameView* view = toFrameView(widget());
  432. int marginWidth = -1;
  433. int marginHeight = -1;
  434. if (node()->hasTagName(iframeTag)) {
  435. HTMLIFrameElement* frame = toHTMLIFrameElement(node());
  436. marginWidth = frame->marginWidth();
  437. marginHeight = frame->marginHeight();
  438. }
  439. if (marginWidth != -1)
  440. view->setMarginWidth(marginWidth);
  441. if (marginHeight != -1)
  442. view->setMarginHeight(marginHeight);
  443. }
  444. }
  445. bool RenderEmbeddedObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
  446. {
  447. if (!RenderPart::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
  448. return false;
  449. if (!widget() || !widget()->isPluginViewBase())
  450. return true;
  451. PluginViewBase* view = toPluginViewBase(widget());
  452. IntPoint roundedPoint = locationInContainer.roundedPoint();
  453. if (Scrollbar* horizontalScrollbar = view->horizontalScrollbar()) {
  454. if (horizontalScrollbar->shouldParticipateInHitTesting() && horizontalScrollbar->frameRect().contains(roundedPoint)) {
  455. result.setScrollbar(horizontalScrollbar);
  456. return true;
  457. }
  458. }
  459. if (Scrollbar* verticalScrollbar = view->verticalScrollbar()) {
  460. if (verticalScrollbar->shouldParticipateInHitTesting() && verticalScrollbar->frameRect().contains(roundedPoint)) {
  461. result.setScrollbar(verticalScrollbar);
  462. return true;
  463. }
  464. }
  465. return true;
  466. }
  467. bool RenderEmbeddedObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float, Node**)
  468. {
  469. if (!widget() || !widget()->isPluginViewBase())
  470. return false;
  471. return toPluginViewBase(widget())->scroll(direction, granularity);
  472. }
  473. bool RenderEmbeddedObject::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
  474. {
  475. // Plugins don't expose a writing direction, so assuming horizontal LTR.
  476. return scroll(logicalToPhysical(direction, true, false), granularity, multiplier, stopNode);
  477. }
  478. bool RenderEmbeddedObject::isInUnavailablePluginIndicator(const LayoutPoint& point) const
  479. {
  480. FloatRect contentRect;
  481. FloatRect indicatorRect;
  482. FloatRect replacementTextRect;
  483. FloatRect arrowRect;
  484. Font font;
  485. TextRun run("");
  486. float textWidth;
  487. return getReplacementTextGeometry(IntPoint(), contentRect, indicatorRect, replacementTextRect, arrowRect, font, run, textWidth)
  488. && indicatorRect.contains(point);
  489. }
  490. bool RenderEmbeddedObject::isInUnavailablePluginIndicator(MouseEvent* event) const
  491. {
  492. return isInUnavailablePluginIndicator(roundedLayoutPoint(absoluteToLocal(event->absoluteLocation(), UseTransforms)));
  493. }
  494. void RenderEmbeddedObject::handleUnavailablePluginIndicatorEvent(Event* event)
  495. {
  496. if (!shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason))
  497. return;
  498. if (!event->isMouseEvent())
  499. return;
  500. MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
  501. HTMLPlugInElement* element = toHTMLPlugInElement(node());
  502. if (event->type() == eventNames().mousedownEvent && static_cast<MouseEvent*>(event)->button() == LeftButton) {
  503. m_mouseDownWasInUnavailablePluginIndicator = isInUnavailablePluginIndicator(mouseEvent);
  504. if (m_mouseDownWasInUnavailablePluginIndicator) {
  505. if (Frame* frame = document()->frame()) {
  506. frame->eventHandler()->setCapturingMouseEventsNode(element);
  507. element->setIsCapturingMouseEvents(true);
  508. }
  509. setUnavailablePluginIndicatorIsPressed(true);
  510. }
  511. event->setDefaultHandled();
  512. }
  513. if (event->type() == eventNames().mouseupEvent && static_cast<MouseEvent*>(event)->button() == LeftButton) {
  514. if (m_unavailablePluginIndicatorIsPressed) {
  515. if (Frame* frame = document()->frame()) {
  516. frame->eventHandler()->setCapturingMouseEventsNode(0);
  517. element->setIsCapturingMouseEvents(false);
  518. }
  519. setUnavailablePluginIndicatorIsPressed(false);
  520. }
  521. if (m_mouseDownWasInUnavailablePluginIndicator && isInUnavailablePluginIndicator(mouseEvent)) {
  522. if (Page* page = document()->page())
  523. page->chrome().client()->unavailablePluginButtonClicked(element, m_pluginUnavailabilityReason);
  524. }
  525. m_mouseDownWasInUnavailablePluginIndicator = false;
  526. event->setDefaultHandled();
  527. }
  528. if (event->type() == eventNames().mousemoveEvent) {
  529. setUnavailablePluginIndicatorIsPressed(m_mouseDownWasInUnavailablePluginIndicator && isInUnavailablePluginIndicator(mouseEvent));
  530. event->setDefaultHandled();
  531. }
  532. }
  533. CursorDirective RenderEmbeddedObject::getCursor(const LayoutPoint& point, Cursor& cursor) const
  534. {
  535. if (showsUnavailablePluginIndicator() && shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason) && isInUnavailablePluginIndicator(point)) {
  536. cursor = handCursor();
  537. return SetCursor;
  538. }
  539. return RenderPart::getCursor(point, cursor);
  540. }
  541. bool RenderEmbeddedObject::canHaveChildren() const
  542. {
  543. #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
  544. if (!node())
  545. return false;
  546. if (toElement(node())->isMediaElement())
  547. return true;
  548. #endif
  549. if (isSnapshottedPlugIn())
  550. return true;
  551. return false;
  552. }
  553. }