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
e59e54c50b
commit
1d11d0dc32
@ -24,6 +24,7 @@ XPIDL_SOURCES += [
|
||||
'nsILoadContext.idl',
|
||||
'nsIMarkupDocumentViewer.idl',
|
||||
'nsIPrivacyTransitionObserver.idl',
|
||||
'nsIReflowObserver.idl',
|
||||
'nsIRefreshURI.idl',
|
||||
'nsIScrollable.idl',
|
||||
'nsITextScroll.idl',
|
||||
|
@ -83,6 +83,7 @@
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIPrivacyTransitionObserver.h"
|
||||
#include "nsIReflowObserver.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsJSON.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
@ -2205,6 +2206,43 @@ nsDocShell::AddWeakPrivacyTransitionObserver(nsIPrivacyTransitionObserver* aObse
|
||||
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_ENSURE_ARG_POINTER(aReturn);
|
||||
|
@ -872,6 +872,7 @@ private:
|
||||
nsCString mForcedCharset;
|
||||
nsCString mParentCharset;
|
||||
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
||||
nsTObserverArray<nsWeakPtr> mReflowObservers;
|
||||
int32_t mParentCharsetSource;
|
||||
nsCString mOriginalUriString;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* 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 "nsIDocShellTreeItem.idl"
|
||||
#include "nsIAtom.idl"
|
||||
|
||||
@ -39,8 +40,9 @@ interface nsIPrincipal;
|
||||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
interface nsIPrivacyTransitionObserver;
|
||||
interface nsIReflowObserver;
|
||||
|
||||
[scriptable, builtinclass, uuid(2b192c9c-dea4-4696-a445-1bef7bc0db6d)]
|
||||
[scriptable, builtinclass, uuid(d15b07e0-c604-11e2-8bdc-651679957a39)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
/**
|
||||
@ -616,6 +618,30 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
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>.
|
||||
* (<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 \
|
||||
bug449780_window.xul \
|
||||
bug454235-subframe.xul \
|
||||
test_bug453650.xul \
|
||||
test_bug456980.xul \
|
||||
test_bug662200.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);
|
||||
|
||||
typedef unsigned long long DOMTimeStamp;
|
||||
typedef double DOMHighResTimeStamp;
|
||||
|
||||
// Core
|
||||
interface nsIDOMAttr;
|
||||
|
@ -123,7 +123,9 @@
|
||||
#include "nsSVGEffects.h"
|
||||
#include "SVGFragmentIdentifier.h"
|
||||
|
||||
#include "nsPerformance.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
#include "nsWidgetsCID.h"
|
||||
@ -7651,6 +7653,8 @@ PresShell::WillDoReflow()
|
||||
mPresContext->FlushUserFontSet();
|
||||
|
||||
mFrameConstructor->BeginUpdate();
|
||||
|
||||
mLastReflowStart = GetPerformanceNow();
|
||||
}
|
||||
|
||||
void
|
||||
@ -7659,6 +7663,16 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
||||
mFrameConstructor->EndUpdate();
|
||||
|
||||
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) {
|
||||
SynthesizeMouseMove(false);
|
||||
}
|
||||
@ -7674,6 +7688,23 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
||||
}
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PresShell::GetPerformanceNow()
|
||||
{
|
||||
DOMHighResTimeStamp now = 0;
|
||||
nsPIDOMWindow* window = mDocument->GetInnerWindow();
|
||||
|
||||
if (window) {
|
||||
nsPerformance* perf = window->GetPerformance();
|
||||
|
||||
if (perf) {
|
||||
now = perf->Now();
|
||||
}
|
||||
}
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
MarkFramesDirtyToRoot(nsPtrHashKey<nsIFrame>* p, void* closure)
|
||||
{
|
||||
|
@ -701,6 +701,8 @@ protected:
|
||||
|
||||
nscolor GetDefaultBackgroundColorToDraw();
|
||||
|
||||
DOMHighResTimeStamp GetPerformanceNow();
|
||||
|
||||
// The callback for the mPaintSuppressionTimer timer.
|
||||
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);
|
||||
|
||||
@ -783,6 +785,9 @@ protected:
|
||||
// moving/sizing loop is running, see bug 491700 for details.
|
||||
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
|
||||
// pre-scroll reflow flush can be interrupted. mContentToScrollTo is
|
||||
// non-null between the initial scroll attempt and the first time we finish
|
||||
|
Loading…
Reference in New Issue
Block a user