Home | History | Annotate | Download | only in intros
      1 <h2 id="manifest">Manifest</h2>
      2 <p>You must declare the "webRequest" permission in the <a
      3   href="manifest.html">extension manifest</a> to use the web request
      4 API, along with <a href="declare_permissions.html">host permissions</a>
      5 for any hosts whose network requests you want to access. If you want to
      6 use the web request API in a blocking fashion, you need to request
      7 the "webRequestBlocking" permission in addition.
      8 For example:</p>
      9 <pre>{
     10   "name": "My extension",
     11   ...
     12   <b>"permissions": [
     13     "webRequest",
     14     "*://*.google.com/"
     15   ]</b>,
     16   ...
     17 }</pre>
     18 
     19 <h2 id="life_cycle">Life cycle of requests</h2>
     20 
     21 <p>
     22 The web request API defines a set of events that follow the life cycle of a web
     23 request. You can use these events to observe and analyze traffic. Certain
     24 synchronous events will allow you to intercept, block, or modify a request.
     25 </p>
     26 
     27 <p>
     28 The event life cycle for successful requests is illustrated here, followed by
     29 event definitions:<br/>
     30 <img src="{{static}}/images/webrequestapi.png"
     31   width="385" height="503"
     32   alt="Life cycle of a web request from the perspective of the webrequest API"
     33   style="margin-left: auto; margin-right: auto; display: block"/>
     34 </p>
     35 
     36 <p>
     37 <dl>
     38   <dt><code>onBeforeRequest</code> (optionally synchronous)</dt>
     39   <dd>Fires when a request is about to occur. This event is sent before any TCP
     40   connection is made and can be used to cancel or redirect requests.</dd>
     41   <dt><code>onBeforeSendHeaders</code> (optionally synchronous)</dt>
     42   <dd>Fires when a request is about to occur and the initial headers have been
     43   prepared. The event is intended to allow extensions to add, modify, and delete
     44   request headers <a href="#life_cycle_footnote">(*)</a>. The
     45   <code>onBeforeSendHeaders</code> event is passed to all subscribers, so
     46   different subscribers may attempt to modify the request; see the <a
     47     href="#implementation">Implementation details</a> section for how this is
     48   handled. This event can be used to cancel the request.</dd>
     49   <dt><code>onSendHeaders</code></dt>
     50   <dd>Fires after all extensions have had a chance to modify the request
     51   headers, and presents the final <a href="#life_cycle_footnote">(*)</a>
     52   version. The event is triggered before the headers are sent to the network.
     53   This event is informational and handled asynchronously. It does not allow
     54   modifying or cancelling the request.</dd>
     55   <dt><code>onHeadersReceived</code> (optionally synchronous)</dt>
     56   <dd>Fires each time that an HTTP(S) response header is received. Due
     57   to redirects and authentication requests this can happen multiple times per
     58   request. This event is intended to allow extensions to add, modify, and delete
     59   response headers, such as incoming Set-Cookie headers.</dd>
     60   <dt><code>onAuthRequired</code> (optionally synchronous)</dt>
     61   <dd>Fires when a request requires authentication of the user. This event can
     62   be handled synchronously to provide authentication credentials. Note that
     63   extensions may provide invalid credentials. Take care not to enter an infinite
     64   loop by repeatedly providing invalid credentials.</dd>
     65   <dt><code>onBeforeRedirect</code></dt>
     66   <dd>Fires when a redirect is about to be executed. A redirection can be
     67   triggered by an HTTP response code or by an extension. This event is
     68   informational and handled asynchronously. It does not allow you to modify or
     69   cancel the request. </dd>
     70   <dt><code>onResponseStarted</code></dt>
     71   <dd>Fires when the first byte of the response body is received. For HTTP
     72   requests, this means that the status line and response headers are
     73   available. This event is informational and handled asynchronously. It does not
     74   allow modifying or cancelling the request.</dd>
     75   <dt><code>onCompleted</code></dt>
     76   <dd>Fires when a request has been processed successfully.</dd>
     77   <dt><code>onErrorOccurred</code></dt>
     78   <dd>Fires when a request could not be processed successfully.</dd>
     79 </dl>
     80 The web request API guarantees that for each request either
     81 <code>onCompleted</code> or <code>onErrorOccurred</code> is fired as the final
     82 event with one exception: If a request is redirected to a <code>data://</code>
     83 URL, <code>onBeforeRedirect</code> is the last reported event.
     84 </p>
     85 
     86 <p id="life_cycle_footnote">(*) Note that the web request API presents an
     87 abstraction of the network stack to the extension. Internally, one URL request
     88 can be split into several HTTP requests (for example to fetch individual byte
     89 ranges from a large file) or can be handled by the network stack without
     90 communicating with the network. For this reason, the API does not provide the
     91 final HTTP headers that are sent to the network. For example, all headers that
     92 are related to caching are invisible to the extension.</p>
     93 
     94 <p>The following headers are currently <b>not provided</b> to the
     95 <code>onBeforeSendHeaders</code> event. This list is not guaranteed to be
     96 complete nor stable.
     97 <ul>
     98   <li>Authorization</li>
     99   <li>Cache-Control</li>
    100   <li>Connection</li>
    101   <li>Content-Length</li>
    102   <li>Host</li>
    103   <li>If-Modified-Since</li>
    104   <li>If-None-Match</li>
    105   <li>If-Range</li>
    106   <li>Partial-Data</li>
    107   <li>Pragma</li>
    108   <li>Proxy-Authorization</li>
    109   <li>Proxy-Connection</li>
    110   <li>Transfer-Encoding</li>
    111 </ul>
    112 </p>
    113 
    114 <p>
    115 The webRequest API only exposes requests that the extension has
    116 permission to see, given its
    117 <a href="declare_permissions.html">host permissions</a>.
    118 Moreover, only the following schemes are accessible:
    119 <code>http://</code>,
    120 <code>https://</code>,
    121 <code>ftp://</code>,
    122 <code>file://</code>, or
    123 <code>chrome-extension://</code>.
    124 In addition, even certain requests with URLs using one of the above schemes
    125 are hidden, e.g.,
    126 <code>chrome-extension://other_extension_id</code> where
    127 <code>other_extension_id</code> is not the ID of the extension to handle
    128 the request,
    129 <code>https://www.google.com/chrome</code>,
    130 and others (this list is not complete). Also synchronous XMLHttpRequests from
    131 your extension are hidden from blocking event handlers in order to prevent
    132 deadlocks.
    133 </p>
    134 
    135 <h2 id="concepts">Concepts</h2>
    136 
    137 <p>As the following sections explain, events in the web request API use request
    138 IDs, and you can optionally specify filters and extra information when you
    139 register event listeners.</p>
    140 
    141 <h3 id="Request IDs">Request IDs</h3>
    142 
    143 <p>Each request is identified by a request ID. This ID is unique within a
    144 browser session and the context of an extension. It remains constant during the
    145 the life cycle of a request and can be used to match events for the same
    146 request. Note that several HTTP requests are mapped to one web request in case
    147 of HTTP redirection or HTTP authentication.</p>
    148 
    149 <h3 id="subscription">Registering event listeners</h3>
    150 
    151 <p>To register an event listener for a web request, you use a variation on the
    152 <a href="events.html">usual <code>addListener()</code> function</a>.
    153 In addition to specifying a callback function,
    154 you have to specify a filter argument and you may specify an optional extra info
    155 argument.</p>
    156 
    157 <p>The three arguments to the web request API's <code>addListener()</code> have
    158 the following definitions:</p>
    159 <pre>
    160 var callback = function(details) {...};
    161 var filter = {...};
    162 var opt_extraInfoSpec = [...];
    163 </pre>
    164 
    165 <p>Here's an example of listening for the <code>onBeforeRequest</code>
    166 event:</p>
    167 <pre>
    168 chrome.webRequest.onBeforeRequest.addListener(
    169   callback, filter, opt_extraInfoSpec);
    170 </pre>
    171 
    172 <p>Each <code>addListener()</code> call takes a mandatory callback function as
    173 the first parameter. This callback function is passed a dictionary containing
    174 information about the current URL request. The information in this dictionary
    175 depends on the specific event type as well as the content of
    176 <code>opt_extraInfoSpec</code>.</p>
    177 
    178 <p>If the optional <code>opt_extraInfoSpec</code> array contains the string
    179 <code>'blocking'</code> (only allowed for specific events), the callback
    180 function is handled synchronously. That means that the request is blocked until
    181 the callback function returns. In this case, the callback can return a 
    182   $ref:webRequest.BlockingResponse that determines the further
    183 life cycle of the request. Depending on the context, this response allows
    184 cancelling or redirecting a request (<code>onBeforeRequest</code>), cancelling a
    185 request or modifying headers (<code>onBeforeSendHeaders</code>,
    186 <code>onHeadersReceived</code>), or providing authentication credentials
    187 (<code>onAuthRequired</code>).</p>
    188 
    189 <p>The $ref:webRequest.RequestFilter
    190 <code>filter</code> allows limiting the requests for which events are
    191 triggered in various dimensions:
    192 <dl>
    193   <dt>URLs</dt>
    194   <dd><a href="match_patterns.html">URL patterns</a> such as
    195   <code>*://www.google.com/foo*bar</code>.</dd>
    196   <dt>Types</dt>
    197   <dd>Request types such as <code>main_frame</code> (a document that is loaded
    198   for a top-level frame), <code>sub_frame</code> (a document that is loaded for
    199   an embedded frame), and <code>image</code> (an image on a web site).
    200   See $ref:webRequest.RequestFilter.</dd>
    201   <dt>Tab ID</dt>
    202   <dd>The identifier for one tab.</dd>
    203   <dt>Window ID</dt>
    204   <dd>The identifier for a window.</dd>
    205 </p>
    206 
    207 <p>Depending on the event type, you can specify strings in
    208 <code>opt_extraInfoSpec</code> to ask for additional information about the
    209 request. This is used to provide detailed information on request's data only
    210 if explicitly requested.</p>
    211 
    212 <h2 id="implementation">Implementation details</h2>
    213 
    214 <p>Several implementation details can be important to understand when developing
    215 an extension that uses the web request API:</p>
    216 
    217 <h3 id="conflict_resolution">Conflict resolution</h3>
    218 <p>In the current implementation of the web request API, a request is considered
    219 as cancelled if at least one extension instructs to cancel the request. If
    220 an extension cancels a request, all extensions are notified by an
    221 <code>onErrorOccurred</code> event. Only one extension is allowed to redirect a
    222 request or modify a header at a time. If more than one extension attempts to
    223 modify the request, the most recently installed extension wins and all others
    224 are ignored. An extension is not notified if its instruction to modify or
    225 redirect has been ignored.</p>
    226 
    227 <h3 id="caching">Caching</h3>
    228 <p>
    229 Chrome employs two caches &mdash; an on-disk cache and a very fast in-memory
    230 cache.  The lifetime of an in-memory cache is attached to the lifetime of a
    231 render process, which roughly corresponds to a tab. Requests that are answered
    232 from the in-memory cache are invisible to the web request API. If a request
    233 handler changes its behavior (for example, the behavior according to which
    234 requests are blocked), a simple page refresh might not respect this changed
    235 behavior.  To make sure the behavior change goes through, call
    236 <code>handlerBehaviorChanged()</code> to flush the in-memory cache. But don't do
    237 it often; flushing the cache is a very expensive operation. You don't need to
    238 call <code>handlerBehaviorChanged()</code> after registering or unregistering an
    239 event listener.</p>
    240 
    241 <h3 id="timestamps">Timestamps</h3>
    242 <p>
    243 The <code>timestamp</code> property of web request events is only guaranteed to
    244 be <i>internally</i> consistent. Comparing one event to another event will give
    245 you the correct offset between them, but comparing them to the current time
    246 inside the extension (via <code>(new Date()).getTime()</code>, for instance)
    247 might give unexpected results.
    248 </p>
    249 
    250 <h2 id="examples">Examples</h2>
    251 
    252 <p>The following example illustrates how to block all requests to
    253 <code>www.evil.com</code>:</p>
    254 <pre>
    255 chrome.webRequest.onBeforeRequest.addListener(
    256   function(details) {
    257     return {cancel: details.url.indexOf("://www.evil.com/") != -1};
    258   },
    259   {urls: ["&lt;all_urls&gt;"]},
    260   ["blocking"]);
    261 </pre>
    262 
    263 <p>As this function uses a blocking event handler, it requires the "webRequest"
    264 as well as the "webRequestBlocking" permission in the manifest file.</p>
    265 
    266 <p>The following example achieves the same goal in a more efficient way because
    267 requests that are not targeted to <code>www.evil.com</code> do not need to be
    268 passed to the extension:</p>
    269 <pre>
    270 chrome.webRequest.onBeforeRequest.addListener(
    271   function(details) { return {cancel: true}; },
    272   {urls: ["*://www.evil.com/*"]},
    273   ["blocking"]);
    274 </pre>
    275 
    276 <p>The following example illustrates how to delete the User-Agent header from
    277 all requests:</p>
    278 <pre>
    279 chrome.webRequest.onBeforeSendHeaders.addListener(
    280   function(details) {
    281     for (var i = 0; i < details.requestHeaders.length; ++i) {
    282       if (details.requestHeaders[i].name === 'User-Agent') {
    283         details.requestHeaders.splice(i, 1);
    284         break;
    285       }
    286     }
    287     return {requestHeaders: details.requestHeaders};
    288   },
    289   {urls: ["&lt;all_urls&gt;"]},
    290   ["blocking", "requestHeaders"]);
    291 </pre>
    292 
    293 <p> For more example code, see the <a href="samples.html#webrequest">web request
    294 samples</a>.</p>
    295