一、chrome.webRequest
注意 :从 Manifest V3 开始,
"webRequestBlocking"
权限不再适用于大多数扩展程序。以
"declarativeNetRequest"
为例,它允许使用 declarativeNetRequest API。除了
"webRequestBlocking"
之外,webRequest API 保持不变,仍可正常使用。通过政策安装的扩展程序可以继续使用
"webRequestBlocking"
。
使用
chrome.webRequest
API 可观察和分析流量,以及拦截、阻止或修改传输中的请求。
权限
webRequest
您必须在扩展程序清单中声明
"webRequest"
权限,才能使用 Web 请求 API 以及必要的主机权限。要拦截子资源请求, 扩展程序必须同时有权访问请求的网址及其发起者。例如:
{
"name": "My extension",
...
"permissions": [
"webRequest"
],
"host_permissions": [
"*://*.google.com/*"
],
...
}
webRequestBlocking
必须填写此字段,才能注册屏蔽事件处理脚本。从 Manifest V3 开始, 适用于通过政策安装的扩展程序
webRequestAuthProvider
使用 onAuthRequired 方法的必需条件。请参阅 处理身份验证。
请求的生命周期
Web 请求 API 定义了一组遵循 Web 请求生命周期的事件。您可以使用 来观察和分析流量。某些同步事件允许您拦截、 屏蔽或修改请求
成功请求的事件生命周期如下所示,其后是事件定义:
更多参考 chrome.webRequest | API | Chrome for Developers
二、chrome.webRequest c++接口定义:
1、web_request.json接口描述文件:
extensions\common\api\web_request.json
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
{
"namespace": "webRequest",
"description": "Use the <code>chrome.webRequest</code> API to observe and analyze traffic and to intercept, block, or modify requests in-flight.",
"properties": {
"MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES": {
"value": 20,
"description": "The maximum number of times that <code>handlerBehaviorChanged</code> can be called per 10 minute sustained interval. <code>handlerBehaviorChanged</code> is an expensive function call that shouldn't be called often."
}
},
"types": [
{
"id": "ResourceType",
"type": "string",
"enum": [
{"name": "main_frame", "description": "Specifies the resource as the main frame."},
{"name": "sub_frame", "description": "Specifies the resource as a sub frame."},
{"name": "stylesheet", "description": "Specifies the resource as a stylesheet."},
{"name": "script", "description": "Specifies the resource as a script."},
{"name": "image", "description": "Specifies the resource as an image."},
{"name": "font", "description": "Specifies the resource as a font."},
{"name": "object", "description": "Specifies the resource as an object."},
{"name": "xmlhttprequest",
"description": "Specifies the resource as an XMLHttpRequest."},
{"name": "ping",
"description": "Specifies the resource as a ping."},
{"name": "csp_report",
"description": "Specifies the resource as a Content Security Policy (CSP) report."},
{"name": "media", "description": "Specifies the resource as a media object."},
{"name": "websocket", "description": "Specifies the resource as a WebSocket."},
{"name": "webbundle", "description": "Specifies the resource as a WebBundle."},
{"name": "other", "description": "Specifies the resource as a type not included in the listed types."}
]
},
{
"id": "OnBeforeRequestOptions",
"type": "string",
"enum": [
{"name": "blocking", "description": "Specifies the request is blocked until the callback function returns."},
{"name": "requestBody", "description": "Specifies that the request body should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnBeforeSendHeadersOptions",
"type": "string",
"enum": [
{"name": "requestHeaders", "description": "Specifies that the request header should be included in the event."},
{"name": "blocking", "description": "Specifies the request is blocked until the callback function returns."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnSendHeadersOptions",
"type": "string",
"enum": [
{"name": "requestHeaders", "description": "Specifies that the request header should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnHeadersReceivedOptions",
"type": "string",
"enum": [
{"name": "blocking", "description": "Specifies the request is blocked until the callback function returns."},
{"name": "responseHeaders", "description": "Specifies that the response headers should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnAuthRequiredOptions",
"type": "string",
"enum": [
{"name": "responseHeaders", "description": "Specifies that the response headers should be included in the event."},
{"name": "blocking", "description": "Specifies the request is blocked until the callback function returns."},
{"name": "asyncBlocking", "description": "Specifies that the callback function is handled asynchronously."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnResponseStartedOptions",
"type": "string",
"enum": [
{"name": "responseHeaders", "description": "Specifies that the response headers should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnBeforeRedirectOptions",
"type": "string",
"enum": [
{"name": "responseHeaders", "description": "Specifies that the response headers should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnCompletedOptions",
"type": "string",
"enum": [
{"name": "responseHeaders", "description": "Specifies that the response headers should be included in the event."},
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "OnErrorOccurredOptions",
"type": "string",
"enum": [
{"name": "extraHeaders", "description": "Specifies that headers can violate Cross-Origin Resource Sharing (CORS)."}
]
},
{
"id": "RequestFilter",
"type": "object",
"description": "An object describing filters to apply to webRequest events.",
"properties": {
"urls": {
"type": "array",
"description": "A list of URLs or URL patterns. Requests that cannot match any of the URLs will be filtered out.",
"items": { "type": "string" }
},
"types": {
"type": "array",
"optional": true,
"description": "A list of request types. Requests that cannot match any of the types will be filtered out.",
"items": { "$ref": "ResourceType" }
},
"tabId": { "type": "integer", "optional": true },
"windowId": { "type": "integer", "optional": true }
}
},
{
"id": "HttpHeaders",
"nocompile": true,
"type": "array",
"description": "An array of HTTP headers. Each header is represented as a dictionary containing the keys <code>name</code> and either <code>value</code> or <code>binaryValue</code>.",
"items": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Name of the HTTP header."},
"value": {"type": "string", "optional": true, "description": "Value of the HTTP header if it can be represented by UTF-8."},
"binaryValue": {
"type": "array",
"optional": true,
"description": "Value of the HTTP header if it cannot be represented by UTF-8, stored as individual byte values (0..255).",
"items": {"type": "integer"}
}
}
}
},
{
"id": "BlockingResponse",
"nocompile": true,
"type": "object",
"description": "Returns value for event handlers that have the 'blocking' extraInfoSpec applied. Allows the event handler to modify network requests.",
"properties": {
"cancel": {
"type": "boolean",
"optional": true,
"description": "If true, the request is cancelled. This prevents the request from being sent. This can be used as a response to the onBeforeRequest, onBeforeSendHeaders, onHeadersReceived and onAuthRequired events."
},
"redirectUrl": {
"type": "string",
"optional": true,
"description": "Only used as a response to the onBeforeRequest and onHeadersReceived events. If set, the original request is prevented from being sent/completed and is instead redirected to the given URL. Redirections to non-HTTP schemes such as <code>data:</code> are allowed. Redirects initiated by a redirect action use the original request method for the redirect, with one exception: If the redirect is initiated at the onHeadersReceived stage, then the redirect will be issued using the GET method. Redirects from URLs with <code>ws://</code> and <code>wss://</code> schemes are <b>ignored</b>."
},
"requestHeaders": {
"$ref": "HttpHeaders",
"optional": true,
"description": "Only used as a response to the onBeforeSendHeaders event. If set, the request is made with these request headers instead."
},
"responseHeaders": {
"$ref": "HttpHeaders",
"optional": true,
"description": "Only used as a response to the onHeadersReceived event. If set, the server is assumed to have responded with these response headers instead. Only return <code>responseHeaders</code> if you really want to modify the headers in order to limit the number of conflicts (only one extension may modify <code>responseHeaders</code> for each request)."
},
"authCredentials": {
"type": "object",
"description": "Only used as a response to the onAuthRequired event. If set, the request is made using the supplied credentials.",
"optional": true,
"properties": {
"username": {"type": "string"},
"password": {"type": "string"}
}
}
}
},
{
"id": "UploadData",
"type": "object",
"properties": {
"bytes": {
"type": "any",
"optional": true,
"description": "An ArrayBuffer with a copy of the data."
},
"file": {
"type": "string",
"optional": true,
"description": "A string with the file's path and name."
}
},
"description": "Contains data uploaded in a URL request."
},
{
"id": "FormDataItem",
"choices": [
{ "type": "binary" },
{ "type": "string" }
],
"description": "Contains data passed within form data. For urlencoded form it is stored as string if data is utf-8 string and as ArrayBuffer otherwise. For form-data it is ArrayBuffer. If form-data represents uploading file, it is string with filename, if the filename is provided."
},
{
"id": "IgnoredActionType",
"decription": "Denotes the extension proposed action which was ignored.",
"type": "string",
"enum": ["redirect", "request_headers", "response_headers", "auth_credentials"]
}
],
"functions": [
{
"name": "handlerBehaviorChanged",
"type": "function",
"description": "Needs to be called when the behavior of the webRequest handlers has changed to prevent incorrect handling due to caching. This function call is expensive. Don't call it often.",
"parameters": [],
"returns_async": {"name": "callback", "optional": true, "parameters": []}
}
],
"events": [
{
"name": "onBeforeRequest",
"type": "function",
"description": "Fired when a request is about to occur.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "optional": true, "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "optional": true, "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "optional": true, "description": "The type of frame the request occurred in."},
"requestBody": {
"type": "object",
"optional": true,
"description": "Contains the HTTP request body data. Only provided if extraInfoSpec contains 'requestBody'.",
"properties": {
"error": {"type": "string", "optional": true, "description": "Errors when obtaining request body data."},
"formData": {
"type": "object",
"optional": true,
"description": "If the request method is POST and the body is a sequence of key-value pairs encoded in UTF8, encoded as either multipart/form-data, or application/x-www-form-urlencoded, this dictionary is present and for each key contains the list of all values for that key. If the data is of another media type, or if it is malformed, the dictionary is not present. An example value of this dictionary is {'key': ['value1', 'value2']}.",
"properties": {},
"additionalProperties": {
"type": "array",
"items": { "$ref": "FormDataItem" }
}
},
"raw" : {
"type": "array",
"optional": true,
"items": {"$ref": "UploadData"},
"description": "If the request method is PUT or POST, and the body is not already parsed in formData, then the unparsed request body elements are contained in this array."
}
}
},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnBeforeRequestOptions"
}
}
],
"returns": {
"$ref": "BlockingResponse",
"description": "If \"blocking\" is specified in the \"extraInfoSpec\" parameter, the event listener should return an object of this type.",
"optional": true
}
},
{
"name": "onBeforeSendHeaders",
"nocompile": true,
"type": "function",
"description": "Fired before sending an HTTP request, once the request headers are available. This may occur after a TCP connection is made to the server, but before any HTTP data is sent. ",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"requestHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP request headers that are going to be sent out with this request."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnBeforeSendHeadersOptions"
}
}
],
"returns": {
"$ref": "BlockingResponse",
"description": "If \"blocking\" is specified in the \"extraInfoSpec\" parameter, the event listener should return an object of this type.",
"optional": true
}
},
{
"name": "onSendHeaders",
"nocompile": true,
"type": "function",
"description": "Fired just before a request is going to be sent to the server (modifications of previous onBeforeSendHeaders callbacks are visible by the time onSendHeaders is fired).",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"requestHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP request headers that have been sent out with this request."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnSendHeadersOptions"
}
}
]
},
{
"name": "onHeadersReceived",
"nocompile": true,
"type": "function",
"description": "Fired when HTTP response headers of a request have been received.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line)."},
"responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that have been received with this response."},
"statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnHeadersReceivedOptions"
}
}
],
"returns": {
"$ref": "BlockingResponse",
"description": "If \"blocking\" is specified in the \"extraInfoSpec\" parameter, the event listener should return an object of this type.",
"optional": true
}
},
{
"name": "onAuthRequired",
"nocompile": true,
"type": "function",
"description": "Fired when an authentication failure is received. The listener has three options: it can provide authentication credentials, it can cancel the request and display the error page, or it can take no action on the challenge. If bad user credentials are provided, this may be called multiple times for the same request. Note, only one of <code>'blocking'</code> or <code>'asyncBlocking'</code> modes must be specified in the <code>extraInfoSpec</code> parameter.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"scheme": {"type": "string", "description": "The authentication scheme, e.g. Basic or Digest."},
"realm": {"type": "string", "description": "The authentication realm provided by the server, if there is one.", "optional": true},
"challenger": {"type": "object", "description": "The server requesting authentication.", "properties": {"host": {"type": "string"}, "port": {"type": "integer"}}},
"isProxy": {"type": "boolean", "description": "True for Proxy-Authenticate, false for WWW-Authenticate."},
"responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that were received along with this response."},
"statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line) or an empty string if there are no headers."},
"statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."}
}
},
{
"type": "function",
"optional": true,
"description" : "Only valid if <code>'asyncBlocking'</code> is specified as one of the <code>OnAuthRequiredOptions</code>.",
"name": "asyncCallback",
"parameters": [
{"name": "response", "$ref": "BlockingResponse"}
]
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnAuthRequiredOptions"
}
}
],
"returns": {
"$ref": "BlockingResponse",
"description": "If \"blocking\" is specified in the \"extraInfoSpec\" parameter, the event listener should return an object of this type.",
"optional": true
}
},
{
"name": "onResponseStarted",
"nocompile": true,
"type": "function",
"description": "Fired when the first byte of the response body is received. For HTTP requests, this means that the status line and response headers are available.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
"fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
"statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
"responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that were received along with this response."},
"statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line) or an empty string if there are no headers."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnResponseStartedOptions"
}
}
]
},
{
"name": "onBeforeRedirect",
"type": "function",
"nocompile": true,
"description": "Fired when a server-initiated redirect is about to occur.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
"fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
"statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
"redirectUrl": {"type": "string", "description": "The new URL."},
"responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that were received along with this redirect."},
"statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line) or an empty string if there are no headers."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnBeforeRedirectOptions"
}
}
]
},
{
"name": "onCompleted",
"type": "function",
"nocompile": true,
"description": "Fired when a request is completed.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
"fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
"statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
"responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that were received along with this response."},
"statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line) or an empty string if there are no headers."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnCompletedOptions"
}
}
]
},
{
"name": "onErrorOccurred",
"type": "function",
"description": "Fired when an error occurs.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"url": {"type": "string"},
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
"documentId": {"type": "string", "description": "The UUID of the document making the request. This value is not present if the request is a navigation of a frame."},
"parentDocumentId": {"type": "string", "optional": true, "description": "The UUID of the parent document owning this frame. This is not set if there is no parent."},
"documentLifecycle": {"$ref": "extensionTypes.DocumentLifecycle", "description": "The lifecycle the document is in."},
"frameType": {"$ref": "extensionTypes.FrameType", "description": "The type of frame the request occurred in."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
"type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
"initiator": {"type": "string", "optional": true, "description": "The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used."},
"timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
"ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
"fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
"error": {"type": "string", "description": "The error description. This string is <em>not</em> guaranteed to remain backwards compatible between releases. You must not parse and act based upon its content."}
}
}
],
"extraParameters": [
{
"$ref": "RequestFilter",
"name": "filter",
"description": "A set of filters that restricts the events that will be sent to this listener."
},
{
"type": "array",
"optional": true,
"name": "extraInfoSpec",
"description": "Array of extra information that should be passed to the listener function.",
"items": {
"$ref": "OnErrorOccurredOptions"
}
}
]
},
{
"name": "onActionIgnored",
"type": "function",
"description": "Fired when an extension's proposed modification to a network request is ignored. This happens in case of conflicts with other extensions.",
"parameters": [
{
"type": "object",
"name": "details",
"properties": {
"requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
"action": {"$ref": "IgnoredActionType", "description": "The proposed action which was ignored."}
}
}
]
}
]
}
]
2、web_request.json生成的c++文件:
out\Debug\gen\extensions\common\api\web_request.h
out\Debug\gen\extensions\common\api\web_request.cc
3、web_request api接口定义c++:
extensions\browser\api\web_request\web_request_api.h
extensions\browser\api\web_request\web_request_api.cc
namespace extensions {
// Support class for the WebRequest API. Lives on the UI thread. Most of the
// work is done by ExtensionWebRequestEventRouter below. This class observes
// extensions::EventRouter to deal with event listeners. There is one instance
// per BrowserContext which is shared with incognito.
class WebRequestAPI : public BrowserContextKeyedAPI,
public EventRouter::Observer,
public ExtensionRegistryObserver {
public:
// A callback used to asynchronously respond to an intercepted authentication
// request. If |should_cancel| is true the request will be cancelled.
// Otherwise any supplied |credentials| will be used. If no credentials are
// supplied, default browser behavior will follow (e.g. UI prompt for login).
using AuthRequestCallback = base::OnceCallback<void(
const std::optional<net::AuthCredentials>& credentials,
bool should_cancel)>;
// An interface which is held by ProxySet defined below.
class Proxy {
public:
virtual ~Proxy() = default;
// Asks the Proxy to handle an auth request on behalf of one of its known
// in-progress network requests. If the request will *not* be handled by
// the proxy, |callback| should be invoked with |std::nullopt|.
virtual void HandleAuthRequest(
const net::AuthChallengeInfo& auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
int32_t request_id,
AuthRequestCallback callback);
};
// A ProxySet is a set of proxies used by WebRequestAPI: It holds Proxy
// instances, and removes all proxies when it is destroyed.
class ProxySet {
public:
ProxySet();
ProxySet(const ProxySet&) = delete;
ProxySet& operator=(const ProxySet&) = delete;
~ProxySet();
// Add a Proxy.
void AddProxy(std::unique_ptr<Proxy> proxy);
// Remove a Proxy. The removed proxy is deleted upon this call.
void RemoveProxy(Proxy* proxy);
// Associates |proxy| with |id|. |proxy| must already be registered within
// this ProxySet.
//
// Each Proxy may be responsible for multiple requests, but any given
// request identified by |id| must be associated with only a single proxy.
void AssociateProxyWithRequestId(Proxy* proxy,
const content::GlobalRequestID& id);
// Disassociates |proxy| with |id|. |proxy| must already be registered
// within this ProxySet.
void DisassociateProxyWithRequestId(Proxy* proxy,
const content::GlobalRequestID& id);
Proxy* GetProxyFromRequestId(const content::GlobalRequestID& id);
void MaybeProxyAuthRequest(
const net::AuthChallengeInfo& auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
const content::GlobalRequestID& request_id,
AuthRequestCallback callback);
private:
// Although these members are initialized on the UI thread, we expect at
// least one memory barrier before actually calling Generate in the IO
// thread, so we don't protect them with a lock.
std::set<std::unique_ptr<Proxy>, base::UniquePtrComparator> proxies_;
// Bi-directional mapping between request ID and Proxy for faster lookup.
std::map<content::GlobalRequestID, Proxy*> request_id_to_proxy_map_;
std::map<Proxy*, std::set<content::GlobalRequestID>>
proxy_to_request_id_map_;
};
class RequestIDGenerator {
public:
RequestIDGenerator();
RequestIDGenerator(const RequestIDGenerator&) = delete;
RequestIDGenerator& operator=(const RequestIDGenerator&) = delete;
~RequestIDGenerator();
// Generates a WebRequest ID. If the same (routing_id,
// network_service_request_id) pair is passed to this as was previously
// passed to SaveID(), the |request_id| passed to SaveID() will be returned.
int64_t Generate(int32_t routing_id, int32_t network_service_request_id);
// This saves a WebRequest ID mapped to the (routing_id,
// network_service_request_id) pair. Clients must call Generate() with the
// same ID pair to retrieve the |request_id|, or else there may be a memory
// leak.
void SaveID(int32_t routing_id,
int32_t network_service_request_id,
uint64_t request_id);
private:
int64_t id_ = 0;
std::map<std::pair<int32_t, int32_t>, uint64_t> saved_id_map_;
};
explicit WebRequestAPI(content::BrowserContext* context);
WebRequestAPI(const WebRequestAPI&) = delete;
WebRequestAPI& operator=(const WebRequestAPI&) = delete;
~WebRequestAPI() override;
// BrowserContextKeyedAPI support:
static BrowserContextKeyedAPIFactory<WebRequestAPI>* GetFactoryInstance();
void Shutdown() override;
// EventRouter::Observer overrides:
void OnListenerRemoved(const EventListenerInfo& details) override;
// If any WebRequest event listeners are currently active for this
// BrowserContext, |*factory_request| is swapped out for a new request which
// proxies through an internal URLLoaderFactory. This supports lifetime
// observation and control on behalf of the WebRequest API.
// |frame| and |render_process_id| are the frame and render process id in
// which the URLLoaderFactory will be used. |frame| can be nullptr for
// factories proxied for service worker.
//
// |navigation_response_task_runner| is a task runner that may be non-null for
// navigation requests and can be used to run navigation request blocking
// tasks.
//
// Returns |true| if the URLLoaderFactory will be proxied; |false| otherwise.
bool MaybeProxyURLLoaderFactory(
content::BrowserContext* browser_context,
content::RenderFrameHost* frame,
int render_process_id,
content::ContentBrowserClient::URLLoaderFactoryType type,
std::optional<int64_t> navigation_id,
ukm::SourceIdObj ukm_source_id,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
header_client,
scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner,
const url::Origin& request_initiator = url::Origin());
// Any request which requires authentication to complete will be bounced
// through this method.
//
// If this returns |true|, |callback| will eventually be invoked on the UI
// thread.
bool MaybeProxyAuthRequest(
content::BrowserContext* browser_context,
const net::AuthChallengeInfo& auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
const content::GlobalRequestID& request_id,
bool is_main_frame,
AuthRequestCallback callback,
WebViewGuest* web_view_guest);
// Starts proxying the connection with |factory|. This function can be called
// only when MayHaveProxies() returns true.
void ProxyWebSocket(
content::RenderFrameHost* frame,
content::ContentBrowserClient::WebSocketFactory factory,
const GURL& url,
const net::SiteForCookies& site_for_cookies,
const std::optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client);
// Starts proxying WebTransport handshake.
void ProxyWebTransport(
content::RenderProcessHost& render_process_host,
int frame_routing_id,
const GURL& url,
const url::Origin& initiator_origin,
mojo::PendingRemote<network::mojom::WebTransportHandshakeClient>
handshake_client,
content::ContentBrowserClient::WillCreateWebTransportCallback callback);
void ForceProxyForTesting();
// Indicates whether or not the WebRequestAPI may have one or more proxies
// installed to support the API.
bool MayHaveProxies() const;
// Indicates whether or not WebRequestAPI may have one or more proxies
// installed to support intercepting websocket connections for extension
// telemetry.
// TODO(psarouthakis): This is here for the current implementation, but
// will be refactored to live somewhere else so that we don't have to
// create a full proxy just for telemetry.
bool MayHaveWebsocketProxiesForExtensionTelemetry() const;
// Indicates whether the WebRequestAPI is available to a RenderFrameHost
// that embeds a WebView instance.
bool IsAvailableToWebViewEmbedderFrame(
content::RenderFrameHost* render_frame_host) const;
bool HasExtraHeadersListenerForTesting();
private:
friend class BrowserContextKeyedAPIFactory<WebRequestAPI>;
// BrowserContextKeyedAPI support:
static const char* service_name() { return "WebRequestAPI"; }
static const bool kServiceRedirectedInIncognito = true;
static const bool kServiceIsNULLWhileTesting = true;
// Checks if |MayHaveProxies()| has changed from false to true, and resets
// URLLoaderFactories if so.
void UpdateMayHaveProxies();
// ExtensionRegistryObserver implementation.
void OnExtensionLoaded(content::BrowserContext* browser_context,
const Extension* extension) override;
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
// This a proxy API for the tasks that are posted. It is either called
// when the task is run and forwards to the corresponding member function
// in ExtensionWebRequestEventRouter, or not, if the owning BrowserContext
// goes away or the WeakPtr instance bound in the callback is invalidated.
void UpdateActiveListener(
content::BrowserContext* browser_context,
WebRequestEventRouter::ListenerUpdateType update_type,
const ExtensionId& extension_id,
const std::string& sub_event_name,
int worker_thread_id,
int64_t service_worker_version_id);
// This a proxy API for the tasks that are posted. It is either called
// when the task is run and forwards to the corresponding member function
// in ExtensionWebRequestEventRouter, or not, if the owning BrowserContext
// goes away or the WeakPtr instance bound in the callback is invalidated.
void RemoveLazyListener(content::BrowserContext* browser_context,
const ExtensionId& extension_id,
const std::string& sub_event_name);
// A count of active extensions for this BrowserContext that use web request
// permissions.
int web_request_extension_count_ = 0;
const raw_ptr<content::BrowserContext, DanglingUntriaged> browser_context_;
RequestIDGenerator request_id_generator_;
std::unique_ptr<ProxySet> proxies_;
// Stores the last result of |MayHaveProxies()|, so it can be used in
// |UpdateMayHaveProxies()|.
bool may_have_proxies_;
base::WeakPtrFactory<WebRequestAPI> weak_factory_{this};
};
class WebRequestInternalFunction : public ExtensionFunction {
public:
WebRequestInternalFunction() = default;
protected:
~WebRequestInternalFunction() override = default;
const std::string& extension_id_safe() const {
return extension() ? extension_id() : base::EmptyString();
}
};
class WebRequestInternalAddEventListenerFunction
: public WebRequestInternalFunction {
public:
DECLARE_EXTENSION_FUNCTION("webRequestInternal.addEventListener",
WEBREQUESTINTERNAL_ADDEVENTLISTENER)
protected:
~WebRequestInternalAddEventListenerFunction() override = default;
// ExtensionFunction:
ResponseAction Run() override;
};
class WebRequestInternalEventHandledFunction
: public WebRequestInternalFunction {
public:
DECLARE_EXTENSION_FUNCTION("webRequestInternal.eventHandled",
WEBREQUESTINTERNAL_EVENTHANDLED)
protected:
~WebRequestInternalEventHandledFunction() override = default;
private:
// Unblocks the network request. Use this function when handling incorrect
// requests from the extension that cannot be detected by the schema
// validator.
void OnError(const std::string& event_name,
const std::string& sub_event_name,
uint64_t request_id,
int render_process_id,
int web_view_instance_id,
std::unique_ptr<WebRequestEventRouter::EventResponse> response);
// ExtensionFunction:
ResponseAction Run() override;
};
class WebRequestHandlerBehaviorChangedFunction
: public WebRequestInternalFunction {
public:
DECLARE_EXTENSION_FUNCTION("webRequest.handlerBehaviorChanged",
WEBREQUEST_HANDLERBEHAVIORCHANGED)
protected:
~WebRequestHandlerBehaviorChangedFunction() override = default;
// ExtensionFunction:
void GetQuotaLimitHeuristics(
extensions::QuotaLimitHeuristics* heuristics) const override;
// Handle quota exceeded gracefully: Only warn the user but still execute the
// function.
void OnQuotaExceeded(std::string error) override;
ResponseAction Run() override;
};
} // namespace extensions
总结:
WebRequest API 接口c++定义介绍完毕,需要调试修改逻辑的可以在以上文件处更改。
版权归原作者 风清扬_jd 所有, 如有侵权,请联系我们删除。