summaryrefslogtreecommitdiff
path: root/src/content/content.js
blob: fb68ae4e5007dca254f54471c3d588aaedc80681 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
'use strict';
// debug = () => {}; // REL_ONLY
var _ = browser.i18n.getMessage;

function createHTMLElement(name) {
  return document.createElementNS("http://www.w3.org/1999/xhtml", name);
}

var seen = {
  _map: new Map(),
  _list: null,
  record(event) {
    let key = event.request.key;
    if (this._map.has(key)) return;
    this._map.set(key, event);
    this._list = null;
  },
  get list() {
    return this._list || (this._list = [...this._map.values()]);
  }
}

Messages.addHandler({
  seen(event) {
    let {allowed, policyType, request, ownFrame} = event;
    if (window.top === window) {
      seen.record(event);
    }
    if (ownFrame) {
      if (!allowed && PlaceHolder.canReplace(policyType)) {
        request.embeddingDocument = ns.embeddingDocument;
        PlaceHolder.create(policyType, request);
      }
    }
  },
  collect(event) {
    let list = seen.list;
    debug("COLLECT", list);
    return list;
  }
});


debug(`Loading NoScript in document %s, scripting=%s, readyState %s`,
  document.URL, ns.canScript, document.readyState);

var notifyPage = async () => {
  debug("Page %s shown, %s", document.URL, document.readyState);
  if (document.readyState === "complete") {
    try {
      if (!("canScript" in ns)) {
        let childPolicy = await Messages.send("fetchChildPolicy", {url: document.URL});
        ns.config.CURRENT = childPolicy.CURRENT;
        ns.setup(childPolicy.DEFAULT, childPolicy.MARKER);
        return;
      }

      await Messages.send("pageshow", {seen: seen.list, canScript: ns.canScript});
      return true;
    } catch (e) {
      debug(e);
      if (/Receiving end does not exist/.test(e.message)) {
        window.setTimeout(notifyPage, 2000);
      }
    }
  }
  return false;
}

notifyPage();

window.addEventListener("pageshow", notifyPage);

ns.on("capabilities", () => {
  seen.record({
      request: {
        key: "noscript-probe",
        url: document.URL,
        documentUrl: document.URL,
        type: window === window.top ? "main_frame" : "script",
      },
      allowed: ns.canScript
    });

  if (!ns.canScript) {
    addEventListener("beforescriptexecute", e => e.preventDefault());
    let mo = new MutationObserver(mutations => {
      for (let m of mutations) {
        console.log(`Mutation `, m);
        if (m.type !== "attribute") continue;
        if (/^on\w+/i.test(m.attributeName)) {
          m.target.removeAttribute(m.attributeName);
        } else if (/^\s*(javascript|data):/i.test(m.target.attributes[m.attributeName])) {
          m.target.setAttribute(m.attributeName, "#");
        }
      }
    });
    // mo.observe(document.documentElement, {attributes: true, subtree: true});
    if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
      (async () => {
        for (let r of await navigator.serviceWorker.getRegistrations()) {
          await r.unregister();
        }
      })();
    }

    if (document.readyState !== "loading") onScriptDisabled();
    window.addEventListener("DOMContentLoaded", onScriptDisabled);
  }

  notifyPage();
});