summaryrefslogtreecommitdiff
path: root/src/content/onScriptDisabled.js
blob: 79912c9d2fcb39ed8af9d0a00e35d4f6ffb5bd9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
function onScriptDisabled() {
  if (document.URL.startsWith("file:")) {
    // file: documents are loaded synchronously and may not be affected by
    // CSP. We already intercept onbeforeexecutescript event, let's cope with
    // event and URL attributes.
    for (let e of document.all) {
      for (let a of e.attributes) {
        if (/^on\w+/i.test(a.name)) {
          debug(`Removed %s.%sevent`, e.tagName, a.name);
          a.value = "";
        } else if (/^\s*(?:data|javascript):/i.test(unescape(a.value))) {
          debug(`Neutralized %s.%s="%s" attribute`, e.tagName, a.name, a.value);
          a.value = "data:";
        }
      }
    }
  }
  for (let noscript of document.querySelectorAll("noscript")) {
    // force show NOSCRIPT elements content
    let replacement = createHTMLElement("span");
    replacement.innerHTML = noscript.innerHTML;
    noscript.parentNode.replaceChild(replacement, noscript);
    // emulate meta-refresh
    let meta = replacement.querySelector('meta[http-equiv="refresh"]');
    if (meta) {
      let content = meta.getAttribute("content");
      if (content) {
        let [secs, url] = content.split(/\s*;\s*url\s*=\s*/i);
        let urlObj;
        if (url) {
          try {
            urlObj = new URL(url.replace(/^(['"]?)(.+?)\1$/, '$2'), document.URL);
            if (!/^https?:/.test(urlObj.protocol)) {
              continue;
            }
          } catch (e) {
            continue;
          }
          window.setTimeout(() => location.href = urlObj, (parseInt(secs) || 0) * 1000);
        }
      }
    }
  }

  {
    let eraser = {
      tapped: null,
      delKey: false,
    };

    addEventListener("pagehide", ev => {
      eraser.tapped = null;
      eraser.delKey = false;
    }, false);

    addEventListener("keyup", ev => {
      let el = eraser.tapped;
      if (el && ev.keyCode === 46) {
        eraser.tapped = null;
        eraser.delKey = true;
        let doc = el.ownerDocument;
        let w = doc.defaultView;
        if (w.getSelection().isCollapsed) {
          let root = doc.body || doc.documentElement;
          let posRx = /^(?:absolute|fixed)$/;
          do {
            if (posRx.test(w.getComputedStyle(el, '').position)) {
              (eraser.tapped = el.parentNode).removeChild(el);
              break;
            }
          } while ((el = el.parentNode) && el != root);
        }
      }
    }, true);

    addEventListener("mousedown", ev => {
      if (ev.button === 0) {
        eraser.tapped = ev.target;
        eraser.delKey = false;
      }
    }, true);

    addEventListener("mouseup", ev => {
      if (eraser.delKey) {
        eraser.delKey = false;
        ev.preventDefault();
        ev.stopPropagation();
      }
      eraser.tapped = null;
    }, true);
  }
}