• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/** Convert chrome tabs API to promise */
2const chromeTabs = {
3  get: function(tabId) {
4    return new Promise(function(resolve) {
5      chrome.tabs.get(tabId, resolve);
6    });
7  },
8
9  sendMessage: function(tabId, message, options) {
10    return new Promise(function(resolve) {
11      chrome.tabs.sendMessage(tabId, message, options, resolve);
12    });
13  },
14};
15
16class TaskMonitor {
17  constructor() {
18    // Bind the callback
19    this._updated = this._updated.bind(this);
20    this._records = [];
21  }
22
23  bind() {
24    chrome.processes.onUpdated.addListener(this._updated);
25  }
26
27  unbind() {
28    chrome.processes.onUpdated.removeListener(this._updated);
29  }
30
31  _updated(processes) {
32    // Structure to hold synthesized data
33    const data = {
34      timestamp: Date.now(),
35      processes: [],
36      tabInfo: [],
37    };
38
39    // Produce a set of tabId's to populate data.tabInfo in a separate loop
40    const tabset = new Set();
41
42    // Only take a subset of the process data
43    for (const process of Object.values(processes)) {
44      // Skip processes that don't consume CPU
45      if (process.cpu == 0) {
46        continue;
47      }
48
49      // Only take a subset of the data
50      const currProcess = {
51        pid: process.osProcessId,
52        network: process.network,
53        cpu: process.cpu,
54        tasks: [],
55      };
56
57      // Populate process info with 'tabId' and 'title' information
58      for (const task of Object.values(process.tasks)) {
59        if ('tabId' in task) {
60          tabset.add(task.tabId);
61          currProcess.tasks.push({
62            tabId: task.tabId,
63            title: task.title,
64          });
65        } else {
66          if ('title' in task) {
67            currProcess.tasks.push({title: task.title});
68          }
69        }
70      }
71      data.processes.push(currProcess);
72    }
73
74    // Populate data.tabInfo with unique tabId's
75    for (const tabId of tabset) {
76      data.tabInfo.push({tabId: tabId});
77    }
78
79    const promises = [];
80
81    // Record url, audio, muted, and video count
82    // information per currently open tab
83    for (const tabInfo of data.tabInfo) {
84      promises.push(
85          chromeTabs.get(tabInfo.tabId).then((tab) => {
86            tabInfo.title = tab.title;
87            tabInfo.url = tab.url;
88            tabInfo.audio_played = !!tab.audible;
89            tabInfo.muted = tab.mutedInfo.muted;
90          })
91      );
92
93      promises.push(
94          chromeTabs.sendMessage(tabInfo.tabId, 'numberOfVideosPlaying')
95              .then((n) => {
96                if (typeof n === 'undefined') {
97                  tabInfo.videos_playing = 0;
98                  return;
99                } else {
100                  tabInfo.videos_playing = n;
101                }
102              })
103      );
104    }
105
106    Promise.all(promises).finally(() => {
107      this._records.push(data);
108
109      if (this._records.length >= 1) {
110        this._send();
111      }
112    });
113  }
114
115  _send() {
116    const formData = new FormData();
117    this._records.forEach(function(record, index) {
118      formData.append(index, JSON.stringify(record));
119    });
120    this._records.length = 0;
121
122    const url = 'http://localhost:8001/task-monitor';
123    const req = new XMLHttpRequest();
124    req.open('POST', url, true);
125    req.send(formData);
126  }
127}
128
129this.task_monitor = new TaskMonitor();
130