1 /* 2 * Copyright (C) 2012 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 * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding 34 * @param {!WebInspector.Workspace} workspace 35 */ 36 WebInspector.NetworkUISourceCodeProvider = function(networkWorkspaceBinding, workspace) 37 { 38 this._networkWorkspaceBinding = networkWorkspaceBinding; 39 this._workspace = workspace; 40 this._processedURLs = {}; 41 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); 42 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); 43 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this); 44 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this); 45 WebInspector.targetManager.addModelListener(WebInspector.CSSStyleModel, WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); 46 } 47 48 WebInspector.NetworkUISourceCodeProvider.prototype = { 49 /** 50 * @param {!WebInspector.Target} target 51 */ 52 _populate: function(target) 53 { 54 /** 55 * @param {!WebInspector.ResourceTreeFrame} frame 56 * @this {WebInspector.NetworkUISourceCodeProvider} 57 */ 58 function populateFrame(frame) 59 { 60 for (var i = 0; i < frame.childFrames.length; ++i) 61 populateFrame.call(this, frame.childFrames[i]); 62 63 var resources = frame.resources(); 64 for (var i = 0; i < resources.length; ++i) 65 this._addFile(resources[i].url, new WebInspector.NetworkUISourceCodeProvider.FallbackResource(resources[i])); 66 } 67 68 var mainFrame = target.resourceTreeModel.mainFrame; 69 if (mainFrame) 70 populateFrame.call(this, mainFrame); 71 }, 72 73 /** 74 * @param {!WebInspector.Event} event 75 */ 76 _parsedScriptSource: function(event) 77 { 78 var script = /** @type {!WebInspector.Script} */ (event.data); 79 if (!script.sourceURL || (script.isInlineScript() && !script.hasSourceURL) || script.isSnippet()) 80 return; 81 // Filter out embedder injected content scripts. 82 if (script.isContentScript() && !script.hasSourceURL) { 83 var parsedURL = new WebInspector.ParsedURL(script.sourceURL); 84 if (!parsedURL.isValid) 85 return; 86 } 87 this._addFile(script.sourceURL, script, script.isContentScript()); 88 }, 89 90 /** 91 * @param {!WebInspector.Event} event 92 */ 93 _styleSheetAdded: function(event) 94 { 95 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); 96 if (header.isInline && header.origin !== "inspector") 97 return; 98 99 this._addFile(header.resourceURL(), header, false); 100 }, 101 102 /** 103 * @param {!WebInspector.Event} event 104 */ 105 _resourceAdded: function(event) 106 { 107 var resource = /** @type {!WebInspector.Resource} */ (event.data); 108 this._addFile(resource.url, new WebInspector.NetworkUISourceCodeProvider.FallbackResource(resource)); 109 }, 110 111 /** 112 * @param {!WebInspector.Event} event 113 */ 114 _mainFrameNavigated: function(event) 115 { 116 var resourceTreeModel = /** @type {!WebInspector.ResourceTreeModel} */ (event.target); 117 //We assume that mainFrameNavigated could be fired only in one main target 118 this._reset(resourceTreeModel.target()); 119 }, 120 121 /** 122 * @param {string} url 123 * @param {!WebInspector.ContentProvider} contentProvider 124 * @param {boolean=} isContentScript 125 */ 126 _addFile: function(url, contentProvider, isContentScript) 127 { 128 if (this._workspace.hasMappingForURL(url)) 129 return; 130 131 var type = contentProvider.contentType(); 132 if (type !== WebInspector.resourceTypes.Stylesheet && type !== WebInspector.resourceTypes.Document && type !== WebInspector.resourceTypes.Script) 133 return; 134 if (this._processedURLs[url]) 135 return; 136 this._processedURLs[url] = true; 137 this._networkWorkspaceBinding.addFileForURL(url, contentProvider, isContentScript); 138 }, 139 140 /** 141 * @param {!WebInspector.Target} target 142 */ 143 _reset: function(target) 144 { 145 this._processedURLs = {}; 146 this._networkWorkspaceBinding.reset(); 147 this._populate(target); 148 } 149 } 150 151 /** 152 * @constructor 153 * @implements {WebInspector.ContentProvider} 154 * @param {!WebInspector.Resource} resource 155 */ 156 WebInspector.NetworkUISourceCodeProvider.FallbackResource = function(resource) 157 { 158 this._resource = resource; 159 } 160 161 WebInspector.NetworkUISourceCodeProvider.FallbackResource.prototype = { 162 163 /** 164 * @return {string} 165 */ 166 contentURL: function() 167 { 168 return this._resource.contentURL(); 169 }, 170 171 /** 172 * @return {!WebInspector.ResourceType} 173 */ 174 contentType: function() 175 { 176 return this._resource.contentType(); 177 }, 178 179 /** 180 * @param {function(?string)} callback 181 */ 182 requestContent: function(callback) 183 { 184 /** 185 * @this {WebInspector.NetworkUISourceCodeProvider.FallbackResource} 186 */ 187 function loadFallbackContent() 188 { 189 var scripts = this._resource.target().debuggerModel.scriptsForSourceURL(this._resource.url); 190 if (!scripts.length) { 191 callback(null); 192 return; 193 } 194 195 var contentProvider; 196 if (this._resource.type === WebInspector.resourceTypes.Document) 197 contentProvider = new WebInspector.ConcatenatedScriptsContentProvider(scripts); 198 else if (this._resource.type === WebInspector.resourceTypes.Script) 199 contentProvider = scripts[0]; 200 201 console.assert(contentProvider, "Resource content request failed. " + this._resource.url); 202 203 contentProvider.requestContent(callback); 204 } 205 206 /** 207 * @param {?string} content 208 * @this {WebInspector.NetworkUISourceCodeProvider.FallbackResource} 209 */ 210 function requestContentLoaded(content) 211 { 212 if (content) 213 callback(content) 214 else 215 loadFallbackContent.call(this); 216 } 217 218 this._resource.requestContent(requestContentLoaded.bind(this)); 219 }, 220 221 /** 222 * @param {string} query 223 * @param {boolean} caseSensitive 224 * @param {boolean} isRegex 225 * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback 226 */ 227 searchInContent: function(query, caseSensitive, isRegex, callback) 228 { 229 /** 230 * @param {?string} content 231 */ 232 function documentContentLoaded(content) 233 { 234 if (content === null) { 235 callback([]); 236 return; 237 } 238 239 var result = WebInspector.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex); 240 callback(result); 241 } 242 243 if (this.contentType() === WebInspector.resourceTypes.Document) { 244 this.requestContent(documentContentLoaded); 245 return; 246 } 247 248 this._resource.searchInContent(query, caseSensitive, isRegex, callback); 249 } 250 } 251 252 /** 253 * @type {!WebInspector.NetworkWorkspaceBinding} 254 */ 255 WebInspector.networkWorkspaceBinding; 256