Home | History | Annotate | Download | only in sdk
      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 /**
     32  * @constructor
     33  * @implements {WebInspector.ContentProvider}
     34  * @param {!Array.<!WebInspector.Script>} scripts
     35  */
     36 WebInspector.ConcatenatedScriptsContentProvider = function(scripts)
     37 {
     38     this._scripts = scripts;
     39 }
     40 
     41 WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag = "<script>";
     42 WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag = "</script>";
     43 
     44 WebInspector.ConcatenatedScriptsContentProvider.prototype = {
     45     /**
     46      * @return {!Array.<!WebInspector.Script>}
     47      */
     48     _sortedScripts: function()
     49     {
     50         if (this._sortedScriptsArray)
     51             return this._sortedScriptsArray;
     52 
     53         this._sortedScriptsArray = [];
     54 
     55         var scripts = this._scripts.slice();
     56         scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });
     57 
     58         var scriptOpenTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag.length;
     59         var scriptCloseTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag.length;
     60 
     61         this._sortedScriptsArray.push(scripts[0]);
     62         for (var i = 1; i < scripts.length; ++i) {
     63             var previousScript = this._sortedScriptsArray[this._sortedScriptsArray.length - 1];
     64 
     65             var lineNumber = previousScript.endLine;
     66             var columnNumber = previousScript.endColumn + scriptCloseTagLength + scriptOpenTagLength;
     67 
     68             if (lineNumber < scripts[i].lineOffset || (lineNumber === scripts[i].lineOffset && columnNumber <= scripts[i].columnOffset))
     69                 this._sortedScriptsArray.push(scripts[i]);
     70         }
     71         return this._sortedScriptsArray;
     72     },
     73 
     74     /**
     75      * @return {string}
     76      */
     77     contentURL: function()
     78     {
     79         return "";
     80     },
     81 
     82     /**
     83      * @return {!WebInspector.ResourceType}
     84      */
     85     contentType: function()
     86     {
     87         return WebInspector.resourceTypes.Document;
     88     },
     89 
     90     /**
     91      * @param {function(?string)} callback
     92      */
     93     requestContent: function(callback)
     94     {
     95         var scripts = this._sortedScripts();
     96         var sources = [];
     97 
     98         /**
     99          * @param {?string} content
    100          * @this {WebInspector.ConcatenatedScriptsContentProvider}
    101          */
    102         function didRequestSource(content)
    103         {
    104             sources.push(content);
    105             if (sources.length == scripts.length)
    106                 callback(this._concatenateScriptsContent(scripts, sources));
    107         }
    108         for (var i = 0; i < scripts.length; ++i)
    109             scripts[i].requestContent(didRequestSource.bind(this));
    110     },
    111 
    112     /**
    113      * @param {string} query
    114      * @param {boolean} caseSensitive
    115      * @param {boolean} isRegex
    116      * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
    117      */
    118     searchInContent: function(query, caseSensitive, isRegex, callback)
    119     {
    120         var results = {};
    121         var scripts = this._sortedScripts();
    122         var scriptsLeft = scripts.length;
    123 
    124         function maybeCallback()
    125         {
    126             if (scriptsLeft)
    127                 return;
    128 
    129             var result = [];
    130             for (var i = 0; i < scripts.length; ++i)
    131                 result = result.concat(results[scripts[i].scriptId]);
    132             callback(result);
    133         }
    134 
    135         /**
    136          * @param {!WebInspector.Script} script
    137          * @param {!Array.<!PageAgent.SearchMatch>} searchMatches
    138          */
    139         function searchCallback(script, searchMatches)
    140         {
    141             results[script.scriptId] = [];
    142             for (var i = 0; i < searchMatches.length; ++i) {
    143                 var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber + script.lineOffset, searchMatches[i].lineContent);
    144                 results[script.scriptId].push(searchMatch);
    145             }
    146             scriptsLeft--;
    147             maybeCallback();
    148         }
    149 
    150         maybeCallback();
    151         for (var i = 0; i < scripts.length; ++i)
    152             scripts[i].searchInContent(query, caseSensitive, isRegex, searchCallback.bind(null, scripts[i]));
    153     },
    154 
    155     /**
    156      * @return {string}
    157      */
    158     _concatenateScriptsContent: function(scripts, sources)
    159     {
    160         var content = "";
    161         var lineNumber = 0;
    162         var columnNumber = 0;
    163 
    164         var scriptOpenTag = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag;
    165         var scriptCloseTag = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag;
    166         for (var i = 0; i < scripts.length; ++i) {
    167             // Fill the gap with whitespace characters.
    168             for (var newLinesCount = scripts[i].lineOffset - lineNumber; newLinesCount > 0; --newLinesCount) {
    169                 columnNumber = 0;
    170                 content += "\n";
    171             }
    172             for (var spacesCount = scripts[i].columnOffset - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount)
    173                 content += " ";
    174 
    175             // Add script tag.
    176             content += scriptOpenTag;
    177             content += sources[i];
    178             content += scriptCloseTag;
    179             lineNumber = scripts[i].endLine;
    180             columnNumber = scripts[i].endColumn + scriptCloseTag.length;
    181         }
    182 
    183         return content;
    184     }
    185 }
    186 
    187 /**
    188  * @constructor
    189  * @implements {WebInspector.ContentProvider}
    190  * @param {string} sourceURL
    191  * @param {!WebInspector.ResourceType} contentType
    192  */
    193 WebInspector.CompilerSourceMappingContentProvider = function(sourceURL, contentType)
    194 {
    195     this._sourceURL = sourceURL;
    196     this._contentType = contentType;
    197 }
    198 
    199 WebInspector.CompilerSourceMappingContentProvider.prototype = {
    200     /**
    201      * @return {string}
    202      */
    203     contentURL: function()
    204     {
    205         return this._sourceURL;
    206     },
    207 
    208     /**
    209      * @return {!WebInspector.ResourceType}
    210      */
    211     contentType: function()
    212     {
    213         return this._contentType;
    214     },
    215 
    216     /**
    217      * @param {function(?string)} callback
    218      */
    219     requestContent: function(callback)
    220     {
    221         NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, this._sourceURL, undefined, contentLoaded.bind(this));
    222 
    223         /**
    224          * @param {?Protocol.Error} error
    225          * @param {number} statusCode
    226          * @param {!NetworkAgent.Headers} headers
    227          * @param {string} content
    228          * @this {WebInspector.CompilerSourceMappingContentProvider}
    229          */
    230         function contentLoaded(error, statusCode, headers, content)
    231         {
    232             if (error || statusCode >= 400) {
    233                 console.error("Could not load content for " + this._sourceURL + " : " + (error || ("HTTP status code: " + statusCode)));
    234                 callback(null);
    235                 return;
    236             }
    237 
    238             callback(content);
    239         }
    240     },
    241 
    242     /**
    243      * @param {string} query
    244      * @param {boolean} caseSensitive
    245      * @param {boolean} isRegex
    246      * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
    247      */
    248     searchInContent: function(query, caseSensitive, isRegex, callback)
    249     {
    250         this.requestContent(contentLoaded);
    251 
    252         /**
    253          * @param {?string} content
    254          */
    255         function contentLoaded(content)
    256         {
    257             if (typeof content !== "string") {
    258                 callback([]);
    259                 return;
    260             }
    261 
    262             callback(WebInspector.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex));
    263         }
    264     }
    265 }
    266 
    267 /**
    268  * @constructor
    269  * @implements {WebInspector.ContentProvider}
    270  * @param {!WebInspector.ResourceType} contentType
    271  * @param {string} content
    272  */
    273 WebInspector.StaticContentProvider = function(contentType, content)
    274 {
    275     this._content = content;
    276     this._contentType = contentType;
    277 }
    278 
    279 WebInspector.StaticContentProvider.prototype = {
    280     /**
    281      * @return {string}
    282      */
    283     contentURL: function()
    284     {
    285         return "";
    286     },
    287 
    288     /**
    289      * @return {!WebInspector.ResourceType}
    290      */
    291     contentType: function()
    292     {
    293         return this._contentType;
    294     },
    295 
    296     /**
    297      * @param {function(?string)} callback
    298      */
    299     requestContent: function(callback)
    300     {
    301         callback(this._content);
    302     },
    303 
    304     /**
    305      * @param {string} query
    306      * @param {boolean} caseSensitive
    307      * @param {boolean} isRegex
    308      * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
    309      */
    310     searchInContent: function(query, caseSensitive, isRegex, callback)
    311     {
    312         /**
    313          * @this {WebInspector.StaticContentProvider}
    314          */
    315         function performSearch()
    316         {
    317             callback(WebInspector.ContentProvider.performSearchInContent(this._content, query, caseSensitive, isRegex));
    318         }
    319 
    320         // searchInContent should call back later.
    321         window.setTimeout(performSearch.bind(this), 0);
    322     }
    323 }
    324