1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/xpcom", 5 "firebug/lib/trace", 6 "firebug/lib/string", 7 "firebug/lib/http", 8 "firebug/trace/traceModule", 9 "firebug/trace/traceListener" 10 ], 11 function(Xpcom, FBTrace, Str, Http, TraceModule, TraceListener) { 12 13 // ********************************************************************************************* // 14 // Constants 15 16 const Cc = Components.classes; 17 const Ci = Components.interfaces; 18 const Cr = Components.results; 19 20 var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); 21 var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); 22 23 // ********************************************************************************************* // 24 // HTTP Request Observer implementation 25 26 /** 27 * @service This service is intended as the only HTTP observer registered by Firebug. 28 * All FB extensions and Firebug itself should register a listener within this 29 * service in order to listen for http-on-modify-request, http-on-examine-response and 30 * http-on-examine-cached-response events. 31 * 32 * See also: <a href="http://developer.mozilla.org/en/Setting_HTTP_request_headers"> 33 * Setting_HTTP_request_headers</a> 34 */ 35 var HttpRequestObserver = 36 /** lends HttpRequestObserver */ 37 { 38 observers: [], 39 observing: false, 40 41 registerObservers: function() 42 { 43 if (FBTrace.DBG_HTTPOBSERVER) 44 FBTrace.sysout("httpObserver.registerObservers; (" + this.observers.length + "), " + 45 "active: " + this.observing, getObserverList()); 46 47 if (!this.observing) 48 { 49 observerService.addObserver(this, "http-on-opening-request", false); 50 observerService.addObserver(this, "http-on-modify-request", false); 51 observerService.addObserver(this, "http-on-examine-response", false); 52 observerService.addObserver(this, "http-on-examine-cached-response", false); 53 } 54 55 this.observing = true; 56 }, 57 58 unregisterObservers: function() 59 { 60 if (FBTrace.DBG_HTTPOBSERVER) 61 FBTrace.sysout("httpObserver.unregisterObservers; (" + this.observers.length + "), " + 62 "active: " + this.observing, getObserverList()); 63 64 if (this.observing) 65 { 66 observerService.removeObserver(this, "http-on-opening-request"); 67 observerService.removeObserver(this, "http-on-modify-request"); 68 observerService.removeObserver(this, "http-on-examine-response"); 69 observerService.removeObserver(this, "http-on-examine-cached-response"); 70 } 71 72 this.observing = false; 73 }, 74 75 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 76 // nsIObserver 77 78 observe: function(subject, topic, data) 79 { 80 try 81 { 82 if (!(subject instanceof Ci.nsIHttpChannel)) 83 return; 84 85 // Notify all registered observers. 86 if (topic == "http-on-modify-request" || 87 topic == "http-on-examine-response" || 88 topic == "http-on-examine-cached-response" || 89 topic == "http-on-opening-request") 90 { 91 this.notifyObservers(subject, topic, data); 92 } 93 } 94 catch (err) 95 { 96 if (FBTrace.DBG_ERRORS) 97 FBTrace.sysout("httpObserver.observe EXCEPTION", err); 98 } 99 }, 100 101 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 102 // nsIObserverService 103 104 addObserver: function(observer, topic, weak) 105 { 106 if (!topic) 107 topic = "firebug-http-event"; 108 109 if (topic != "firebug-http-event") 110 throw Cr.NS_ERROR_INVALID_ARG; 111 112 // Do not add an observer twice. 113 for (var i=0; i<this.observers.length; i++) 114 { 115 if (this.observers[i] == observer) 116 { 117 // xxxHonza: firebug/debugger is registering itself more times, 118 // not sure if it's on purpose, but it causes following error message: 119 // Error: attempt to run compile-and-go script on a cleared scope 120 // (on the first line of the observe method) 121 if (FBTrace.DBG_HTTPOBSERVER) 122 FBTrace.sysout("httpObserver.addObserver; ERROR? Observer already registered: " + 123 observer.dispatchName, getObserverList()); 124 return; 125 } 126 } 127 128 this.observers.push(observer); 129 130 if (FBTrace.DBG_HTTPOBSERVER) 131 FBTrace.sysout("httpObserver.addObserver; (" + this.observers.length + 132 "), added: " + observer.dispatchName); 133 134 if (this.observers.length > 0) 135 this.registerObservers(); 136 }, 137 138 removeObserver: function(observer, topic) 139 { 140 if (!topic) 141 topic = "firebug-http-event"; 142 143 if (topic != "firebug-http-event") 144 throw Cr.NS_ERROR_INVALID_ARG; 145 146 for (var i=0; i<this.observers.length; i++) 147 { 148 if (this.observers[i] == observer) 149 { 150 this.observers.splice(i, 1); 151 152 if (this.observers.length == 0) 153 this.unregisterObservers(); 154 155 if (FBTrace.DBG_HTTPOBSERVER) 156 FBTrace.sysout("httpObserver.removeObserver; (" + this.observers.length + 157 "), removed: " + observer.dispatchName, getObserverList()); 158 return; 159 } 160 } 161 162 if (FBTrace.DBG_HTTPOBSERVER) 163 FBTrace.sysout("httpObserver.removeObserver ERROR? (no such observer): " + 164 observer.dispatchName); 165 }, 166 167 notifyObservers: function(subject, topic, data) 168 { 169 if (FBTrace.DBG_HTTPOBSERVER) 170 { 171 FBTrace.sysout("httpObserver.notifyObservers (" + this.observers.length + ") " + 172 (topic ? topic.toUpperCase() : topic) + ", " + Http.safeGetRequestName(subject), 173 getObserverList()); 174 } 175 176 for (var i=0; i<this.observers.length; i++) 177 { 178 var observer = this.observers[i]; 179 try 180 { 181 if (observer.observe) 182 observer.observe(subject, topic, data); 183 } 184 catch (err) 185 { 186 if (FBTrace.DBG_HTTPOBSERVER) 187 FBTrace.sysout("httpObserver.notifyObservers; EXCEPTION " + err, err); 188 } 189 } 190 } 191 } 192 193 // ********************************************************************************************* // 194 // Tracing Support 195 196 function getObserverList() 197 { 198 var observerNames = []; 199 for (var i=0; i<HttpRequestObserver.observers.length; i++) 200 observerNames.push(HttpRequestObserver.observers[i].dispatchName); 201 202 return observerNames; 203 } 204 205 // ********************************************************************************************* // 206 // Registration 207 208 // Compatibility with Firebug 1.7 extensions: deprecated, obsolete 209 FBL.httpObserver = HttpRequestObserver; 210 211 // xxxHonza: Do we need to remove the listener? 212 TraceModule.addListener(new TraceListener("httpObserver.", "DBG_HTTPOBSERVER", true)); 213 214 return HttpRequestObserver; 215 216 // ********************************************************************************************* // 217 }); 218