Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2007, 2008 Apple 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /**
     30  * @constructor
     31  * @extends {WebInspector.Object}
     32  * @implements {WebInspector.ContentProvider}
     33  * @param {?WebInspector.NetworkRequest} request
     34  * @param {string} url
     35  * @param {string} documentURL
     36  * @param {NetworkAgent.FrameId} frameId
     37  * @param {NetworkAgent.LoaderId} loaderId
     38  * @param {WebInspector.ResourceType} type
     39  * @param {string} mimeType
     40  * @param {boolean=} isHidden
     41  */
     42 WebInspector.Resource = function(request, url, documentURL, frameId, loaderId, type, mimeType, isHidden)
     43 {
     44     this._request = request;
     45     this.url = url;
     46     this._documentURL = documentURL;
     47     this._frameId = frameId;
     48     this._loaderId = loaderId;
     49     this._type = type || WebInspector.resourceTypes.Other;
     50     this._mimeType = mimeType;
     51     this._isHidden = isHidden;
     52 
     53     /** @type {?string} */ this._content;
     54     /** @type {boolean} */ this._contentEncoded;
     55     this._pendingContentCallbacks = [];
     56     if (this._request && !this._request.finished)
     57         this._request.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._requestFinished, this);
     58 }
     59 
     60 WebInspector.Resource.Events = {
     61     MessageAdded: "message-added",
     62     MessagesCleared: "messages-cleared",
     63 }
     64 
     65 WebInspector.Resource.prototype = {
     66     /**
     67      * @return {?WebInspector.NetworkRequest}
     68      */
     69     get request()
     70     {
     71         return this._request;
     72     },
     73 
     74     /**
     75      * @return {string}
     76      */
     77     get url()
     78     {
     79         return this._url;
     80     },
     81 
     82     set url(x)
     83     {
     84         this._url = x;
     85         this._parsedURL = new WebInspector.ParsedURL(x);
     86     },
     87 
     88     get parsedURL()
     89     {
     90         return this._parsedURL;
     91     },
     92 
     93     /**
     94      * @return {string}
     95      */
     96     get documentURL()
     97     {
     98         return this._documentURL;
     99     },
    100 
    101     /**
    102      * @return {NetworkAgent.FrameId}
    103      */
    104     get frameId()
    105     {
    106         return this._frameId;
    107     },
    108 
    109     /**
    110      * @return {NetworkAgent.LoaderId}
    111      */
    112     get loaderId()
    113     {
    114         return this._loaderId;
    115     },
    116 
    117     /**
    118      * @return {string}
    119      */
    120     get displayName()
    121     {
    122         return this._parsedURL.displayName;
    123     },
    124 
    125     /**
    126      * @return {WebInspector.ResourceType}
    127      */
    128     get type()
    129     {
    130         return this._request ? this._request.type : this._type;
    131     },
    132 
    133     /**
    134      * @return {string}
    135      */
    136     get mimeType()
    137     {
    138         return this._request ? this._request.mimeType : this._mimeType;
    139     },
    140 
    141     /**
    142      * @return {Array.<WebInspector.ConsoleMessage>}
    143      */
    144     get messages()
    145     {
    146         return this._messages || [];
    147     },
    148 
    149     /**
    150      * @param {WebInspector.ConsoleMessage} msg
    151      */
    152     addMessage: function(msg)
    153     {
    154         if (!msg.isErrorOrWarning() || !msg.message)
    155             return;
    156 
    157         if (!this._messages)
    158             this._messages = [];
    159         this._messages.push(msg);
    160         this.dispatchEventToListeners(WebInspector.Resource.Events.MessageAdded, msg);
    161     },
    162 
    163     /**
    164      * @return {number}
    165      */
    166     get errors()
    167     {
    168         return this._errors || 0;
    169     },
    170 
    171     set errors(x)
    172     {
    173         this._errors = x;
    174     },
    175 
    176     /**
    177      * @return {number}
    178      */
    179     get warnings()
    180     {
    181         return this._warnings || 0;
    182     },
    183 
    184     set warnings(x)
    185     {
    186         this._warnings = x;
    187     },
    188 
    189     clearErrorsAndWarnings: function()
    190     {
    191         this._messages = [];
    192         this._warnings = 0;
    193         this._errors = 0;
    194         this.dispatchEventToListeners(WebInspector.Resource.Events.MessagesCleared);
    195     },
    196 
    197     /**
    198      * @return {?string}
    199      */
    200     get content()
    201     {
    202         return this._content;
    203     },
    204 
    205     /**
    206      * @return {boolean}
    207      */
    208     get contentEncoded()
    209     {
    210         return this._contentEncoded;
    211     },
    212 
    213     /**
    214      * @return {string}
    215      */
    216     contentURL: function()
    217     {
    218         return this._url;
    219     },
    220 
    221     /**
    222      * @return {WebInspector.ResourceType}
    223      */
    224     contentType: function()
    225     {
    226         return this.type;
    227     },
    228 
    229     /**
    230      * @param {function(?string, boolean, string)} callback
    231      */
    232     requestContent: function(callback)
    233     {
    234         if (typeof this._content !== "undefined") {
    235             callback(this._content, !!this._contentEncoded, this.canonicalMimeType());
    236             return;
    237         }
    238 
    239         this._pendingContentCallbacks.push(callback);
    240         if (!this._request || this._request.finished)
    241             this._innerRequestContent();
    242     },
    243 
    244     canonicalMimeType: function()
    245     {
    246         return this.type.canonicalMimeType() || this.mimeType;
    247     },
    248 
    249     /**
    250      * @param {string} query
    251      * @param {boolean} caseSensitive
    252      * @param {boolean} isRegex
    253      * @param {function(Array.<WebInspector.ContentProvider.SearchMatch>)} callback
    254      */
    255     searchInContent: function(query, caseSensitive, isRegex, callback)
    256     {
    257         /**
    258          * @param {?Protocol.Error} error
    259          * @param {Array.<PageAgent.SearchMatch>} searchMatches
    260          */
    261         function callbackWrapper(error, searchMatches)
    262         {
    263             callback(searchMatches || []);
    264         }
    265 
    266         if (this.type === WebInspector.resourceTypes.Document) {
    267             /**
    268              * @param {?string} content
    269              * @param {boolean} contentEncoded
    270              * @param {string} mimeType
    271              */
    272             function documentContentLoaded(content, contentEncoded, mimeType)
    273             {
    274                 if (content === null) {
    275                     callback([]);
    276                     return;
    277                 }
    278 
    279                 var result = WebInspector.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
    280                 callback(result);
    281             }
    282 
    283             this.requestContent(documentContentLoaded);
    284             return;
    285         }
    286 
    287         if (this.frameId)
    288             PageAgent.searchInResource(this.frameId, this.url, query, caseSensitive, isRegex, callbackWrapper);
    289         else
    290             callback([]);
    291     },
    292 
    293     /**
    294      * @param {Element} image
    295      */
    296     populateImageSource: function(image)
    297     {
    298         function onResourceContent()
    299         {
    300             var imageSrc = WebInspector.contentAsDataURL(this._content, this.mimeType, this._contentEncoded);
    301             if (imageSrc === null)
    302                 imageSrc = this.url;
    303             image.src = imageSrc;
    304         }
    305 
    306         this.requestContent(onResourceContent.bind(this));
    307     },
    308 
    309     _requestFinished: function()
    310     {
    311         this._request.removeEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._requestFinished, this);
    312         if (this._pendingContentCallbacks.length)
    313             this._innerRequestContent();
    314     },
    315 
    316 
    317     _innerRequestContent: function()
    318     {
    319         if (this._contentRequested)
    320             return;
    321         this._contentRequested = true;
    322 
    323         /**
    324          * @param {?Protocol.Error} error
    325          * @param {?string} content
    326          * @param {boolean} contentEncoded
    327          */
    328         function contentLoaded(error, content, contentEncoded)
    329         {
    330             if (error || content === null) {
    331                 loadFallbackContent.call(this, error);
    332                 return;
    333             }
    334             replyWithContent.call(this, content, contentEncoded);
    335         }
    336 
    337         /**
    338          * @param {?string} content
    339          * @param {boolean} contentEncoded
    340          */
    341         function replyWithContent(content, contentEncoded)
    342         {
    343             this._content = content;
    344             this._contentEncoded = contentEncoded;
    345             var callbacks = this._pendingContentCallbacks.slice();
    346             for (var i = 0; i < callbacks.length; ++i)
    347                 callbacks[i](this._content, this._contentEncoded, this.canonicalMimeType());
    348             this._pendingContentCallbacks.length = 0;
    349             delete this._contentRequested;
    350         }
    351 
    352         /**
    353          * @param {?Protocol.Error} error
    354          * @param {string} content
    355          * @param {boolean} contentEncoded
    356          */
    357         function resourceContentLoaded(error, content, contentEncoded)
    358         {
    359             contentLoaded.call(this, error, content, contentEncoded);
    360         }
    361 
    362         /**
    363          * @param {?Protocol.Error} error
    364          */
    365         function loadFallbackContent(error)
    366         {
    367             var scripts = WebInspector.debuggerModel.scriptsForSourceURL(this.url);
    368             if (!scripts.length) {
    369                 console.error("Resource content request failed: " + error);
    370                 replyWithContent.call(this, null, false);
    371                 return;
    372             }
    373 
    374             var contentProvider;
    375             if (this.type === WebInspector.resourceTypes.Document)
    376                 contentProvider = new WebInspector.ConcatenatedScriptsContentProvider(scripts);
    377             else if (this.type === WebInspector.resourceTypes.Script)
    378                 contentProvider = scripts[0];
    379 
    380             if (!contentProvider) {
    381                 console.error("Resource content request failed: " + error);
    382                 replyWithContent.call(this, null, false);
    383                 return;
    384             }
    385 
    386             contentProvider.requestContent(fallbackContentLoaded.bind(this));
    387         }
    388 
    389         /**
    390          * @param {?string} content
    391          * @param {boolean} contentEncoded
    392          * @param {string} mimeType
    393          */
    394         function fallbackContentLoaded(content, contentEncoded, mimeType)
    395         {
    396             replyWithContent.call(this, content, contentEncoded);
    397         }
    398 
    399         if (this.request) {
    400             /**
    401              * @param {?string} content
    402              * @param {boolean} contentEncoded
    403              * @param {string} mimeType
    404              */
    405             function requestContentLoaded(content, contentEncoded, mimeType)
    406             {
    407                 contentLoaded.call(this, null, content, contentEncoded);
    408             }
    409 
    410             this.request.requestContent(requestContentLoaded.bind(this));
    411             return;
    412         }
    413         PageAgent.getResourceContent(this.frameId, this.url, resourceContentLoaded.bind(this));
    414     },
    415 
    416     /**
    417      * @return {boolean}
    418      */
    419     isHidden: function()
    420     {
    421         return !!this._isHidden;
    422     },
    423 
    424     __proto__: WebInspector.Object.prototype
    425 }
    426 
    427