Bug 1151368 - Block requests by URL in DevTools. r=ochameau

This is a very basic form of request blocking for the Network Monitor. It only
supports blocking a request via right-click. This change adds the minimal UI and
server support to block the request.

There is no UI to indicate what happened to the request yet, so it will just
look like a "confused" request that never started. Future patches will improve
from here.

Differential Revision: https://phabricator.services.mozilla.com/D26579

--HG--
extra : moz-landing-system : lando
This commit is contained in:
J. Ryan Stinnett 2019-04-19 18:25:19 +00:00
Родитель 74149656b7
Коммит d4c5593416
11 изменённых файлов: 119 добавлений и 1 удалений

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

@ -1071,6 +1071,10 @@ netmonitor.context.editAndResend=Edit and Resend
# for the "Edit and Resend" menu item displayed in the context menu for a request
netmonitor.context.editAndResend.accesskey=E
# LOCALIZATION NOTE (netmonitor.context.blockURL): This is the label displayed
# on the context menu that blocks any requests matching the selected request's URL.
netmonitor.context.blockURL=Block URL
# LOCALIZATION NOTE (netmonitor.context.newTab): This is the label
# for the Open in New Tab menu item displayed in the context menu of the
# network container

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

@ -77,6 +77,22 @@ function sendCustomRequest(connector) {
};
}
/**
* Tell the backend to block future requests that match the URL of the selected one.
*/
function blockSelectedRequestURL(connector) {
return (dispatch, getState) => {
const selected = getSelectedRequest(getState());
if (!selected) {
return;
}
const { url } = selected;
connector.blockRequest({ url });
};
}
/**
* Remove a request from the list. Supports removing only cloned requests with a
* "isCustom" attribute. Other requests never need to be removed.
@ -104,6 +120,7 @@ function toggleRecording() {
module.exports = {
addRequest,
blockSelectedRequestURL,
clearRequests,
cloneSelectedRequest,
removeSelectedCustomRequest,

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

@ -50,6 +50,7 @@ const MAX_SCROLL_HEIGHT = 2147483647;
class RequestListContent extends Component {
static get propTypes() {
return {
blockSelectedRequestURL: PropTypes.func.isRequired,
connector: PropTypes.object.isRequired,
columns: PropTypes.object.isRequired,
networkDetailsOpen: PropTypes.bool.isRequired,
@ -265,12 +266,14 @@ class RequestListContent extends Component {
if (!this.contextMenu) {
const {
blockSelectedRequestURL,
connector,
cloneSelectedRequest,
sendCustomRequest,
openStatistics,
} = this.props;
this.contextMenu = new RequestListContextMenu({
blockSelectedRequestURL,
connector,
cloneSelectedRequest,
sendCustomRequest,
@ -359,6 +362,9 @@ module.exports = connect(
requestFilterTypes: state.filters.requestFilterTypes,
}),
(dispatch, props) => ({
blockSelectedRequestURL: () => {
dispatch(Actions.blockSelectedRequestURL(props.connector));
},
cloneSelectedRequest: () => dispatch(Actions.cloneSelectedRequest()),
sendCustomRequest: () => dispatch(Actions.sendCustomRequest(props.connector)),
openStatistics: (open) => dispatch(Actions.openStatistics(props.connector, open)),

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

@ -89,6 +89,15 @@ class ChromeConnector {
// TODO : not support. currently didn't provide this feature in CDP API.
}
/**
* Block future requests matching a filter.
*
* @param {object} filter request filter specifying what to block
*/
blockRequest(filter) {
// TODO: Implement for Chrome as well.
}
setPreferences() {
// TODO : implement.
}

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

@ -233,6 +233,15 @@ class FirefoxConnector {
this.webConsoleClient.sendHTTPRequest(data).then(callback);
}
/**
* Block future requests matching a filter.
*
* @param {object} filter request filter specifying what to block
*/
blockRequest(filter) {
return this.webConsoleClient.blockRequest(filter);
}
/**
* Set network preferences to control network flow
*

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

@ -96,6 +96,10 @@ class Connector {
return this.connector.sendHTTPRequest(...arguments);
}
blockRequest() {
return this.connector.blockRequest(...arguments);
}
setPreferences() {
return this.connector.setPreferences(...arguments);
}

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

@ -44,6 +44,7 @@ class RequestListContextMenu {
url,
} = selectedRequest;
const {
blockSelectedRequestURL,
connector,
cloneSelectedRequest,
sendCustomRequest,
@ -201,6 +202,13 @@ class RequestListContextMenu {
click: cloneSelectedRequest,
});
menu.push({
id: "request-list-context-block-url",
label: L10N.getStr("netmonitor.context.blockURL"),
visible: !!selectedRequest,
click: blockSelectedRequestURL,
});
menu.push({
type: "separator",
visible: copySubmenu.slice(15, 16).some((subMenu) => subMenu.visible),

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

@ -52,6 +52,7 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
this.onStackTraceAvailable = this.onStackTraceAvailable.bind(this);
this.onRequestContent = this.onRequestContent.bind(this);
this.onSetPreference = this.onSetPreference.bind(this);
this.onBlockRequest = this.onBlockRequest.bind(this);
this.onGetNetworkEventActor = this.onGetNetworkEventActor.bind(this);
this.onDestroyMessage = this.onDestroyMessage.bind(this);
@ -71,6 +72,8 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
this.onRequestContent);
this.messageManager.addMessageListener("debug:netmonitor-preference",
this.onSetPreference);
this.messageManager.addMessageListener("debug:block-request",
this.onBlockRequest);
this.messageManager.addMessageListener("debug:get-network-event-actor:request",
this.onGetNetworkEventActor);
this.messageManager.addMessageListener("debug:destroy-network-monitor",
@ -84,6 +87,8 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
this.onRequestContent);
this.messageManager.removeMessageListener("debug:netmonitor-preference",
this.onSetPreference);
this.messageManager.removeMessageListener("debug:block-request",
this.onBlockRequest);
this.messageManager.removeMessageListener("debug:get-network-event-actor:request",
this.onGetNetworkEventActor);
this.messageManager.removeMessageListener("debug:destroy-network-monitor",
@ -172,6 +177,11 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
}
},
onBlockRequest({ data }) {
const { filter } = data;
this.observer.blockRequest(filter);
},
onGetNetworkEventActor({ data }) {
const actor = this.getNetworkEventActor(data.channelId);
this.messageManager.sendAsyncMessage("debug:get-network-event-actor:response", {

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

@ -6,7 +6,7 @@
"use strict";
const {Cc, Ci} = require("chrome");
const {Cc, Ci, Cr} = require("chrome");
const Services = require("Services");
const flags = require("devtools/shared/flags");
@ -126,6 +126,8 @@ function NetworkObserver(filters, owner) {
this.openRequests = new Map();
this.openResponses = new Map();
this.blockedURLs = new Set();
this._httpResponseExaminer =
DevToolsUtils.makeInfallible(this._httpResponseExaminer).bind(this);
this._httpModifyExaminer =
@ -644,6 +646,21 @@ NetworkObserver.prototype = {
return httpActivity;
},
/**
* Block a request based on certain filtering options.
*
* Currently, an exact URL match is the only supported filter type.
*/
blockRequest(filter) {
if (!filter || !filter.url) {
// In the future, there may be other types of filters, such as domain.
// For now, ignore anything other than URL.
return;
}
this.blockedURLs.add(filter.url);
},
/**
* Setup the network response listener for the given HTTP activity. The
* NetworkResponseListener is responsible for storing the response body.
@ -656,6 +673,11 @@ NetworkObserver.prototype = {
const channel = httpActivity.channel;
channel.QueryInterface(Ci.nsITraceableChannel);
if (this.blockedURLs.has(httpActivity.url)) {
channel.cancel(Cr.NS_BINDING_ABORTED);
return;
}
if (!fromCache) {
const throttler = this._getThrottler();
if (throttler) {

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

@ -1681,6 +1681,28 @@ WebConsoleActor.prototype =
});
},
/**
* Block a request based on certain filtering options.
*
* Currently, an exact URL match is the only supported filter type.
* In the future, there may be other types of filters, such as domain.
* For now, ignore anything other than URL.
*
* @param object filter
* An object containing a `url` key with a URL to block.
*/
async blockRequest({ filter }) {
if (this.netmonitors) {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:block-request", {
filter,
});
}
}
return {};
},
/**
* Handler for file activity. This method sends the file request information
* to the remote Web Console client.
@ -1832,6 +1854,7 @@ WebConsoleActor.prototype.requestTypes =
getPreferences: WebConsoleActor.prototype.getPreferences,
setPreferences: WebConsoleActor.prototype.setPreferences,
sendHTTPRequest: WebConsoleActor.prototype.sendHTTPRequest,
blockRequest: WebConsoleActor.prototype.blockRequest,
};
exports.WebConsoleActor = WebConsoleActor;

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

@ -234,6 +234,12 @@ const webconsoleSpecPrototype = {
},
response: RetVal("json"),
},
blockRequest: {
request: {
filter: Arg(0, "json"),
},
},
},
};