<commit_before>/* globals Services, Locale */

const tabs = require("sdk/tabs");
const {Cu} = require("chrome");
const self = require("sdk/self");
const {uuid} = require("sdk/util/uuid");
const simplePrefs = require("sdk/simple-prefs");
const eventConstants = require("../common/event-constants");

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Locale.jsm");

const TELEMETRY_PREF = "telemetry";
const COMPLETE_NOTIF = "tab-session-complete";
const ACTION_NOTIF = "user-action-event";
const PERFORMANCE_NOTIF = "performance-event";
const PERF_LOG_COMPLETE_NOTIF = "performance-log-complete";

function TabTracker(trackableURLs, clientID, placesQueries, experimentId) {
  this._tabData = {};

  this._clientID = clientID;
  this._experimentID = experimentId;
  this._trackableURLs = trackableURLs;
  this._placesQueries = placesQueries;
  this.onOpen = this.onOpen.bind(this);
  this.onPerfLoadComplete = this.onPerfLoadComplete.bind(this);

  this._onPrefChange = this._onPrefChange.bind(this);
  this.enabled = simplePrefs.prefs[TELEMETRY_PREF];
  if (this.enabled) {
    this._addListeners();
  }
  simplePrefs.on(TELEMETRY_PREF, this._onPrefChange);
}

TabTracker.prototype = {
  _openTabs: {},

  get tabData() {
    return this._tabData;
  },

  _addListeners() {
    tabs.on("open", this.onOpen);
    Services.obs.addObserver(this.onPerfLoadComplete, PERF_LOG_COMPLETE_NOTIF);
  },

  _removeListeners() {
    for (let id in this._openTabs) {
      let tab = this._openTabs[id].tab;
      tab.removeListener("ready", this.logReady);
      tab.removeListener("pageshow", this.logPageShow);
      tab.removeListener("activate", this.logActivate);
      tab.removeListener("deactivate", this.logDeactivate);
      tab.removeListener("close", this.logClose);
    }
    tabs.removeListener("open", this.onOpen);

    if (this.enabled) {
      Services.obs.removeObserver(this.onPerfLoadComplete, PERF_LOG_COMPLETE_NOTIF);
    }
  },

  _clearTabData() {
    // keep history and bookmarks sizes of the current tabData
    let {total_history_size, total_bookmarks} = this._tabData;
    this._tabData = {
      total_history_size,
      total_bookmarks
    };
  },

  _resolvePageType(tabUrl) {
    let page = eventConstants.defaultPage;
    eventConstants.urlPatternToPageMap.forEach((value, pattern) => {
      if (pattern.test(tabUrl)) {
        page = value;
      }
    });
    return page;
  },

  _setCommonProperties(payload, url) {
    payload.client_id = this._clientID;
    payload.addon_version = self.version;
    payload.locale = Locale.getLocale();
    payload.page = this._resolvePageType(url);
    payload.session_id = this._tabData.session_id;
    if (this._experimentID) {
      payload.experiment_id = this._experimentID;
    }
  },

  uninit() {
    this._removeListeners();
    if (this.enabled) {
      simplePrefs.removeListener(TELEMETRY_PREF, this._onPrefChange);
      this.enabled = false;
    }
  },

  isActivityStreamsURL(URL) {
    return this._trackableURLs.indexOf(URL) !== -1;
  },

  handleUserEvent(payload, experimentId) {
    payload.action = "activity_stream_event";
    payload.tab_id = tabs.activeTab.id;
    this._setCommonProperties(payload, tabs.activeTab.url);
    Services.obs.notifyObservers(null, ACTION_NOTIF, JSON.stringify(payload));
    if (payload.event === "SEARCH" || payload.event === "CLICK") {
      this._tabData.unload_reason = payload.event.toLowerCase();
    }
  },

  handlePerformanceEvent(eventData, eventName, value) {
    let payload = Object.assign({}, eventData);
    payload.action = "activity_stream_performance";
    payload.tab_id = tabs.activeTab.id;
    payload.event = eventName;
    payload.value = value;
    this._setCommonProperties(payload, tabs.activeTab.url);
    Services.obs.notifyObservers(null, PERFORMANCE_NOTIF, JSON.stringify(payload));
  },

  handleRouteChange(tab, route) {
    if (!route.isFirstLoad) {
      this.navigateAwayFromPage(tab, "route_change");
      this.logReady(tab);
    }
  },

  generateEvent(eventData) {
    return Object.assign({}, eventData, {event_id: String(uuid())});
  },

  _initTabSession(tab, loadReason) {
    // For session IDs that were set on tab open, let's make sure we
    // don't overwrite them.<commit_msg>fix (addon): #1013 only send tab data if there is an active tab (#1031)<commit_after>/* globals Services, Locale */

const tabs = require("sdk/tabs");
const {Cu} = require("chrome");
const self = require("sdk/self");
const {uuid} = require("sdk/util/uuid");
const simplePrefs = require("sdk/simple-prefs");
const eventConstants = require("../common/event-constants");

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Locale.jsm");

const TELEMETRY_PREF = "telemetry";
const COMPLETE_NOTIF = "tab-session-complete";
const ACTION_NOTIF = "user-action-event";
const PERFORMANCE_NOTIF = "performance-event";
const PERF_LOG_COMPLETE_NOTIF = "performance-log-complete";

function TabTracker(trackableURLs, clientID, placesQueries, experimentId) {
  this._tabData = {};

  this._clientID = clientID;
  this._experimentID = experimentId;
  this._trackableURLs = trackableURLs;
  this._placesQueries = placesQueries;
  this.onOpen = this.onOpen.bind(this);
  this.onPerfLoadComplete = this.onPerfLoadComplete.bind(this);

  this._onPrefChange = this._onPrefChange.bind(this);
  this.enabled = simplePrefs.prefs[TELEMETRY_PREF];
  if (this.enabled) {
    this._addListeners();
  }
  simplePrefs.on(TELEMETRY_PREF, this._onPrefChange);
}

TabTracker.prototype = {
  _openTabs: {},

  get tabData() {
    return this._tabData;
  },

  _addListeners() {
    tabs.on("open", this.onOpen);
    Services.obs.addObserver(this.onPerfLoadComplete, PERF_LOG_COMPLETE_NOTIF);
  },

  _removeListeners() {
    for (let id in this._openTabs) {
      let tab = this._openTabs[id].tab;
      tab.removeListener("ready", this.logReady);
      tab.removeListener("pageshow", this.logPageShow);
      tab.removeListener("activate", this.logActivate);
      tab.removeListener("deactivate", this.logDeactivate);
      tab.removeListener("close", this.logClose);
    }
    tabs.removeListener("open", this.onOpen);

    if (this.enabled) {
      Services.obs.removeObserver(this.onPerfLoadComplete, PERF_LOG_COMPLETE_NOTIF);
    }
  },

  _clearTabData() {
    // keep history and bookmarks sizes of the current tabData
    let {total_history_size, total_bookmarks} = this._tabData;
    this._tabData = {
      total_history_size,
      total_bookmarks
    };
  },

  _resolvePageType(tabUrl) {
    let page = eventConstants.defaultPage;
    eventConstants.urlPatternToPageMap.forEach((value, pattern) => {
      if (pattern.test(tabUrl)) {
        page = value;
      }
    });
    return page;
  },

  _setCommonProperties(payload, url) {
    payload.client_id = this._clientID;
    payload.addon_version = self.version;
    payload.locale = Locale.getLocale();
    payload.page = this._resolvePageType(url);
    payload.session_id = this._tabData.session_id;
    if (this._experimentID) {
      payload.experiment_id = this._experimentID;
    }
  },

  uninit() {
    this._removeListeners();
    if (this.enabled) {
      simplePrefs.removeListener(TELEMETRY_PREF, this._onPrefChange);
      this.enabled = false;
    }
  },

  isActivityStreamsURL(URL) {
    return this._trackableURLs.indexOf(URL) !== -1;
  },

  handleUserEvent(payload, experimentId) {
    payload.action = "activity_stream_event";
    payload.tab_id = tabs.activeTab.id;
    this._setCommonProperties(payload, tabs.activeTab.url);
    Services.obs.notifyObservers(null, ACTION_NOTIF, JSON.stringify(payload));
    if (payload.event === "SEARCH" || payload.event === "CLICK") {
      this._tabData.unload_reason = payload.event.toLowerCase();
    }
  },

  handlePerformanceEvent(eventData, eventName, value) {
    if (!tabs.activeTab) {
      // short circuit out if there is no active tab
      return;
    }

    let payload = Object.assign({}, eventData);
    payload.action = "activity_stream_performance";
    payload.tab_id = tabs.activeTab.id;
    payload.event = eventName;
    payload.value = value;
    this._setCommonProperties(payload, tabs.activeTab.url);
    Services.obs.notifyObservers(null, PERFORMANCE_NOTIF, JSON.stringify(payload));
  },

  handleRouteChange(tab, route) {
    if (!route.isFirstLoad) {
      this.navigateAwayFromPage(tab, "route_change");
      this.logReady(tab);
    }
  },

  generateEvent(eventData) {
    return Object.assign({}, eventData, {event_id: String(uuid())});
  },

  _initTabSession(tab, loadReason) {
    // For session IDs that were set on tab open, let's make sure we
    // don't overwrite them.
{'fraction_non_alphanumeric': 0.13362415336930317, 'fraction_numerical': 0.0011479738261967627, 'mean_word_length': 3.8916339135317237, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5785746', 'n_tokens_mistral': 2872, 'n_tokens_neox': 2826, 'n_words': 480}