1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/xpcom", 5 "firebug/lib/object", 6 "firebug/lib/trace", 7 "firebug/lib/http", 8 "firebug/chrome/window", 9 "firebug/net/netProgress", 10 "firebug/net/netUtils" 11 ], 12 function(Xpcom, Obj, FBTrace, Http, Win, NetProgress, NetUtils) { 13 14 // ********************************************************************************************* // 15 // Constants 16 17 var Cc = Components.classes; 18 var Ci = Components.interfaces; 19 var Cr = Components.results; 20 21 var nsIHttpActivityObserver = Ci.nsIHttpActivityObserver; 22 var nsISocketTransport = Ci.nsISocketTransport; 23 24 var activeRequests = []; 25 26 // ********************************************************************************************* // 27 // Callbacks 28 29 var startFile = NetProgress.prototype.startFile; 30 var requestedHeaderFile = NetProgress.prototype.requestedHeaderFile; 31 var respondedHeaderFile = NetProgress.prototype.respondedHeaderFile; 32 var requestedFile = NetProgress.prototype.requestedFile; 33 var respondedFile = NetProgress.prototype.respondedFile; 34 var bodySentFile = NetProgress.prototype.bodySentFile; 35 var responseStartedFile = NetProgress.prototype.responseStartedFile; 36 var respondedCacheFile = NetProgress.prototype.respondedCacheFile; 37 var connectingFile = NetProgress.prototype.connectingFile; 38 var connectedFile = NetProgress.prototype.connectedFile; 39 var waitingForFile = NetProgress.prototype.waitingForFile; 40 var sendingFile = NetProgress.prototype.sendingFile; 41 var receivingFile = NetProgress.prototype.receivingFile; 42 var responseCompletedFile = NetProgress.prototype.responseCompletedFile; 43 var closedFile = NetProgress.prototype.closedFile; 44 var resolvingFile = NetProgress.prototype.resolvingFile; 45 var resolvedFile = NetProgress.prototype.resolvedFile; 46 var windowPaint = NetProgress.prototype.windowPaint; 47 var timeStamp = NetProgress.prototype.timeStamp; 48 var windowLoad = NetProgress.prototype.windowLoad; 49 var contentLoad = NetProgress.prototype.contentLoad; 50 51 // ********************************************************************************************* // 52 // Activity Observer 53 54 var NetHttpActivityObserver = 55 { 56 registered: false, 57 58 registerObserver: function() 59 { 60 if (!Ci.nsIHttpActivityDistributor) 61 return; 62 63 if (this.registered) 64 return; 65 66 var distributor = this.getActivityDistributor(); 67 if (!distributor) 68 return; 69 70 distributor.addObserver(this); 71 this.registered = true; 72 73 if (FBTrace.DBG_ACTIVITYOBSERVER || FBTrace.DBG_OBSERVERS) 74 { 75 // import fbObserverService 76 Components.utils.import("resource://firebug/observer-service.js"); 77 this.trackId = fbObserverService.track(Components.stack); 78 FBTrace.sysout("activityObserver.registerObserver;"+this.trackId+" this.registered: "+this.registered); 79 } 80 81 }, 82 83 unregisterObserver: function() 84 { 85 if (!Ci.nsIHttpActivityDistributor) 86 return; 87 88 if (!this.registered) 89 return; 90 91 var distributor = this.getActivityDistributor(); 92 if (!distributor) 93 return; 94 95 distributor.removeObserver(this); 96 this.registered = false; 97 98 if (FBTrace.DBG_ACTIVITYOBSERVER || FBTrace.DBG_OBSERVERS) 99 { 100 // import fbObserverService 101 Components.utils.import("resource://firebug/observer-service.js"); 102 fbObserverService.untrack(this.trackId); 103 FBTrace.sysout("activityObserver.unregisterObserver;"+this.trackId+" this.registered: "+this.registered); 104 } 105 106 }, 107 108 getActivityDistributor: function() 109 { 110 if (!this.activityDistributor) 111 { 112 try 113 { 114 var hadClass = Cc["@mozilla.org/network/http-activity-distributor;1"]; 115 if (!hadClass) 116 return null; 117 118 this.activityDistributor = hadClass.getService(Ci.nsIHttpActivityDistributor); 119 120 if (FBTrace.DBG_NET) 121 FBTrace.sysout("net.NetHttpActivityObserver; Activity Observer Registered"); 122 } 123 catch (err) 124 { 125 if (FBTrace.DBG_NET || FBTrace.DBG_ERRORS) 126 FBTrace.sysout("net.NetHttpActivityObserver; Activity Observer EXCEPTION", err); 127 } 128 } 129 return this.activityDistributor; 130 }, 131 132 /* nsIActivityObserver */ 133 observeActivity: function(httpChannel, activityType, activitySubtype, timestamp, 134 extraSizeData, extraStringData) 135 { 136 try 137 { 138 if (httpChannel instanceof Ci.nsIHttpChannel) 139 this.observeRequest(httpChannel, activityType, activitySubtype, timestamp, 140 extraSizeData, extraStringData); 141 } 142 catch (exc) 143 { 144 if ( (typeof(FBTrace) !== undefined) && FBTrace && FBTrace.DBG_ERRORS) // then we are in some sane scope 145 FBTrace.sysout("net.observeActivity: EXCEPTION "+exc, exc); 146 } 147 }, 148 149 observeRequest: function(httpChannel, activityType, activitySubtype, timestamp, 150 extraSizeData, extraStringData) 151 { 152 var win = Http.getWindowForRequest(httpChannel); 153 if (!win) 154 { 155 var index = activeRequests.indexOf(httpChannel); 156 if (index == -1) 157 return; 158 159 if (!(win = activeRequests[index+1])) 160 return; 161 } 162 163 var context = Firebug.connection.getContextByWindow(win); 164 var tabId = Win.getWindowProxyIdForWindow(win); 165 if (!(tabId && win)) 166 return; 167 168 var networkContext = Firebug.NetMonitor.contexts[tabId]; 169 if (!networkContext) 170 networkContext = context ? context.netProgress : null; 171 172 if (!networkContext) 173 return; 174 175 var time = new Date(); 176 time.setTime(timestamp/1000); 177 178 if (FBTrace.DBG_ACTIVITYOBSERVER) 179 { 180 FBTrace.sysout("activityObserver.observeActivity; " + 181 NetUtils.getTimeLabel(time) + ", " + 182 Http.safeGetRequestName(httpChannel) + ", " + 183 getActivityTypeDescription(activityType) + ", " + 184 getActivitySubtypeDescription(activitySubtype) + ", " + 185 extraSizeData, 186 extraStringData); 187 } 188 189 time = time.getTime(); 190 191 if (activityType == nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION) 192 { 193 if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_HEADER) 194 { 195 activeRequests.push(httpChannel); 196 activeRequests.push(win); 197 198 var isXHR = Http.isXHR(httpChannel); 199 networkContext.post(requestedHeaderFile, [httpChannel, time, win, isXHR, extraStringData]); 200 } 201 else if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE) 202 { 203 var index = activeRequests.indexOf(httpChannel); 204 activeRequests.splice(index, 2); 205 206 networkContext.post(closedFile, [httpChannel, time]); 207 } 208 else if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_HEADER) 209 networkContext.post(respondedHeaderFile, [httpChannel, time, extraStringData]); 210 else if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_BODY_SENT) 211 networkContext.post(bodySentFile, [httpChannel, time]); 212 else if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_START) 213 networkContext.post(responseStartedFile, [httpChannel, time]); 214 else if (activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE) 215 networkContext.post(responseCompletedFile, [httpChannel, time, extraSizeData]); 216 } 217 else if (activityType == nsIHttpActivityObserver.ACTIVITY_TYPE_SOCKET_TRANSPORT) 218 { 219 if (activitySubtype == nsISocketTransport.STATUS_RESOLVING) 220 networkContext.post(resolvingFile, [httpChannel, time]); 221 //else if (activitySubtype == nsISocketTransport.STATUS_RESOLVED) 222 // networkContext.post(resolvedFile, [httpChannel, time]); 223 else if (activitySubtype == nsISocketTransport.STATUS_CONNECTING_TO) 224 networkContext.post(connectingFile, [httpChannel, time]); 225 else if (activitySubtype == nsISocketTransport.STATUS_CONNECTED_TO) 226 networkContext.post(connectedFile, [httpChannel, time]); 227 else if (activitySubtype == nsISocketTransport.STATUS_SENDING_TO) 228 networkContext.post(sendingFile, [httpChannel, time, extraSizeData]); 229 else if (activitySubtype == nsISocketTransport.STATUS_WAITING_FOR) 230 networkContext.post(waitingForFile, [httpChannel, time]); 231 else if (activitySubtype == nsISocketTransport.STATUS_RECEIVING_FROM) 232 networkContext.post(receivingFile, [httpChannel, time, extraSizeData]); 233 } 234 }, 235 236 /* nsISupports */ 237 QueryInterface: function(iid) 238 { 239 if (iid.equals(Ci.nsISupports) || 240 iid.equals(Ci.nsIActivityObserver)) { 241 return this; 242 } 243 244 throw Cr.NS_ERROR_NO_INTERFACE; 245 } 246 } 247 248 // ********************************************************************************************* // 249 // Activity Observer Tracing Support 250 251 function getActivityTypeDescription(a) 252 { 253 switch (a) 254 { 255 case nsIHttpActivityObserver.ACTIVITY_TYPE_SOCKET_TRANSPORT: 256 return "ACTIVITY_TYPE_SOCKET_TRANSPORT"; 257 case nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION: 258 return "ACTIVITY_TYPE_HTTP_TRANSACTION"; 259 default: 260 return a; 261 } 262 } 263 264 function getActivitySubtypeDescription(a) 265 { 266 switch (a) 267 { 268 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_HEADER: 269 return "ACTIVITY_SUBTYPE_REQUEST_HEADER"; 270 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_BODY_SENT: 271 return "ACTIVITY_SUBTYPE_REQUEST_BODY_SENT"; 272 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_START: 273 return "ACTIVITY_SUBTYPE_RESPONSE_START"; 274 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_HEADER: 275 return "ACTIVITY_SUBTYPE_RESPONSE_HEADER"; 276 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE: 277 return "ACTIVITY_SUBTYPE_RESPONSE_COMPLETE"; 278 case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE: 279 return "ACTIVITY_SUBTYPE_TRANSACTION_CLOSE"; 280 281 case nsISocketTransport.STATUS_RESOLVING: 282 return "STATUS_RESOLVING"; 283 case nsISocketTransport.STATUS_RESOLVED: 284 return "STATUS_RESOLVED"; 285 case nsISocketTransport.STATUS_CONNECTING_TO: 286 return "STATUS_CONNECTING_TO"; 287 case nsISocketTransport.STATUS_CONNECTED_TO: 288 return "STATUS_CONNECTED_TO"; 289 case nsISocketTransport.STATUS_SENDING_TO: 290 return "STATUS_SENDING_TO"; 291 case nsISocketTransport.STATUS_WAITING_FOR: 292 return "STATUS_WAITING_FOR"; 293 case nsISocketTransport.STATUS_RECEIVING_FROM: 294 return "STATUS_RECEIVING_FROM"; 295 296 default: 297 return a; 298 } 299 } 300 301 // ********************************************************************************************* // 302 303 // https://bugzilla.mozilla.org/show_bug.cgi?id=669730 304 var HttpActivityObserverModule = Obj.extend(Firebug.Module, 305 { 306 dispatchName: "HttpActivityObserverModule", 307 308 destroyContext: function(context) 309 { 310 this.cleanUp(context.window); 311 }, 312 313 unwatchWindow: function(context, win) 314 { 315 this.cleanUp(win); 316 }, 317 318 cleanUp: function(win) 319 { 320 for (var i=0; i<activeRequests.length; i+=2) 321 { 322 if (activeRequests[i+1] == win) 323 { 324 activeRequests.splice(i, 2); 325 i -= 2; 326 } 327 } 328 }, 329 330 shutdown: function() 331 { 332 // destroy NetHttpActivityObserver 333 NetHttpActivityObserver.unregisterObserver(); 334 NetHttpActivityObserver.registerObserver = function() {}; 335 } 336 }); 337 338 // ********************************************************************************************* // 339 // Registration 340 341 Firebug.registerModule(HttpActivityObserverModule); 342 343 return NetHttpActivityObserver; 344 345 // ********************************************************************************************* // 346 }); 347