• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
36WebInspector.ConcatenatedScriptsContentProvider = function(scripts)
37{
38    this._scripts = scripts;
39}
40
41WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag = "<script>";
42WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag = "</script>";
43
44WebInspector.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         * @this {WebInspector.ConcatenatedScriptsContentProvider}
139         */
140        function searchCallback(script, searchMatches)
141        {
142            results[script.scriptId] = [];
143            for (var i = 0; i < searchMatches.length; ++i) {
144                var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber + script.lineOffset, searchMatches[i].lineContent);
145                results[script.scriptId].push(searchMatch);
146            }
147            scriptsLeft--;
148            maybeCallback.call(this);
149        }
150
151        maybeCallback();
152        for (var i = 0; i < scripts.length; ++i)
153            scripts[i].searchInContent(query, caseSensitive, isRegex, searchCallback.bind(this, scripts[i]));
154    },
155
156    /**
157     * @return {string}
158     */
159    _concatenateScriptsContent: function(scripts, sources)
160    {
161        var content = "";
162        var lineNumber = 0;
163        var columnNumber = 0;
164
165        var scriptOpenTag = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag;
166        var scriptCloseTag = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag;
167        for (var i = 0; i < scripts.length; ++i) {
168            // Fill the gap with whitespace characters.
169            for (var newLinesCount = scripts[i].lineOffset - lineNumber; newLinesCount > 0; --newLinesCount) {
170                columnNumber = 0;
171                content += "\n";
172            }
173            for (var spacesCount = scripts[i].columnOffset - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount)
174                content += " ";
175
176            // Add script tag.
177            content += scriptOpenTag;
178            content += sources[i];
179            content += scriptCloseTag;
180            lineNumber = scripts[i].endLine;
181            columnNumber = scripts[i].endColumn + scriptCloseTag.length;
182        }
183
184        return content;
185    },
186
187    __proto__: WebInspector.ContentProvider.prototype
188}
189
190/**
191 * @constructor
192 * @param {string} sourceURL
193 * @param {!WebInspector.ResourceType} contentType
194 * @implements {WebInspector.ContentProvider}
195 */
196WebInspector.CompilerSourceMappingContentProvider = function(sourceURL, contentType)
197{
198    this._sourceURL = sourceURL;
199    this._contentType = contentType;
200}
201
202WebInspector.CompilerSourceMappingContentProvider.prototype = {
203    /**
204     * @return {string}
205     */
206    contentURL: function()
207    {
208        return this._sourceURL;
209    },
210
211    /**
212     * @return {!WebInspector.ResourceType}
213     */
214    contentType: function()
215    {
216        return this._contentType;
217    },
218
219    /**
220     * @param {function(?string)} callback
221     */
222    requestContent: function(callback)
223    {
224        NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, this._sourceURL, undefined, contentLoaded.bind(this));
225
226        /**
227         * @param {?Protocol.Error} error
228         * @param {number} statusCode
229         * @param {!NetworkAgent.Headers} headers
230         * @param {string} content
231         * @this {WebInspector.CompilerSourceMappingContentProvider}
232         */
233        function contentLoaded(error, statusCode, headers, content)
234        {
235            if (error || statusCode >= 400) {
236                console.error("Could not load content for " + this._sourceURL + " : " + (error || ("HTTP status code: " + statusCode)));
237                callback(null);
238                return;
239            }
240
241            callback(content);
242        }
243    },
244
245    /**
246     * @param {string} query
247     * @param {boolean} caseSensitive
248     * @param {boolean} isRegex
249     * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
250     */
251    searchInContent: function(query, caseSensitive, isRegex, callback)
252    {
253        this.requestContent(contentLoaded);
254
255        /**
256         * @param {?string} content
257         */
258        function contentLoaded(content)
259        {
260            if (typeof content !== "string") {
261                callback([]);
262                return;
263            }
264
265            callback(WebInspector.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex));
266        }
267    },
268
269    __proto__: WebInspector.ContentProvider.prototype
270}
271
272/**
273 * @constructor
274 * @implements {WebInspector.ContentProvider}
275 * @param {!WebInspector.ResourceType} contentType
276 * @param {string} content
277 */
278WebInspector.StaticContentProvider = function(contentType, content)
279{
280    this._content = content;
281    this._contentType = contentType;
282}
283
284WebInspector.StaticContentProvider.prototype = {
285    /**
286     * @return {string}
287     */
288    contentURL: function()
289    {
290        return "";
291    },
292
293    /**
294     * @return {!WebInspector.ResourceType}
295     */
296    contentType: function()
297    {
298        return this._contentType;
299    },
300
301    /**
302     * @param {function(?string)} callback
303     */
304    requestContent: function(callback)
305    {
306        callback(this._content);
307    },
308
309    /**
310     * @param {string} query
311     * @param {boolean} caseSensitive
312     * @param {boolean} isRegex
313     * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
314     */
315    searchInContent: function(query, caseSensitive, isRegex, callback)
316    {
317        /**
318         * @this {WebInspector.StaticContentProvider}
319         */
320        function performSearch()
321        {
322            callback(WebInspector.ContentProvider.performSearchInContent(this._content, query, caseSensitive, isRegex));
323        }
324
325        // searchInContent should call back later.
326        window.setTimeout(performSearch.bind(this), 0);
327    },
328
329    __proto__: WebInspector.ContentProvider.prototype
330}
331