OLD | NEW |
1 /* | 1 /* |
2 * This Source Code is subject to the terms of the Mozilla Public License | 2 * This Source Code is subject to the terms of the Mozilla Public License |
3 * version 2.0 (the "License"). You can obtain a copy of the License at | 3 * version 2.0 (the "License"). You can obtain a copy of the License at |
4 * http://mozilla.org/MPL/2.0/. | 4 * http://mozilla.org/MPL/2.0/. |
5 */ | 5 */ |
6 | 6 |
7 const Ci = Components.interfaces; | 7 "use strict"; |
8 const Cu = Components.utils; | |
9 | 8 |
10 let console; | 9 let console; |
11 try | 10 try |
12 { | 11 { |
13 // Gecko 44+ | 12 // Gecko 44+ |
14 ({console} = Cu.import("resource://gre/modules/Console.jsm", {})); | 13 ({console} = Cu.import("resource://gre/modules/Console.jsm", {})); |
15 } | 14 } |
16 catch (e) | 15 catch (e) |
17 { | 16 { |
18 ({console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {})); | 17 ({console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {})); |
19 } | 18 } |
20 | 19 |
21 let DebuggerServer; | 20 let DebuggerServer; |
22 try | 21 try |
23 { | 22 { |
24 // Firefox 44+ | 23 // Firefox 44+ |
25 let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); | 24 let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); |
26 ({DebuggerServer} = require("devtools/server/main")); | 25 ({DebuggerServer} = require("devtools/server/main")); |
27 } | 26 } |
28 catch (e) | 27 catch (e) |
29 { | 28 { |
30 ({DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm"
, {})); | 29 ({DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm"
, {})); |
31 } | 30 } |
32 | 31 |
33 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 32 let {getNodeInfo} = require("./nodeInfo"); |
34 | 33 |
35 let processID = Services.appinfo.processID; | 34 function Actor(connection, tabActor) |
36 let maxNodeID = 0; | 35 { |
37 let nodes = new Map(); | 36 } |
| 37 |
| 38 Actor.prototype = { |
| 39 requestTypes: { |
| 40 nodeinfo: function(request, connection) |
| 41 { |
| 42 let nodeActor = connection.getActor(request.nodeActor); |
| 43 return getNodeInfo(nodeActor ? nodeActor.rawNode : null); |
| 44 } |
| 45 } |
| 46 }; |
38 | 47 |
39 let name = "elemhidehelper"; | 48 let name = "elemhidehelper"; |
40 let actor = { | 49 let actor = { |
41 constructorFun: Actor, | 50 constructorFun: Actor, |
42 constructorName: name, | 51 constructorName: name, |
43 name: name | 52 name: name |
44 }; | 53 }; |
45 | 54 |
46 addMessageListener("ElemHideHelper:Shutdown", onShutdown); | |
47 addMessageListener("ElemHideHelper:GetNodeInfo", onGetNodeInfo); | |
48 addMessageListener("ElemHideHelper:Preview", onTogglePreview); | |
49 | |
50 DebuggerServer.addTabActor(actor, name); | 55 DebuggerServer.addTabActor(actor, name); |
51 | 56 onShutdown.add(() => |
52 function onShutdown() | |
53 { | 57 { |
54 removeMessageListener("ElemHideHelper:Shutdown", onShutdown); | |
55 removeMessageListener("ElemHideHelper:GetNodeInfo", onGetNodeInfo); | |
56 removeMessageListener("ElemHideHelper:Preview", onTogglePreview); | |
57 | |
58 try | 58 try |
59 { | 59 { |
60 DebuggerServer.removeTabActor(actor); | 60 DebuggerServer.removeTabActor(actor); |
61 } | 61 } |
62 catch (e) | 62 catch (e) |
63 { | 63 { |
64 // The call above will throw in the content process despite succeeding, | 64 // The call above will throw in the content process despite succeeding, |
65 // see https://bugzilla.mozilla.org/show_bug.cgi?id=1189780. | 65 // see https://bugzilla.mozilla.org/show_bug.cgi?id=1189780. |
66 Cu.reportError(e); | 66 Cu.reportError(e); |
67 } | 67 } |
68 } | 68 }); |
69 | |
70 function onGetNodeInfo(message) | |
71 { | |
72 if (Cu.isCrossProcessWrapper(message.objects.element)) | |
73 return; | |
74 | |
75 let nodeInfo = getNodeInfo(message.objects.element); | |
76 nodeInfo.messageId = message.data; | |
77 sendAsyncMessage("ElemHideHelper:GetNodeInfo:Response", nodeInfo); | |
78 } | |
79 | |
80 function onTogglePreview(message) | |
81 { | |
82 togglePreview(message.data.nodeID, message.data.stylesheetData); | |
83 if (message.data.forgetNode) | |
84 forgetNode(message.data.nodeID); | |
85 } | |
86 | |
87 function Actor(connection, tabActor) | |
88 { | |
89 } | |
90 | |
91 Actor.prototype = { | |
92 requestTypes: { | |
93 nodeinfo: function(request, connection) | |
94 { | |
95 let nodeActor = connection.getActor(request.nodeActor); | |
96 return getNodeInfo(nodeActor ? nodeActor.rawNode: null); | |
97 } | |
98 } | |
99 }; | |
100 | |
101 function getNodeInfo(node) | |
102 { | |
103 let nodeData = getNodeData(node); | |
104 if (nodeData) | |
105 { | |
106 let nodeID = processID + "-" + (++maxNodeID); | |
107 nodes.set(nodeID, {document: node.ownerDocument, style: null}); | |
108 return { | |
109 host: node.ownerDocument.defaultView.location.hostname, | |
110 nodeData: nodeData, | |
111 nodeID: nodeID | |
112 }; | |
113 } | |
114 | |
115 return {}; | |
116 } | |
117 | |
118 function getNodeData(node, parentNode) | |
119 { | |
120 if (!node || node.nodeType != Ci.nsIDOMNode.ELEMENT_NODE) | |
121 return null; | |
122 | |
123 let result = {}; | |
124 result.tagName = {value: node.tagName, checked: false}; | |
125 | |
126 if (typeof parentNode != "undefined") | |
127 result.parentNode = parentNode; | |
128 else | |
129 result.parentNode = getNodeData(node.parentElement); | |
130 | |
131 let prevSibling = node.previousElementSibling; | |
132 result.prevSibling = getNodeData(prevSibling, result.parentNode); | |
133 | |
134 if (result.parentNode && !prevSibling) | |
135 result.firstChild = {checked: false}; | |
136 | |
137 let nextSibling = node.nextElementSibling; | |
138 if (result.parentNode && !nextSibling) | |
139 result.lastChild = {checked: false}; | |
140 | |
141 result.attributes = []; | |
142 for (let attribute of node.attributes) | |
143 { | |
144 let data = { | |
145 name: attribute.name, | |
146 value: attribute.value, | |
147 selected: attribute.value, | |
148 checked: false | |
149 }; | |
150 if (data.name == "id" || data.name == "class") | |
151 result.attributes.unshift(data); | |
152 else | |
153 result.attributes.push(data); | |
154 } | |
155 | |
156 if (result.attributes.length >= 2 && result.attributes[1].name == "id") | |
157 { | |
158 // Make sure ID attribute comes first | |
159 let tmp = result.attributes[1]; | |
160 result.attributes[1] = result.attributes[0]; | |
161 result.attributes[0] = tmp; | |
162 } | |
163 | |
164 result.customCSS = {selected: "", checked: false}; | |
165 return result; | |
166 } | |
167 | |
168 function togglePreview(nodeID, stylesheetData) | |
169 { | |
170 let context = nodes.get(nodeID); | |
171 if (!context) | |
172 return; | |
173 | |
174 if (stylesheetData) | |
175 { | |
176 if (!context.style || !context.style.parentNode) | |
177 { | |
178 context.style = context.document.createElementNS( | |
179 "http://www.w3.org/1999/xhtml", "style"); | |
180 context.style.setAttribute("type", "text/css"); | |
181 context.document.documentElement.appendChild(context.style); | |
182 } | |
183 context.style.textContent = stylesheetData; | |
184 } | |
185 else | |
186 { | |
187 try | |
188 { | |
189 if (context.style && context.style.parentNode) | |
190 context.style.parentNode.removeChild(context.style); | |
191 context.style = null; | |
192 } | |
193 catch (e) | |
194 { | |
195 // If the window was closed (reloaded) we end up with a dead object | |
196 // reference (https://bugzilla.mozilla.org/show_bug.cgi?id=695480). Just | |
197 // forget this node then. | |
198 forgetNode(nodeID); | |
199 } | |
200 } | |
201 } | |
202 | |
203 function forgetNode(nodeID) | |
204 { | |
205 nodes.delete(nodeID); | |
206 } | |
OLD | NEW |