1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/firebug", 6 "firebug/lib/domplate", 7 "firebug/lib/locale", 8 "firebug/lib/events", 9 "firebug/lib/url", 10 "firebug/lib/css", 11 "firebug/lib/dom", 12 "firebug/lib/array", 13 "firebug/net/netUtils", 14 ], 15 function(Obj, Firebug, Domplate, Locale, Events, Url, Css, Dom, Arr, NetUtils) { 16 17 // ********************************************************************************************* // 18 // Constants 19 20 const Cc = Components.classes; 21 const Ci = Components.interfaces; 22 const Cr = Components.results; 23 24 var panelName = "net"; 25 26 // ********************************************************************************************* // 27 // Breakpoints 28 29 function NetBreakpointGroup() 30 { 31 this.breakpoints = []; 32 } 33 34 NetBreakpointGroup.prototype = Obj.extend(new Firebug.Breakpoint.BreakpointGroup(), 35 { 36 name: "netBreakpoints", 37 title: Locale.$STR("net.label.XHR Breakpoints"), 38 39 addBreakpoint: function(href) 40 { 41 this.breakpoints.push(new Breakpoint(href)); 42 }, 43 44 removeBreakpoint: function(href) 45 { 46 var bp = this.findBreakpoint(href); 47 Arr.remove(this.breakpoints, bp); 48 }, 49 50 matchBreakpoint: function(bp, args) 51 { 52 var href = args[0]; 53 return bp.href == href; 54 } 55 }); 56 57 // ********************************************************************************************* // 58 59 function Breakpoint(href) 60 { 61 this.href = href; 62 this.checked = true; 63 this.condition = ""; 64 this.onEvaluateFails = Obj.bind(this.onEvaluateFails, this); 65 this.onEvaluateSucceeds = Obj.bind(this.onEvaluateSucceeds, this); 66 } 67 68 Breakpoint.prototype = 69 { 70 evaluateCondition: function(context, file) 71 { 72 try 73 { 74 var scope = {}; 75 76 var params = file.urlParams; 77 for (var i=0; params && i<params.length; i++) 78 { 79 var param = params[i]; 80 scope[param.name] = param.value; 81 } 82 83 scope["$postBody"] = NetUtils.getPostText(file, context); 84 85 // The properties of scope are all strings; we pass them in then 86 // unpack them using 'with'. The function is called immediately. 87 var expr = "(function (){var scope = " + JSON.stringify(scope) + 88 "; with (scope) { return " + this.condition + ";}})();" 89 90 // The callbacks will set this if the condition is true or if the eval faults. 91 delete context.breakingCause; 92 93 var rc = Firebug.CommandLine.evaluate(expr, context, null, context.window, 94 this.onEvaluateSucceeds, this.onEvaluateFails ); 95 96 if (FBTrace.DBG_NET) 97 FBTrace.sysout("net.evaluateCondition; rc " + rc, {expr: expr,scope: scope, 98 json: JSON.stringify(scope)}); 99 100 return !!context.breakingCause; 101 } 102 catch (err) 103 { 104 if (FBTrace.DBG_NET) 105 FBTrace.sysout("net.evaluateCondition; EXCEPTION "+err, err); 106 } 107 108 return false; 109 }, 110 111 onEvaluateSucceeds: function(result, context) 112 { 113 // Don't break if the result is false. 114 if (!result) 115 return; 116 117 context.breakingCause = { 118 title: Locale.$STR("net.Break On XHR"), 119 message: this.condition 120 }; 121 }, 122 123 onEvaluateFails: function(result, context) 124 { 125 // Break if there is an error when evaluating the condition (to display the error). 126 context.breakingCause = { 127 title: Locale.$STR("net.Break On XHR"), 128 message: "Breakpoint condition evaluation fails ", 129 prevValue: this.condition, 130 newValue:result 131 }; 132 }, 133 } 134 135 // ********************************************************************************************* // 136 // Breakpoint UI 137 138 with (Domplate) { 139 var BreakpointRep = domplate(Firebug.Rep, 140 { 141 inspectable: false, 142 143 tag: 144 DIV({"class": "breakpointRow focusRow", $disabled: "$bp|isDisabled", _repObject: "$bp", 145 role: "option", "aria-checked": "$bp.checked"}, 146 DIV({"class": "breakpointBlockHead"}, 147 INPUT({"class": "breakpointCheckbox", type: "checkbox", 148 _checked: "$bp.checked", tabindex: "-1", onclick: "$onEnable"}), 149 SPAN({"class": "breakpointName", title: "$bp|getTitle"}, "$bp|getName"), 150 IMG({"class": "closeButton", src: "blank.gif", onclick: "$onRemove"}) 151 ), 152 DIV({"class": "breakpointCondition"}, 153 SPAN("$bp.condition") 154 ) 155 ), 156 157 getTitle: function(bp) 158 { 159 return bp.href; 160 }, 161 162 getName: function(bp) 163 { 164 return Url.getFileName(bp.href); 165 }, 166 167 isDisabled: function(bp) 168 { 169 return !bp.checked; 170 }, 171 172 onRemove: function(event) 173 { 174 Events.cancelEvent(event); 175 176 if (!Css.hasClass(event.target, "closeButton")) 177 return; 178 179 var bpPanel = Firebug.getElementPanel(event.target); 180 var context = bpPanel.context; 181 182 // Remove from list of breakpoints. 183 var row = Dom.getAncestorByClass(event.target, "breakpointRow"); 184 var bp = row.repObject; 185 context.netProgress.breakpoints.removeBreakpoint(bp.href); 186 187 bpPanel.refresh(); 188 189 var panel = context.getPanel(panelName, true); 190 if (!panel) 191 return; 192 193 panel.enumerateRequests(function(file) 194 { 195 if (file.getFileURL() == bp.href) 196 { 197 file.row.removeAttribute("breakpoint"); 198 file.row.removeAttribute("disabledBreakpoint"); 199 } 200 }) 201 }, 202 203 onEnable: function(event) 204 { 205 var checkBox = event.target; 206 var bpRow = Dom.getAncestorByClass(checkBox, "breakpointRow"); 207 208 if (checkBox.checked) 209 { 210 Css.removeClass(bpRow, "disabled"); 211 bpRow.setAttribute("aria-checked", "true"); 212 } 213 else 214 { 215 Css.setClass(bpRow, "disabled"); 216 bpRow.setAttribute("aria-checked", "false"); 217 } 218 219 var bp = bpRow.repObject; 220 bp.checked = checkBox.checked; 221 222 var bpPanel = Firebug.getElementPanel(event.target); 223 var context = bpPanel.context; 224 225 var panel = context.getPanel(panelName, true); 226 if (!panel) 227 return; 228 229 panel.enumerateRequests(function(file) 230 { 231 if (file.getFileURL() == bp.href) 232 file.row.setAttribute("disabledBreakpoint", bp.checked ? "false" : "true"); 233 }); 234 }, 235 236 supportsObject: function(object, type) 237 { 238 return object instanceof Breakpoint; 239 } 240 })}; 241 242 // ********************************************************************************************* // 243 // Registration 244 245 Firebug.registerRep(BreakpointRep); 246 247 return { 248 NetBreakpointGroup: NetBreakpointGroup 249 }; 250 251 // ********************************************************************************************* // 252 }); 253