1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/gcli/commands/calllog.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,213 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const { Cc, Ci, Cu } = require("chrome"); 1.11 +const TargetFactory = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.TargetFactory; 1.12 +const gcli = require("gcli/index"); 1.13 + 1.14 +loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm"); 1.15 + 1.16 +loader.lazyGetter(this, "Debugger", () => { 1.17 + let global = Cu.getGlobalForObject({}); 1.18 + let JsDebugger = Cu.import("resource://gre/modules/jsdebugger.jsm", {}); 1.19 + JsDebugger.addDebuggerToGlobal(global); 1.20 + return global.Debugger; 1.21 +}); 1.22 + 1.23 +let debuggers = []; 1.24 +let chromeDebuggers = []; 1.25 +let sandboxes = []; 1.26 + 1.27 +exports.items = [ 1.28 + { 1.29 + name: "calllog", 1.30 + description: gcli.lookup("calllogDesc") 1.31 + }, 1.32 + { 1.33 + name: "calllog start", 1.34 + description: gcli.lookup("calllogStartDesc"), 1.35 + 1.36 + exec: function(args, context) { 1.37 + let contentWindow = context.environment.window; 1.38 + 1.39 + let dbg = new Debugger(contentWindow); 1.40 + dbg.onEnterFrame = function(frame) { 1.41 + // BUG 773652 - Make the output from the GCLI calllog command nicer 1.42 + contentWindow.console.log("Method call: " + this.callDescription(frame)); 1.43 + }.bind(this); 1.44 + 1.45 + debuggers.push(dbg); 1.46 + 1.47 + let gBrowser = context.environment.chromeDocument.defaultView.gBrowser; 1.48 + let target = TargetFactory.forTab(gBrowser.selectedTab); 1.49 + gDevTools.showToolbox(target, "webconsole"); 1.50 + 1.51 + return gcli.lookup("calllogStartReply"); 1.52 + }, 1.53 + 1.54 + callDescription: function(frame) { 1.55 + let name = "<anonymous>"; 1.56 + if (frame.callee.name) { 1.57 + name = frame.callee.name; 1.58 + } 1.59 + else { 1.60 + let desc = frame.callee.getOwnPropertyDescriptor("displayName"); 1.61 + if (desc && desc.value && typeof desc.value == "string") { 1.62 + name = desc.value; 1.63 + } 1.64 + } 1.65 + 1.66 + let args = frame.arguments.map(this.valueToString).join(", "); 1.67 + return name + "(" + args + ")"; 1.68 + }, 1.69 + 1.70 + valueToString: function(value) { 1.71 + if (typeof value !== "object" || value === null) { 1.72 + return uneval(value); 1.73 + } 1.74 + return "[object " + value.class + "]"; 1.75 + } 1.76 + }, 1.77 + { 1.78 + name: "calllog stop", 1.79 + description: gcli.lookup("calllogStopDesc"), 1.80 + 1.81 + exec: function(args, context) { 1.82 + let numDebuggers = debuggers.length; 1.83 + if (numDebuggers == 0) { 1.84 + return gcli.lookup("calllogStopNoLogging"); 1.85 + } 1.86 + 1.87 + for (let dbg of debuggers) { 1.88 + dbg.onEnterFrame = undefined; 1.89 + } 1.90 + debuggers = []; 1.91 + 1.92 + return gcli.lookupFormat("calllogStopReply", [ numDebuggers ]); 1.93 + } 1.94 + }, 1.95 + { 1.96 + name: "calllog chromestart", 1.97 + description: gcli.lookup("calllogChromeStartDesc"), 1.98 + get hidden() gcli.hiddenByChromePref(), 1.99 + params: [ 1.100 + { 1.101 + name: "sourceType", 1.102 + type: { 1.103 + name: "selection", 1.104 + data: ["content-variable", "chrome-variable", "jsm", "javascript"] 1.105 + } 1.106 + }, 1.107 + { 1.108 + name: "source", 1.109 + type: "string", 1.110 + description: gcli.lookup("calllogChromeSourceTypeDesc"), 1.111 + manual: gcli.lookup("calllogChromeSourceTypeManual"), 1.112 + } 1.113 + ], 1.114 + exec: function(args, context) { 1.115 + let globalObj; 1.116 + let contentWindow = context.environment.window; 1.117 + 1.118 + if (args.sourceType == "jsm") { 1.119 + try { 1.120 + globalObj = Cu.import(args.source); 1.121 + } 1.122 + catch (e) { 1.123 + return gcli.lookup("callLogChromeInvalidJSM"); 1.124 + } 1.125 + } else if (args.sourceType == "content-variable") { 1.126 + if (args.source in contentWindow) { 1.127 + globalObj = Cu.getGlobalForObject(contentWindow[args.source]); 1.128 + } else { 1.129 + throw new Error(gcli.lookup("callLogChromeVarNotFoundContent")); 1.130 + } 1.131 + } else if (args.sourceType == "chrome-variable") { 1.132 + let chromeWin = context.environment.chromeDocument.defaultView; 1.133 + if (args.source in chromeWin) { 1.134 + globalObj = Cu.getGlobalForObject(chromeWin[args.source]); 1.135 + } else { 1.136 + return gcli.lookup("callLogChromeVarNotFoundChrome"); 1.137 + } 1.138 + } else { 1.139 + let chromeWin = context.environment.chromeDocument.defaultView; 1.140 + let sandbox = new Cu.Sandbox(chromeWin, 1.141 + { 1.142 + sandboxPrototype: chromeWin, 1.143 + wantXrays: false, 1.144 + sandboxName: "gcli-cmd-calllog-chrome" 1.145 + }); 1.146 + let returnVal; 1.147 + try { 1.148 + returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5"); 1.149 + sandboxes.push(sandbox); 1.150 + } catch(e) { 1.151 + // We need to save the message before cleaning up else e contains a dead 1.152 + // object. 1.153 + let msg = gcli.lookup("callLogChromeEvalException") + ": " + e; 1.154 + Cu.nukeSandbox(sandbox); 1.155 + return msg; 1.156 + } 1.157 + 1.158 + if (typeof returnVal == "undefined") { 1.159 + return gcli.lookup("callLogChromeEvalNeedsObject"); 1.160 + } 1.161 + 1.162 + globalObj = Cu.getGlobalForObject(returnVal); 1.163 + } 1.164 + 1.165 + let dbg = new Debugger(globalObj); 1.166 + chromeDebuggers.push(dbg); 1.167 + 1.168 + dbg.onEnterFrame = function(frame) { 1.169 + // BUG 773652 - Make the output from the GCLI calllog command nicer 1.170 + contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") + 1.171 + ": " + this.callDescription(frame)); 1.172 + }.bind(this); 1.173 + 1.174 + let gBrowser = context.environment.chromeDocument.defaultView.gBrowser; 1.175 + let target = TargetFactory.forTab(gBrowser.selectedTab); 1.176 + gDevTools.showToolbox(target, "webconsole"); 1.177 + 1.178 + return gcli.lookup("calllogChromeStartReply"); 1.179 + }, 1.180 + 1.181 + valueToString: function(value) { 1.182 + if (typeof value !== "object" || value === null) 1.183 + return uneval(value); 1.184 + return "[object " + value.class + "]"; 1.185 + }, 1.186 + 1.187 + callDescription: function(frame) { 1.188 + let name = frame.callee.name || gcli.lookup("callLogChromeAnonFunction"); 1.189 + let args = frame.arguments.map(this.valueToString).join(", "); 1.190 + return name + "(" + args + ")"; 1.191 + } 1.192 + }, 1.193 + { 1.194 + name: "calllog chromestop", 1.195 + description: gcli.lookup("calllogChromeStopDesc"), 1.196 + get hidden() gcli.hiddenByChromePref(), 1.197 + exec: function(args, context) { 1.198 + let numDebuggers = chromeDebuggers.length; 1.199 + if (numDebuggers == 0) { 1.200 + return gcli.lookup("calllogChromeStopNoLogging"); 1.201 + } 1.202 + 1.203 + for (let dbg of chromeDebuggers) { 1.204 + dbg.onEnterFrame = undefined; 1.205 + dbg.enabled = false; 1.206 + } 1.207 + for (let sandbox of sandboxes) { 1.208 + Cu.nukeSandbox(sandbox); 1.209 + } 1.210 + chromeDebuggers = []; 1.211 + sandboxes = []; 1.212 + 1.213 + return gcli.lookupFormat("calllogChromeStopReply", [ numDebuggers ]); 1.214 + } 1.215 + } 1.216 +];