-
Notifications
You must be signed in to change notification settings - Fork 11
/
extension.js
224 lines (178 loc) · 6.55 KB
/
extension.js
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
const St = imports.gi.St;
const Main = imports.ui.main;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Soup = imports.gi.Soup;
const Lang = imports.lang;
const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem;
const MessageTray = imports.ui.messageTray;
const Mainloop = imports.mainloop;
const Util = imports.misc.util;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Utils = Me.imports.utils;
const Format = imports.format;
const Gettext = imports.gettext.domain('update-extensions');
const _ = Gettext.gettext;
const REPOSITORY_URL_UPDATE = 'https://extensions.gnome.org/update-info/';
let settings;
let _httpSession;
let _timeoutId = 0;
let metadatas = {};
let LIST = [];
let batches = 0;
let nBatch = 0;
/* Code based on extensionDownloader.js from Jasper St. Pierre */
/* Forked by franglais125 from
* https://extensions.gnome.org/extension/797/extension-update-notifier/ */
function init() {
Utils.initTranslations('update-extensions');
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
// _httpSession.add_feature(new Soup.ProxyResolverDefault());
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
}
function openExtensionList() {
Gio.app_info_launch_default_for_uri('https://extensions.gnome.org/local', global.create_app_launch_context(0, -1));
}
function doNotify() {
let title = _('Extension Updates Available');
let message = _('Some of your installed extensions have updated versions available.\n\n');
message += LIST.join('\n');//
let notifSource = new MessageTray.SystemNotificationSource();
notifSource.createIcon = function() {
return new St.Icon({ icon_name: 'software-update-available-symbolic' });
};
// Take care of note leaving unneeded sources
notifSource.connect('destroy', function() {notifSource = null;});
Main.messageTray.add(notifSource);
let notification = null;
// We do not want to have multiple notifications stacked
// instead we will update previous
if (notifSource.notifications.length == 0) {
notification = new MessageTray.Notification(notifSource, title, message);
notification.addAction( _('Show updates') , openExtensionList);
} else {
notification = notifSource.notifications[0];
notification.update( title, message, { clear: true });
}
notification.setTransient(settings.get_boolean('transient'));
notifSource.notify(notification);
}
function isLocal(uuid) {
if (settings.get_boolean('system-wide-ext'))
return true;
let extension = ExtensionUtils.extensions[uuid];
return extension.path.indexOf(GLib.get_home_dir()) != -1;
}
function setMetadata() {
// Reset
metadatas = {};
let countValidExtensions = 0;
for (let uuid in ExtensionUtils.extensions) {
if (isLocal(uuid)) {
if (typeof ExtensionUtils.extensions[uuid].metadata.version == 'number') {
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
countValidExtensions++;
}
else if (typeof ExtensionUtils.extensions[uuid].metadata.version == 'undefined') {
// Some extensions, especially global, have no version
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
metadatas[uuid].version = 1;
countValidExtensions++;
}
}
}
// In groups of 10 or less, not to overload the server
batches = Math.ceil(countValidExtensions/10.);
}
function getMetadata(i) {
let batchMetadatas = {};
let counter = 0;
for (let uuid in metadatas) {
if (i*10 <= counter && counter < (i+1)*10)
batchMetadatas[uuid] = { version: metadatas[uuid].version };
counter++;
}
return batchMetadatas;
}
function checkForUpdates() {
// Look for all metadatas first
setMetadata();
// Reset batch number and list of updates
nBatch = 0;
LIST = [];
for (let i = 0; i < batches; i++) {
// We get batches of 10
let batchMetadatas = getMetadata(i);
let params = { shell_version: Config.PACKAGE_VERSION,
installed: JSON.stringify(batchMetadatas) };
let url = REPOSITORY_URL_UPDATE;
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, function(session, message) {
let operations = JSON.parse(message.response_body.data);
for (let uuid in operations) {
let operation = operations[uuid];
if (operation == 'blacklist')
continue;
else if (operation == 'upgrade' || operation == 'downgrade')
LIST.push(ExtensionUtils.extensions[uuid].metadata.name);
}
if (hasFinished() && LIST.length > 0) {
doNotify();
}
});
}
scheduleCheck();
}
function hasFinished() {
nBatch++;
if (nBatch == batches)
settings.set_double('last-check-date-double', new Date());
return nBatch == batches;
}
function scheduleCheck() {
if (_timeoutId != 0) {
Mainloop.source_remove(_timeoutId);
_timeoutId = 0;
}
let unit = settings.get_enum('interval-unit');
let conversion = 0;
switch (unit) {
case 0: // Hours
conversion = 60 * 60;
break;
case 1: // Days
conversion = 24 * 60 * 60;
break;
case 2: // Weeks
conversion = 7 * 24 * 60 * 60;
break;
}
let timeout = conversion * settings.get_int('check-interval');
// Check how much time passed since the last check
let last_check = settings.get_double('last-check-date-double');
let now = new Date();
let elapsed = (now - last_check)/1000; // Milliseconds to seconds
// If the difference is low, we should perform a check soon
timeout -= elapsed;
if (timeout < 120)
timeout = 120;
_timeoutId = Mainloop.timeout_add_seconds(timeout, checkForUpdates);
}
function enable() {
// Load settings
settings = Utils.getSettings();
settings.connect('changed::check-interval', scheduleCheck);
settings.connect('changed::interval-unit', scheduleCheck);
scheduleCheck();
}
function disable() {
if (_timeoutId != 0) {
Mainloop.source_remove (_timeoutId);
_timeoutId = 0;
}
settings.run_dispose();
settings = null;
}