1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/firebug", 6 "firebug/chrome/firefox", 7 "firebug/lib/events", 8 "firebug/chrome/window", 9 "firebug/lib/search", 10 "firebug/lib/xml", 11 "firebug/lib/options", 12 "firebug/console/profiler", 13 "firebug/chrome/searchBox", 14 "firebug/console/consolePanel", 15 "firebug/console/commandEditor", 16 "firebug/console/functionMonitor", 17 "firebug/console/performanceTiming", 18 ], 19 function(Obj, Firebug, Firefox, Events, Win, Search, Xml, Options) { 20 21 // ********************************************************************************************* // 22 // Constants 23 24 const Cc = Components.classes; 25 const Ci = Components.interfaces; 26 27 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 28 29 var maxQueueRequests = 500; 30 31 // ********************************************************************************************* // 32 33 Firebug.ConsoleBase = 34 { 35 log: function(object, context, className, rep, noThrottle, sourceLink) 36 { 37 Events.dispatch(this.fbListeners,"log",[context, object, className, sourceLink]); 38 return this.logRow(appendObject, object, context, className, rep, sourceLink, noThrottle); 39 }, 40 41 logFormatted: function(objects, context, className, noThrottle, sourceLink) 42 { 43 Events.dispatch(this.fbListeners,"logFormatted",[context, objects, className, sourceLink]); 44 return this.logRow(appendFormatted, objects, context, className, null, sourceLink, 45 noThrottle); 46 }, 47 48 openGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush) 49 { 50 return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink, 51 noThrottle); 52 }, 53 54 openCollapsedGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush) 55 { 56 return this.logRow(appendCollapsedGroup, objects, context, className, rep, sourceLink, 57 noThrottle); 58 }, 59 60 closeGroup: function(context, noThrottle) 61 { 62 return this.logRow(appendCloseGroup, null, context, null, null, null, noThrottle, true); 63 }, 64 65 logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow) 66 { 67 if (!context) 68 context = Firebug.currentContext; 69 70 if (FBTrace.DBG_ERRORS && FBTrace.DBG_CONSOLE && !context) 71 FBTrace.sysout("Console.logRow has no context, skipping objects", objects); 72 73 if (!context) 74 return; 75 76 if (noThrottle || !context) 77 { 78 var panel = this.getPanel(context); 79 if (panel) 80 { 81 var row = panel.append(appender, objects, className, rep, sourceLink, noRow); 82 var container = panel.panelNode; 83 var template = Firebug.NetMonitor.NetLimit; 84 85 while (container.childNodes.length > maxQueueRequests + 1) 86 { 87 container.removeChild(container.firstChild.nextSibling); 88 panel.limit.limitInfo.totalCount++; 89 template.updateCounter(panel.limit); 90 } 91 Events.dispatch(this.fbListeners, "onLogRowCreated", [panel, row]); 92 return row; 93 } 94 } 95 else 96 { 97 if (!context.throttle) 98 { 99 FBTrace.sysout("console.logRow has not context.throttle! "); 100 return; 101 } 102 var args = [appender, objects, context, className, rep, sourceLink, true, noRow]; 103 context.throttle(this.logRow, this, args); 104 } 105 }, 106 107 appendFormatted: function(args, row, context) 108 { 109 if (!context) 110 context = Firebug.currentContext; 111 112 var panel = this.getPanel(context); 113 panel.appendFormatted(args, row); 114 }, 115 116 clear: function(context) 117 { 118 if (!context) 119 context = Firebug.currentContext; 120 121 if (context) 122 { 123 // There could be some logs waiting in the throttle queue, so 124 // clear asynchronously after the queue is flushed. 125 context.throttle(this.clearPanel, this, [context]); 126 127 // Also clear now 128 this.clearPanel(context); 129 130 // Let listeners react to console clearing 131 Events.dispatch(this.fbListeners, "onConsoleCleared", [context]); 132 } 133 }, 134 135 clearPanel: function(context) 136 { 137 Firebug.Errors.clear(context); 138 139 var panel = this.getPanel(context, true); 140 if (panel) 141 panel.clear(); 142 }, 143 144 // Override to direct output to your panel 145 getPanel: function(context, noCreate) 146 { 147 if (context) 148 return context.getPanel("console", noCreate); 149 }, 150 }; 151 152 // ********************************************************************************************* // 153 154 var ActivableConsole = Obj.extend(Firebug.ActivableModule, Firebug.ConsoleBase); 155 156 Firebug.Console = Obj.extend(ActivableConsole, 157 { 158 dispatchName: "console", 159 toolName: "console", 160 161 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 162 // extends Module 163 164 showPanel: function(browser, panel) 165 { 166 }, 167 168 // this is the only code that should call injector.attachIfNeeded 169 isReadyElsePreparing: function(context, win) 170 { 171 if (FBTrace.DBG_CONSOLE) 172 FBTrace.sysout("console.isReadyElsePreparing, win is " + 173 (win?"an argument: ":"null, context.window: ") + 174 (win?win.location:context.window.location)); 175 176 if (Xml.isXMLPrettyPrint(context, win)) 177 return false; 178 179 if (win) 180 { 181 return this.injector.attachIfNeeded(context, win); 182 } 183 else 184 { 185 var attached = true; 186 for (var i = 0; i < context.windows.length; i++) 187 attached = attached && this.injector.attachIfNeeded(context, context.windows[i]); 188 189 // already in the list above: 190 // attached = attached && this.injector.attachIfNeeded(context, context.window); 191 if (context.windows.indexOf(context.window) == -1) 192 FBTrace.sysout("isReadyElsePreparing: context.window not in context.windows"); 193 194 if (FBTrace.DBG_CONSOLE) 195 FBTrace.sysout("console.isReadyElsePreparing attached to " + 196 context.windows.length + " and returns "+attached); 197 198 return attached; 199 } 200 }, 201 202 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 203 // extends Module 204 205 initialize: function() 206 { 207 // Initialize log limit. 208 this.updateMaxLimit(); 209 210 Firebug.ActivableModule.initialize.apply(this, arguments); 211 212 Firebug.connection.addListener(this); 213 214 this.syncFilterButtons(Firebug.chrome); 215 }, 216 217 shutdown: function() 218 { 219 Firebug.connection.removeListener(this); 220 Firebug.ActivableModule.shutdown.apply(this, arguments); 221 }, 222 223 initContext: function(context, persistedState) 224 { 225 Firebug.ActivableModule.initContext.apply(this, arguments); 226 context.consoleReloadWarning = true; // mark as need to warn. 227 }, 228 229 loadedContext: function(context) 230 { 231 for (var url in context.sourceFileMap) 232 return; // if there are any sourceFiles, then do nothing 233 234 // Inject console handler if not injected yet. It's injected only in the case that 235 // the page has JS (and thus may call console) and Firebug has been activated after 236 // the first JS call (and thus we have not already injected). 237 if (!this.injector.isAttached(context, context.window) && !context.jsDebuggerCalledUs) 238 this.isReadyElsePreparing(context); 239 240 // else we saw no JS, so the reload warning is not needed. 241 this.clearReloadWarning(context); 242 }, 243 244 clearReloadWarning: function(context) // remove the warning about reloading. 245 { 246 if (context.consoleReloadWarning) 247 { 248 var panel = context.getPanel("console"); 249 if (panel) 250 { 251 panel.clearReloadWarning(); 252 delete context.consoleReloadWarning; 253 } 254 } 255 }, 256 257 togglePersist: function(context) 258 { 259 var panel = context.getPanel("console"); 260 panel.persistContent = panel.persistContent ? false : true; 261 262 Firebug.chrome.setGlobalAttribute("cmd_firebug_togglePersistConsole", "checked", 263 panel.persistContent); 264 }, 265 266 showContext: function(browser, context) 267 { 268 Firebug.chrome.setGlobalAttribute("cmd_firebug_clearConsole", "disabled", !context); 269 270 Firebug.ActivableModule.showContext.apply(this, arguments); 271 }, 272 273 destroyContext: function(context, persistedState) 274 { 275 Win.iterateWindows(context.window, function detachOneConsole(win) 276 { 277 // remove this first since it needs the console 278 Firebug.CommandLine.injector.detachCommandLine(context, win); 279 Firebug.Console.injector.detachConsole(context, win); 280 }); 281 }, 282 283 unwatchWindow: function(context, win) 284 { 285 Firebug.Console.injector.detachConsole(context, win); 286 }, 287 288 updateOption: function(name, value) 289 { 290 if (name == "console.logLimit") 291 this.updateMaxLimit(); 292 }, 293 294 updateMaxLimit: function() 295 { 296 var value = Options.get("console.logLimit"); 297 maxQueueRequests = value ? value : maxQueueRequests; 298 }, 299 300 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 301 // extend ActivableModule 302 303 onObserverChange: function(observer) 304 { 305 if (this.isAlwaysEnabled()) 306 { 307 // we inject the console during JS compiles so we need jsd 308 Firebug.Debugger.addObserver(this); 309 } 310 else 311 { 312 Firebug.Debugger.removeObserver(this); 313 } 314 315 if (!Firebug.getSuspended()) // then Firebug is in action 316 this.onResumeFirebug(); // and we need to test to see if we need to addObserver 317 else 318 this.onSuspendFirebug(); 319 }, 320 321 onSuspendFirebug: function() 322 { 323 if (FBTrace.DBG_CONSOLE) 324 FBTrace.sysout("console.onSuspendFirebug isAlwaysEnabled:" + 325 Firebug.Console.isAlwaysEnabled()); 326 327 if (Firebug.Errors.toggleWatchForErrors(false)) 328 { 329 this.setStatus(); 330 // Make sure possible errors coming from the page and displayed in the Firefox 331 // status bar are removed. 332 this.clear(); 333 } 334 }, 335 336 onResumeFirebug: function() 337 { 338 if (FBTrace.DBG_CONSOLE) 339 FBTrace.sysout("console.onResumeFirebug\n"); 340 341 var watchForErrors = Firebug.Console.isAlwaysEnabled() || Firebug.Console.hasObservers(); 342 if (Firebug.Errors.toggleWatchForErrors(watchForErrors)) 343 this.setStatus(); 344 }, 345 346 onToggleFilter: function(context, filterType) 347 { 348 if (!context) 349 context = Firebug.currentContext; 350 351 /* Preparation for multiple filters (see issue 4621) 352 if (filterType == "") 353 Firebug.consoleFilterTypes = ""; 354 else 355 { 356 var index = Firebug.consoleFilterTypes.indexOf(filterType); 357 if (index >= 0) 358 Firebug.consoleFilterTypes = Firebug.consoleFilterTypes.substr(0, index-1) + 359 Firebug.consoleFilterTypes.substr(index+filterType.length); 360 else 361 Firebug.consoleFilterTypes += " " + filterType; 362 } 363 */ 364 365 Firebug.consoleFilterTypes = filterType; 366 367 Options.set("consoleFilterTypes", Firebug.consoleFilterTypes); 368 369 var panel = this.getPanel(context, true); 370 if (panel) 371 { 372 panel.setFilter(Firebug.consoleFilterTypes); 373 Firebug.Search.update(context); 374 } 375 }, 376 377 syncFilterButtons: function(chrome) 378 { 379 if (Firebug.consoleFilterTypes == "") 380 { 381 var button = chrome.$("fbConsoleFilter-all"); 382 button.checked = true; 383 } 384 else 385 { 386 var filterTypes = Firebug.consoleFilterTypes.split(" "); 387 for (var type = 0; type < filterTypes.length; type++) 388 { 389 var button = chrome.$("fbConsoleFilter-" + filterTypes[type]); 390 button.checked = true; 391 } 392 } 393 }, 394 395 setStatus: function() 396 { 397 var fbStatus = Firefox.getElementById("firebugStatus"); 398 if (fbStatus) 399 { 400 if (Firebug.Errors.watchForErrors) 401 fbStatus.setAttribute("console", "on"); 402 else 403 fbStatus.removeAttribute("console"); 404 } 405 else 406 { 407 if (FBTrace.DBG_ERRORS) 408 FBTrace.sysout("console.setStatus ERROR no firebugStatus element"); 409 } 410 }, 411 412 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 413 // BTI 414 415 /** 416 * A previously enabled tool becomes active and sends us an event. 417 */ 418 onActivateTool: function(toolname, active) 419 { 420 if (FBTrace.DBG_ACTIVATION) 421 FBTrace.sysout("Console.onActivateTool "+toolname+" = "+active); 422 423 // Console depends on script to get injected (for now) 424 if (toolname === "script") 425 { 426 if (this.isAlwaysEnabled()) 427 { 428 //this.asTool.setActive(active); // then track the activation of the debugger; 429 } 430 } 431 }, 432 433 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 434 435 logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow) 436 { 437 if (!context) 438 context = Firebug.currentContext; 439 440 if (FBTrace.DBG_WINDOWS && !context) 441 FBTrace.sysout("Console.logRow: no context \n"); 442 443 if (this.isAlwaysEnabled()) 444 return Firebug.ConsoleBase.logRow.apply(this, arguments); 445 }, 446 447 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 448 449 getDefaultReturnValue: function(win) 450 { 451 var defaultValue = "_firebugIgnore"; 452 var console = win.wrappedJSObject.console; 453 if (!console) 454 return defaultValue; 455 456 if (Obj.isNonNativeGetter(console, "__returnValue__")) 457 return defaultValue; 458 459 var returnValue = console.__returnValue__; 460 if (returnValue) 461 return returnValue; 462 463 return defaultValue; 464 } 465 }); 466 467 // ********************************************************************************************* // 468 469 Firebug.ConsoleListener = 470 { 471 log: function(context, object, className, sourceLink) 472 { 473 }, 474 475 logFormatted: function(context, objects, className, sourceLink) 476 { 477 } 478 }; 479 480 // ********************************************************************************************* // 481 482 var appendObject = Firebug.ConsolePanel.prototype.appendObject; 483 var appendFormatted = Firebug.ConsolePanel.prototype.appendFormatted; 484 var appendOpenGroup = Firebug.ConsolePanel.prototype.appendOpenGroup; 485 var appendCollapsedGroup = Firebug.ConsolePanel.prototype.appendCollapsedGroup; 486 var appendCloseGroup = Firebug.ConsolePanel.prototype.appendCloseGroup; 487 488 // ********************************************************************************************* // 489 // Registration 490 491 Firebug.registerActivableModule(Firebug.Console); 492 493 return Firebug.Console; 494 495 // ********************************************************************************************* // 496 }); 497