mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 453650 - implement reflow observers for docShells; r=bz
This commit is contained in:
parent
6d670aaa3f
commit
58b4cffba4
@ -24,6 +24,7 @@ XPIDL_SOURCES += [
|
|||||||
'nsILoadContext.idl',
|
'nsILoadContext.idl',
|
||||||
'nsIMarkupDocumentViewer.idl',
|
'nsIMarkupDocumentViewer.idl',
|
||||||
'nsIPrivacyTransitionObserver.idl',
|
'nsIPrivacyTransitionObserver.idl',
|
||||||
|
'nsIReflowObserver.idl',
|
||||||
'nsIRefreshURI.idl',
|
'nsIRefreshURI.idl',
|
||||||
'nsIScrollable.idl',
|
'nsIScrollable.idl',
|
||||||
'nsITextScroll.idl',
|
'nsITextScroll.idl',
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
#include "nsIOfflineCacheUpdate.h"
|
#include "nsIOfflineCacheUpdate.h"
|
||||||
#include "nsITimedChannel.h"
|
#include "nsITimedChannel.h"
|
||||||
#include "nsIPrivacyTransitionObserver.h"
|
#include "nsIPrivacyTransitionObserver.h"
|
||||||
|
#include "nsIReflowObserver.h"
|
||||||
#include "nsCPrefetchService.h"
|
#include "nsCPrefetchService.h"
|
||||||
#include "nsJSON.h"
|
#include "nsJSON.h"
|
||||||
#include "nsIDocShellTreeItem.h"
|
#include "nsIDocShellTreeItem.h"
|
||||||
@ -2205,6 +2206,43 @@ nsDocShell::AddWeakPrivacyTransitionObserver(nsIPrivacyTransitionObserver* aObse
|
|||||||
return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
|
return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver)
|
||||||
|
{
|
||||||
|
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
|
||||||
|
if (!weakObs) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
return mReflowObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver)
|
||||||
|
{
|
||||||
|
nsWeakPtr obs = do_GetWeakReference(aObserver);
|
||||||
|
return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::NotifyReflowObservers(bool aInterruptible,
|
||||||
|
DOMHighResTimeStamp aStart,
|
||||||
|
DOMHighResTimeStamp aEnd)
|
||||||
|
{
|
||||||
|
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
|
||||||
|
while (iter.HasMore()) {
|
||||||
|
nsWeakPtr ref = iter.GetNext();
|
||||||
|
nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
|
||||||
|
if (!obs) {
|
||||||
|
mReflowObservers.RemoveElement(ref);
|
||||||
|
} else if (aInterruptible) {
|
||||||
|
obs->ReflowInterruptible(aStart, aEnd);
|
||||||
|
} else {
|
||||||
|
obs->Reflow(aStart, aEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocShell::GetAllowMetaRedirects(bool * aReturn)
|
NS_IMETHODIMP nsDocShell::GetAllowMetaRedirects(bool * aReturn)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aReturn);
|
NS_ENSURE_ARG_POINTER(aReturn);
|
||||||
|
@ -872,6 +872,7 @@ private:
|
|||||||
nsCString mForcedCharset;
|
nsCString mForcedCharset;
|
||||||
nsCString mParentCharset;
|
nsCString mParentCharset;
|
||||||
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
||||||
|
nsTObserverArray<nsWeakPtr> mReflowObservers;
|
||||||
int32_t mParentCharsetSource;
|
int32_t mParentCharsetSource;
|
||||||
nsCString mOriginalUriString;
|
nsCString mOriginalUriString;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "domstubs.idl"
|
||||||
#include "nsIDocShellTreeItem.idl"
|
#include "nsIDocShellTreeItem.idl"
|
||||||
#include "nsIAtom.idl"
|
#include "nsIAtom.idl"
|
||||||
|
|
||||||
@ -39,8 +40,9 @@ interface nsIPrincipal;
|
|||||||
interface nsIWebBrowserPrint;
|
interface nsIWebBrowserPrint;
|
||||||
interface nsIVariant;
|
interface nsIVariant;
|
||||||
interface nsIPrivacyTransitionObserver;
|
interface nsIPrivacyTransitionObserver;
|
||||||
|
interface nsIReflowObserver;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(2b192c9c-dea4-4696-a445-1bef7bc0db6d)]
|
[scriptable, builtinclass, uuid(d15b07e0-c604-11e2-8bdc-651679957a39)]
|
||||||
interface nsIDocShell : nsIDocShellTreeItem
|
interface nsIDocShell : nsIDocShellTreeItem
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -616,6 +618,30 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|||||||
*/
|
*/
|
||||||
void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
|
void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an observer to the list of parties to be notified when reflows are
|
||||||
|
* occurring. |obs| must support weak references.
|
||||||
|
*/
|
||||||
|
void addWeakReflowObserver(in nsIReflowObserver obs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an observer from the list of parties to be notified about reflows.
|
||||||
|
*/
|
||||||
|
void removeWeakReflowObserver(in nsIReflowObserver obs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify all attached observers that a reflow has just occurred.
|
||||||
|
*
|
||||||
|
* @param interruptible if true, the reflow was interruptible.
|
||||||
|
* @param start timestamp when reflow started, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
* @param end timestamp when reflow ended, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
*/
|
||||||
|
[noscript] void notifyReflowObservers(in bool interruptible,
|
||||||
|
in DOMHighResTimeStamp start,
|
||||||
|
in DOMHighResTimeStamp end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
||||||
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
||||||
|
32
docshell/base/nsIReflowObserver.idl
Normal file
32
docshell/base/nsIReflowObserver.idl
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "domstubs.idl"
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
|
[scriptable, uuid(832e692c-c4a6-11e2-8fd1-dce678957a39)]
|
||||||
|
interface nsIReflowObserver : nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when an uninterruptible reflow has occurred.
|
||||||
|
*
|
||||||
|
* @param start timestamp when reflow ended, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
* @param end timestamp when reflow ended, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
*/
|
||||||
|
void reflow(in DOMHighResTimeStamp start,
|
||||||
|
in DOMHighResTimeStamp end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an interruptible reflow has occurred.
|
||||||
|
*
|
||||||
|
* @param start timestamp when reflow ended, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
* @param end timestamp when reflow ended, in milliseconds since
|
||||||
|
* navigationStart (accurate to 1/1000 of a ms)
|
||||||
|
*/
|
||||||
|
void reflowInterruptible(in DOMHighResTimeStamp start,
|
||||||
|
in DOMHighResTimeStamp end);
|
||||||
|
};
|
@ -80,6 +80,7 @@ MOCHITEST_CHROME_FILES = \
|
|||||||
test_bug449780.xul \
|
test_bug449780.xul \
|
||||||
bug449780_window.xul \
|
bug449780_window.xul \
|
||||||
bug454235-subframe.xul \
|
bug454235-subframe.xul \
|
||||||
|
test_bug453650.xul \
|
||||||
test_bug456980.xul \
|
test_bug456980.xul \
|
||||||
test_bug662200.xul \
|
test_bug662200.xul \
|
||||||
bug662200_window.xul \
|
bug662200_window.xul \
|
||||||
|
116
docshell/test/chrome/test_bug453650.xul
Normal file
116
docshell/test/chrome/test_bug453650.xul
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=453650
|
||||||
|
-->
|
||||||
|
<window title="Mozilla Bug 453650"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<title>Test for Bug 453650</title>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
|
<!-- test code goes here -->
|
||||||
|
<script type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
/** Test for Bug 453650 **/
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var Ci = Components.interfaces;
|
||||||
|
var Cr = Components.results;
|
||||||
|
|
||||||
|
var iter = runTests();
|
||||||
|
nextTest();
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
var iframe = document.createElement("iframe");
|
||||||
|
iframe.style.width = "300px";
|
||||||
|
iframe.style.height = "300px";
|
||||||
|
iframe.setAttribute("src", "data:text/html,<h1 id='h'>hello</h1>");
|
||||||
|
|
||||||
|
document.documentElement.appendChild(iframe);
|
||||||
|
yield whenLoaded(iframe);
|
||||||
|
info("iframe loaded");
|
||||||
|
|
||||||
|
var h1 = iframe.contentDocument.getElementById("h");
|
||||||
|
h1.style.width = "400px";
|
||||||
|
yield waitForInterruptibleReflow(iframe.docShell);
|
||||||
|
|
||||||
|
h1.style.width = "300px";
|
||||||
|
waitForReflow(iframe.docShell);
|
||||||
|
yield is(300, h1.offsetWidth, "h1 has correct width");
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForInterruptibleReflow(docShell) {
|
||||||
|
waitForReflow(docShell, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForReflow(docShell, interruptible = false) {
|
||||||
|
function done() {
|
||||||
|
docShell.removeWeakReflowObserver(observer);
|
||||||
|
SimpleTest.executeSoon(nextTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
var observer = {
|
||||||
|
reflow: function (start, end) {
|
||||||
|
if (interruptible) {
|
||||||
|
ok(false, "expected interruptible reflow");
|
||||||
|
} else {
|
||||||
|
ok(true, "observed uninterruptible reflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
info("times: " + start + ", " + end);
|
||||||
|
ok(start < end, "reflow start time lower than end time");
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
|
||||||
|
reflowInterruptible: function (start, end) {
|
||||||
|
if (!interruptible) {
|
||||||
|
ok(false, "expected uninterruptible reflow");
|
||||||
|
} else {
|
||||||
|
ok(true, "observed interruptible reflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
info("times: " + start + ", " + end);
|
||||||
|
ok(start < end, "reflow start time lower than end time");
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
|
||||||
|
QueryInterface: function (iid) {
|
||||||
|
if (Ci.nsIReflowObserver.equals(iid) ||
|
||||||
|
Ci.nsISupportsWeakReference.equals(iid) ||
|
||||||
|
Ci.nsISupports.equals(iid))
|
||||||
|
return this;
|
||||||
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
docShell.addWeakReflowObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function whenLoaded(iframe) {
|
||||||
|
iframe.addEventListener("load", function onLoad() {
|
||||||
|
iframe.removeEventListener("load", onLoad);
|
||||||
|
SimpleTest.executeSoon(nextTest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextTest() {
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
} catch (e if e instanceof StopIteration) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- test results are displayed in the html:body -->
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=453650"
|
||||||
|
target="_blank">Mozilla Bug 453650</a>
|
||||||
|
</body>
|
||||||
|
</window>
|
@ -12,6 +12,7 @@ class nsWrapperCache;
|
|||||||
[ptr] native nsWrapperCachePtr(nsWrapperCache);
|
[ptr] native nsWrapperCachePtr(nsWrapperCache);
|
||||||
|
|
||||||
typedef unsigned long long DOMTimeStamp;
|
typedef unsigned long long DOMTimeStamp;
|
||||||
|
typedef double DOMHighResTimeStamp;
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
interface nsIDOMAttr;
|
interface nsIDOMAttr;
|
||||||
|
@ -123,7 +123,9 @@
|
|||||||
#include "nsSVGEffects.h"
|
#include "nsSVGEffects.h"
|
||||||
#include "SVGFragmentIdentifier.h"
|
#include "SVGFragmentIdentifier.h"
|
||||||
|
|
||||||
|
#include "nsPerformance.h"
|
||||||
#include "nsRefreshDriver.h"
|
#include "nsRefreshDriver.h"
|
||||||
|
#include "nsDOMNavigationTiming.h"
|
||||||
|
|
||||||
// Drag & Drop, Clipboard
|
// Drag & Drop, Clipboard
|
||||||
#include "nsWidgetsCID.h"
|
#include "nsWidgetsCID.h"
|
||||||
@ -7651,6 +7653,8 @@ PresShell::WillDoReflow()
|
|||||||
mPresContext->FlushUserFontSet();
|
mPresContext->FlushUserFontSet();
|
||||||
|
|
||||||
mFrameConstructor->BeginUpdate();
|
mFrameConstructor->BeginUpdate();
|
||||||
|
|
||||||
|
mLastReflowStart = GetPerformanceNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -7659,6 +7663,16 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
|||||||
mFrameConstructor->EndUpdate();
|
mFrameConstructor->EndUpdate();
|
||||||
|
|
||||||
HandlePostedReflowCallbacks(aInterruptible);
|
HandlePostedReflowCallbacks(aInterruptible);
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
||||||
|
if (container) {
|
||||||
|
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
|
||||||
|
if (docShell) {
|
||||||
|
DOMHighResTimeStamp now = GetPerformanceNow();
|
||||||
|
docShell->NotifyReflowObservers(aInterruptible, mLastReflowStart, now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sSynthMouseMove) {
|
if (sSynthMouseMove) {
|
||||||
SynthesizeMouseMove(false);
|
SynthesizeMouseMove(false);
|
||||||
}
|
}
|
||||||
@ -7674,6 +7688,23 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp
|
||||||
|
PresShell::GetPerformanceNow()
|
||||||
|
{
|
||||||
|
DOMHighResTimeStamp now = 0;
|
||||||
|
nsPIDOMWindow* window = mDocument->GetWindow();
|
||||||
|
|
||||||
|
if (window) {
|
||||||
|
nsPerformance* perf = window->GetPerformance();
|
||||||
|
|
||||||
|
if (perf) {
|
||||||
|
now = perf->Now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
MarkFramesDirtyToRoot(nsPtrHashKey<nsIFrame>* p, void* closure)
|
MarkFramesDirtyToRoot(nsPtrHashKey<nsIFrame>* p, void* closure)
|
||||||
{
|
{
|
||||||
|
@ -701,6 +701,8 @@ protected:
|
|||||||
|
|
||||||
nscolor GetDefaultBackgroundColorToDraw();
|
nscolor GetDefaultBackgroundColorToDraw();
|
||||||
|
|
||||||
|
DOMHighResTimeStamp GetPerformanceNow();
|
||||||
|
|
||||||
// The callback for the mPaintSuppressionTimer timer.
|
// The callback for the mPaintSuppressionTimer timer.
|
||||||
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);
|
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);
|
||||||
|
|
||||||
@ -783,6 +785,9 @@ protected:
|
|||||||
// moving/sizing loop is running, see bug 491700 for details.
|
// moving/sizing loop is running, see bug 491700 for details.
|
||||||
nsCOMPtr<nsITimer> mReflowContinueTimer;
|
nsCOMPtr<nsITimer> mReflowContinueTimer;
|
||||||
|
|
||||||
|
// The `performance.now()` value when we last started to process reflows.
|
||||||
|
DOMHighResTimeStamp mLastReflowStart;
|
||||||
|
|
||||||
// Information needed to properly handle scrolling content into view if the
|
// Information needed to properly handle scrolling content into view if the
|
||||||
// pre-scroll reflow flush can be interrupted. mContentToScrollTo is
|
// pre-scroll reflow flush can be interrupted. mContentToScrollTo is
|
||||||
// non-null between the initial scroll attempt and the first time we finish
|
// non-null between the initial scroll attempt and the first time we finish
|
||||||
|
Loading…
Reference in New Issue
Block a user