summaryrefslogtreecommitdiffstats
path: root/src/js/contentscripts/supercookie.js
blob: 0b15211fe2747818239073a4775a505ed99d8117 (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * This file is part of Privacy Badger <https://www.eff.org/privacybadger>
 * Copyright (C) 2015 Electronic Frontier Foundation
 *
 * Derived from Chameleon <https://github.com/ghostwords/chameleon>
 * Copyright (C) 2015 ghostwords
 *
 * Privacy Badger is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Privacy Badger is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Privacy Badger.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Generate script to inject into the page
 *
 * @returns {string}
 */
function getScPageScript() {
  // code below is not a content script: no chrome.* APIs /////////////////////

  // return a string
  return "(" + function () {

    /*
     * If localStorage is inaccessible, such as when "Block third-party cookies"
     * in enabled in Chrome or when `dom.storage.enabled` is set to `false` in
     * Firefox, do not go any further.
     */
    try {
      // No localStorage raises an Exception in Chromium-based browsers, while
      // it's equal to `null` in Firefox.
      if (null === localStorage) {
        throw false;
      }
    } catch (ex) {
      return;
    }

    (function (DOCUMENT, dispatchEvent, CUSTOM_EVENT, LOCAL_STORAGE, OBJECT, keys) {

      var event_id = DOCUMENT.currentScript.getAttribute('data-event-id-super-cookie');

      /**
       * send message to the content script
       *
       * @param {*} message
       */
      var send = function (message) {
        dispatchEvent.call(DOCUMENT, new CUSTOM_EVENT(event_id, {
          detail: message
        }));
      };

      /**
       * Read HTML5 local storage and return contents
       * @returns {Object}
       */
      let getLocalStorageItems = function () {
        let lsItems = {};
        for (let i = 0; i < LOCAL_STORAGE.length; i++) {
          let key = LOCAL_STORAGE.key(i);
          lsItems[key] = LOCAL_STORAGE.getItem(key);
        }
        return lsItems;
      };

      if (event_id) { // inserted script may run before the event_id is available
        let localStorageItems = getLocalStorageItems();
        if (keys.call(OBJECT, localStorageItems).length) {
          // send to content script
          send({ localStorageItems });
        }
      }

    // save locally to keep from getting overwritten by site code
    } (document, document.dispatchEvent, CustomEvent, localStorage, Object, Object.keys));

  } + "());";

  // code above is not a content script: no chrome.* APIs /////////////////////

}

// END FUNCTION DEFINITIONS ///////////////////////////////////////////////////

(function () {

// don't inject into non-HTML documents (such as XML documents)
// but do inject into XHTML documents
if (document instanceof HTMLDocument === false && (
  document instanceof XMLDocument === false ||
  document.createElement('div') instanceof HTMLDivElement === false
)) {
  return;
}

// don't bother asking to run when trivially in first-party context
if (window.top == window) {
  return;
}

// TODO race condition; fix waiting on https://crbug.com/478183

// TODO here we could also be injected too quickly
// and miss localStorage setting upon initial page load
//
// we should eventually switch injection back to document_start
// (reverting https://github.com/EFForg/privacybadger/pull/1522),
// and fix localstorage detection
// (such as by delaying it or peforming it periodically)
//
// could then remove test workarounds like
// https://github.com/EFForg/privacybadger/commit/39d5d0899e22d1c451d429e44553c5f9cad7fc46

// TODO sometimes contentscripts/utils.js isn't here?!
// TODO window.FRAME_URL / window.injectScript are undefined ...
chrome.runtime.sendMessage({
  type: "inspectLocalStorage",
  frameUrl: window.FRAME_URL
}, function (enabledAndThirdParty) {
  if (!enabledAndThirdParty) {
    return;
  }

  var event_id_super_cookie = Math.random();

  // listen for messages from the script we are about to insert
  document.addEventListener(event_id_super_cookie, function (e) {
    // pass these on to the background page (handled by webrequest.js)
    chrome.runtime.sendMessage({
      type: "supercookieReport",
      data: e.detail,
      frameUrl: window.FRAME_URL
    });
  });

  window.injectScript(getScPageScript(), {
    event_id_super_cookie: event_id_super_cookie
  });

});

}());