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 {!PageAgent.FrameId} frameId 37 * @param {!NetworkAgent.LoaderId} loaderId 38 * @param {!WebInspector.ResourceType} type 39 * @param {string} mimeType 40 * @param {boolean=} isHidden 41 */ 42WebInspector.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 60WebInspector.Resource.Events = { 61 MessageAdded: "message-added", 62 MessagesCleared: "messages-cleared", 63} 64 65WebInspector.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 {!PageAgent.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)} callback 231 */ 232 requestContent: function(callback) 233 { 234 if (typeof this._content !== "undefined") { 235 callback(this._content); 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 this.requestContent(documentContentLoaded); 268 return; 269 } 270 271 /** 272 * @param {?string} content 273 */ 274 function documentContentLoaded(content) 275 { 276 if (content === null) { 277 callback([]); 278 return; 279 } 280 281 var result = WebInspector.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex); 282 callback(result); 283 } 284 285 if (this.frameId) 286 PageAgent.searchInResource(this.frameId, this.url, query, caseSensitive, isRegex, callbackWrapper); 287 else 288 callback([]); 289 }, 290 291 /** 292 * @param {!Element} image 293 */ 294 populateImageSource: function(image) 295 { 296 /** 297 * @param {?string} content 298 * @this {WebInspector.Resource} 299 */ 300 function onResourceContent(content) 301 { 302 var imageSrc = WebInspector.contentAsDataURL(this._content, this.mimeType, this._contentEncoded); 303 if (imageSrc === null) 304 imageSrc = this.url; 305 image.src = imageSrc; 306 } 307 308 this.requestContent(onResourceContent.bind(this)); 309 }, 310 311 _requestFinished: function() 312 { 313 this._request.removeEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._requestFinished, this); 314 if (this._pendingContentCallbacks.length) 315 this._innerRequestContent(); 316 }, 317 318 319 _innerRequestContent: function() 320 { 321 if (this._contentRequested) 322 return; 323 this._contentRequested = true; 324 325 /** 326 * @param {?Protocol.Error} error 327 * @param {?string} content 328 * @param {boolean} contentEncoded 329 * @this {WebInspector.Resource} 330 */ 331 function contentLoaded(error, content, contentEncoded) 332 { 333 if (error || content === null) { 334 loadFallbackContent.call(this, error); 335 return; 336 } 337 replyWithContent.call(this, content, contentEncoded); 338 } 339 340 /** 341 * @param {?string} content 342 * @param {boolean} contentEncoded 343 * @this {WebInspector.Resource} 344 */ 345 function replyWithContent(content, contentEncoded) 346 { 347 this._content = content; 348 this._contentEncoded = contentEncoded; 349 var callbacks = this._pendingContentCallbacks.slice(); 350 for (var i = 0; i < callbacks.length; ++i) 351 callbacks[i](this._content); 352 this._pendingContentCallbacks.length = 0; 353 delete this._contentRequested; 354 } 355 356 /** 357 * @param {?Protocol.Error} error 358 * @param {string} content 359 * @param {boolean} contentEncoded 360 * @this {WebInspector.Resource} 361 */ 362 function resourceContentLoaded(error, content, contentEncoded) 363 { 364 contentLoaded.call(this, error, content, contentEncoded); 365 } 366 367 /** 368 * @param {?Protocol.Error} error 369 * @this {WebInspector.Resource} 370 */ 371 function loadFallbackContent(error) 372 { 373 var scripts = WebInspector.debuggerModel.scriptsForSourceURL(this.url); 374 if (!scripts.length) { 375 console.error("Resource content request failed: " + error); 376 replyWithContent.call(this, null, false); 377 return; 378 } 379 380 var contentProvider; 381 if (this.type === WebInspector.resourceTypes.Document) 382 contentProvider = new WebInspector.ConcatenatedScriptsContentProvider(scripts); 383 else if (this.type === WebInspector.resourceTypes.Script) 384 contentProvider = scripts[0]; 385 386 if (!contentProvider) { 387 console.error("Resource content request failed: " + error); 388 replyWithContent.call(this, null, false); 389 return; 390 } 391 392 contentProvider.requestContent(fallbackContentLoaded.bind(this)); 393 } 394 395 /** 396 * @param {?string} content 397 * @this {WebInspector.Resource} 398 */ 399 function fallbackContentLoaded(content) 400 { 401 replyWithContent.call(this, content, false); 402 } 403 404 if (this.request) { 405 this.request.requestContent(requestContentLoaded.bind(this)); 406 return; 407 } 408 409 /** 410 * @param {?string} content 411 * @this {WebInspector.Resource} 412 */ 413 function requestContentLoaded(content) 414 { 415 contentLoaded.call(this, null, content, this.request.contentEncoded); 416 } 417 418 PageAgent.getResourceContent(this.frameId, this.url, resourceContentLoaded.bind(this)); 419 }, 420 421 /** 422 * @return {boolean} 423 */ 424 isHidden: function() 425 { 426 return !!this._isHidden; 427 }, 428 429 __proto__: WebInspector.Object.prototype 430} 431 432