- Revision
- 145332
- Author
- [email protected]
- Date
- 2013-03-10 13:40:47 -0700 (Sun, 10 Mar 2013)
Log Message
Add a heuristic to determine the “primary” snapshotted plugin
https://bugs.webkit.org/show_bug.cgi?id=111932
<rdar://problem/13270208>
Reviewed by Dean Jackson.
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDidCommitLoad):
Forward didCommitLoad to WebPage. Move existing code that manipulated WebPage
itself during didCommitLoad into WebPage, where it belongs.
(WebKit::WebFrameLoaderClient::dispatchDidFinishLoad): Forward didFinishLoad to WebPage.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage): Initialize m_didFindPrimarySnapshottedPlugin to false.
(WebKit::WebPage::didCommitLoad): Move code from WebPageFrameLoaderClient.
Reset the flag that says we've already found a snapshotted plugin.
(WebKit::WebPage::didFinishLoad):
Call determinePrimarySnapshottedPlugIn when any frame finishes loading. We call this for subframes,
not just the main frame, in case the main frame loads with no "primary" plugins, but a subframe later loads with one.
(WebKit::WebPage::determinePrimarySnapshottedPlugIn):
Attempt to find the primary snapshotted plugin on the page, by hit-testing a grid of points spaced 200px apart.
A plugin is considered if it is snapshotted and > 450x300. We scan vertically and left-to-right, only discarding
a previous candidate if another candidate is at least 110% the size of the previous candidate.
This tends to select plugins near the top left of the page, unless there is a significantly larger plugin elsewhere.
(WebKit::WebPage::resetPrimarySnapshottedPlugIn):
* WebProcess/WebPage/WebPage.h:
(WebPage):
* WebCore.exp.in: Export a few things.
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement):
(WebCore::classNameForShadowRoot): If we've been informed that we are the primary snapshotted plugin, add the 'primary' class.
(WebCore::HTMLPlugInImageElement::setIsPrimarySnapshottedPlugIn): Added
(WebCore::HTMLPlugInImageElement::updateSnapshotInfo): Hand classNameForShadowRoot our primary-ness.
* html/HTMLPlugInImageElement.h:
(HTMLPlugInImageElement): Add storage for m_isPrimarySnapshottedPlugIn.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (145331 => 145332)
--- trunk/Source/WebCore/ChangeLog 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebCore/ChangeLog 2013-03-10 20:40:47 UTC (rev 145332)
@@ -1,3 +1,20 @@
+2013-03-10 Tim Horton <[email protected]>
+
+ Add a heuristic to determine the “primary” snapshotted plugin
+ https://bugs.webkit.org/show_bug.cgi?id=111932
+ <rdar://problem/13270208>
+
+ Reviewed by Dean Jackson.
+
+ * WebCore.exp.in: Export a few things.
+ * html/HTMLPlugInImageElement.cpp:
+ (WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement):
+ (WebCore::classNameForShadowRoot): If we've been informed that we are the primary snapshotted plugin, add the 'primary' class.
+ (WebCore::HTMLPlugInImageElement::setIsPrimarySnapshottedPlugIn): Added
+ (WebCore::HTMLPlugInImageElement::updateSnapshotInfo): Hand classNameForShadowRoot our primary-ness.
+ * html/HTMLPlugInImageElement.h:
+ (HTMLPlugInImageElement): Add storage for m_isPrimarySnapshottedPlugIn.
+
2013-03-10 Mike West <[email protected]>
XSSAuditor doesn't need a copy of the original document URL.
Modified: trunk/Source/WebCore/WebCore.exp.in (145331 => 145332)
--- trunk/Source/WebCore/WebCore.exp.in 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebCore/WebCore.exp.in 2013-03-10 20:40:47 UTC (rev 145332)
@@ -76,6 +76,7 @@
__ZN7WebCore10MouseEvent6createERKN3WTF12AtomicStringEbbNS1_10PassRefPtrINS_9DOMWindowEEEiiiiibbbbtNS5_INS_11EventTargetEEENS5_INS_9ClipboardEEEb
__ZN7WebCore10MouseEventC1ERKN3WTF12AtomicStringEbbNS1_10PassRefPtrINS_9DOMWindowEEEiiiiibbbbtNS5_INS_11EventTargetEEENS5_INS_9ClipboardEEEb
__ZN7WebCore10RenderView10compositorEv
+__ZN7WebCore10RenderView7hitTestERKNS_14HitTestRequestERNS_13HitTestResultE
__ZN7WebCore10ScrollView17setUseFixedLayoutEb
__ZN7WebCore10ScrollView18setFixedLayoutSizeERKNS_7IntSizeE
__ZN7WebCore10ScrollView20setCanHaveScrollbarsEb
@@ -248,6 +249,7 @@
__ZN7WebCore13HTTPHeaderMapC1Ev
__ZN7WebCore13HTTPHeaderMapD1Ev
__ZN7WebCore13HitTestResultC1ERKS0_
+__ZN7WebCore13HitTestResultC1ERKNS_11LayoutPointE
__ZN7WebCore13HitTestResultD1Ev
__ZN7WebCore13IdentifierRep3getEPKc
__ZN7WebCore13IdentifierRep3getEi
@@ -673,6 +675,7 @@
__ZN7WebCore22externalRepresentationEPNS_7ElementEj
__ZN7WebCore22systemMarketingVersionEv
__ZN7WebCore22userPreferredLanguagesEv
+__ZN7WebCore22HTMLPlugInImageElement29setIsPrimarySnapshottedPlugInEb
__ZN7WebCore23ApplicationCacheStorage14setMaximumSizeEx
__ZN7WebCore23ApplicationCacheStorage16deleteAllEntriesEv
__ZN7WebCore23ApplicationCacheStorage16storeCopyOfCacheERKN3WTF6StringEPNS_20ApplicationCacheHostE
@@ -1254,6 +1257,7 @@
__ZNK7WebCore13HitTestResult10isSelectedEv
__ZNK7WebCore13HitTestResult11targetFrameEv
__ZNK7WebCore13HitTestResult11textContentEv
+__ZNK7WebCore13HitTestResult12innerElementEv
__ZNK7WebCore13HitTestResult14absolutePDFURLEv
__ZNK7WebCore13HitTestResult14innerNodeFrameEv
__ZNK7WebCore13HitTestResult15absoluteLinkURLEv
@@ -1431,6 +1435,7 @@
__ZNK7WebCore4Node9nodeIndexEv
__ZNK7WebCore4Page10pluginDataEv
__ZNK7WebCore4Page14renderTreeSizeEv
+__ZNK7WebCore4Page16hasSeenAnyPluginEv
__ZNK7WebCore4Page15backForwardListEv
__ZNK7WebCore4Page17viewportArgumentsEv
__ZNK7WebCore4Page34inLowQualityImageInterpolationModeEv
@@ -1547,6 +1552,8 @@
__ZNK7WebCore9FrameView34setWantsLayerForBottomOverHangAreaEb
#endif
__ZNK7WebCore9PageCache10frameCountEv
+__ZNK7WebCore9RenderBox12clientHeightEv
+__ZNK7WebCore9RenderBox11clientWidthEv
__ZTVN7WebCore12ChromeClientE
__ZTVN7WebCore14LoaderStrategyE
__ZTVN7WebCore15StorageStrategyE
Modified: trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp (145331 => 145332)
--- trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp 2013-03-10 20:40:47 UTC (rev 145332)
@@ -71,6 +71,7 @@
, m_needsWidgetUpdate(!createdByParser)
, m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPreferPlugInsForImages)
, m_needsDocumentActivationCallbacks(false)
+ , m_isPrimarySnapshottedPlugIn(false)
, m_simulatedMouseClickTimer(this, &HTMLPlugInImageElement::simulatedMouseClickTimerFired, simulatedMouseClickTimerDelay)
, m_swapRendererTimer(this, &HTMLPlugInImageElement::swapRendererTimerFired)
{
@@ -295,12 +296,13 @@
renderer()->repaint();
}
-static AtomicString classNameForShadowRoot(const Node* node)
+static AtomicString classNameForShadowRoot(const Node* node, bool isPrimary)
{
DEFINE_STATIC_LOCAL(const AtomicString, plugInTinySizeClassName, ("tiny", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, plugInSmallSizeClassName, ("small", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, plugInMediumSizeClassName, ("medium", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, plugInLargeSizeClassName, ("large", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, plugInLargeSizePrimaryClassName, ("large primary", AtomicString::ConstructFromLiteral));
RenderBox* renderBox = static_cast<RenderBox*>(node->renderer());
LayoutUnit width = renderBox->contentWidth();
@@ -315,8 +317,15 @@
if (width < sizingMediumWidthThreshold || height < sizingMediumHeightThreshold)
return plugInMediumSizeClassName;
- return plugInLargeSizeClassName;
+ return isPrimary ? plugInLargeSizePrimaryClassName : plugInLargeSizeClassName;
}
+
+void HTMLPlugInImageElement::setIsPrimarySnapshottedPlugIn(bool isPrimarySnapshottedPlugIn)
+{
+ m_isPrimarySnapshottedPlugIn = isPrimarySnapshottedPlugIn;
+
+ updateSnapshotInfo();
+}
void HTMLPlugInImageElement::updateSnapshotInfo()
{
@@ -325,7 +334,7 @@
return;
Element* shadowContainer = static_cast<Element*>(root->firstChild());
- shadowContainer->setAttribute(classAttr, classNameForShadowRoot(this));
+ shadowContainer->setAttribute(classAttr, classNameForShadowRoot(this, m_isPrimarySnapshottedPlugIn));
}
void HTMLPlugInImageElement::didAddUserAgentShadowRoot(ShadowRoot* root)
Modified: trunk/Source/WebCore/html/HTMLPlugInImageElement.h (145331 => 145332)
--- trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2013-03-10 20:40:47 UTC (rev 145332)
@@ -71,6 +71,8 @@
// Plug-in URL might not be the same as url() with overriding parameters.
void subframeLoaderWillCreatePlugIn(const KURL& plugInURL);
void subframeLoaderDidCreatePlugIn(const Widget*);
+
+ void setIsPrimarySnapshottedPlugIn(bool);
protected:
HTMLPlugInImageElement(const QualifiedName& tagName, Document*, bool createdByParser, PreferPlugInsForImagesOption);
@@ -117,6 +119,7 @@
bool m_needsWidgetUpdate;
bool m_shouldPreferPlugInsForImages;
bool m_needsDocumentActivationCallbacks;
+ bool m_isPrimarySnapshottedPlugIn;
RefPtr<RenderStyle> m_customStyleForPageCache;
RefPtr<MouseEvent> m_pendingClickEventFromSnapshot;
DeferrableOneShotTimer<HTMLPlugInImageElement> m_simulatedMouseClickTimer;
Modified: trunk/Source/WebKit2/ChangeLog (145331 => 145332)
--- trunk/Source/WebKit2/ChangeLog 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebKit2/ChangeLog 2013-03-10 20:40:47 UTC (rev 145332)
@@ -1,3 +1,32 @@
+2013-03-10 Tim Horton <[email protected]>
+
+ Add a heuristic to determine the “primary” snapshotted plugin
+ https://bugs.webkit.org/show_bug.cgi?id=111932
+ <rdar://problem/13270208>
+
+ Reviewed by Dean Jackson.
+
+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+ (WebKit::WebFrameLoaderClient::dispatchDidCommitLoad):
+ Forward didCommitLoad to WebPage. Move existing code that manipulated WebPage
+ itself during didCommitLoad into WebPage, where it belongs.
+ (WebKit::WebFrameLoaderClient::dispatchDidFinishLoad): Forward didFinishLoad to WebPage.
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::WebPage): Initialize m_didFindPrimarySnapshottedPlugin to false.
+ (WebKit::WebPage::didCommitLoad): Move code from WebPageFrameLoaderClient.
+ Reset the flag that says we've already found a snapshotted plugin.
+ (WebKit::WebPage::didFinishLoad):
+ Call determinePrimarySnapshottedPlugIn when any frame finishes loading. We call this for subframes,
+ not just the main frame, in case the main frame loads with no "primary" plugins, but a subframe later loads with one.
+ (WebKit::WebPage::determinePrimarySnapshottedPlugIn):
+ Attempt to find the primary snapshotted plugin on the page, by hit-testing a grid of points spaced 200px apart.
+ A plugin is considered if it is snapshotted and > 450x300. We scan vertically and left-to-right, only discarding
+ a previous candidate if another candidate is at least 110% the size of the previous candidate.
+ This tends to select plugins near the top left of the page, unless there is a significantly larger plugin elsewhere.
+ (WebKit::WebPage::resetPrimarySnapshottedPlugIn):
+ * WebProcess/WebPage/WebPage.h:
+ (WebPage):
+
2013-03-10 Sheriff Bot <[email protected]>
Unreviewed, rolling out r145039 and r145096.
Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (145331 => 145332)
--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2013-03-10 20:40:47 UTC (rev 145332)
@@ -444,12 +444,7 @@
webPage->send(Messages::WebPageProxy::DidCommitLoadForFrame(m_frame->frameID(), response.mimeType(), m_frameHasCustomRepresentation, m_frame->coreFrame()->loader()->loadType(), PlatformCertificateInfo(response), InjectedBundleUserMessageEncoder(userData.get())));
- // Only restore the scale factor for standard frame loads (of the main frame).
- if (m_frame->isMainFrame() && m_frame->coreFrame()->loader()->loadType() == FrameLoadTypeStandard) {
- Page* page = m_frame->coreFrame()->page();
- if (page && page->pageScaleFactor() != 1)
- webPage->scalePage(1, IntPoint());
- }
+ webPage->didCommitLoad(m_frame);
}
void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
@@ -524,6 +519,8 @@
// If we have a load listener, notify it.
if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
loadListener->didFinishLoad(m_frame);
+
+ webPage->didFinishLoad(m_frame);
}
void WebFrameLoaderClient::dispatchDidLayout(LayoutMilestones milestones)
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (145331 => 145332)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2013-03-10 20:40:47 UTC (rev 145332)
@@ -101,6 +101,7 @@
#include <WebCore/HTMLFormElement.h>
#include <WebCore/HTMLInputElement.h>
#include <WebCore/HTMLPlugInElement.h>
+#include <WebCore/HTMLPlugInImageElement.h>
#include <WebCore/HistoryItem.h>
#include <WebCore/KeyboardEvent.h>
#include <WebCore/MIMETypeRegistry.h>
@@ -235,6 +236,9 @@
, m_artificialPluginInitializationDelayEnabled(false)
, m_scrollingPerformanceLoggingEnabled(false)
, m_mainFrameIsScrollable(true)
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+ , m_didFindPrimarySnapshottedPlugin(false)
+#endif
#if PLATFORM(MAC)
, m_pdfPluginEnabled(false)
, m_hasCachedWindowFrame(false)
@@ -3864,4 +3868,109 @@
m_pendingTextCheckingRequestMap.remove(requestID);
}
+void WebPage::didCommitLoad(WebFrame* frame)
+{
+ // Only restore the scale factor for standard frame loads (of the main frame).
+ if (frame->isMainFrame() && frame->coreFrame()->loader()->loadType() == FrameLoadTypeStandard) {
+ Page* page = frame->coreFrame()->page();
+ if (page && page->pageScaleFactor() != 1)
+ scalePage(1, IntPoint());
+ }
+
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+ if (frame->isMainFrame())
+ resetPrimarySnapshottedPlugIn();
+#endif
+}
+
+void WebPage::didFinishLoad(WebFrame* frame)
+{
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+ determinePrimarySnapshottedPlugIn();
+#endif
+}
+
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+static int primarySnapshottedPlugInSearchLimit = 3000;
+static int primarySnapshottedPlugInSearchGap = 200;
+static float primarySnapshottedPlugInSearchBucketSize = 1.1;
+static int primarySnapshottedPlugInMinimumWidth = 450;
+static int primarySnapshottedPlugInMinimumHeight = 300;
+
+void WebPage::determinePrimarySnapshottedPlugIn()
+{
+ if (!corePage()->hasSeenAnyPlugin())
+ return;
+
+ if (m_didFindPrimarySnapshottedPlugin)
+ return;
+
+ RenderView* renderView = corePage()->mainFrame()->view()->renderView();
+
+ IntRect searchRect = IntRect(IntPoint(), corePage()->mainFrame()->view()->contentsSize());
+ searchRect.intersect(IntRect(IntPoint(), IntSize(primarySnapshottedPlugInSearchLimit, primarySnapshottedPlugInSearchLimit)));
+
+ HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping);
+
+ HashSet<RenderObject*> seenRenderers;
+ HTMLPlugInImageElement* candidatePlugIn = 0;
+ unsigned candidatePlugInArea = 0;
+
+ for (int x = searchRect.x(); x <= searchRect.width(); x += primarySnapshottedPlugInSearchGap) {
+ for (int y = searchRect.y(); y <= searchRect.height(); y += primarySnapshottedPlugInSearchGap) {
+ HitTestResult hitTestResult = HitTestResult(LayoutPoint(x, y));
+ renderView->hitTest(request, hitTestResult);
+
+ Element* element = hitTestResult.innerElement();
+ if (!element)
+ continue;
+
+ RenderObject* renderer = element->renderer();
+ if (!renderer || !renderer->isBox())
+ continue;
+
+ RenderBox* renderBox = toRenderBox(renderer);
+
+ if (seenRenderers.contains(renderer))
+ continue;
+ seenRenderers.add(renderer);
+
+ if (!element->isPluginElement())
+ continue;
+
+ HTMLPlugInElement* plugInElement = toHTMLPlugInElement(element);
+ if (!plugInElement->isPlugInImageElement())
+ continue;
+
+ HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(plugInElement);
+
+ if (plugInElement->displayState() == HTMLPlugInElement::Playing)
+ continue;
+
+ if (renderBox->contentWidth() < primarySnapshottedPlugInMinimumWidth || renderBox->contentHeight() < primarySnapshottedPlugInMinimumHeight)
+ continue;
+
+ LayoutUnit contentArea = renderBox->contentWidth() * renderBox->contentHeight();
+
+ if (contentArea > candidatePlugInArea * primarySnapshottedPlugInSearchBucketSize) {
+ candidatePlugIn = plugInImageElement;
+ candidatePlugInArea = contentArea;
+ }
+ }
+ }
+
+ if (!candidatePlugIn)
+ return;
+
+ m_didFindPrimarySnapshottedPlugin = true;
+
+ candidatePlugIn->setIsPrimarySnapshottedPlugIn(true);
+}
+
+void WebPage::resetPrimarySnapshottedPlugIn()
+{
+ m_didFindPrimarySnapshottedPlugin = false;
+}
+#endif // ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (145331 => 145332)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2013-03-10 19:57:08 UTC (rev 145331)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2013-03-10 20:40:47 UTC (rev 145332)
@@ -98,6 +98,8 @@
OBJC_CLASS NSDictionary;
OBJC_CLASS NSObject;
OBJC_CLASS WKAccessibilityWebPageObject;
+
+#define WTF_ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC 1
#endif
namespace CoreIPC {
@@ -217,6 +219,8 @@
void didStartPageTransition();
void didCompletePageTransition();
+ void didCommitLoad(WebFrame*);
+ void didFinishLoad(WebFrame*);
void show();
String userAgent() const { return m_userAgent; }
WebCore::IntRect windowResizerRect() const;
@@ -630,6 +634,11 @@
void didFinishCheckingText(uint64_t requestID, const Vector<WebCore::TextCheckingResult>&);
void didCancelCheckingText(uint64_t requestID);
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+ void determinePrimarySnapshottedPlugIn();
+ void resetPrimarySnapshottedPlugIn();
+#endif
+
private:
WebPage(uint64_t pageID, const WebPageCreationParameters&);
@@ -844,6 +853,10 @@
bool m_mainFrameIsScrollable;
+#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
+ bool m_didFindPrimarySnapshottedPlugin;
+#endif
+
#if PLATFORM(MAC)
bool m_pdfPluginEnabled;