Changeset 148482 in webkit
- Timestamp:
- Apr 15, 2013 6:05:39 PM (11 years ago)
- Location:
- trunk/Source
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r148481 r148482 1 2013-04-15 Dean Jackson <dino@apple.com> 2 3 Plugins that resize might need to be snapshotted. 4 https://bugs.webkit.org/show_bug.cgi?id=102157 5 <rdar://problem/12696259> 6 7 Reviewed by Tim Horton. 8 9 A plugin could avoid snapshotting if it started very 10 small (below the threshold where we autostart), and then 11 resized to be large (above the threshold). Detect this 12 case and tell the plugin to snapshot. 13 14 There unfortunately is a bit of state to track when doing 15 this. We have to start the snapshotting in a post-layout 16 task, so we carry a flag to say we're checking size but 17 not wanting the plugin to update (which would restart it). 18 We also might be a plugin that would have already restarted 19 due to a similar plugin being clicked or detected as dominant. 20 So this patch introduces a member variable that tracks what 21 decision has been made on snapshotting. 22 23 I also added some more logging to be more clear about what is 24 happening to plugins going through the snapshot process, and 25 changed the order of the tests in the algorithm so that domain 26 detection comes before examining the size. 27 28 * html/HTMLPlugInImageElement.cpp: 29 (WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement): Initialise 30 the two new member variables. 31 (WebCore::HTMLPlugInImageElement::setDisplayState): Mark a restarted 32 plugin as NeverSnapshot. This means that if it later resizes above the 33 threshold, it won't trigger the snapshot detection. 34 (WebCore::HTMLPlugInImageElement::checkSnapshotStatus): Renamed from 35 updateSnapshotInfo. This now updates the snapshot, but also runs 36 the check for size changes. 37 (WebCore::addPlugInsFromNodeListMatchingPlugInOrigin): Gather all plugins 38 that look like a restarting plugin, not just those snapshotted. That 39 way they can all be marked as NeverSnapshot. 40 (WebCore::HTMLPlugInImageElement::restartSimilarPlugIns): Bless every 41 plugin that looks similar, whether or not it is snapshotted. 42 (WebCore::HTMLPlugInImageElement::userDidClickSnapshot): More logging. 43 (WebCore::HTMLPlugInImageElement::setIsPrimarySnapshottedPlugIn): Ditto. 44 (WebCore::HTMLPlugInImageElement::checkSizeChangeForSnapshotting): New 45 method. If the plugin was below the threshold and is now above it, 46 begin the snapshotting process. 47 (WebCore::HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn): Plugins 48 that were marked as NeverSnapshot should start immediately. Move the origin 49 test earlier in the method. If a plugin avoided snapshotting due to size, 50 remember the size. 51 (WebCore::HTMLPlugInImageElement::subframeLoaderDidCreatePlugIn): Mark the 52 plugin as NeverSnapshot. 53 54 * html/HTMLPlugInImageElement.h: 55 (HTMLPlugInImageElement): Four new member variables: 56 - the decision we made regarding snapshotting (or not), uses the SnapshotDecision enum 57 - the size when it avoided snapshotting 58 - a flag to indicate the post layout update was triggered due to 59 a size change 60 (WebCore::HTMLPlugInImageElement::needsCheckForSizeChange): New method. 61 (WebCore::HTMLPlugInImageElement::setNeedsCheckForSizeChange): New method. 62 (WebCore::HTMLPlugInImageElement::snapshotDecision): Return the decision 63 regarding snapshotting or not snapshotting. 64 65 * page/FrameView.cpp: 66 (WebCore::FrameView::addWidgetToUpdate): Guard updating the widget. We don't 67 want to do it when we're checking for a size change in the plugin. 68 (WebCore::FrameView::updateWidget): Call new name. 69 70 * plugins/PluginViewBase.h: 71 (WebCore::PluginViewBase::beginSnapshottingRunningPlugin): Empty virtual 72 method to snapshot a running plugin. 73 74 * rendering/RenderEmbeddedObject.cpp: 75 (WebCore::RenderEmbeddedObject::layout): If the plugin has increased in 76 size add it to the post layout list so that it will be checked. 77 1 78 2013-04-15 Chris Fleizach <cfleizach@apple.com> 2 79 -
trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp
r148373 r148482 83 83 , m_createdDuringUserGesture(ScriptController::processingUserGesture()) 84 84 , m_restartedPlugin(false) 85 , m_needsCheckForSizeChange(false) 86 , m_snapshotDecision(SnapshotNotYetDecided) 85 87 { 86 88 setHasCustomStyleCallbacks(); … … 98 100 if (state == RestartingWithPendingMouseClick || state == Restarting) { 99 101 m_restartedPlugin = true; 102 m_snapshotDecision = NeverSnapshot; 100 103 if (displayState() == DisplayingSnapshot) 101 104 m_removeSnapshotTimer.startOneShot(removeSnapshotTimerDelay); … … 337 340 } 338 341 339 void HTMLPlugInImageElement::updateSnapshotInfo() 340 { 342 void HTMLPlugInImageElement::checkSnapshotStatus() 343 { 344 if (!renderer()->isSnapshottedPlugIn()) { 345 if (displayState() == Playing) 346 checkSizeChangeForSnapshotting(); 347 return; 348 } 349 341 350 ShadowRoot* root = userAgentShadowRoot(); 342 351 if (!root) … … 429 438 if (node->isPluginElement()) { 430 439 HTMLPlugInElement* plugInElement = toHTMLPlugInElement(node); 431 if (plugInElement->isPlugInImageElement() && plugInElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot) {440 if (plugInElement->isPlugInImageElement()) { 432 441 HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(node); 433 442 const KURL& loadedURL = plugInImageElement->loadedUrl(); … … 447 456 String plugInOrigin = m_loadedUrl.host(); 448 457 String mimeType = loadedMimeType(); 449 HTMLPlugInImageElementList pluginsNeedingRestart;458 HTMLPlugInImageElementList similarPlugins; 450 459 451 460 if (!document()->page()) … … 453 462 454 463 for (Frame* frame = document()->page()->mainFrame(); frame; frame = frame->tree()->traverseNext()) { 455 if (frame->loader()->subframeLoader()->containsPlugins()) { 456 if (!frame->document()) 457 continue; 458 459 RefPtr<NodeList> plugins = frame->document()->getElementsByTagName(embedTag.localName()); 460 if (plugins) 461 addPlugInsFromNodeListMatchingPlugInOrigin(pluginsNeedingRestart, plugins, plugInOrigin, mimeType); 462 463 plugins = frame->document()->getElementsByTagName(objectTag.localName()); 464 if (plugins) 465 addPlugInsFromNodeListMatchingPlugInOrigin(pluginsNeedingRestart, plugins, plugInOrigin, mimeType); 464 if (!frame->loader()->subframeLoader()->containsPlugins()) 465 continue; 466 467 if (!frame->document()) 468 continue; 469 470 RefPtr<NodeList> plugIns = frame->document()->getElementsByTagName(embedTag.localName()); 471 if (plugIns) 472 addPlugInsFromNodeListMatchingPlugInOrigin(similarPlugins, plugIns, plugInOrigin, mimeType); 473 474 plugIns = frame->document()->getElementsByTagName(objectTag.localName()); 475 if (plugIns) 476 addPlugInsFromNodeListMatchingPlugInOrigin(similarPlugins, plugIns, plugInOrigin, mimeType); 477 } 478 479 for (size_t i = 0, length = similarPlugins.size(); i < length; ++i) { 480 HTMLPlugInImageElement* plugInToRestart = similarPlugins[i].get(); 481 if (plugInToRestart->displayState() <= HTMLPlugInElement::DisplayingSnapshot) { 482 LOG(Plugins, "%p Plug-in looks similar to a restarted plug-in. Restart.", plugInToRestart); 483 plugInToRestart->setDisplayState(Playing); 484 plugInToRestart->restartSnapshottedPlugIn(); 466 485 } 467 } 468 469 for (size_t i = 0, length = pluginsNeedingRestart.size(); i < length; i++) { 470 pluginsNeedingRestart[i]->setDisplayState(Playing); 471 pluginsNeedingRestart[i]->restartSnapshottedPlugIn(); 486 plugInToRestart->m_snapshotDecision = NeverSnapshot; 472 487 } 473 488 } … … 482 497 document()->page()->plugInClient()->didStartFromOrigin(document()->page()->mainFrame()->document()->baseURL().host(), plugInOrigin, loadedMimeType()); 483 498 499 LOG(Plugins, "%p User clicked on snapshotted plug-in. Restart.", this); 484 500 restartSnapshottedPlugIn(); 485 501 restartSimilarPlugIns(); … … 492 508 493 509 if (isPrimarySnapshottedPlugIn) { 510 LOG(Plugins, "%p Plug-in was detected as the primary element in the page. Restart.", this); 494 511 restartSnapshottedPlugIn(); 495 512 restartSimilarPlugIns(); … … 522 539 } 523 540 541 void HTMLPlugInImageElement::checkSizeChangeForSnapshotting() 542 { 543 if (!m_needsCheckForSizeChange || m_snapshotDecision != MaySnapshotWhenResized) 544 return; 545 546 m_needsCheckForSizeChange = false; 547 LayoutRect contentBoxRect = toRenderBox(renderer())->contentBoxRect(); 548 int contentWidth = contentBoxRect.width(); 549 int contentHeight = contentBoxRect.height(); 550 551 if (contentWidth <= sizingTinyDimensionThreshold || contentHeight <= sizingTinyDimensionThreshold) 552 return; 553 554 LOG(Plugins, "%p Plug-in originally avoided snapshotting because it was sized %dx%d. Now it is %dx%d. Tell it to snapshot.\n", this, m_sizeWhenSnapshotted.width(), m_sizeWhenSnapshotted.height(), contentWidth, contentHeight); 555 setDisplayState(WaitingForSnapshot); 556 m_snapshotDecision = Snapshotted; 557 Widget* widget = pluginWidget(); 558 if (widget && widget->isPluginViewBase()) 559 toPluginViewBase(widget)->beginSnapshottingRunningPlugin(); 560 } 561 524 562 void HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn(const KURL& url) 525 563 { … … 529 567 m_loadedUrl = url; 530 568 531 if (!document()->page() 532 || !document()->page()->settings()->plugInSnapshottingEnabled()) 533 return; 569 if (!document()->page() || !document()->page()->settings()->plugInSnapshottingEnabled()) { 570 m_snapshotDecision = NeverSnapshot; 571 return; 572 } 534 573 535 574 if (displayState() == Restarting) { 575 LOG(Plugins, "%p Plug-in is explicitly restarting", this); 576 m_snapshotDecision = NeverSnapshot; 536 577 setDisplayState(Playing); 537 LOG(Plugins, "%p Plug-in is explicitly restarting", this);538 578 return; 539 579 } … … 541 581 if (displayState() == RestartingWithPendingMouseClick) { 542 582 LOG(Plugins, "%p Plug-in is explicitly restarting but also waiting for a click", this); 543 return; 544 } 545 583 m_snapshotDecision = NeverSnapshot; 584 return; 585 } 586 587 if (m_snapshotDecision == NeverSnapshot) { 588 LOG(Plugins, "%p Plug-in is blessed, allow it to start", this); 589 return; 590 } 591 546 592 bool inMainFrame = document()->frame() == document()->page()->mainFrame(); 547 593 548 594 if (document()->isPluginDocument() && inMainFrame) { 549 595 LOG(Plugins, "%p Plug-in document in main frame", this); 596 m_snapshotDecision = NeverSnapshot; 550 597 return; 551 598 } … … 553 600 if (ScriptController::processingUserGesture()) { 554 601 LOG(Plugins, "%p Script is currently processing user gesture, set to play", this); 602 m_snapshotDecision = NeverSnapshot; 555 603 return; 556 604 } … … 558 606 if (m_createdDuringUserGesture) { 559 607 LOG(Plugins, "%p Plug-in was created when processing user gesture, set to play", this); 608 m_snapshotDecision = NeverSnapshot; 560 609 return; 561 610 } … … 566 615 if (currentTime() - lastKnownUserGestureTimestamp < autostartSoonAfterUserGestureThreshold) { 567 616 LOG(Plugins, "%p Plug-in was created shortly after a user gesture, set to play", this); 617 m_snapshotDecision = NeverSnapshot; 568 618 return; 569 619 } … … 571 621 if (document()->page()->settings()->snapshotAllPlugIns()) { 572 622 LOG(Plugins, "%p Plug-in forced to snapshot by user preference", this); 623 m_snapshotDecision = Snapshotted; 573 624 setDisplayState(WaitingForSnapshot); 625 return; 626 } 627 628 if (document()->page()->settings()->autostartOriginPlugInSnapshottingEnabled() && document()->page()->plugInClient()->shouldAutoStartFromOrigin(document()->page()->mainFrame()->document()->baseURL().host(), url.host(), loadedMimeType())) { 629 LOG(Plugins, "%p Plug-in from (%s, %s) is marked to auto-start, set to play", this, document()->page()->mainFrame()->document()->baseURL().host().utf8().data(), url.host().utf8().data()); 630 m_snapshotDecision = NeverSnapshot; 574 631 return; 575 632 } … … 589 646 && (static_cast<float>(contentArea) / visibleArea > sizingFullPageAreaRatioThreshold)) { 590 647 LOG(Plugins, "%p Plug-in is top level full page, set to play", this); 648 m_snapshotDecision = NeverSnapshot; 591 649 return; 592 650 } … … 594 652 if (contentWidth <= sizingTinyDimensionThreshold || contentHeight <= sizingTinyDimensionThreshold) { 595 653 LOG(Plugins, "%p Plug-in is very small %dx%d, set to play", this, contentWidth, contentHeight); 654 m_sizeWhenSnapshotted = IntSize(contentBoxRect.width().toInt(), contentBoxRect.height().toInt()); 655 m_snapshotDecision = MaySnapshotWhenResized; 596 656 return; 597 657 } 598 658 599 659 if (!document()->page()->plugInClient()) { 660 LOG(Plugins, "%p There is no plug-in client. Set to wait for snapshot", this); 661 m_snapshotDecision = NeverSnapshot; 600 662 setDisplayState(WaitingForSnapshot); 601 663 return; 602 664 } 603 665 604 if (document()->page()->settings()->autostartOriginPlugInSnapshottingEnabled() && document()->page()->plugInClient()->shouldAutoStartFromOrigin(document()->page()->mainFrame()->document()->baseURL().host(), url.host(), loadedMimeType())) {605 LOG(Plugins, "%p Plug-in from (%s, %s) is marked to auto-start, set to play", this, document()->page()->mainFrame()->document()->baseURL().host().utf8().data(), url.host().utf8().data());606 return;607 }608 609 666 LOG(Plugins, "%p Plug-in from (%s, %s) is not auto-start, sized at %dx%d, set to wait for snapshot", this, document()->page()->mainFrame()->document()->baseURL().host().utf8().data(), url.host().utf8().data(), contentWidth, contentHeight); 667 m_snapshotDecision = Snapshotted; 610 668 setDisplayState(WaitingForSnapshot); 611 669 } … … 613 671 void HTMLPlugInImageElement::subframeLoaderDidCreatePlugIn(const Widget* widget) 614 672 { 615 if (!widget->isPluginViewBase() 616 || !static_cast<const PluginViewBase*>(widget)->shouldAlwaysAutoStart()) 673 if (!widget->isPluginViewBase() || !toPluginViewBase(widget)->shouldAlwaysAutoStart()) 617 674 return; 618 675 619 676 LOG(Plugins, "%p Plug-in should auto-start, set to play", this); 677 m_snapshotDecision = NeverSnapshot; 620 678 setDisplayState(Playing); 621 679 } -
trunk/Source/WebCore/html/HTMLPlugInImageElement.h
r147693 r148482 76 76 77 77 void userDidClickSnapshot(PassRefPtr<MouseEvent>, bool forwardEvent); 78 void updateSnapshotInfo();78 void checkSnapshotStatus(); 79 79 Image* snapshotImage() const { return m_snapshotImage.get(); } 80 80 … … 85 85 void setIsPrimarySnapshottedPlugIn(bool); 86 86 bool partOfSnapshotLabel(Node*); 87 88 bool needsCheckForSizeChange() const { return m_needsCheckForSizeChange; } 89 void setNeedsCheckForSizeChange() { m_needsCheckForSizeChange = true; } 90 void checkSizeChangeForSnapshotting(); 91 92 enum SnapshotDecision { 93 SnapshotNotYetDecided, 94 NeverSnapshot, 95 Snapshotted, 96 MaySnapshotWhenResized 97 }; 98 SnapshotDecision snapshotDecision() const { return m_snapshotDecision; } 87 99 88 100 protected: … … 148 160 bool m_createdDuringUserGesture; 149 161 bool m_restartedPlugin; 162 bool m_needsCheckForSizeChange; 163 IntSize m_sizeWhenSnapshotted; 164 SnapshotDecision m_snapshotDecision; 150 165 }; 151 166 -
trunk/Source/WebCore/page/FrameView.cpp
r148481 r148482 1433 1433 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) { 1434 1434 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node); 1435 pluginElement->setNeedsWidgetUpdate(true); 1435 if (!pluginElement->needsCheckForSizeChange()) 1436 pluginElement->setNeedsWidgetUpdate(true); 1436 1437 } 1437 1438 … … 2611 2612 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) { 2612 2613 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement); 2613 pluginElement-> updateSnapshotInfo();2614 pluginElement->checkSnapshotStatus(); 2614 2615 } 2615 2616 return; … … 2620 2621 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) { 2621 2622 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement); 2623 if (pluginElement->needsCheckForSizeChange()) { 2624 pluginElement->checkSnapshotStatus(); 2625 return; 2626 } 2622 2627 if (pluginElement->needsWidgetUpdate()) 2623 2628 pluginElement->updateWidget(CreateAnyWidgetType); -
trunk/Source/WebCore/plugins/PluginViewBase.h
r147795 r148482 65 65 66 66 virtual bool shouldAlwaysAutoStart() const { return false; } 67 virtual void beginSnapshottingRunningPlugin() { } 67 68 68 69 virtual bool shouldAllowNavigationFromDrags() const { return false; } -
trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp
r147579 r148482 294 294 updateLayerTransform(); 295 295 296 if (!widget() && frameView() && canHaveWidget()) 296 bool wasMissingWidget = false; 297 if (!widget() && frameView() && canHaveWidget()) { 298 wasMissingWidget = true; 297 299 frameView()->addWidgetToUpdate(this); 300 } 298 301 299 302 setNeedsLayout(false); 303 304 LayoutSize newSize = contentBoxRect().size(); 305 306 if (!wasMissingWidget && newSize.width() >= oldSize.width() && newSize.height() >= oldSize.height()) { 307 Element* element = toElement(node()); 308 if (element && element->isPluginElement() && toHTMLPlugInElement(element)->isPlugInImageElement()) { 309 HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(element); 310 if (plugInImageElement->displayState() > HTMLPlugInElement::DisplayingSnapshot && plugInImageElement->snapshotDecision() == HTMLPlugInImageElement::MaySnapshotWhenResized && document()->view()) { 311 plugInImageElement->setNeedsCheckForSizeChange(); 312 document()->view()->addWidgetToUpdate(this); 313 } 314 } 315 } 300 316 301 317 if (!canHaveChildren()) … … 313 329 return; 314 330 315 LayoutSize newSize = contentBoxRect().size();316 331 if (newSize == oldSize && !childBox->needsLayout()) 317 332 return; -
trunk/Source/WebKit2/ChangeLog
r148477 r148482 1 2013-04-15 Dean Jackson <dino@apple.com> 2 3 Plugins that resize might need to be snapshotted. 4 https://bugs.webkit.org/show_bug.cgi?id=102157 5 <rdar://problem/12696259> 6 7 Reviewed by Tim Horton. 8 9 Allow a running plugin to be snapshotted. All this 10 means is that we start the snapshot timer again. 11 12 * WebProcess/Plugins/PluginView.cpp: 13 (WebKit::PluginView::beginSnapshottingRunningPlugin): Restart 14 the timer. 15 * WebProcess/Plugins/PluginView.h: Virtual method declaration. 16 1 17 2013-04-15 Seokju Kwon <seokju.kwon@gmail.com> 2 18 -
trunk/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
r148373 r148482 1641 1641 } 1642 1642 1643 void PluginView::beginSnapshottingRunningPlugin() 1644 { 1645 m_pluginSnapshotTimer.restart(); 1646 } 1647 1643 1648 bool PluginView::shouldAlwaysAutoStart() const 1644 1649 { -
trunk/Source/WebKit2/WebProcess/Plugins/PluginView.h
r145477 r148482 149 149 virtual bool wantsWheelEvents(); 150 150 virtual bool shouldAlwaysAutoStart() const OVERRIDE; 151 virtual void beginSnapshottingRunningPlugin() OVERRIDE; 151 152 virtual bool shouldAllowNavigationFromDrags() const OVERRIDE; 152 153
Note: See TracChangeset
for help on using the changeset viewer.