1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/xpcom", 5 "firebug/lib/trace", 6 "firebug/lib/deprecated", 7 "firebug/js/stackFrame", 8 "firebug/lib/string" 9 ], 10 function(Xpcom, FBTrace, Deprecated, StackFrame, Str) { 11 12 // ********************************************************************************************* // 13 // Constants 14 15 const Cc = Components.classes; 16 const Ci = Components.interfaces; 17 const Cr = Components.results; 18 19 const NS_SEEK_SET = Ci.nsISeekableStream.NS_SEEK_SET; 20 const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); 21 22 var Http = {}; 23 24 // ********************************************************************************************* // 25 // Module Implementation 26 27 Http.readFromStream = function(stream, charset, noClose) 28 { 29 // Causes a memory leak (see https://bugzilla.mozilla.org/show_bug.cgi?id=699801) 30 //var sis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); 31 //sis.setInputStream(stream); 32 33 var sis = Cc["@mozilla.org/scriptableinputstream;1"]. 34 createInstance(Ci.nsIScriptableInputStream); 35 sis.init(stream); 36 37 var segments = []; 38 for (var count = stream.available(); count; count = stream.available()) 39 segments.push(sis.readBytes(count)); 40 41 if (!noClose) 42 sis.close(); 43 44 var text = segments.join(""); 45 46 try 47 { 48 return Str.convertToUnicode(text, charset); 49 } 50 catch (err) 51 { 52 if (FBTrace.DBG_ERRORS) 53 FBTrace.sysout("http.readFromStream EXCEPTION charset: " + charset, err); 54 } 55 56 return text; 57 }; 58 59 Http.readPostTextFromPage = function(url, context) 60 { 61 if (url == context.browser.contentWindow.location.href) 62 { 63 try 64 { 65 var webNav = context.browser.webNavigation; 66 var descriptor = (webNav instanceof Ci.nsIWebPageDescriptor) ? 67 webNav.currentDescriptor : null; 68 69 if (!(descriptor instanceof Ci.nsISHEntry)) 70 return; 71 72 var entry = descriptor; 73 if (entry && entry.postData) 74 { 75 if (!(entry.postData instanceof Ci.nsISeekableStream)) 76 return; 77 78 var postStream = entry.postData; 79 postStream.seek(NS_SEEK_SET, 0); 80 81 var charset = context.window.document.characterSet; 82 return Http.readFromStream(postStream, charset, true); 83 } 84 } 85 catch (exc) 86 { 87 if (FBTrace.DBG_ERRORS) 88 FBTrace.sysout("http.readPostText FAILS, url:"+url, exc); 89 } 90 } 91 }; 92 93 Http.getResource = function(aURL) 94 { 95 try 96 { 97 var channel = ioService.newChannel(aURL, null, null); 98 var input = channel.open(); 99 100 return Http.readFromStream(input); 101 } 102 catch (e) 103 { 104 if (FBTrace.DBG_ERRORS) 105 FBTrace.sysout("lib.getResource FAILS for \'"+aURL+"\'", e); 106 } 107 }; 108 109 /** 110 * Returns a posted data for specified request object. The return value might contain 111 * headers (if request.uploadStreamHasHeaders is set to true). You can remove these 112 * headers using {@link Http.removeHeadersFromPostText} 113 * 114 * @param {Object} request The request object 115 * @param {Object} context Current Firebug context (to get charset of the current document) 116 */ 117 Http.readPostTextFromRequest = function(request, context) 118 { 119 try 120 { 121 var is = (request instanceof Ci.nsIUploadChannel) ? request.uploadStream : null; 122 if (is) 123 { 124 if (!(is instanceof Ci.nsISeekableStream)) 125 return; 126 127 var ss = is; 128 var prevOffset; 129 if (ss) 130 { 131 prevOffset = ss.tell(); 132 ss.seek(NS_SEEK_SET, 0); 133 } 134 135 // Read data from the stream.. 136 var charset = (context && context.window) ? context.window.document.characterSet : null; 137 var text = Http.readFromStream(is, charset, true); 138 139 // Seek locks the file, so seek to the beginning only if necko hasn't read it yet, 140 // since necko doesn't seek to 0 before reading (at least not till 459384 is fixed). 141 if (ss && prevOffset == 0) 142 ss.seek(NS_SEEK_SET, 0); 143 144 return text; 145 } 146 } 147 catch(exc) 148 { 149 if (FBTrace.DBG_ERRORS) 150 FBTrace.sysout("http.readPostTextFromRequest FAILS ", exc); 151 } 152 153 return null; 154 }; 155 156 /** 157 * Removes headers from post body, https://bugzilla.mozilla.org/show_bug.cgi?id=649338 158 * 159 * @param {Object} request Channel implementing nsIUploadChannel2 160 * @param {Object} text Extracted text (can include headers at the beginning). 161 */ 162 Http.removeHeadersFromPostText = function(request, text) 163 { 164 if (!text) 165 return text; 166 167 if (typeof(Ci.nsIUploadChannel2) == "undefined") 168 return text; 169 170 if (!(request instanceof Ci.nsIUploadChannel2)) 171 return text; 172 173 if (!request.uploadStreamHasHeaders) 174 return text; 175 176 var headerSeparator = "\r\n\r\n"; 177 var index = text.indexOf(headerSeparator); 178 if (index == -1) 179 return text; 180 181 return text.substring(index + headerSeparator.length); 182 } 183 184 /** 185 * Returns an array of headers from posted data (appended by Firefox) 186 * 187 * @param {Object} request Channel implementing nsIUploadChannel2 188 * @param {Object} text Posted data from the channel object. 189 */ 190 Http.getHeadersFromPostText = function(request, text) 191 { 192 var headers = []; 193 if (!text) 194 return headers; 195 196 if (typeof(Ci.nsIUploadChannel2) == "undefined") 197 return headers; 198 199 if (!(request instanceof Ci.nsIUploadChannel2)) 200 return headers; 201 202 if (!request.uploadStreamHasHeaders) 203 return headers; 204 205 var headerSeparator = "\r\n\r\n"; 206 var index = text.indexOf(headerSeparator); 207 if (index == -1) 208 return headers; 209 210 var text = text.substring(0, index); 211 var lines = Str.splitLines(text); 212 213 for (var i=0; i<lines.length; i++) 214 { 215 var header = lines[i].split(":"); 216 if (header.length != 2) 217 continue; 218 219 headers.push({ 220 name: Str.trim(header[0]), 221 value: Str.trim(header[1]), 222 }); 223 } 224 225 return headers; 226 } 227 228 Http.getInputStreamFromString = function(dataString) 229 { 230 var stringStream = Cc["@mozilla.org/io/string-input-stream;1"]. 231 createInstance(Ci.nsIStringInputStream); 232 233 if ("data" in stringStream) // Gecko 1.9 or newer 234 stringStream.data = dataString; 235 else // 1.8 or older 236 stringStream.setData(dataString, dataString.length); 237 238 return stringStream; 239 }; 240 241 Http.getWindowForRequest = function(request) 242 { 243 var loadContext = Http.getRequestLoadContext(request); 244 try 245 { 246 if (loadContext) 247 return loadContext.associatedWindow; 248 } 249 catch (ex) 250 { 251 } 252 253 return null; 254 }; 255 256 Http.getRequestLoadContext = function(request) 257 { 258 try 259 { 260 if (request && request.notificationCallbacks) 261 { 262 StackFrame.suspendShowStackTrace(); 263 return request.notificationCallbacks.getInterface(Ci.nsILoadContext); 264 } 265 } 266 catch (exc) 267 { 268 } 269 finally 270 { 271 StackFrame.resumeShowStackTrace(); 272 } 273 274 try 275 { 276 if (request && request.loadGroup && request.loadGroup.notificationCallbacks) 277 { 278 StackFrame.suspendShowStackTrace(); 279 return request.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext); 280 } 281 } 282 catch (exc) 283 { 284 } 285 finally 286 { 287 StackFrame.resumeShowStackTrace(); 288 } 289 290 return null; 291 }; 292 293 Http.getRequestWebProgress = Deprecated.deprecated("Use getRequestLoadContext function", 294 Http.getRequestLoadContext); 295 296 // ********************************************************************************************* // 297 // HTTP Channel Fields 298 299 Http.safeGetRequestName = function(request) 300 { 301 try 302 { 303 return request.name; 304 } 305 catch (exc) 306 { 307 } 308 309 return null; 310 } 311 312 Http.safeGetURI = function(browser) 313 { 314 try 315 { 316 return browser.currentURI; 317 } 318 catch (exc) 319 { 320 } 321 322 return null; 323 } 324 325 Http.safeGetContentType = function(request) 326 { 327 try 328 { 329 return new String(request.contentType).toLowerCase(); 330 } 331 catch (err) 332 { 333 } 334 335 return null; 336 } 337 338 Http.safeGetXHRResponseText = function(xhr) 339 { 340 try 341 { 342 return xhr.responseText; 343 } 344 catch (err) 345 { 346 } 347 348 return null; 349 } 350 351 // ********************************************************************************************* // 352 // IP Adress and port number (Requires Gecko 5). 353 354 Http.safeGetLocalAddress = function(request) 355 { 356 try 357 { 358 if (request instanceof Ci.nsIHttpChannelInternal) 359 return request.localAddress; 360 } 361 catch (err) 362 { 363 } 364 return null; 365 } 366 367 Http.safeGetLocalPort = function(request) 368 { 369 try 370 { 371 if (request instanceof Ci.nsIHttpChannelInternal) 372 return request.localPort; 373 } 374 catch (err) 375 { 376 } 377 return null; 378 } 379 380 Http.safeGetRemoteAddress = function(request) 381 { 382 try 383 { 384 if (request instanceof Ci.nsIHttpChannelInternal) 385 return request.remoteAddress; 386 } 387 catch (err) 388 { 389 } 390 return null; 391 } 392 393 Http.safeGetRemotePort = function(request) 394 { 395 try 396 { 397 if (request instanceof Ci.nsIHttpChannelInternal) 398 return request.remotePort; 399 } 400 catch (err) 401 { 402 } 403 return null; 404 } 405 406 // ********************************************************************************************* // 407 // XHR 408 409 Http.isXHR = function(request) 410 { 411 try 412 { 413 var callbacks = request.notificationCallbacks; 414 StackFrame.suspendShowStackTrace(); 415 var xhrRequest = callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null; 416 return (xhrRequest != null); 417 } 418 catch (exc) 419 { 420 } 421 finally 422 { 423 StackFrame.resumeShowStackTrace(); 424 } 425 426 return false; 427 }, 428 429 // ********************************************************************************************* // 430 // Conversions 431 432 Http.convertToUnicode = Deprecated.deprecated("Function moved to 'firebug/lib/string' module", 433 Str.convertToUnicode); 434 435 Http.convertFromUnicode = Deprecated.deprecated("Function moved to 'firebug/lib/string' module", 436 Str.convertFromUnicode); 437 438 // ************************************************************************************************ 439 // Network Tracing 440 441 Http.getStateDescription = function(flag) 442 { 443 var state = []; 444 var nsIWebProgressListener = Ci.nsIWebProgressListener; 445 if (flag & nsIWebProgressListener.STATE_START) state.push("STATE_START"); 446 else if (flag & nsIWebProgressListener.STATE_REDIRECTING) state.push("STATE_REDIRECTING"); 447 else if (flag & nsIWebProgressListener.STATE_TRANSFERRING) state.push("STATE_TRANSFERRING"); 448 else if (flag & nsIWebProgressListener.STATE_NEGOTIATING) state.push("STATE_NEGOTIATING"); 449 else if (flag & nsIWebProgressListener.STATE_STOP) state.push("STATE_STOP"); 450 451 if (flag & nsIWebProgressListener.STATE_IS_REQUEST) state.push("STATE_IS_REQUEST"); 452 if (flag & nsIWebProgressListener.STATE_IS_DOCUMENT) state.push("STATE_IS_DOCUMENT"); 453 if (flag & nsIWebProgressListener.STATE_IS_NETWORK) state.push("STATE_IS_NETWORK"); 454 if (flag & nsIWebProgressListener.STATE_IS_WINDOW) state.push("STATE_IS_WINDOW"); 455 if (flag & nsIWebProgressListener.STATE_RESTORING) state.push("STATE_RESTORING"); 456 if (flag & nsIWebProgressListener.STATE_IS_INSECURE) state.push("STATE_IS_INSECURE"); 457 if (flag & nsIWebProgressListener.STATE_IS_BROKEN) state.push("STATE_IS_BROKEN"); 458 if (flag & nsIWebProgressListener.STATE_IS_SECURE) state.push("STATE_IS_SECURE"); 459 if (flag & nsIWebProgressListener.STATE_SECURE_HIGH) state.push("STATE_SECURE_HIGH"); 460 if (flag & nsIWebProgressListener.STATE_SECURE_MED) state.push("STATE_SECURE_MED"); 461 if (flag & nsIWebProgressListener.STATE_SECURE_LOW) state.push("STATE_SECURE_LOW"); 462 463 return state.join(", "); 464 }; 465 466 Http.getStatusDescription = function(status) 467 { 468 var nsISocketTransport = Ci.nsISocketTransport; 469 var nsITransport = Ci.nsITransport; 470 471 if (status == nsISocketTransport.STATUS_RESOLVING) return "STATUS_RESOLVING"; 472 if (status == nsISocketTransport.STATUS_CONNECTING_TO) return "STATUS_CONNECTING_TO"; 473 if (status == nsISocketTransport.STATUS_CONNECTED_TO) return "STATUS_CONNECTED_TO"; 474 if (status == nsISocketTransport.STATUS_SENDING_TO) return "STATUS_SENDING_TO"; 475 if (status == nsISocketTransport.STATUS_WAITING_FOR) return "STATUS_WAITING_FOR"; 476 if (status == nsISocketTransport.STATUS_RECEIVING_FROM) return "STATUS_RECEIVING_FROM"; 477 if (status == nsITransport.STATUS_READING) return "STATUS_READING"; 478 if (status == nsITransport.STATUS_WRITING) return "STATUS_WRITING"; 479 }; 480 481 Http.getLoadFlagsDescription = function(loadFlags) 482 { 483 var flags = []; 484 var nsIChannel = Ci.nsIChannel; 485 var nsICachingChannel = Ci.nsICachingChannel; 486 487 if (loadFlags & nsIChannel.LOAD_DOCUMENT_URI) flags.push("LOAD_DOCUMENT_URI"); 488 if (loadFlags & nsIChannel.LOAD_RETARGETED_DOCUMENT_URI) flags.push("LOAD_RETARGETED_DOCUMENT_URI"); 489 if (loadFlags & nsIChannel.LOAD_REPLACE) flags.push("LOAD_REPLACE"); 490 if (loadFlags & nsIChannel.LOAD_INITIAL_DOCUMENT_URI) flags.push("LOAD_INITIAL_DOCUMENT_URI"); 491 if (loadFlags & nsIChannel.LOAD_TARGETED) flags.push("LOAD_TARGETED"); 492 if (loadFlags & nsIChannel.LOAD_CALL_CONTENT_SNIFFERS) flags.push("LOAD_CALL_CONTENT_SNIFFERS"); 493 if (loadFlags & nsICachingChannel.LOAD_NO_NETWORK_IO) flags.push("LOAD_NO_NETWORK_IO"); 494 if (loadFlags & nsICachingChannel.LOAD_CHECK_OFFLINE_CACHE) flags.push("LOAD_CHECK_OFFLINE_CACHE"); 495 if (loadFlags & nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE) flags.push("LOAD_BYPASS_LOCAL_CACHE"); 496 if (loadFlags & nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) flags.push("LOAD_BYPASS_LOCAL_CACHE_IF_BUSY"); 497 if (loadFlags & nsICachingChannel.LOAD_ONLY_FROM_CACHE) flags.push("LOAD_ONLY_FROM_CACHE"); 498 if (loadFlags & nsICachingChannel.LOAD_ONLY_IF_MODIFIED) flags.push("LOAD_ONLY_IF_MODIFIED"); 499 500 return flags.join(", "); 501 }; 502 503 // ********************************************************************************************* // 504 505 Http.BaseProgressListener = 506 { 507 QueryInterface : function(iid) 508 { 509 if (iid.equals(Ci.nsIWebProgressListener) || 510 iid.equals(Ci.nsISupportsWeakReference) || 511 iid.equals(Ci.nsISupports)) 512 { 513 return this; 514 } 515 516 throw Components.results.NS_NOINTERFACE; 517 }, 518 519 stateIsRequest: false, 520 onLocationChange: function() {}, 521 onStateChange : function() {}, 522 onProgressChange : function() {}, 523 onStatusChange : function() {}, 524 onSecurityChange : function() {}, 525 onLinkIconAvailable : function() {} 526 }; 527 528 // ********************************************************************************************* // 529 // Registration 530 531 return Http; 532 533 // ********************************************************************************************* // 534 }); 535