summaryrefslogtreecommitdiff
path: root/src/content/content.js
blob: d13d13e9dad551c9d9a9547c0bbfc9f932c227a1 (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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict';
// debug = () => {}; // REL_ONLY
function _(...args) {
  let fakeLang = navigator.language === "en-US" &&
                  browser.i18n.getUILanguage() !== "en-US";
  return (_ = (template, ...substitutions) => {
        let [key, defTemplate] = template.split("|");
        return fakeLang
          ? (defTemplate || key).replace(/\$([1-9])/g,
              (m, p) => substitutions[parseInt(p) - 1] || "$" + p)
          : browser.i18n.getMessage(template, ...substitutions);
      })(...args);
}

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, serviceWorker} = event;
    if (serviceWorker) {
      for (let e of seen.list) {
        let {request} = e;
        if (e.serviceWorker === serviceWorker ||
            (request.type === "main_frame" || request.type === "sub_frame") &&
             new URL(request.url).origin === serviceWorker) {
          seen.record(event);
          break;
        }
      }
      return;
    }
    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 {
      await Messages.send("pageshow", {seen: seen.list, canScript: ns.canScript});
      return true;
    } catch (e) {
      debug(e);
      if (Messages.isMissingEndpoint(e)) {
        window.setTimeout(notifyPage, 2000);
      }
    }
  }
  return false;
}

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

    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();
});

ns.fetchPolicy();
notifyPage();

addEventListener("DOMContentLoaded", e => {
  if (ns.canScript) return;
  for (let m of document.querySelectorAll("meta[http-equiv=refresh]")) {
    if (/^[^,;]*[,;](?:\W*url[^=]*=)?[^!#$%&()*+,/:;=?@[\]\w.,~-]*data:/i.test(m.getAttribute("content"))) {
      let url = m.getAttribute("content").replace(/.*?(?=data:)/i, "");
      log(`Blocking refresh to ${url}`);
      window.stop();
    }
  }
});