Bug 1359682 - Open Netmonitor response panel when clicking on file thumbnail. r=gasolin

This commit is contained in:
Michael Brennan 2017-05-04 05:07:00 +08:00
Родитель 71365c8b72
Коммит 6abfb0bad6
7 изменённых файлов: 81 добавлений и 22 удалений

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

@ -17,7 +17,7 @@ const RequestListColumnCause = createClass({
propTypes: { propTypes: {
item: PropTypes.object.isRequired, item: PropTypes.object.isRequired,
onCauseBadgeClick: PropTypes.func.isRequired, onCauseBadgeMouseDown: PropTypes.func.isRequired,
}, },
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
@ -27,7 +27,7 @@ const RequestListColumnCause = createClass({
render() { render() {
let { let {
item: { cause }, item: { cause },
onCauseBadgeClick, onCauseBadgeMouseDown,
} = this.props; } = this.props;
let causeType = "unknown"; let causeType = "unknown";
@ -43,7 +43,7 @@ const RequestListColumnCause = createClass({
div({ className: "requests-list-column requests-list-cause", title: causeType }, div({ className: "requests-list-column requests-list-cause", title: causeType },
causeHasStack && div({ causeHasStack && div({
className: "requests-list-cause-stack", className: "requests-list-cause-stack",
onClick: onCauseBadgeClick, onMouseDown: onCauseBadgeMouseDown,
}, "JS"), }, "JS"),
causeType causeType
) )

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

@ -26,7 +26,7 @@ const RequestListColumnDomain = createClass({
propTypes: { propTypes: {
item: PropTypes.object.isRequired, item: PropTypes.object.isRequired,
onSecurityIconClick: PropTypes.func.isRequired, onSecurityIconMouseDown: PropTypes.func.isRequired,
}, },
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
@ -34,7 +34,7 @@ const RequestListColumnDomain = createClass({
}, },
render() { render() {
let { item, onSecurityIconClick } = this.props; let { item, onSecurityIconMouseDown } = this.props;
let { remoteAddress, remotePort, securityState, let { remoteAddress, remotePort, securityState,
urlDetails: { host, isLocal } } = item; urlDetails: { host, isLocal } } = item;
let iconClassList = ["requests-security-state-icon"]; let iconClassList = ["requests-security-state-icon"];
@ -54,7 +54,7 @@ const RequestListColumnDomain = createClass({
div({ className: "requests-list-column requests-list-domain", title }, div({ className: "requests-list-column requests-list-domain", title },
div({ div({
className: iconClassList.join(" "), className: iconClassList.join(" "),
onMouseDown: onSecurityIconClick, onMouseDown: onSecurityIconMouseDown,
title: iconTitle, title: iconTitle,
}), }),
host, host,

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

@ -23,6 +23,7 @@ const RequestListColumnFile = createClass({
propTypes: { propTypes: {
item: PropTypes.object.isRequired, item: PropTypes.object.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
}, },
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
@ -30,7 +31,10 @@ const RequestListColumnFile = createClass({
}, },
render() { render() {
let { responseContentDataUri, urlDetails } = this.props.item; let {
item: { responseContentDataUri, urlDetails },
onThumbnailMouseDown
} = this.props;
return ( return (
div({ div({
@ -40,6 +44,7 @@ const RequestListColumnFile = createClass({
img({ img({
className: "requests-list-icon", className: "requests-list-icon",
src: responseContentDataUri, src: responseContentDataUri,
onMouseDown: onThumbnailMouseDown,
}), }),
urlDetails.baseNameWithQuery urlDetails.baseNameWithQuery
) )

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

@ -40,10 +40,11 @@ const RequestListContent = createClass({
displayedRequests: PropTypes.object.isRequired, displayedRequests: PropTypes.object.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired, firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool, fromCache: PropTypes.bool,
onCauseBadgeClick: PropTypes.func.isRequired, onCauseBadgeMouseDown: PropTypes.func.isRequired,
onItemMouseDown: PropTypes.func.isRequired, onItemMouseDown: PropTypes.func.isRequired,
onSecurityIconClick: PropTypes.func.isRequired, onSecurityIconMouseDown: PropTypes.func.isRequired,
onSelectDelta: PropTypes.func.isRequired, onSelectDelta: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
scale: PropTypes.number, scale: PropTypes.number,
selectedRequestId: PropTypes.string, selectedRequestId: PropTypes.string,
}, },
@ -224,9 +225,10 @@ const RequestListContent = createClass({
columns, columns,
displayedRequests, displayedRequests,
firstRequestStartedMillis, firstRequestStartedMillis,
onCauseBadgeClick, onCauseBadgeMouseDown,
onItemMouseDown, onItemMouseDown,
onSecurityIconClick, onSecurityIconMouseDown,
onThumbnailMouseDown,
selectedRequestId, selectedRequestId,
} = this.props; } = this.props;
@ -250,8 +252,9 @@ const RequestListContent = createClass({
onContextMenu: this.onContextMenu, onContextMenu: this.onContextMenu,
onFocusedNodeChange: this.onFocusedNodeChange, onFocusedNodeChange: this.onFocusedNodeChange,
onMouseDown: () => onItemMouseDown(item.id), onMouseDown: () => onItemMouseDown(item.id),
onCauseBadgeClick: () => onCauseBadgeClick(item.cause), onCauseBadgeMouseDown: () => onCauseBadgeMouseDown(item.cause),
onSecurityIconClick: () => onSecurityIconClick(item.securityState), onSecurityIconMouseDown: () => onSecurityIconMouseDown(item.securityState),
onThumbnailMouseDown: () => onThumbnailMouseDown(),
})) }))
) )
) )
@ -273,7 +276,7 @@ module.exports = connect(
/** /**
* A handler that opens the stack trace tab when a stack trace is available * A handler that opens the stack trace tab when a stack trace is available
*/ */
onCauseBadgeClick: (cause) => { onCauseBadgeMouseDown: (cause) => {
if (cause.stacktrace && cause.stacktrace.length > 0) { if (cause.stacktrace && cause.stacktrace.length > 0) {
dispatch(Actions.selectDetailsPanelTab("stack-trace")); dispatch(Actions.selectDetailsPanelTab("stack-trace"));
} }
@ -283,11 +286,18 @@ module.exports = connect(
* A handler that opens the security tab in the details view if secure or * A handler that opens the security tab in the details view if secure or
* broken security indicator is clicked. * broken security indicator is clicked.
*/ */
onSecurityIconClick: (securityState) => { onSecurityIconMouseDown: (securityState) => {
if (securityState && securityState !== "insecure") { if (securityState && securityState !== "insecure") {
dispatch(Actions.selectDetailsPanelTab("security")); dispatch(Actions.selectDetailsPanelTab("security"));
} }
}, },
onSelectDelta: (delta) => dispatch(Actions.selectDelta(delta)), onSelectDelta: (delta) => dispatch(Actions.selectDelta(delta)),
/**
* A handler that opens the response tab in the details view if
* the thumbnail is clicked.
*/
onThumbnailMouseDown: () => {
dispatch(Actions.selectDetailsPanelTab("response"));
},
}), }),
)(RequestListContent); )(RequestListContent);

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

@ -76,11 +76,12 @@ const RequestListItem = createClass({
isSelected: PropTypes.bool.isRequired, isSelected: PropTypes.bool.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired, firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool, fromCache: PropTypes.bool,
onCauseBadgeClick: PropTypes.func.isRequired, onCauseBadgeMouseDown: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired, onContextMenu: PropTypes.func.isRequired,
onFocusedNodeChange: PropTypes.func, onFocusedNodeChange: PropTypes.func,
onMouseDown: PropTypes.func.isRequired, onMouseDown: PropTypes.func.isRequired,
onSecurityIconClick: PropTypes.func.isRequired, onSecurityIconMouseDown: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number, waterfallWidth: PropTypes.number,
}, },
@ -115,8 +116,9 @@ const RequestListItem = createClass({
fromCache, fromCache,
onContextMenu, onContextMenu,
onMouseDown, onMouseDown,
onCauseBadgeClick, onCauseBadgeMouseDown,
onSecurityIconClick, onSecurityIconMouseDown,
onThumbnailMouseDown,
} = this.props; } = this.props;
let classList = ["request-list-item", index % 2 ? "odd" : "even"]; let classList = ["request-list-item", index % 2 ? "odd" : "even"];
@ -134,12 +136,13 @@ const RequestListItem = createClass({
}, },
columns.get("status") && RequestListColumnStatus({ item }), columns.get("status") && RequestListColumnStatus({ item }),
columns.get("method") && RequestListColumnMethod({ item }), columns.get("method") && RequestListColumnMethod({ item }),
columns.get("file") && RequestListColumnFile({ item }), columns.get("file") && RequestListColumnFile({ item, onThumbnailMouseDown }),
columns.get("protocol") && RequestListColumnProtocol({ item }), columns.get("protocol") && RequestListColumnProtocol({ item }),
columns.get("scheme") && RequestListColumnScheme({ item }), columns.get("scheme") && RequestListColumnScheme({ item }),
columns.get("domain") && RequestListColumnDomain({ item, onSecurityIconClick }), columns.get("domain") && RequestListColumnDomain({ item,
onSecurityIconMouseDown }),
columns.get("remoteip") && RequestListColumnRemoteIP({ item }), columns.get("remoteip") && RequestListColumnRemoteIP({ item }),
columns.get("cause") && RequestListColumnCause({ item, onCauseBadgeClick }), columns.get("cause") && RequestListColumnCause({ item, onCauseBadgeMouseDown }),
columns.get("type") && RequestListColumnType({ item }), columns.get("type") && RequestListColumnType({ item }),
columns.get("cookies") && RequestListColumnCookies({ item }), columns.get("cookies") && RequestListColumnCookies({ item }),
columns.get("setCookies") && RequestListColumnSetCookies({ item }), columns.get("setCookies") && RequestListColumnSetCookies({ item }),

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

@ -159,6 +159,7 @@ skip-if = true # Bug 1258809
[browser_net_status-codes.js] [browser_net_status-codes.js]
[browser_net_streaming-response.js] [browser_net_streaming-response.js]
[browser_net_throttle.js] [browser_net_throttle.js]
[browser_net_thumbnail-click.js]
[browser_net_timeline_ticks.js] [browser_net_timeline_ticks.js]
skip-if = true # TODO: fix the test skip-if = true # TODO: fix the test
[browser_net_timing-division.js] [browser_net_timing-division.js]

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

@ -0,0 +1,40 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that clicking on the file thumbnail opens the response details tab.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
let { document } = monitor.panelWin;
yield performRequestsAndWait();
let wait = waitForDOM(document, "#response-panel");
let request = document.querySelectorAll(".request-list-item")[5];
let icon = request.querySelector(".requests-list-icon");
info("Clicking thumbnail of the sixth request.");
EventUtils.synthesizeMouseAtCenter(icon, {}, monitor.panelWin);
yield wait;
ok(document.querySelector("#response-tab[aria-selected=true]"),
"Response tab is selected.");
ok(document.querySelector(".response-image-box"),
"Response image preview is shown.");
yield teardown(monitor);
function* performRequestsAndWait() {
let onAllEvents = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests();
});
yield onAllEvents;
}
});