Home | History | Annotate | Download | only in front-end
      1 /*
      2  * Copyright (C) 2011 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 WebInspector.NetworkManager = function()
     32 {
     33     WebInspector.Object.call(this);
     34     this._dispatcher = new WebInspector.NetworkDispatcher(this);
     35     NetworkAgent.enable();
     36 }
     37 
     38 WebInspector.NetworkManager.EventTypes = {
     39     ResourceStarted: "ResourceStarted",
     40     ResourceUpdated: "ResourceUpdated",
     41     ResourceFinished: "ResourceFinished",
     42     FrameCommittedLoad: "FrameCommittedLoad",
     43     FrameDetached: "FrameDetached"
     44 }
     45 
     46 WebInspector.NetworkManager.prototype = {
     47     frontendReused: function()
     48     {
     49         NetworkAgent.enable();
     50     },
     51 
     52     requestContent: function(resource, base64Encode, callback)
     53     {
     54         function callbackWrapper(error, content)
     55         {
     56             callback(!error ? content : null);
     57         }
     58         NetworkAgent.getResourceContent(resource.frameId, resource.url, base64Encode, callbackWrapper);
     59     },
     60 
     61     inflightResourceForURL: function(url)
     62     {
     63         return this._dispatcher._inflightResourcesByURL[url];
     64     }
     65 }
     66 
     67 WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype;
     68 
     69 WebInspector.NetworkDispatcher = function(manager)
     70 {
     71     this._manager = manager;
     72     this._inflightResourcesById = {};
     73     this._inflightResourcesByURL = {};
     74     this._lastIdentifierForCachedResource = 0;
     75     InspectorBackend.registerDomainDispatcher("Network", this);
     76 }
     77 
     78 WebInspector.NetworkDispatcher.prototype = {
     79     _updateResourceWithRequest: function(resource, request)
     80     {
     81         resource.requestMethod = request.method;
     82         resource.requestHeaders = request.headers;
     83         resource.requestFormData = request.postData;
     84     },
     85 
     86     _updateResourceWithResponse: function(resource, response)
     87     {
     88         if (!response)
     89             return;
     90 
     91         resource.mimeType = response.mimeType;
     92         resource.statusCode = response.status;
     93         resource.statusText = response.statusText;
     94         resource.responseHeaders = response.headers;
     95         if (response.headersText)
     96             resource.responseHeadersText = response.headersText;
     97         if (response.requestHeaders)
     98             resource.requestHeaders = response.requestHeaders;
     99         if (response.requestHeadersText)
    100             resource.requestHeadersText = response.requestHeadersText;
    101 
    102         resource.connectionReused = response.connectionReused;
    103         resource.connectionID = response.connectionID;
    104 
    105         if (response.fromDiskCache)
    106             resource.cached = true;
    107         else
    108             resource.timing = response.timing;
    109     },
    110 
    111     _updateResourceWithCachedResource: function(resource, cachedResource)
    112     {
    113         resource.type = WebInspector.Resource.Type[cachedResource.type];
    114         resource.resourceSize = cachedResource.bodySize;
    115         this._updateResourceWithResponse(resource, cachedResource.response);
    116     },
    117 
    118     _isNull: function(response)
    119     {
    120         return response && !response.status && !response.mimeType && !Object.keys(response.headers).length;
    121     },
    122 
    123     requestWillBeSent: function(identifier, frameId, loaderId, documentURL, request, time, stackTrace, redirectResponse)
    124     {
    125         var resource = this._inflightResourcesById[identifier];
    126         if (resource) {
    127             // FIXME: move this check to the backend.
    128             if (this._isNull(redirectResponse))
    129                 return;
    130             this.responseReceived(identifier, time, "Other", redirectResponse);
    131             resource = this._appendRedirect(identifier, time, request.url);
    132         } else
    133             resource = this._createResource(identifier, frameId, loaderId, request.url, documentURL, stackTrace);
    134         this._updateResourceWithRequest(resource, request);
    135         resource.startTime = time;
    136 
    137         this._startResource(resource);
    138     },
    139 
    140     resourceMarkedAsCached: function(identifier)
    141     {
    142         var resource = this._inflightResourcesById[identifier];
    143         if (!resource)
    144             return;
    145 
    146         resource.cached = true;
    147         this._updateResource(resource);
    148     },
    149 
    150     responseReceived: function(identifier, time, resourceType, response)
    151     {
    152         // FIXME: move this check to the backend.
    153         if (this._isNull(response))
    154             return;
    155 
    156         var resource = this._inflightResourcesById[identifier];
    157         if (!resource)
    158             return;
    159 
    160         resource.responseReceivedTime = time;
    161         resource.type = WebInspector.Resource.Type[resourceType];
    162 
    163         this._updateResourceWithResponse(resource, response);
    164 
    165         this._updateResource(resource);
    166     },
    167 
    168     domContentEventFired: function(time)
    169     {
    170         if (WebInspector.panels.network)
    171             WebInspector.panels.network.mainResourceDOMContentTime = time;
    172     },
    173 
    174     loadEventFired: function(time)
    175     {
    176         if (WebInspector.panels.network)
    177             WebInspector.panels.network.mainResourceLoadTime = time;
    178     },
    179 
    180     dataReceived: function(identifier, time, dataLength, encodedDataLength)
    181     {
    182         var resource = this._inflightResourcesById[identifier];
    183         if (!resource)
    184             return;
    185 
    186         resource.resourceSize += dataLength;
    187         if (encodedDataLength != -1)
    188             resource.increaseTransferSize(encodedDataLength);
    189         resource.endTime = time;
    190 
    191         this._updateResource(resource);
    192     },
    193 
    194     loadingFinished: function(identifier, finishTime)
    195     {
    196         var resource = this._inflightResourcesById[identifier];
    197         if (!resource)
    198             return;
    199 
    200         this._finishResource(resource, finishTime);
    201     },
    202 
    203     loadingFailed: function(identifier, time, localizedDescription, canceled)
    204     {
    205         var resource = this._inflightResourcesById[identifier];
    206         if (!resource)
    207             return;
    208 
    209         resource.failed = true;
    210         resource.canceled = canceled;
    211         resource.localizedFailDescription = localizedDescription;
    212         this._finishResource(resource, time);
    213     },
    214 
    215     resourceLoadedFromMemoryCache: function(frameId, loaderId, documentURL, time, cachedResource)
    216     {
    217         var resource = this._createResource("cached:" + ++this._lastIdentifierForCachedResource, frameId, loaderId, cachedResource.url, documentURL);
    218         this._updateResourceWithCachedResource(resource, cachedResource);
    219         resource.cached = true;
    220         resource.requestMethod = "GET";
    221         this._startResource(resource);
    222         resource.startTime = resource.responseReceivedTime = time;
    223         this._finishResource(resource, time);
    224     },
    225 
    226     frameDetached: function(frameId)
    227     {
    228         this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.FrameDetached, frameId);
    229     },
    230 
    231     initialContentSet: function(identifier, sourceString, type)
    232     {
    233         var resource = WebInspector.networkResourceById(identifier);
    234         if (!resource)
    235             return;
    236 
    237         resource.type = WebInspector.Resource.Type[type];
    238         resource.setInitialContent(sourceString);
    239         this._updateResource(resource);
    240     },
    241 
    242     frameNavigated: function(frame, loaderId)
    243     {
    244         this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.FrameCommittedLoad, { frame: frame, loaderId: loaderId });
    245     },
    246 
    247     webSocketCreated: function(identifier, requestURL)
    248     {
    249         var resource = this._createResource(identifier, null, null, requestURL);
    250         resource.type = WebInspector.Resource.Type.WebSocket;
    251         this._startResource(resource);
    252     },
    253 
    254     webSocketWillSendHandshakeRequest: function(identifier, time, request)
    255     {
    256         var resource = this._inflightResourcesById[identifier];
    257         if (!resource)
    258             return;
    259 
    260         resource.requestMethod = "GET";
    261         resource.requestHeaders = request.headers;
    262         resource.webSocketRequestKey3 = request.requestKey3;
    263         resource.startTime = time;
    264 
    265         this._updateResource(resource);
    266     },
    267 
    268     webSocketHandshakeResponseReceived: function(identifier, time, response)
    269     {
    270         var resource = this._inflightResourcesById[identifier];
    271         if (!resource)
    272             return;
    273 
    274         resource.statusCode = response.status;
    275         resource.statusText = response.statusText;
    276         resource.responseHeaders = response.headers;
    277         resource.webSocketChallengeResponse = response.challengeResponse;
    278         resource.responseReceivedTime = time;
    279 
    280         this._updateResource(resource);
    281     },
    282 
    283     webSocketClosed: function(identifier, time)
    284     {
    285         var resource = this._inflightResourcesById[identifier];
    286         if (!resource)
    287             return;
    288         this._finishResource(resource, time);
    289     },
    290 
    291     _appendRedirect: function(identifier, time, redirectURL)
    292     {
    293         var originalResource = this._inflightResourcesById[identifier];
    294         var previousRedirects = originalResource.redirects || [];
    295         originalResource.identifier = "redirected:" + identifier + "." + previousRedirects.length;
    296         delete originalResource.redirects;
    297         this._finishResource(originalResource, time);
    298         var newResource = this._createResource(identifier, originalResource.frameId, originalResource.loaderId,
    299              redirectURL, originalResource.documentURL, originalResource.stackTrace);
    300         newResource.redirects = previousRedirects.concat(originalResource);
    301         return newResource;
    302     },
    303 
    304     _startResource: function(resource)
    305     {
    306         this._inflightResourcesById[resource.identifier] = resource;
    307         this._inflightResourcesByURL[resource.url] = resource;
    308         this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceStarted, resource);
    309     },
    310 
    311     _updateResource: function(resource)
    312     {
    313         this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdated, resource);
    314     },
    315 
    316     _finishResource: function(resource, finishTime)
    317     {
    318         resource.endTime = finishTime;
    319         resource.finished = true;
    320         this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceFinished, resource);
    321         delete this._inflightResourcesById[resource.identifier];
    322         delete this._inflightResourcesByURL[resource.url];
    323     },
    324 
    325     _dispatchEventToListeners: function(eventType, resource)
    326     {
    327         this._manager.dispatchEventToListeners(eventType, resource);
    328     },
    329 
    330     _createResource: function(identifier, frameId, loaderId, url, documentURL, stackTrace)
    331     {
    332         var resource = new WebInspector.Resource(identifier, url);
    333         resource.documentURL = documentURL;
    334         resource.frameId = frameId;
    335         resource.loaderId = loaderId;
    336         resource.stackTrace = stackTrace;
    337         return resource;
    338     }
    339 }
    340