| 235 | } |
| 236 | |
| 237 | function findEditable() { |
| 238 | // find textareas and elements with contenteditable attribute, filter out <body> |
| 239 | let editable = Array.from(document.querySelectorAll('[contenteditable="true"], textarea')).filter(isVisible).filter(element => element.tagName.toLowerCase() !== 'body'); |
| 240 | const iframes = Array.from(document.getElementsByTagName('iframe')).filter(isVisible); |
| 241 | const dynFrames = []; |
| 242 | const origFrames = []; |
| 243 | for (const frame of iframes) { |
| 244 | // find dynamically created iframes where src is not set |
| 245 | if (!frame.src || /^javascript.*/.test(frame.src) || /^about.*/.test(frame.src)) { |
| 246 | dynFrames.push(frame); |
| 247 | } else { |
| 248 | origFrames.push(frame); |
| 249 | } |
| 250 | } |
| 251 | // find editable elements inside dynamic iframe (content script is not injected here) |
| 252 | for (const dynFrame of dynFrames) { |
| 253 | const content = dynFrame.contentDocument; |
| 254 | // document of iframe in design mode or contenteditable set on the body |
| 255 | if (content.designMode === 'on' || content.querySelector('body[contenteditable="true"]')) { |
| 256 | // add iframe to editable elements |
| 257 | editable.push(dynFrame); |
| 258 | } else { |
| 259 | // editable elements inside iframe |
| 260 | const editblElem = Array.from(content.querySelectorAll('[contenteditable="true"], textarea')).filter(isVisible); |
| 261 | editable.push(...editblElem); |
| 262 | } |
| 263 | } |
| 264 | // find iframes from same origin with a contenteditable body (content script is injected, but encrypt frame needs to be attached to outer iframe) |
| 265 | const anchor = document.createElement('a'); |
| 266 | for (const origFrame of origFrames) { |
| 267 | anchor.href = origFrame.href; |
| 268 | if (anchor.hostname !== document.location.hostname) { |
| 269 | continue; |
| 270 | } |
| 271 | try { |
| 272 | const content = origFrame.contentDocument; |
| 273 | if (content.designMode === 'on' || content.querySelector('body[contenteditable="true"]')) { |
| 274 | editable.push(origFrame); |
| 275 | } |
| 276 | } catch (e) {} |
| 277 | } |
| 278 | // filter out elements below a certain height limit |
| 279 | editable = editable.filter(element => element.getBoundingClientRect().height > MIN_EDIT_HEIGHT); |
| 280 | return editable; |
| 281 | } |
| 282 | |
| 283 | export function getMessageType(armored) { |
| 284 | if (/(BEGIN|END)\sPGP\sMESSAGE/.test(armored)) { |