1 /* See license.txt for terms of usage */ 2 3 FBL.ns(function() { with (FBL) { 4 5 // ************************************************************************************************ 6 // Constants 7 8 const Cc = Components.classes; 9 const Ci = Components.interfaces; 10 11 const detachCommand = $("cmd_toggleDetachFirebug"); 12 13 // ************************************************************************************************ 14 15 /** 16 * @class Implements Firebug activation logic. 17 * 18 * 1) Part of the logic is based on annotation service (see components/firebug-annotations.js) 19 * in order to remember whether Firebug is activated for given site or not. 20 * If there is "firebugged.showFirebug" annotation for a given site Firbug is activated. 21 * If there is "firebugged.closed" annotation for a given site Firbug is not activated. 22 * 23 * 2) Other part is based on extensions.firebug.allPagesActivation option. This option 24 * can be set to the following values: 25 * none: The option isn't used (default value) 26 * on: Firebug is activated for all URLs. 27 * off: Firebug is never activated. 28 * 29 * This logic has higher priority over the URL annotations. 30 * If "off" options is selected, all existing URL annotations are removed. 31 */ 32 Firebug.Activation = extend(Firebug.Module, 33 { 34 dispatchName: "activation", 35 36 initializeUI: function() // called once 37 { 38 Firebug.Module.initializeUI.apply(this, arguments); 39 40 TabWatcher.addListener(this.TabWatcherListener); 41 42 // The "off" option is removed so make sure to convert previsous prev value 43 // into "none" if necessary. 44 if (Firebug.allPagesActivation == "off") 45 Firebug.allPagesActivation = "none"; 46 47 // Update option menu item. 48 this.updateAllPagesActivation(); 49 }, 50 51 getAnnotationService: function() 52 { 53 if(!this.annotationSvc) 54 { 55 // Create annotation service. 56 this.annotationSvc = Cc["@joehewitt.com/firebug-annotation-service;1"] 57 .getService(Ci.nsISupports).wrappedJSObject; 58 } 59 return this.annotationSvc; 60 }, 61 62 shutdown: function() 63 { 64 Firebug.Module.shutdown.apply(this, arguments); 65 66 TabWatcher.removeListener(this.TabWatcherListener); 67 68 this.getAnnotationService().flush(); 69 }, 70 71 convertToURIKey: function(url, sameOrigin) // process the URL to canonicalize it. Need not be reversible. 72 { 73 var uri = makeURI(normalizeURL(url)); 74 75 if (Firebug.filterSystemURLs && isSystemURL(url)) 76 return uri; 77 78 if (url == "about:blank") // avoid exceptions. 79 return uri; 80 81 if (uri && sameOrigin) 82 { 83 try 84 { 85 var prePath = uri.prePath; // returns the string before the path (such as "scheme://user:password@host:port"). 86 var shortURI = makeURI(prePath); 87 if (!shortURI) 88 return uri; 89 90 var host = shortURI.host; 91 if (host) 92 { 93 var crossDomain = host.split('.').slice(-2) 94 shortURI.host = crossDomain.join('.'); 95 return shortURI 96 } 97 } 98 catch (exc) 99 { 100 if (FBTrace.DBG_ERRORS) 101 FBTrace.sysout("activation.convertToURIKey returning full URI, activateSameOrigin FAILS for shortURI "+shortURI+" because: "+exc, exc); 102 return uri; 103 } 104 } 105 return uri; 106 }, 107 108 shouldCreateContext: function(browser, url, userCommands) // true if the Places annotation the URI "firebugged" 109 { 110 if (FBTrace.DBG_ACTIVATION) 111 FBTrace.sysout("shouldCreateContext allPagesActivation " + Firebug.allPagesActivation); 112 113 if (Firebug.allPagesActivation == "on") 114 return true; 115 116 if (Firebug.filterSystemURLs && isSystemURL(url)) // if about:blank gets thru, 1483 fails 117 return false; 118 119 if (userCommands) 120 return true; 121 122 if (browser.showFirebug && url.substr(0, 8) === "wyciwyg:") // document.open on a firebugged page 123 return true; 124 125 try 126 { 127 var uri = this.convertToURIKey(url, Firebug.activateSameOrigin); 128 if (!uri) 129 return false; 130 131 var hasAnnotation = this.getAnnotationService().pageHasAnnotation(uri); 132 133 if (FBTrace.DBG_ACTIVATION) 134 FBTrace.sysout("shouldCreateContext hasAnnotation "+hasAnnotation + 135 " for "+uri.spec+" in "+browser.contentWindow.location + 136 " using activateSameOrigin: "+Firebug.activateSameOrigin); 137 138 // Annotated so, return the value. 139 if (hasAnnotation) 140 return this.checkAnnotation(browser, uri); 141 142 if (browser.FirebugLink) // then TabWatcher found a connection 143 { 144 var dst = browser.FirebugLink.dst; 145 var dstURI = this.convertToURIKey(dst.spec, Firebug.activateSameOrigin); 146 if (FBTrace.DBG_ACTIVATION) 147 FBTrace.sysout("shouldCreateContext found FirebugLink pointing to " + 148 dstURI.spec, browser.FirebugLink); 149 150 if (dstURI && dstURI.equals(uri)) // and it matches us now 151 { 152 var srcURI = this.convertToURIKey(browser.FirebugLink.src.spec, Firebug.activateSameOrigin); 153 if (srcURI) 154 { 155 if (FBTrace.DBG_ACTIVATION) 156 FBTrace.sysout("shouldCreateContext found FirebugLink pointing from " + 157 srcURI.spec, browser.FirebugLink); 158 159 if (srcURI.schemeIs("file") || (dstURI.host == srcURI.host) ) // and it's on the same domain 160 { 161 hasAnnotation = this.getAnnotationService().pageHasAnnotation(srcURI); 162 if (hasAnnotation) // and the source page was annotated. 163 { 164 var srcShow = this.checkAnnotation(browser, srcURI); 165 if (srcShow) // and the source annotation said show it 166 this.watchBrowser(browser); // so we show dst as well. 167 return srcShow; 168 } 169 } 170 } 171 } 172 else 173 { 174 if (FBTrace.DBG_ACTIVATION) 175 FBTrace.sysout("shouldCreateContext FirebugLink does not match "+uri.spec, browser.FirebugLink); 176 } 177 } 178 else if (browser.contentWindow.opener) 179 { 180 var openerContext = TabWatcher.getContextByWindow(browser.contentWindow.opener); 181 182 if (FBTrace.DBG_ACTIVATION) 183 FBTrace.sysout("shouldCreateContext opener found, has "+ 184 (openerContext?"a ":"no ")+" context: "+ 185 browser.contentWindow.opener.location); 186 187 if (openerContext) 188 return true; // popup windows of Firebugged windows are Firebugged 189 } 190 191 return false; // don't createContext 192 } 193 catch (exc) 194 { 195 if (FBTrace.DBG_ERRORS) 196 FBTrace.sysout("pageHasAnnoation FAILS for url: "+url+" which gave uri "+(uri?uri.spec:"null"), exc); 197 } 198 }, 199 200 checkAnnotation: function(browser, uri) 201 { 202 var annotation = this.getAnnotationService().getPageAnnotation(uri); 203 204 if (FBTrace.DBG_ACTIVATION) 205 FBTrace.sysout("shouldCreateContext read back annotation "+annotation+" for uri "+uri.spec); 206 207 // then the user closed Firebug on this page last time 208 if ((Firebug.allPagesActivation != "on") && (annotation.indexOf("closed") > 0)) 209 return false; // annotated as 'closed', don't create 210 else 211 return true; // annotated, createContext 212 }, 213 214 shouldShowContext: function(context) 215 { 216 return this.shouldCreateContext(context.browser, context.getWindowLocation().toString()); 217 }, 218 219 watchBrowser: function(browser) // Firebug is opened in browser 220 { 221 var annotation = "firebugged.showFirebug"; 222 this.setPageAnnotation(browser.currentURI.spec, annotation); 223 }, 224 225 unwatchBrowser: function(browser, userCommands) // Firebug closes in browser 226 { 227 var uri = browser.currentURI.spec; 228 if (userCommands) // then mark to not open virally. 229 this.setPageAnnotation(uri, "firebugged.closed"); 230 else 231 this.removePageAnnotation(uri); // unmark this URI 232 }, 233 234 clearAnnotations: function() 235 { 236 this.getAnnotationService().clear(); 237 }, 238 239 setPageAnnotation: function(currentURI, annotation) 240 { 241 var uri = this.convertToURIKey(currentURI, Firebug.activateSameOrigin); 242 if (uri) 243 this.getAnnotationService().setPageAnnotation(uri, annotation); 244 245 if (Firebug.activateSameOrigin) 246 { 247 uri = this.convertToURIKey(currentURI, false); 248 if (uri) 249 this.getAnnotationService().setPageAnnotation(uri, annotation); 250 } 251 }, 252 253 removePageAnnotation: function(currentURI) 254 { 255 var uri = this.convertToURIKey(currentURI, Firebug.activateSameOrigin); 256 if (uri) 257 this.getAnnotationService().removePageAnnotation(uri); 258 259 if (Firebug.activateSameOrigin) 260 { 261 uri = this.convertToURIKey(currentURI, false); 262 if (uri) 263 this.getAnnotationService().removePageAnnotation(uri); 264 } 265 266 if (FBTrace.DBG_ACTIVATION) 267 FBTrace.sysout("Firebug.Activation.unwatchBrowser untagged "+uri.spec); 268 }, 269 270 iterateAnnotations: function(fn) // stops at the first fn(uri) that returns a true value 271 { 272 var annotations = this.getAnnotationService().getAnnotations(this.annotationName); 273 for (var uri in annotations) 274 { 275 var rc = fn(uri, annotations[uri]); 276 if (rc) 277 return rc; 278 } 279 }, 280 281 toggleAll: function(state) 282 { 283 if (FBTrace.DBG_ACTIVATION) 284 FBTrace.sysout("Firebug.toggleAll("+state+") with allPagesActivation: " + 285 Firebug.allPagesActivation); 286 287 if (state == "on") 288 { 289 if (Firebug.allPagesActivation == state) // then we were armed 290 Firebug.allPagesActivation = "none"; 291 else 292 this.allOn(); 293 294 // don't show Off button if we are always on 295 Firebug.chrome.disableOff(Firebug.allPagesActivation == "on"); 296 } 297 else 298 { 299 Firebug.allPagesActivation = "none"; 300 } 301 302 Firebug.setPref(Firebug.prefDomain, "allPagesActivation", Firebug.allPagesActivation); 303 this.updateAllPagesActivation(); 304 }, 305 306 updateOption: function(name, value) 307 { 308 if (name = "allPagesActivation") 309 this.updateAllPagesActivation(); 310 }, 311 312 updateAllPagesActivation: function() 313 { 314 var menu = $('menu_AllOn'); 315 if (menu) 316 menu.setAttribute("checked", (Firebug.allPagesActivation=="on")); 317 }, 318 319 allOn: function() 320 { 321 Firebug.allPagesActivation = "on"; // In future we always create contexts, 322 Firebug.toggleBar(true); // and we turn on for the current page 323 } 324 }); 325 326 // ************************************************************************************************ 327 328 Firebug.Activation.TabWatcherListener = 329 { 330 watchBrowser: function(browser) 331 { 332 Firebug.Activation.watchBrowser(browser); 333 }, 334 335 unwatchBrowser: function(browser, userCommands) 336 { 337 Firebug.Activation.unwatchBrowser(browser, userCommands); 338 } 339 }; 340 341 // ************************************************************************************************ 342 343 Firebug.registerModule(Firebug.Activation); 344 345 // ************************************************************************************************ 346 }}); 347