first commit
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Types tests / Test (lts/*) (push) Has been cancelled
				
			
		
			
				
	
				Lint / Lint (lts/*) (push) Has been cancelled
				
			
		
			
				
	
				CodeQL / Analyze (javascript) (push) Has been cancelled
				
			
		
			
				
	
				CI / Test (20) (push) Has been cancelled
				
			
		
			
				
	
				CI / Test (22) (push) Has been cancelled
				
			
		
			
				
	
				CI / Test (24) (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Types tests / Test (lts/*) (push) Has been cancelled
				
			Lint / Lint (lts/*) (push) Has been cancelled
				
			CodeQL / Analyze (javascript) (push) Has been cancelled
				
			CI / Test (20) (push) Has been cancelled
				
			CI / Test (22) (push) Has been cancelled
				
			CI / Test (24) (push) Has been cancelled
				
			This commit is contained in:
		
							
								
								
									
										187
									
								
								extensions/chromium/telemetry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								extensions/chromium/telemetry.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2016 Mozilla Foundation
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
/* eslint strict: ["error", "function"] */
 | 
			
		||||
 | 
			
		||||
(function () {
 | 
			
		||||
  "use strict";
 | 
			
		||||
  // This module sends the browser and extension version to a server, to
 | 
			
		||||
  // determine whether it is safe to drop support for old Chrome versions in
 | 
			
		||||
  // future extension updates.
 | 
			
		||||
  //
 | 
			
		||||
  // The source code for the server is available at:
 | 
			
		||||
  // https://github.com/Rob--W/pdfjs-telemetry
 | 
			
		||||
  var LOG_URL = "https://pdfjs.robwu.nl/logpdfjs";
 | 
			
		||||
 | 
			
		||||
  // The minimum time to wait before sending a ping, so that we don't send too
 | 
			
		||||
  // many requests even if the user restarts their browser very often.
 | 
			
		||||
  // We want one ping a day, so a minimum delay of 12 hours should be OK.
 | 
			
		||||
  var MINIMUM_TIME_BETWEEN_PING = 12 * 36e5;
 | 
			
		||||
 | 
			
		||||
  if (chrome.extension.inIncognitoContext) {
 | 
			
		||||
    // The extension uses incognito split mode, so there are two background
 | 
			
		||||
    // pages. Only send telemetry when not in incognito mode.
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (chrome.runtime.id !== "oemmndcbldboiebfnladdacbdfmadadm") {
 | 
			
		||||
    // Only send telemetry for the official PDF.js extension.
 | 
			
		||||
    console.warn("Disabled telemetry because this is not an official build.");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // The localStorage API is unavailable in service workers. We store data in
 | 
			
		||||
  // chrome.storage.local and use this "localStorage" object to enable
 | 
			
		||||
  // synchronous access in the logic.
 | 
			
		||||
  const localStorage = {
 | 
			
		||||
    telemetryLastTime: 0,
 | 
			
		||||
    telemetryDeduplicationId: "",
 | 
			
		||||
    telemetryLastVersion: "",
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  chrome.alarms.onAlarm.addListener(alarm => {
 | 
			
		||||
    if (alarm.name === "maybeSendPing") {
 | 
			
		||||
      maybeSendPing();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  chrome.storage.session.get({ didPingCheck: false }, async items => {
 | 
			
		||||
    if (items?.didPingCheck) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    maybeSendPing();
 | 
			
		||||
    await chrome.alarms.clear("maybeSendPing");
 | 
			
		||||
    await chrome.alarms.create("maybeSendPing", { periodInMinutes: 60 });
 | 
			
		||||
    chrome.storage.session.set({ didPingCheck: true });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  function updateLocalStorage(key, value) {
 | 
			
		||||
    localStorage[key] = value;
 | 
			
		||||
    // Note: We mirror the data in localStorage because the following is async.
 | 
			
		||||
    chrome.storage.local.set({ [key]: value });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function maybeSendPing() {
 | 
			
		||||
    getLoggingPref(function (didOptOut) {
 | 
			
		||||
      if (didOptOut) {
 | 
			
		||||
        // Respect the user's decision to not send statistics.
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (!navigator.onLine) {
 | 
			
		||||
        // No network available; Wait until the next scheduled ping opportunity.
 | 
			
		||||
        // Even if onLine is true, the server may still be unreachable. But
 | 
			
		||||
        // because it is impossible to tell whether a request failed due to the
 | 
			
		||||
        // inability to connect, or a deliberate connection termination by the
 | 
			
		||||
        // server, we don't validate the response and assume that the request
 | 
			
		||||
        // succeeded. This ensures that the server cannot ask the client to
 | 
			
		||||
        // send more pings.
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      doSendPing();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function doSendPing() {
 | 
			
		||||
    chrome.storage.local.get(localStorage, items => {
 | 
			
		||||
      Object.assign(localStorage, items);
 | 
			
		||||
 | 
			
		||||
      var lastTime = parseInt(localStorage.telemetryLastTime) || 0;
 | 
			
		||||
      var wasUpdated = didUpdateSinceLastCheck();
 | 
			
		||||
      if (!wasUpdated && Date.now() - lastTime < MINIMUM_TIME_BETWEEN_PING) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      updateLocalStorage("telemetryLastTime", Date.now());
 | 
			
		||||
 | 
			
		||||
      var deduplication_id = getDeduplicationId(wasUpdated);
 | 
			
		||||
      var extension_version = chrome.runtime.getManifest().version;
 | 
			
		||||
      fetch(LOG_URL, {
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        headers: new Headers({
 | 
			
		||||
          "Deduplication-Id": deduplication_id,
 | 
			
		||||
          "Extension-Version": extension_version,
 | 
			
		||||
        }),
 | 
			
		||||
        // Set mode=cors so that the above custom headers are included in the
 | 
			
		||||
        // request.
 | 
			
		||||
        mode: "cors",
 | 
			
		||||
        // Omits credentials such as cookies in the requests, which guarantees
 | 
			
		||||
        // that the server cannot track the client via HTTP cookies.
 | 
			
		||||
        credentials: "omit",
 | 
			
		||||
        cache: "no-store",
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Generate a 40-bit hexadecimal string (=10 letters, 1.1E12 possibilities).
 | 
			
		||||
   * This is used by the server to discard duplicate entries of the same browser
 | 
			
		||||
   * version when the log data is aggregated.
 | 
			
		||||
   */
 | 
			
		||||
  function getDeduplicationId(wasUpdated) {
 | 
			
		||||
    var id = localStorage.telemetryDeduplicationId;
 | 
			
		||||
    // The ID is only used to deduplicate reports for the same browser version,
 | 
			
		||||
    // so it is OK to change the ID if the browser is updated. By changing the
 | 
			
		||||
    // ID, the server cannot track users for a long period even if it wants to.
 | 
			
		||||
    if (!id || !/^[0-9a-f]{10}$/.test(id) || wasUpdated) {
 | 
			
		||||
      id = "";
 | 
			
		||||
      var buf = new Uint8Array(5);
 | 
			
		||||
      crypto.getRandomValues(buf);
 | 
			
		||||
      for (const c of buf) {
 | 
			
		||||
        id += (c >>> 4).toString(16) + (c & 0xf).toString(16);
 | 
			
		||||
      }
 | 
			
		||||
      updateLocalStorage("telemetryDeduplicationId", id);
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns whether the browser has received a major update since the last call
 | 
			
		||||
   * to this function.
 | 
			
		||||
   */
 | 
			
		||||
  function didUpdateSinceLastCheck() {
 | 
			
		||||
    var chromeVersion = /Chrome\/(\d+)\./.exec(navigator.userAgent);
 | 
			
		||||
    chromeVersion = chromeVersion && chromeVersion[1];
 | 
			
		||||
    if (!chromeVersion || localStorage.telemetryLastVersion === chromeVersion) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    updateLocalStorage("telemetryLastVersion", chromeVersion);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the value of the telemetry preference. The callback is invoked with a
 | 
			
		||||
   * boolean if a preference is found, and with the undefined value otherwise.
 | 
			
		||||
   */
 | 
			
		||||
  function getLoggingPref(callback) {
 | 
			
		||||
    // Try to look up the preference in the storage, in the following order:
 | 
			
		||||
    var areas = ["sync", "local", "managed"];
 | 
			
		||||
 | 
			
		||||
    next();
 | 
			
		||||
    function next(result) {
 | 
			
		||||
      var storageAreaName = areas.shift();
 | 
			
		||||
      if (typeof result === "boolean" || !storageAreaName) {
 | 
			
		||||
        callback(result);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!chrome.storage[storageAreaName]) {
 | 
			
		||||
        next();
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      chrome.storage[storageAreaName].get("disableTelemetry", function (items) {
 | 
			
		||||
        next(items && items.disableTelemetry);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})();
 | 
			
		||||
		Reference in New Issue
	
	Block a user