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:
Will Hawkins 2019-07-11 04:00:41 +00:00
Родитель 60a8cce828
Коммит 88b4396a69
9 изменённых файлов: 157 добавлений и 3 удалений

Просмотреть файл

@ -3494,6 +3494,29 @@ NS_IMETHODIMP BrowserChild::OnStateChange(nsIWebProgress* aWebProgress,
MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData, MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData,
requestData)); 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()) { if (webProgressData->isTopLevel()) {
stateChangeData.emplace(); stateChangeData.emplace();

Просмотреть файл

@ -2623,7 +2623,7 @@ void BrowserParent::ReconstructWebProgressAndRequest(
if (aRequestData.requestURI()) { if (aRequestData.requestURI()) {
nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>( nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
aRequestData.requestURI(), aRequestData.originalRequestURI(), aRequestData.requestURI(), aRequestData.originalRequestURI(),
aRequestData.matchedList()); aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
request.forget(aOutRequest); request.forget(aOutRequest);
} else { } else {
*aOutRequest = nullptr; *aOutRequest = nullptr;

Просмотреть файл

@ -118,6 +118,12 @@ struct RequestData
nsIURI requestURI; nsIURI requestURI;
nsIURI originalRequestURI; nsIURI originalRequestURI;
nsCString matchedList; 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 struct WebProgressStateChangeData

Просмотреть файл

@ -18,6 +18,17 @@ NS_IMETHODIMP RemoteWebProgressRequest::Init(nsIURI* aURI,
return NS_OK; 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 // nsIChannel methods
NS_IMETHODIMP RemoteWebProgressRequest::GetOriginalURI(nsIURI** aOriginalURI) { NS_IMETHODIMP RemoteWebProgressRequest::GetOriginalURI(nsIURI** aOriginalURI) {

Просмотреть файл

@ -26,8 +26,12 @@ class RemoteWebProgressRequest final : public nsIRemoteWebProgressRequest,
: mURI(nullptr), mOriginalURI(nullptr), mMatchedList(VoidCString()) {} : mURI(nullptr), mOriginalURI(nullptr), mMatchedList(VoidCString()) {}
RemoteWebProgressRequest(nsIURI* aURI, nsIURI* aOriginalURI, RemoteWebProgressRequest(nsIURI* aURI, nsIURI* aOriginalURI,
const nsACString& aMatchedList) const nsACString& aMatchedList,
: mURI(aURI), mOriginalURI(aOriginalURI), mMatchedList(aMatchedList) {} const Maybe<uint64_t>& aMaybeElapsedLoadTimeMS)
: mURI(aURI),
mOriginalURI(aOriginalURI),
mMatchedList(aMatchedList),
mMaybeElapsedLoadTimeMS(aMaybeElapsedLoadTimeMS) {}
protected: protected:
~RemoteWebProgressRequest() = default; ~RemoteWebProgressRequest() = default;
@ -36,6 +40,13 @@ class RemoteWebProgressRequest final : public nsIRemoteWebProgressRequest,
nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI; nsCOMPtr<nsIURI> mOriginalURI;
nsCString mMatchedList; 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 } // namespace dom

Просмотреть файл

@ -10,4 +10,11 @@ interface nsIURI;
interface nsIRemoteWebProgressRequest : nsISupports interface nsIRemoteWebProgressRequest : nsISupports
{ {
void init(in nsIURI aURI, in nsIURI aOriginalURI); 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. skip-if = !e10 # This is an e10s only probe.
[browser_cancel_content_js.js] [browser_cancel_content_js.js]
skip-if = !e10s # This is an e10s only probe. 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);
}