| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
|
saroyanm
2016/11/23 17:44:39
I thought that this code belongs to Aardvark ?
Wha
Wladimir Palant
2016/11/24 14:02:01
Yes, E10S is the reason for this whole change. Any
| |
| 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 | |
| 4 * http://mozilla.org/MPL/2.0/. | |
| 5 */ | |
| 6 | |
| 7 "use strict"; | |
| 8 | |
| 9 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | |
| 10 | |
| 11 let messageManager = require("messageManager"); | |
| 12 let { | |
| 13 createElement, getWindowSize, getParentElement, getElementPosition | |
| 14 } = require("./utils"); | |
| 15 | |
| 16 let state = exports.state = {}; | |
|
Wladimir Palant
2016/11/17 13:54:48
Original code was storing the selection state as p
saroyanm
2016/11/23 17:44:39
We are setting the properties of state in other fu
Wladimir Palant
2016/11/24 14:02:02
Setting them here doesn't make sense - the definit
| |
| 17 | |
| 18 messageManager.addMessageListener("ElemHideHelper:StartSelection", startSelectio n); | |
| 19 | |
| 20 onShutdown.add(() => | |
| 21 { | |
| 22 messageManager.removeMessageListener("ElemHideHelper:StartSelection", startSel ection); | |
| 23 | |
| 24 stopSelection(); | |
| 25 }); | |
| 26 | |
| 27 function startSelection(message) | |
| 28 { | |
| 29 stopSelection(); | |
| 30 | |
| 31 let outerWindowID = message.data; | |
| 32 let wnd = Services.wm.getOuterWindowWithId(outerWindowID); | |
| 33 if (!wnd || !canSelect(wnd)) | |
| 34 return; | |
| 35 | |
| 36 state.window = wnd; | |
| 37 state.id = outerWindowID; | |
| 38 | |
| 39 wnd.addEventListener("click", onMouseClick, true); | |
| 40 wnd.addEventListener("wheel", onMouseScroll, true); | |
|
saroyanm
2016/11/23 17:44:39
It's a deprecated event:
https://developer.mozilla
Wladimir Palant
2016/11/24 14:02:02
That page is about the mousewheel event, not wheel
| |
| 41 wnd.addEventListener("mousemove", onMouseMove, true); | |
| 42 wnd.addEventListener("pagehide", onPageHide, true); | |
| 43 | |
| 44 wnd.focus(); | |
| 45 | |
| 46 let doc = wnd.document; | |
| 47 let {elementMarkerClass} = require("info"); | |
| 48 state.boxElement = createElement(doc, "div", {"class": elementMarkerClass}, [ | |
| 49 createElement(doc, "div", {"class": "ehh-border"}), | |
| 50 createElement(doc, "div", {"class": "ehh-label"}, [ | |
| 51 createElement(doc, "span", {"class": "ehh-labelTag"}), | |
| 52 createElement(doc, "span", {"class": "ehh-labelAddition"}) | |
| 53 ]) | |
| 54 ]); | |
| 55 | |
| 56 // Make sure to select some element immeditely (whichever is in the center of the browser window) | |
| 57 let [wndWidth, wndHeight] = getWindowSize(wnd); | |
| 58 state.isUserSelected = false; | |
| 59 onMouseMove({clientX: wndWidth / 2, clientY: wndHeight / 2, screenX: -1, scree nY: -1, target: null}); | |
| 60 | |
| 61 messageManager.sendAsyncMessage("ElemHideHelper:SelectionStarted"); | |
| 62 } | |
| 63 | |
| 64 function stopSelection() | |
| 65 { | |
| 66 if (!state.boxElement) | |
| 67 return; | |
| 68 | |
| 69 hideSelection(); | |
| 70 | |
| 71 let wnd = state.window; | |
| 72 wnd.removeEventListener("click", onMouseClick, true); | |
| 73 wnd.removeEventListener("wheel", onMouseScroll, true); | |
| 74 wnd.removeEventListener("mousemove", onMouseMove, true); | |
| 75 wnd.removeEventListener("pagehide", onPageHide, true); | |
| 76 | |
| 77 for (let key of Object.keys(state)) | |
| 78 delete state[key]; | |
| 79 | |
| 80 messageManager.sendAsyncMessage("ElemHideHelper:SelectionStopped"); | |
| 81 } | |
| 82 exports.stopSelection = stopSelection; | |
| 83 | |
| 84 function canSelect(wnd) | |
| 85 { | |
| 86 let acceptlocalfiles; | |
|
saroyanm
2016/11/23 17:44:39
Nit: camelCase is missing
Wladimir Palant
2016/11/24 14:02:02
Done.
| |
| 87 try | |
| 88 { | |
| 89 acceptlocalfiles = Services.prefs.getBoolPref("extensions.elemhidehelper.acc eptlocalfiles"); | |
|
saroyanm
2016/11/23 17:44:39
Nit: exceeding 80 chars.
Wladimir Palant
2016/11/24 14:02:01
Done.
| |
| 90 } | |
| 91 catch (e) | |
| 92 { | |
| 93 acceptlocalfiles = false; | |
| 94 } | |
| 95 | |
| 96 if (!acceptlocalfiles) | |
| 97 { | |
| 98 let localSchemes; | |
| 99 try | |
| 100 { | |
| 101 localSchemes = new Set( | |
| 102 Services.prefs.getCharPref("extensions.adblockplus.whitelistschemes") | |
| 103 .split(/\s+/) | |
| 104 ); | |
|
Wladimir Palant
2016/11/17 13:54:48
This changes the original logic which was simply h
| |
| 105 } | |
| 106 catch (e) | |
| 107 { | |
| 108 localSchemes = new Set(); | |
| 109 } | |
| 110 | |
| 111 if (localSchemes.has(wnd.location.protocol.replace(/:$/, ""))) | |
| 112 return false; | |
| 113 } | |
| 114 | |
| 115 return true; | |
| 116 } | |
| 117 | |
| 118 function getElementLabel(elem) | |
| 119 { | |
| 120 let tagName = elem.localName; | |
|
saroyanm
2016/11/23 17:44:39
localName is a deprecated property:
https://develo
Wladimir Palant
2016/11/24 14:02:02
That would have been surprising - the docs say tha
| |
| 121 let addition = ""; | |
| 122 if (elem.id != "") | |
| 123 addition += ", id: " + elem.id; | |
| 124 if (elem.className != "") | |
| 125 addition += ", class: " + elem.className; | |
| 126 if (elem.style.cssText != "") | |
| 127 addition += ", style: " + elem.style.cssText; | |
|
saroyanm
2016/11/23 17:44:39
Weak suggestion: What about mentioning that it's n
Wladimir Palant
2016/11/24 14:02:02
Hasn't lead to any confusion so far, we can just a
| |
| 128 | |
| 129 return [tagName, addition]; | |
| 130 } | |
| 131 | |
| 132 function setAnchorElement(anchor) | |
|
saroyanm
2016/11/23 17:44:39
What is the anchor element ? I assume it's not rel
Wladimir Palant
2016/11/24 14:02:01
Nope. I've documented the state properties now, sh
| |
| 133 { | |
| 134 state.anchorElement = anchor; | |
| 135 | |
| 136 let newSelection = anchor; | |
| 137 if (state.isUserSelected) | |
| 138 { | |
| 139 // User chose an element via wider/narrower commands, keep the selection if | |
| 140 // our new anchor is still a child of that element | |
| 141 let e = newSelection; | |
| 142 while (e && e != state.selectedElement) | |
| 143 e = getParentElement(e); | |
| 144 | |
| 145 if (e) | |
| 146 newSelection = state.selectedElement; | |
| 147 else | |
| 148 state.isUserSelected = false; | |
| 149 } | |
| 150 | |
| 151 selectElement(newSelection); | |
| 152 } | |
| 153 exports.setAnchorElement = setAnchorElement; | |
| 154 | |
| 155 function selectElement(elem) | |
| 156 { | |
| 157 state.selectedElement = elem; | |
| 158 state.prevSelectionUpdate = Date.now(); | |
| 159 | |
| 160 let border = state.boxElement.querySelector(".ehh-border"); | |
| 161 let label = state.boxElement.querySelector(".ehh-label"); | |
| 162 let labelTag = state.boxElement.querySelector(".ehh-labelTag"); | |
| 163 let labelAddition = state.boxElement.querySelector(".ehh-labelAddition"); | |
| 164 | |
| 165 let doc = state.window.document; | |
| 166 let [wndWidth, wndHeight] = getWindowSize(state.window); | |
| 167 | |
| 168 let pos = getElementPosition(elem); | |
| 169 state.boxElement.style.left = Math.min(pos.left - 1, wndWidth - 2) + "px"; | |
|
saroyanm
2016/11/23 17:44:38
Is this approach even working with RTL websites ?
Wladimir Palant
2016/11/24 14:02:01
Well, it works with RTL websites. Our UI is always
saroyanm
2016/11/25 16:18:13
Here you go: #4665
| |
| 170 state.boxElement.style.top = Math.min(pos.top - 1, wndHeight - 2) + "px"; | |
| 171 border.style.width = Math.max(pos.right - pos.left - 2, 0) + "px"; | |
| 172 border.style.height = Math.max(pos.bottom - pos.top - 2, 0) + "px"; | |
| 173 | |
| 174 [labelTag.textContent, labelAddition.textContent] = getElementLabel(elem); | |
| 175 | |
| 176 // If there is not enough space to show the label move it up a little | |
| 177 if (pos.bottom < wndHeight - 25) | |
| 178 label.className = "ehh-label"; | |
| 179 else | |
| 180 label.className = "ehh-label onTop"; | |
| 181 | |
| 182 doc.documentElement.appendChild(state.boxElement); | |
| 183 | |
| 184 state.prevPos = pos; | |
| 185 state.window.addEventListener("MozAfterPaint", onAfterPaint, false); | |
| 186 } | |
| 187 exports.selectElement = selectElement; | |
| 188 | |
| 189 function hideSelection() | |
| 190 { | |
| 191 if (!Cu.isDeadWrapper(state.boxElement) && state.boxElement.parentNode) | |
| 192 state.boxElement.parentNode.removeChild(state.boxElement); | |
| 193 | |
| 194 if (!Cu.isDeadWrapper(state.window)) | |
| 195 state.window.removeEventListener("MozAfterPaint", onAfterPaint, false); | |
| 196 } | |
| 197 | |
| 198 /****************** | |
| 199 * Event handlers * | |
| 200 ******************/ | |
| 201 | |
| 202 function onMouseClick(event) | |
| 203 { | |
| 204 if (event.button != 0 || event.shiftKey || event.altKey || event.ctrlKey || ev ent.metaKey) | |
| 205 return; | |
| 206 | |
| 207 require("./commands").select(); | |
| 208 event.preventDefault(); | |
| 209 } | |
| 210 | |
| 211 function onMouseScroll(event) | |
| 212 { | |
| 213 if (!event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) | |
| 214 return; | |
| 215 | |
| 216 let delta = event.deltaY || event.deltaX; | |
|
Wladimir Palant
2016/11/17 13:54:48
This was dead code originally, using DOMMouseScrol
saroyanm
2016/11/23 17:44:38
Acknowledged.
| |
| 217 if (!delta) | |
| 218 return; | |
| 219 | |
| 220 let commands = require("./commands"); | |
|
saroyanm
2016/11/23 17:44:38
Detail: we already loading the module in onMouseCl
Wladimir Palant
2016/11/24 14:02:01
That would create a circular reference.
| |
| 221 if (delta > 0) | |
| 222 commands.wider(); | |
| 223 else | |
| 224 commands.narrower(); | |
| 225 event.preventDefault(); | |
| 226 } | |
| 227 | |
| 228 function onMouseMove(event) | |
| 229 { | |
| 230 hideSelection(); | |
| 231 | |
| 232 let x = event.clientX; | |
| 233 let y = event.clientY; | |
| 234 | |
| 235 // We might have coordinates relative to a frame, recalculate relative to top window | |
| 236 let node = event.target; | |
| 237 while (node && node.ownerDocument && node.ownerDocument.defaultView && node.ow nerDocument.defaultView.frameElement) | |
| 238 { | |
| 239 node = node.ownerDocument.defaultView.frameElement; | |
| 240 let rect = node.getBoundingClientRect(); | |
| 241 x += rect.left; | |
| 242 y += rect.top; | |
| 243 } | |
| 244 | |
| 245 // Get the element matching the coordinates, probably within a frame | |
| 246 let elem = state.window.document.elementFromPoint(x, y); | |
| 247 while (elem && "contentWindow" in elem && canSelect(elem.contentWindow)) | |
| 248 { | |
| 249 let rect = elem.getBoundingClientRect(); | |
| 250 x -= rect.left; | |
| 251 y -= rect.top; | |
| 252 elem = elem.contentWindow.document.elementFromPoint(x, y); | |
| 253 } | |
| 254 | |
| 255 if (elem) | |
| 256 { | |
| 257 if (!state.lockedAnchor) | |
| 258 setAnchorElement(elem); | |
| 259 else | |
| 260 { | |
| 261 state.lockedAnchor = elem; | |
| 262 selectElement(state.selectedElement); | |
| 263 } | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 function onPageHide(event) | |
| 268 { | |
| 269 stopSelection(); | |
| 270 } | |
| 271 | |
| 272 function onAfterPaint(event) | |
|
Wladimir Palant
2016/11/17 13:54:48
This code path is untested, I'm not sure whether i
saroyanm
2016/11/23 17:44:39
We do have "onMouseScroll" function, I thought it
Wladimir Palant
2016/11/24 14:02:02
Given that the purpose of this function is selecti
| |
| 273 { | |
| 274 // Don't update position too often | |
| 275 if (state.selectedElement && Date.now() - state.prevSelectionUpdate > 20) | |
| 276 { | |
| 277 let pos = getElementPosition(state.selectedElement); | |
| 278 if (!state.prevPos || state.prevPos.left != pos.left || | |
| 279 state.prevPos.right != pos.right || state.prevPos.top != pos.top || | |
| 280 state.prevPos.bottom != pos.bottom) | |
| 281 { | |
| 282 selectElement(state.selectedElement); | |
| 283 } | |
| 284 } | |
| 285 } | |
| OLD | NEW |