| 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 | 
|---|