Skip to content

Commit 866b901

Browse files
committed
#20 Fix compatibility with Fx38
1 parent 26f0ad8 commit 866b901

File tree

3 files changed

+106
-23
lines changed

3 files changed

+106
-23
lines changed

lib/data-tooltip.js

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const { Cu, Ci } = require("chrome");
1414
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
1515
const { Widgets } = devtools.require("devtools/webconsole/console-output");
1616
const { VariablesView } = Cu.import("resource:///modules/devtools/VariablesView.jsm", {});
17+
const { makeInfallible } = devtools["require"]("devtools/toolkit/DevToolsUtils.js");
18+
const { Tooltip } = devtools["require"]("devtools/shared/widgets/Tooltip");
19+
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
1720

1821
// Platform
1922
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
@@ -22,6 +25,15 @@ const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
2225
const { Trace, TraceError } = require("firebug.sdk/lib/core/trace.js").get(module.id);
2326
const { Content } = require("firebug.sdk/lib/core/content.js");
2427

28+
// Constants
29+
const XHTML_NS = "http://www.w3.org/1999/xhtml";
30+
31+
/**
32+
* This object implements a tooltip used in the MarkupView that
33+
* displays jQuery data (JSON) as an expandable tree.
34+
* Content of the tooltip is rendered using an iframe. Content
35+
* of the iframe is implemented by markup-tooltip.html
36+
*/
2537
function DataTooltip(options) {
2638
this.markup = options.markup;
2739
this.target = options.target;
@@ -32,16 +44,10 @@ function DataTooltip(options) {
3244
this.onTooltipLoaded = this.onTooltipLoaded.bind(this);
3345
}
3446

35-
/**
36-
* This object implements a tooltip used in the MarkupView that
37-
* displays jQuery data (JSON) as an expandable tree.
38-
* Content of the tooltip is rendered using an iframe. Content
39-
* of the iframe is implemented by markup-tooltip.html
40-
*/
4147
DataTooltip.prototype =
4248
/** @lends DataTooltip */
4349
{
44-
show: function() {
50+
show: makeInfallible(function() {
4551
this.tooltip.hide(this.target);
4652

4753
let dimensions = {
@@ -59,7 +65,7 @@ DataTooltip.prototype =
5965
});
6066

6167
this.tooltip.show(this.target);
62-
},
68+
}),
6369

6470
// Tooltip Event Handlers
6571

@@ -121,5 +127,37 @@ DataTooltip.prototype =
121127
},
122128
}
123129

130+
// Patch Tooltip
131+
// The Tooltip widget has been introduced in Fx40
132+
// https://bugzilla.mozilla.org/show_bug.cgi?id=980006
133+
if (!Tooltip.prototype.setIFrameContent) {
134+
Tooltip.prototype.setIFrameContent = makeInfallible(function({width, height}, url) {
135+
let def = promise.defer();
136+
137+
// Create an iframe
138+
let iframe = this.doc.createElementNS(XHTML_NS, "iframe");
139+
iframe.setAttribute("transparent", true);
140+
iframe.setAttribute("width", width);
141+
iframe.setAttribute("height", height);
142+
iframe.setAttribute("flex", "1");
143+
iframe.setAttribute("class", "devtools-tooltip-iframe");
144+
145+
// Wait for the load to initialize the widget
146+
function onLoad() {
147+
iframe.removeEventListener("load", onLoad, true);
148+
def.resolve(iframe);
149+
}
150+
iframe.addEventListener("load", onLoad, true);
151+
152+
// load the document from url into the iframe
153+
iframe.setAttribute("src", url);
154+
155+
// Put the iframe in the tooltip
156+
this.content = iframe;
157+
158+
return def.promise;
159+
});
160+
}
161+
124162
// Exports from this module
125163
exports.DataTooltip = DataTooltip;

lib/firequery-actor.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server
1616
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
1717
const protocol = devtools["require"]("devtools/server/protocol");
1818
const { method, RetVal, ActorClass, Actor, Arg, types } = protocol;
19-
const Events = require("sdk/event/core");
19+
const Events = devtools["require"]("sdk/event/core");
2020
const { makeInfallible } = devtools["require"]("devtools/toolkit/DevToolsUtils.js");
2121
const DevToolsUtils = devtools["require"]("devtools/toolkit/DevToolsUtils");
2222
const { NodeActor } = devtools["require"]("devtools/server/actors/inspector");
@@ -184,7 +184,14 @@ var FireQueryActor = ActorClass(
184184
length: length,
185185
};
186186

187-
if (actor.threadActor._gripDepth > 1) {
187+
// Introduced in Fx42
188+
let hooks = actor.hooks;
189+
if (hooks && hooks.getGripDepth() > 1) {
190+
return true;
191+
}
192+
193+
let threadActor = this.parent.threadActor;
194+
if (threadActor && threadActor._gripDepth > 1) {
188195
return true;
189196
}
190197

@@ -205,14 +212,14 @@ var FireQueryActor = ActorClass(
205212
let value = Cu.unwaiveXrays(desc.value);
206213
value = makeDebuggeeValueIfNeeded(actor.obj, value);
207214

208-
let grip = actor.threadActor.createValueGrip(value);
215+
let grip = this.createValueGrip(actor, value);
209216
preview.items.push(grip);
210217

211218
let data = hasJQueryData(desc.value);
212219
if (data) {
213220
data = Cu.unwaiveXrays(data);
214221
data = makeDebuggeeValueIfNeeded(actor.obj, data);
215-
grip.preview.jQueryData = actor.threadActor.createValueGrip(data);
222+
grip.preview.jQueryData = this.createValueGrip(actor, data);
216223

217224
// xxxHonza: generate preview for the data?
218225
}
@@ -230,6 +237,15 @@ var FireQueryActor = ActorClass(
230237
return true;
231238
}),
232239

240+
createValueGrip: function(actor, value) {
241+
// Introduced in Fx42
242+
if (actor.hooks) {
243+
return actor.hooks.createValueGrip(value);
244+
}
245+
246+
return actor.threadActor.createValueGrip(value);
247+
},
248+
233249
/**
234250
* Set UI stylesheet for anonymous content (sent from the client).
235251
*/
@@ -248,7 +264,6 @@ var FireQueryActor = ActorClass(
248264
}, true);
249265

250266
win.addEventListener("firequery-event", event => {
251-
let threadActor = this.parent.threadActor;
252267
let walkerActor = this.conn.getActor(this.walkerActorID);
253268
if (!walkerActor) {
254269
return;
@@ -367,7 +382,7 @@ function hasJQueryData(object) {
367382

368383
// Patching NodeActor (add custom info into actor form)
369384
// Bug 1036949 - New API: MarkupView customization
370-
// xxxHonza: Can be removed as soon as Firefox 41 is the
385+
// xxxHonza: Can be removed as soon as Fx42 is the
371386
// minimum required version.
372387
let originalForm = NodeActor.prototype.form;
373388
NodeActor.prototype.form = function(detail) {
@@ -379,7 +394,6 @@ NodeActor.prototype.form = function(detail) {
379394
}
380395

381396
// form.setFormProperty has been introduced in Bug 1036949
382-
// (released in Firefox 41)
383397
// The content of the following if block is taken from the
384398
// patch attached to Bug 1036949
385399
if (!form.setFormProperty) {

lib/inspector-overlay.js

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const { Class } = require("sdk/core/heritage");
1313
const { loadSheet, removeSheet } = require("sdk/stylesheet/utils");
1414
const { on, off } = require("sdk/event/core");
1515

16+
// DevTools
17+
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
18+
const { MarkupView } = devtools["require"]("devtools/markupview/markup-view");
19+
1620
// Firebug SDK
1721
const { Trace, TraceError } = require("firebug.sdk/lib/core/trace.js").get(module.id);
1822
const { PanelOverlay } = require("firebug.sdk/lib/panel-overlay.js");
@@ -187,14 +191,17 @@ const InspectorOverlay = Class(
187191
onMarkupViewContainerCreated: function(eventId, container) {
188192
Trace.sysout("InspectorOverlay.onMarkupViewContainerCreated; ", arguments);
189193

194+
let nodeFront = container.node;
195+
let hasJQueryData = false;
196+
190197
// nodeFront.getFormProperty has been introduced in Bug 1036949
191-
// (released in Firefox 41)
192198
// xxxHonza: Checking existence of the method can be removed
193-
// as soon as Firefox 41 is the minimum required version.
194-
let nodeFront = container.node;
195-
let hasJQueryData = nodeFront.getFormProperty ?
196-
nodeFront.getFormProperty("hasJQueryData") :
197-
nodeFront._form.props.hasJQueryData;
199+
// as soon as Fx42 is the minimum required version.
200+
if (nodeFront.getFormProperty) {
201+
hasJQueryData = nodeFront.getFormProperty("hasJQueryData");
202+
} else if (nodeFront._form.props) {
203+
hasJQueryData = nodeFront._form.props.hasJQueryData;
204+
}
198205

199206
if (!hasJQueryData) {
200207
return;
@@ -204,6 +211,8 @@ const InspectorOverlay = Class(
204211
},
205212

206213
createDataIcon: function(element) {
214+
Trace.sysout("InspectorOverlay.createDataIcon; ", element);
215+
207216
let icon = element.querySelector(".fireQueryData");
208217
if (icon) {
209218
return;
@@ -398,7 +407,29 @@ const InspectorOverlay = Class(
398407
},
399408
});
400409

401-
// Helpers
402-
410+
// Patching MarkupView (fire a new "container-created" event)
411+
// Bug 1036949 - New API: MarkupView customization
412+
// xxxHonza: Can be removed as soon as Fx42 is the
413+
// minimum required version.
414+
let originalImportNode = MarkupView.prototype.importNode;
415+
MarkupView.prototype.importNode = function(aNode, aFlashNode) {
416+
if (!aNode) {
417+
return null;
418+
}
419+
420+
if (this._containers.has(aNode)) {
421+
return this.getContainer(aNode);
422+
}
423+
424+
let container = originalImportNode.apply(this, arguments);
425+
426+
// Feature detection based on nodeFront.getFormProperty() API
427+
let nodeFront = container.node;
428+
if (!nodeFront.getFormProperty) {
429+
this._inspector.emit("container-created", container);
430+
}
431+
432+
return container;
433+
}
403434
// Exports from this module
404435
exports.InspectorOverlay = InspectorOverlay;

0 commit comments

Comments
 (0)