Commit 497d9415 authored by dgozman@chromium.org's avatar dgozman@chromium.org

[DevTools] Implementation of resource requests blocked by specific urls.

Initial UI is hidden behind "blockedURLs" experiment.

BUG=520259

Review URL: https://codereview.chromium.org/1295903005

git-svn-id: svn://svn.chromium.org/blink/trunk@201079 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e9fce3b6
......@@ -86,6 +86,7 @@ static const char extraRequestHeaders[] = "extraRequestHeaders";
static const char cacheDisabled[] = "cacheDisabled";
static const char userAgentOverride[] = "userAgentOverride";
static const char monitoringXHR[] = "monitoringXHR";
static const char blockedURLs[] = "blockedURLs";
}
namespace {
......@@ -365,6 +366,17 @@ DEFINE_TRACE(InspectorResourceAgent)
InspectorBaseAgent::trace(visitor);
}
bool InspectorResourceAgent::shouldBlockRequest(const ResourceRequest& request)
{
String url = request.url().string();
RefPtr<JSONObject> blockedURLs = m_state->getObject(ResourceAgentState::blockedURLs);
for (const auto& blocked : *blockedURLs) {
if (url.contains(blocked.key))
return true;
}
return false;
}
void InspectorResourceAgent::willSendRequest(LocalFrame* frame, unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse, const FetchInitiatorInfo& initiatorInfo)
{
// Ignore the request initiated internally.
......@@ -882,6 +894,20 @@ void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const Str
callback->sendFailure("No data found for resource with given identifier");
}
void InspectorResourceAgent::addBlockedURL(ErrorString*, const String& url)
{
RefPtr<JSONObject> blockedURLs = m_state->getObject(ResourceAgentState::blockedURLs);
blockedURLs->setBoolean(url, true);
m_state->setObject(ResourceAgentState::blockedURLs, blockedURLs.release());
}
void InspectorResourceAgent::removeBlockedURL(ErrorString*, const String& url)
{
RefPtr<JSONObject> blockedURLs = m_state->getObject(ResourceAgentState::blockedURLs);
blockedURLs->remove(url);
m_state->setObject(ResourceAgentState::blockedURLs, blockedURLs.release());
}
void InspectorResourceAgent::replayXHR(ErrorString*, const String& requestId)
{
String actualRequestId = requestId;
......
......@@ -135,6 +135,8 @@ public:
void setUserAgentOverride(ErrorString*, const String& userAgent) override;
void setExtraHTTPHeaders(ErrorString*, const RefPtr<JSONObject>&) override;
void getResponseBody(ErrorString*, const String& requestId, PassRefPtrWillBeRawPtr<GetResponseBodyCallback>) override;
void addBlockedURL(ErrorString*, const String& url) override;
void removeBlockedURL(ErrorString*, const String& url) override;
void replayXHR(ErrorString*, const String& requestId) override;
void setMonitoringXHREnabled(ErrorString*, bool) override;
......@@ -149,6 +151,7 @@ public:
// Called from other agents.
void setHostId(const String&);
bool fetchResourceContent(Document*, const KURL&, String* content, bool* base64Encoded);
bool shouldBlockRequest(const ResourceRequest&);
private:
explicit InspectorResourceAgent(InspectorPageAgent*);
......
......@@ -44,7 +44,9 @@
#include "core/html/imports/HTMLImportsController.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorResourceAgent.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
......@@ -345,6 +347,12 @@ void FrameFetchContext::printAccessDeniedMessage(const KURL& url) const
bool FrameFetchContext::canRequest(Resource::Type type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRestriction) const
{
InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsFor(frame());
if (agents && agents->inspectorResourceAgent()) {
if (agents->inspectorResourceAgent()->shouldBlockRequest(resourceRequest))
return false;
}
SecurityOrigin* securityOrigin = options.securityOrigin.get();
if (!securityOrigin && m_document)
securityOrigin = m_document->securityOrigin();
......
......@@ -125,6 +125,7 @@ WebInspector.Main.prototype = {
Runtime.experiments.register("animationInspection", "Animation Inspection");
Runtime.experiments.register("applyCustomStylesheet", "Allow custom UI themes");
Runtime.experiments.register("blackboxJSFramesOnTimeline", "Blackbox JavaScript frames on Timeline", true);
Runtime.experiments.register("blockedURLs", "Blocked resource URLs", true);
Runtime.experiments.register("colorContrastRatio", "Contrast ratio line in color picker", true);
Runtime.experiments.register("customObjectFormatters", "Custom object formatters", true);
Runtime.experiments.register("emptySourceMapAutoStepping", "Empty sourcemap auto-stepping");
......
......@@ -1299,6 +1299,12 @@ WebInspector.NetworkLogView.prototype = {
contextMenu.appendItem(WebInspector.UIString.capitalize("Clear ^browser ^cache"), this._clearBrowserCache.bind(this));
contextMenu.appendItem(WebInspector.UIString.capitalize("Clear ^browser ^cookies"), this._clearBrowserCookies.bind(this));
var manager = WebInspector.multitargetNetworkManager;
if (Runtime.experiments.isEnabled("blockedURLs") && request && !manager.blockedURLs().has(request.url)) {
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString.capitalize("Block ^request URL"), manager.toggleURLBlocked.bind(manager, request.url));
}
if (request && request.resourceType() === WebInspector.resourceTypes.XHR) {
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString("Replay XHR"), request.replayXHR.bind(request));
......
......@@ -52,6 +52,11 @@ WebInspector.NetworkPanel = function()
this._filterBar = new WebInspector.FilterBar("networkPanel", true);
this.element.appendChild(this._filterBar.filtersElement());
if (Runtime.experiments.isEnabled("blockedURLs")) {
this._blockedURLsBar = new WebInspector.BlockedURLsBar();
this.element.appendChild(this._blockedURLsBar.element);
}
this._searchableView = new WebInspector.SearchableView(this);
this._searchableView.setPlaceholder(WebInspector.UIString("Find by filename or path"));
this._searchableView.show(this.element);
......@@ -157,6 +162,8 @@ WebInspector.NetworkPanel.prototype = {
this._panelToolbar.appendToolbarItem(this._disableCacheCheckbox);
this._panelToolbar.appendSeparator();
if (Runtime.experiments.isEnabled("blockedURLs"))
this._panelToolbar.appendToolbarItem(this._blockedURLsBar.toolbarButton());
this._panelToolbar.appendToolbarItem(this._createNetworkConditionsSelect());
this._panelToolbar.appendToolbarItem(new WebInspector.ToolbarItem(this._progressBarContainer));
},
......@@ -738,3 +745,61 @@ WebInspector.NetworkPanel.FilmStripRecorder.prototype = {
this._filmStripView.setStatusText(WebInspector.UIString("Fetching frames..."));
}
}
/**
* @constructor
*/
WebInspector.BlockedURLsBar = function()
{
this.element = createElementWithClass("div", "blocked-urls-bar");
this._toolbarButton = new WebInspector.ToolbarButton(WebInspector.UIString("Manage blocked URLs"), "filter-toolbar-item", 3);
this._toolbarButton.addEventListener("click", this._toggleVisibility, this);
this._manager = WebInspector.multitargetNetworkManager;
this._manager.addEventListener(WebInspector.MultitargetNetworkManager.EventTypes.BlockedURLsChanged, this._update, this);
this._visible = true;
this._toggleVisibility();
this._update();
}
WebInspector.BlockedURLsBar.prototype = {
_updateToolbarButton: function()
{
this._toolbarButton.setState(this._visible ? "shown" : (this._manager.blockedURLs().size ? "active" : "inactive"));
},
_update: function()
{
this._updateToolbarButton();
this.element.removeChildren();
for (var url of this._manager.blockedURLs()) {
var container = this.element.createChild("div", "blocked-url-container");
var text = container.createChild("div", "blocked-url-text");
text.textContent = url;
text.title = url;
var closeButton = container.createChild("div", "close-button", "dt-close-button");
closeButton.addEventListener("click", this._manager.toggleURLBlocked.bind(this._manager, url), false);
closeButton.gray = true;
}
if (!this._manager.blockedURLs().size)
this.element.createChild("div", "blocked-urls-empty").textContent = WebInspector.UIString("No blocked URLs.");
},
_toggleVisibility: function()
{
this._visible = !this._visible;
this.element.classList.toggle("hidden", !this._visible);
this._updateToolbarButton();
},
/**
* @return {!WebInspector.ToolbarButton}
*/
toolbarButton: function()
{
return this._toolbarButton;
}
}
......@@ -229,3 +229,39 @@
border-bottom: solid 1px #cdcdcd;
flex: none !important;
}
.blocked-urls-bar {
background-color: #f3f3f3;
flex: none;
border-bottom: 1px solid #dadada;
flex-wrap: wrap;
max-height: 127px;
overflow-y: auto;
overflow-x: hidden;
}
.blocked-urls-bar .blocked-url-container {
display: inline-flex;
padding: 2px;
margin: 2px;
background-color: #dadada;
}
.blocked-urls-bar .blocked-url-text {
max-width: 140px;
margin-right: 5px;
overflow: hidden;
flex: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.blocked-urls-bar .blocked-urls-empty {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
height: 24px;
display: flex;
align-items: center;
padding: 5px;
}
......@@ -666,11 +666,20 @@ WebInspector.NetworkDispatcher.prototype = {
/**
* @constructor
* @extends {WebInspector.Object}
* @implements {WebInspector.TargetManager.Observer}
*/
WebInspector.MultitargetNetworkManager = function()
{
WebInspector.Object.call(this);
WebInspector.targetManager.observeTargets(this);
/** @type {!Set<string>} */
this._blockedURLs = new Set();
}
WebInspector.MultitargetNetworkManager.EventTypes = {
BlockedURLsChanged: "BlockedURLsChanged"
}
WebInspector.MultitargetNetworkManager.prototype = {
......@@ -685,6 +694,8 @@ WebInspector.MultitargetNetworkManager.prototype = {
networkAgent.setExtraHTTPHeaders(this._extraHeaders);
if (typeof this._userAgent !== "undefined")
networkAgent.setUserAgentOverride(this._userAgent);
for (var url of this._blockedURLs)
networkAgent.addBlockedURL(url);
},
/**
......@@ -714,7 +725,34 @@ WebInspector.MultitargetNetworkManager.prototype = {
this._userAgent = userAgent;
for (var target of WebInspector.targetManager.targets())
target.networkAgent().setUserAgentOverride(this._userAgent);
}
},
/**
* @param {string} url
*/
toggleURLBlocked: function(url)
{
if (this._blockedURLs.has(url)) {
this._blockedURLs.delete(url);
for (var target of WebInspector.targetManager.targets())
target.networkAgent().removeBlockedURL(url);
} else {
this._blockedURLs.add(url);
for (var target of WebInspector.targetManager.targets())
target.networkAgent().addBlockedURL(url);
}
this.dispatchEventToListeners(WebInspector.MultitargetNetworkManager.EventTypes.BlockedURLsChanged);
},
/**
* @return {!Set<string>}
*/
blockedURLs: function()
{
return this._blockedURLs;
},
__proto__: WebInspector.Object.prototype
}
/**
......
......@@ -1358,6 +1358,22 @@
{ "name": "base64Encoded", "type": "boolean", "description": "True, if content was sent as base64." }
]
},
{
"name": "addBlockedURL",
"description": "Blocks specific URL from loading.",
"parameters": [
{ "name": "url", "type": "string", "description": "URL to block." }
],
"hidden": true
},
{
"name": "removeBlockedURL",
"description": "Cancels blocking of a specific URL from loading.",
"parameters": [
{ "name": "url", "type": "string", "description": "URL to stop blocking." }
],
"hidden": true
},
{
"name": "replayXHR",
"description": "This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment