summaryrefslogtreecommitdiff
path: root/src/content/content.js
blob: a74aa0c79e1800a7b40f365825c23fa538f7637a (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
'use strict';

 // debug = () => {}; // XPI_ONLY

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

var _ = browser.i18n.getMessage;

var canScript = true;

var embeddingDocument = false;

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

var handlers = {

  seen(event) {
    let {allowed, policyType, request, ownFrame} = event;
    if (window.top === window) {
      seen.record(event);
    }
    if (ownFrame) {
      init();
      if (!allowed && PlaceHolder.canReplace(policyType)) {
        request.embeddingDocument = embeddingDocument;
        PlaceHolder.create(policyType, request);
      }
    }
  },

  collect(event) {
    let list = seen.list;
    debug("COLLECT", list);
    return list;
  }
};

browser.runtime.onMessage.addListener(async event => {
  if (event.type in handlers) {
    debug("Received message", event);
    return handlers[event.type](event);
  }
});

if (document.readyState !== "complete") {
  let pageshown = e => {
    removeEventListener("pageshow", pageshown);
    init();
  };
  addEventListener("pageshow", pageshown);
} else init();

let notifyPage = () => {
  if (document.readyState === "complete") {
    browser.runtime.sendMessage({type: "pageshow", seen, canScript});
    return true;
  }
  return false;
}


async function init() {
  try {
    canScript = await browser.runtime.sendMessage({type: "canScript"});
    init = () => {};
    debug("canScript:", canScript);
  } catch (e) {
    // background script not initialized yet?
    setTimeout(() => init(), 100);
    return;
  }

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

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

  if (/application|video|audio/.test(document.contentType)) {
    debug("Embedding document detected");
    embeddingDocument = true;
    window.addEventListener("pageshow", e => {
      debug("Active content still in document %s: %o", document.url, document.querySelectorAll("embed,object,video,audio"));
    }, true);
    // document.write("<plaintext>");
  }
  notifyPage() || addEventListener("pageshow", notifyPage);
};