зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1559657: Pass load time in RemoteWebProgress. r=Ehsan,barret
Differential Revision: https://phabricator.services.mozilla.com/D35147 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
60a8cce828
Коммит
88b4396a69
|
@ -3494,6 +3494,29 @@ NS_IMETHODIMP BrowserChild::OnStateChange(nsIWebProgress* aWebProgress,
|
|||
MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData,
|
||||
requestData));
|
||||
|
||||
/*
|
||||
* If
|
||||
* 1) this is a document,
|
||||
* 2) the document is top-level,
|
||||
* 3) the document is completely loaded (STATE_STOP), and
|
||||
* 4) this is the end of activity for the document
|
||||
* (STATE_IS_WINDOW, STATE_IS_NETWORK),
|
||||
* then record the elapsed time that it took to load.
|
||||
*/
|
||||
if (document && webProgressData->isTopLevel() &&
|
||||
(aStateFlags & nsIWebProgressListener::STATE_STOP) &&
|
||||
(aStateFlags & nsIWebProgressListener::STATE_IS_WINDOW) &&
|
||||
(aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)) {
|
||||
RefPtr<nsDOMNavigationTiming> navigationTiming =
|
||||
document->GetNavigationTiming();
|
||||
if (navigationTiming) {
|
||||
TimeDuration elapsedLoadTimeMS =
|
||||
TimeStamp::Now() - navigationTiming->GetNavigationStartTimeStamp();
|
||||
requestData.elapsedLoadTimeMS() =
|
||||
Some(elapsedLoadTimeMS.ToMilliseconds());
|
||||
}
|
||||
}
|
||||
|
||||
if (webProgressData->isTopLevel()) {
|
||||
stateChangeData.emplace();
|
||||
|
||||
|
|
|
@ -2623,7 +2623,7 @@ void BrowserParent::ReconstructWebProgressAndRequest(
|
|||
if (aRequestData.requestURI()) {
|
||||
nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
|
||||
aRequestData.requestURI(), aRequestData.originalRequestURI(),
|
||||
aRequestData.matchedList());
|
||||
aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
|
||||
request.forget(aOutRequest);
|
||||
} else {
|
||||
*aOutRequest = nullptr;
|
||||
|
|
|
@ -118,6 +118,12 @@ struct RequestData
|
|||
nsIURI requestURI;
|
||||
nsIURI originalRequestURI;
|
||||
nsCString matchedList;
|
||||
// The elapsedLoadTimeMS is only set when the request has finished loading.
|
||||
// In other words, this field is set only during and |OnStateChange| event
|
||||
// where |aStateFlags| contains |nsIWebProgressListener::STATE_STOP| and
|
||||
// |nsIWebProgressListener::STATE_IS_NETWORK| and
|
||||
// |nsIWebProgressListener::STATE_IS_WINDOW|, and the document is top level.
|
||||
uint64_t? elapsedLoadTimeMS;
|
||||
};
|
||||
|
||||
struct WebProgressStateChangeData
|
||||
|
|
|
@ -18,6 +18,17 @@ NS_IMETHODIMP RemoteWebProgressRequest::Init(nsIURI* aURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP RemoteWebProgressRequest::GetElapsedLoadTimeMS(
|
||||
uint64_t* aElapsedLoadTimeMS) {
|
||||
NS_ENSURE_ARG_POINTER(aElapsedLoadTimeMS);
|
||||
if (mMaybeElapsedLoadTimeMS) {
|
||||
*aElapsedLoadTimeMS = *mMaybeElapsedLoadTimeMS;
|
||||
return NS_OK;
|
||||
}
|
||||
*aElapsedLoadTimeMS = 0;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// nsIChannel methods
|
||||
|
||||
NS_IMETHODIMP RemoteWebProgressRequest::GetOriginalURI(nsIURI** aOriginalURI) {
|
||||
|
|
|
@ -26,8 +26,12 @@ class RemoteWebProgressRequest final : public nsIRemoteWebProgressRequest,
|
|||
: mURI(nullptr), mOriginalURI(nullptr), mMatchedList(VoidCString()) {}
|
||||
|
||||
RemoteWebProgressRequest(nsIURI* aURI, nsIURI* aOriginalURI,
|
||||
const nsACString& aMatchedList)
|
||||
: mURI(aURI), mOriginalURI(aOriginalURI), mMatchedList(aMatchedList) {}
|
||||
const nsACString& aMatchedList,
|
||||
const Maybe<uint64_t>& aMaybeElapsedLoadTimeMS)
|
||||
: mURI(aURI),
|
||||
mOriginalURI(aOriginalURI),
|
||||
mMatchedList(aMatchedList),
|
||||
mMaybeElapsedLoadTimeMS(aMaybeElapsedLoadTimeMS) {}
|
||||
|
||||
protected:
|
||||
~RemoteWebProgressRequest() = default;
|
||||
|
@ -36,6 +40,13 @@ class RemoteWebProgressRequest final : public nsIRemoteWebProgressRequest,
|
|||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCString mMatchedList;
|
||||
|
||||
// This field is only Some(...) when the RemoteWebProgressRequest
|
||||
// is created at a time that the document whose progress is being
|
||||
// described by this request is top level and its status changes
|
||||
// from loading to completely loaded.
|
||||
// See BrowserChild::OnStateChange.
|
||||
Maybe<uint64_t> mMaybeElapsedLoadTimeMS;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -10,4 +10,11 @@ interface nsIURI;
|
|||
interface nsIRemoteWebProgressRequest : nsISupports
|
||||
{
|
||||
void init(in nsIURI aURI, in nsIURI aOriginalURI);
|
||||
|
||||
// This field is available to users in |OnStateChange| methods only
|
||||
// when the document whose progress is being described by this progress
|
||||
// request is top level and its status has just changed from loading to
|
||||
// completely loaded; for invocations of |OnStateChange| before or after
|
||||
// that transition, this field will throw |NS_ERROR_UNAVAILABLE|.
|
||||
readonly attribute uint64_t elapsedLoadTimeMS;
|
||||
};
|
||||
|
|
|
@ -9,3 +9,5 @@ support-files =
|
|||
skip-if = !e10 # This is an e10s only probe.
|
||||
[browser_cancel_content_js.js]
|
||||
skip-if = !e10s # This is an e10s only probe.
|
||||
[browser_ElapsedTime.js]
|
||||
support-files = elapsed_time.sjs
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
"use strict";
|
||||
|
||||
/*
|
||||
* Synchronize DELAY_MS with DELAY_MS from elapsed_time.sjs
|
||||
*/
|
||||
const DELAY_MS = 200;
|
||||
const SLOW_PAGE =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "elapsed_time.sjs";
|
||||
|
||||
add_task(async function testLongElapsedTime() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{ gBrowser, url: "about:blank" },
|
||||
async function(tabBrowser) {
|
||||
const flags = Ci.nsIWebProgress.NOTIFY_STATE_NETWORK;
|
||||
let listener;
|
||||
|
||||
let stateChangeWaiter = new Promise(resolve => {
|
||||
listener = {
|
||||
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (!aWebProgress.isTopLevel) {
|
||||
return;
|
||||
}
|
||||
const isTopLevel = aWebProgress.isTopLevel;
|
||||
const isStop = aStateFlags & Ci.nsIWebProgressListener.STATE_STOP;
|
||||
const isNetwork =
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
|
||||
const isWindow =
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
|
||||
const isLoadingDocument = aWebProgress.isLoadingDocument;
|
||||
|
||||
if (
|
||||
isTopLevel &&
|
||||
isStop &&
|
||||
isWindow &&
|
||||
isNetwork &&
|
||||
!isLoadingDocument
|
||||
) {
|
||||
aRequest.QueryInterface(Ci.nsIRemoteWebProgressRequest);
|
||||
if (aRequest.elapsedLoadTimeMS >= DELAY_MS) {
|
||||
resolve(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
tabBrowser.addProgressListener(listener, flags);
|
||||
|
||||
BrowserTestUtils.loadURI(tabBrowser, SLOW_PAGE);
|
||||
await BrowserTestUtils.browserLoaded(tabBrowser);
|
||||
let pass = await stateChangeWaiter;
|
||||
|
||||
tabBrowser.removeProgressListener(listener);
|
||||
|
||||
ok(
|
||||
pass,
|
||||
"Bug 1559657: Check that the elapsedLoadTimeMS in RemoteWebProgress meets expectations."
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const DELAY_MS = 200;
|
||||
|
||||
const HTML = `<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
/*
|
||||
* Keep timer as a global so that it is not GC'd
|
||||
* between the time that handleRequest() completes
|
||||
* and it expires.
|
||||
*/
|
||||
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
function handleRequest(req, resp) {
|
||||
resp.processAsync();
|
||||
resp.setHeader("Cache-Control", "no-cache", false);
|
||||
resp.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
|
||||
resp.write(HTML);
|
||||
timer.init(() => {
|
||||
resp.write("");
|
||||
resp.finish();
|
||||
}, DELAY_MS, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
Загрузка…
Ссылка в новой задаче