1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/firebug", 6 "firebug/chrome/reps", 7 "firebug/lib/locale", 8 "firebug/lib/events", 9 "firebug/lib/url", 10 "firebug/js/stackFrame", 11 "firebug/chrome/window", 12 "firebug/console/console", 13 "firebug/lib/array", 14 "firebug/lib/dom", 15 "firebug/console/consoleExposed", 16 "firebug/console/errors", 17 ], 18 function(Obj, Firebug, FirebugReps, Locale, Events, Url, StackFrame, Win, Console, Arr, Dom) { 19 20 // ********************************************************************************************* // 21 // Constants 22 23 const Cc = Components.classes; 24 const Ci = Components.interfaces; 25 const Cu = Components.utils; 26 27 // ********************************************************************************************* // 28 // Console Injector 29 30 Firebug.Console.injector = 31 { 32 isAttached: function(context, win) 33 { 34 var handler = this.getConsoleHandler(context, win); 35 36 if (FBTrace.DBG_CONSOLE) 37 FBTrace.sysout("Console.isAttached "+handler+" in context "+context.getName()+ 38 " and win "+Win.safeGetWindowLocation(win), handler); 39 40 return handler; 41 }, 42 43 attachIfNeeded: function(context, win) 44 { 45 if (this.isAttached(context, win)) 46 return true; 47 48 if (FBTrace.DBG_CONSOLE) 49 FBTrace.sysout("Console.attachIfNeeded found isAttached false " + 50 Win.safeGetWindowLocation(win)); 51 52 this.attachConsoleInjector(context, win); 53 this.addConsoleListener(context, win); 54 55 Firebug.Console.clearReloadWarning(context); 56 57 var attached = this.isAttached(context, win); 58 if (attached) 59 Events.dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]); 60 61 return attached; 62 }, 63 64 attachConsoleInjector: function(context, win) 65 { 66 // Get the 'console' object (this comes from chrome scope). 67 var console = Firebug.ConsoleExposed.createFirebugConsole(context, win); 68 69 // Do not expose the chrome object as is but, rather do a wrapper, see below. 70 //win.wrappedJSObject.console = console; 71 //return; 72 73 // Construct a script string that defines a function. This function returns 74 // an object that wraps every 'console' method. This function will be evaluated 75 // in a window content sandbox and return a wrapper for the 'console' object. 76 // Note that this wrapper appends an additional frame that shouldn't be displayed 77 // to the user. 78 var expr = "(function(x) { return {\n"; 79 for (var p in console) 80 { 81 var func = console[p]; 82 if (typeof(func) == "function") 83 { 84 expr += p + ": function() { return Function.apply.call(x." + p + 85 ", x, arguments); },\n"; 86 } 87 } 88 expr += "};})"; 89 90 // Evaluate the function in the window sandbox/scope and execute. The return value 91 // is a wrapper for the 'console' object. 92 var sandbox = Cu.Sandbox(win); 93 var getConsoleWrapper = Cu.evalInSandbox(expr, sandbox); 94 win.wrappedJSObject.console = getConsoleWrapper(console); 95 96 if (FBTrace.DBG_CONSOLE) 97 FBTrace.sysout("console.attachConsoleInjector; Firebug console attached to: " + 98 context.getName()); 99 }, 100 101 addConsoleListener: function(context, win) 102 { 103 if (!win) 104 win = context.window; 105 106 var handler = this.getConsoleHandler(context, win); 107 if (handler) 108 return; 109 110 var handler = createConsoleHandler(context, win); 111 112 // Initialize Firebug token 113 Dom.setMappedData(win.document, "firebug-Token", handler.token); 114 115 this.setConsoleHandler(context, win, handler); 116 117 return true; 118 }, 119 120 getConsoleHandler: function(context, win) 121 { 122 if (!win.document) 123 { 124 if (FBTrace.DBG_ERRORS) 125 { 126 FBTrace.sysout("console.getConsoleHandler; NO DOCUMENT", 127 {win:win, context:context}); 128 } 129 return null; 130 } 131 132 var attachedToken = Dom.getMappedData(win.document, "firebug-Token"); 133 if (context.activeConsoleHandlers) 134 { 135 for(var i = 0; i < context.activeConsoleHandlers.length; i++) 136 { 137 if (context.activeConsoleHandlers[i].token === attachedToken) 138 return context.activeConsoleHandlers[i]; 139 } 140 } 141 }, 142 143 removeConsoleHandler: function(context, win) 144 { 145 var handler = this.getConsoleHandler(context, win); 146 if (handler) 147 { 148 handler.detach(); 149 Arr.remove(context.activeConsoleHandlers, handler); 150 151 if (FBTrace.DBG_CONSOLE) 152 FBTrace.sysout("consoleInjector.removeConsoleHandler; token " + handler.token + 153 " and attached handler("+handler.handler_name+") to _firebugConsole in : "+ 154 Win.safeGetWindowLocation(win)); 155 } 156 }, 157 158 setConsoleHandler: function(context, win, handler) 159 { 160 if (!context.activeConsoleHandlers) 161 context.activeConsoleHandlers = []; 162 163 context.activeConsoleHandlers.push(handler); 164 165 if (FBTrace.DBG_CONSOLE) 166 FBTrace.sysout("consoleInjector addConsoleListener set token "+handler.token+ 167 " and attached handler("+handler.handler_name+") to _firebugConsole in : "+ 168 Win.safeGetWindowLocation(win)); 169 }, 170 171 detachConsole: function(context, win) 172 { 173 if (!win) 174 win = context.window; 175 176 this.removeConsoleHandler(context, win); 177 }, 178 } 179 180 // ********************************************************************************************* // 181 182 var total_handlers = 0; 183 function createConsoleHandler(context, win) 184 { 185 var handler = {}; 186 handler.console = Firebug.ConsoleExposed.createFirebugConsole(context, win); 187 188 // xxxHonza: these two functions should be automatically overridden, check this out 189 // can be probably removed (evaluated and evaluateError). 190 console.evaluated = function(result, context) 191 { 192 if (FBTrace.DBG_CONSOLE) 193 { 194 FBTrace.sysout("consoleInjector.FirebugConsoleHandler evaluated default called", 195 result); 196 } 197 198 Firebug.Console.log(result, context); 199 }; 200 201 console.evaluateError = function(result, context) 202 { 203 Firebug.Console.log(result, context, "errorMessage"); 204 }; 205 206 handler.detach = function() 207 { 208 Events.removeEventListener(win.document, 'firebugAppendConsole', this.boundHandler, true); 209 210 if (FBTrace.DBG_CONSOLE) 211 FBTrace.sysout("consoleInjector FirebugConsoleHandler removeEventListener "+ 212 this.handler_name); 213 }; 214 215 handler.handler_name = ++total_handlers; 216 handler.token = Math.random(); 217 218 handler.handleEvent = function(event) 219 { 220 if (FBTrace.DBG_CONSOLE) 221 FBTrace.sysout("FirebugConsoleHandler(" + this.handler_name + ") " + 222 Dom.getMappedData(win.document, "firebug-methodName") + ", event", event); 223 224 if (!Firebug.CommandLine.CommandHandler.handle(event, this.console, win)) 225 { 226 if (FBTrace.DBG_CONSOLE) 227 FBTrace.sysout("FirebugConsoleHandler", this); 228 229 var methodName = Dom.getMappedData(win.document, "firebug-methodName"); 230 Firebug.Console.log(Locale.$STRF("console.MethodNotSupported", [methodName])); 231 } 232 }; 233 234 handler.setEvaluatedCallback = function( fnOfResult ) 235 { 236 this.console.evaluated = fnOfResult; 237 }; 238 239 handler.setEvaluateErrorCallback = function( fnOfResultAndContext ) 240 { 241 this.console.evaluateError = fnOfResultAndContext; 242 }; 243 244 handler.win = win; 245 handler.context = context; 246 247 // When raised on our injected element, callback to Firebug and append to console 248 handler.boundHandler = Obj.bind(handler.handleEvent, handler); 249 250 // capturing 251 Events.addEventListener(win.document, "firebugAppendConsole", handler.boundHandler, true); 252 253 if (FBTrace.DBG_CONSOLE) 254 FBTrace.sysout("consoleInjector FirebugConsoleHandler addEventListener " + 255 handler.handler_name); 256 257 return handler; 258 } 259 260 // ********************************************************************************************* // 261 // Registration 262 263 return Firebug.Console.injector; 264 265 // ********************************************************************************************* // 266 }); 267