Bug 873225 - Totals for displayed file sizes, r=rcampbell

This commit is contained in:
Victor Porof 2013-05-30 21:46:36 +03:00
parent 4651f2bd00
commit 8f0dfea7cd
11 changed files with 234 additions and 1 deletions

View File

@ -16,6 +16,9 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
Cu.import("resource:///modules/devtools/VariablesView.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");

View File

@ -278,6 +278,8 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
dumpn("Initializing the RequestsMenuView");
this.node = new SideMenuWidget($("#requests-menu-contents"), false);
this._summary = $("#request-menu-network-summary");
this.node.maintainSelectionVisible = false;
this.node.autoscrollWithAppendedItems = true;
@ -351,6 +353,7 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
$("#details-pane-toggle").disabled = false;
$("#requests-menu-empty-notice").hidden = true;
this.refreshSummary();
this._cache.set(aId, requestItem);
},
@ -404,6 +407,8 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
this.filterContents(this._onFlash);
break;
}
this.refreshSummary();
},
/**
@ -572,6 +577,32 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
_bySize: function({ attachment: first }, { attachment: second })
first.contentSize > second.contentSize,
/**
* Refreshes the status displayed in this container's footer, providing
* concise information about all requests.
*/
refreshSummary: function() {
let visibleItems = this.visibleItems;
let visibleRequestsCount = visibleItems.length;
if (!visibleRequestsCount) {
this._summary.setAttribute("value", L10N.getStr("networkMenu.empty"));
return;
}
let totalBytes = this._getTotalBytesOfRequests(visibleItems);
let totalMillis =
this._getNewestRequest(visibleItems).attachment.endedMillis -
this._getOldestRequest(visibleItems).attachment.startedMillis;
// https://developer.mozilla.org/en-US/docs/Localization_and_Plurals
let str = PluralForm.get(visibleRequestsCount, L10N.getStr("networkMenu.summary"));
this._summary.setAttribute("value", str
.replace("#1", visibleRequestsCount)
.replace("#2", L10N.numberWithDecimals((totalBytes || 0) / 1024, 2))
.replace("#3", L10N.numberWithDecimals((totalMillis || 0) / 1000, 2))
);
},
/**
* Schedules adding additional information to a network request.
*
@ -691,6 +722,7 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
// so this doesn't happen once per network event update).
this.sortContents();
this.filterContents();
this.refreshSummary();
},
/**
@ -1116,6 +1148,50 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
return (aMimeType.split(";")[0].split("/")[1] || "").split("+")[0];
},
/**
* Gets the total number of bytes representing the cumulated content size of
* a set of requests. Returns 0 for an empty set.
*
* @param array aItemsArray
* @return number
*/
_getTotalBytesOfRequests: function(aItemsArray) {
if (!aItemsArray.length) {
return 0;
}
return aItemsArray.reduce((prev, curr) => prev + curr.attachment.contentSize || 0, 0);
},
/**
* Gets the oldest (first performed) request in a set. Returns null for an
* empty set.
*
* @param array aItemsArray
* @return MenuItem
*/
_getOldestRequest: function(aItemsArray) {
if (!aItemsArray.length) {
return null;
}
return aItemsArray.reduce((prev, curr) =>
prev.attachment.startedMillis < curr.attachment.startedMillis ? prev : curr);
},
/**
* Gets the newest (latest performed) request in a set. Returns null for an
* empty set.
*
* @param array aItemsArray
* @return MenuItem
*/
_getNewestRequest: function(aItemsArray) {
if (!aItemsArray.length) {
return null;
}
return aItemsArray.reduce((prev, curr) =>
prev.attachment.startedMillis > curr.attachment.startedMillis ? prev : curr);
},
/**
* Gets the available waterfall width in this container.
* @return number
@ -1132,6 +1208,7 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
},
_cache: null,
_summary: null,
_canvas: null,
_ctx: null,
_cachedWaterfallWidth: 0,

View File

@ -27,7 +27,8 @@
}
@media (min-width: 701px) and (max-width: 1024px) {
#body:not([pane-collapsed]) #requests-menu-footer {
#body:not([pane-collapsed]) .requests-menu-footer-button,
#body:not([pane-collapsed]) .requests-menu-footer-spacer {
display: none;
}
}

View File

@ -178,6 +178,10 @@
<spacer id="requests-menu-spacer-end"
class="requests-menu-footer-spacer"
flex="100"/>
<label id="request-menu-network-summary"
class="plain requests-menu-footer-label"
flex="1"
crop="end"/>
</hbox>
</vbox>

View File

@ -39,6 +39,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_net_filter-03.js \
browser_net_accessibility-01.js \
browser_net_accessibility-02.js \
browser_net_footer-summary.js \
head.js \
$(NULL)

View File

@ -0,0 +1,121 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test if the summary text displayed in the network requests menu footer
* is correct.
*/
function test() {
let { PluralForm } = Cu.import("resource://gre/modules/PluralForm.jsm", {});
initNetMonitor(FILTERING_URL).then(([aTab, aDebuggee, aMonitor]) => {
info("Starting test... ");
let { $, L10N, NetMonitorView } = aMonitor.panelWin;
let { RequestsMenu } = NetMonitorView;
RequestsMenu.lazyUpdate = false;
testStatus();
waitForNetworkEvents(aMonitor, 8).then(() => {
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-css-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-js-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-xhr-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-fonts-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-images-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-media-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-flash-button"));
testStatus();
info("Performing more requests.");
aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }');
return waitForNetworkEvents(aMonitor, 8);
})
.then(() => {
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-html-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-css-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-js-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-xhr-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-fonts-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-images-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-media-button"));
testStatus();
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-filter-flash-button"));
testStatus();
teardown(aMonitor).then(finish);
})
function testStatus() {
let summary = $("#request-menu-network-summary");
let value = summary.getAttribute("value");
info("Current summary: " + value);
let visibleItems = RequestsMenu.visibleItems;
let visibleRequestsCount = visibleItems.length;
let totalRequestsCount = RequestsMenu.itemCount;
info("Current requests: " + visibleRequestsCount + " of " + totalRequestsCount + ".");
if (!totalRequestsCount) {
is(value, "",
"The current summary text is incorrect, expected an empty string.");
return;
}
if (!visibleRequestsCount) {
is(value, L10N.getStr("networkMenu.empty"),
"The current summary text is incorrect, expected an 'empty' label.");
return;
}
let totalBytes = RequestsMenu._getTotalBytesOfRequests(visibleItems);
let totalMillis =
RequestsMenu._getNewestRequest(visibleItems).attachment.endedMillis -
RequestsMenu._getOldestRequest(visibleItems).attachment.startedMillis;
info("Computed total bytes: " + totalBytes);
info("Computed total millis: " + totalMillis);
is(value, PluralForm.get(visibleRequestsCount, L10N.getStr("networkMenu.summary"))
.replace("#1", visibleRequestsCount)
.replace("#2", L10N.numberWithDecimals((totalBytes || 0) / 1024, 2))
.replace("#3", L10N.numberWithDecimals((totalMillis || 0) / 1000, 2))
, "The current summary text is incorrect.")
}
aDebuggee.performRequests('{ "getMedia": true, "getFlash": true }');
});
}

View File

@ -1215,6 +1215,12 @@ MenuContainer.prototype = {
*/
get itemCount() this._itemsByElement.size,
/**
* Gets the total number of visible (non-hidden) items in this container.
* @return number
*/
get visibleItemsCount() this.visibleItems.length,
/**
* Returns a list of all items in this container, in the displayed order.
* @return array

View File

@ -105,6 +105,14 @@ networkMenu.sortedAsc=Sorted ascending
# in the network table toolbar, for any column that is sorted descending.
networkMenu.sortedDesc=Sorted descending
# LOCALIZATION NOTE (networkMenu.empty): This is the label displayed
# in the network table footer when there are no requests available.
networkMenu.empty=No requests
# LOCALIZATION NOTE (networkMenu.summary): This is the label displayed
# in the network table footer providing concise information about all requests.
networkMenu.summary=One request, #2 KB, #3 s;#1 requests, #2 KB, #3 s
# LOCALIZATION NOTE (networkMenu.sizeKB): This is the label displayed
# in the network menu specifying the size of a request (in kilobytes).
networkMenu.sizeKB=%S KB

View File

@ -378,6 +378,10 @@ box.requests-menu-status[code^="5"] {
color: #fff;
}
.requests-menu-footer-spacer {
min-width: 2px;
}
.requests-menu-footer-spacer,
.requests-menu-footer-button {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);

View File

@ -378,6 +378,10 @@ box.requests-menu-status[code^="5"] {
color: #fff;
}
.requests-menu-footer-spacer {
min-width: 2px;
}
.requests-menu-footer-spacer,
.requests-menu-footer-button {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);

View File

@ -378,6 +378,10 @@ box.requests-menu-status[code^="5"] {
color: #fff;
}
.requests-menu-footer-spacer {
min-width: 2px;
}
.requests-menu-footer-spacer,
.requests-menu-footer-button {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);