]> git.wh0rd.org Git - chrome-ext/tabs-backup.git/blob - background.js
use SI unit labels
[chrome-ext/tabs-backup.git] / background.js
1
2 // Set default values if needed
3 if (!localStorage.prefsMaxBackupItems) {
4         localStorage.prefsMaxBackupItems = "10";
5 }
6
7 if (!localStorage.prefsBackupTimer) {
8         localStorage.prefsBackupTimer = "30";
9 }
10
11 if (!localStorage.lastBackupTime) {
12         localStorage.lastBackupTime = -1;
13
14         // Create a backup now
15         var d = new Date();
16         var formattedDate = date_format (d);
17
18         backupNow(true, formattedDate, function(success, backupName, backupObj) {
19                 // backup completed
20         });
21 }
22
23 function initAlarm () {
24         //console.log("initAlarm");
25
26         var BACKUP_ALARM_NAME = "backup_alarm";
27
28         // Clear any previous alarm
29         chrome.alarms.clearAll();
30
31         var timerMinutes = parseInt(localStorage.prefsBackupTimer);
32         chrome.alarms.create(BACKUP_ALARM_NAME, {periodInMinutes: timerMinutes});
33 }
34
35 initAlarm();
36
37 function onAlarm (alarm) {
38         var d = new Date();
39         var formattedDate = date_format (d);
40
41         console.log("Alarm {" + alarm + "} fired up: " + formattedDate);
42
43         // if last backup time != lastTabsEdit
44         //      perform automatic backup
45                 backupNow(true, formattedDate, function(success, backupName, backupObj) {
46                         // automatic backup completed
47                         var popupViews = chrome.extension.getViews({type: "popup"});
48                         if (popupViews.length > 0) {
49                                 for (var i = 0; i < popupViews.length; i++) {
50                                         var popupView = popupViews[i];
51                                         if (!popupView.insertBackupItem) {
52                                                 continue;
53                                         }
54
55                                         popupView.insertBackupItem(backupName, backupObj, true /*insertAtBeginning*/, true /*doAnimation*/);
56                                         popupView.updateStorageInfo();
57                                 }
58                         }
59                 });
60 }
61
62 chrome.alarms.onAlarm.addListener(onAlarm);
63
64 function date_prependZero (val) {
65         return val < 10 ? "0" + val : "" + val;
66 }
67
68 // yyyy-m-d h:i:s
69 function date_format (d) {
70         var monthOneOffset = d.getMonth() + 1; // convert from 0-11 to 1-12
71
72         var formattedDate = d.getFullYear() + "-" + date_prependZero(monthOneOffset) + "-" + date_prependZero(d.getDate())
73                 + " " + date_prependZero(d.getHours()) + ":" + date_prependZero(d.getMinutes()) + ":" + date_prependZero(d.getSeconds());
74
75         return formattedDate;
76 }
77
78
79 function backupNowManual (callbackDone) {
80         var d = new Date();
81         var formattedDate = date_format (d);
82
83         backupNow(false, formattedDate, callbackDone);
84
85
86 }
87
88 function deleteOldestBackup () {
89         chrome.storage.local.get("backups_list", function(items) {
90                 if(!items.backups_list) {
91                         return;
92                 }
93
94                 var backupsList = items.backups_list;
95                 var numItemsToDelete = backupsList.length - parseInt(localStorage.prefsMaxBackupItems);
96                 if (numItemsToDelete > 0) {
97                         var i = 0;
98                         var loopFunc = function () {
99                                 //
100                                 if (i > 0) {
101                                         var deletedBackupName = backupsList[i-1];
102                                         var popupViews = chrome.extension.getViews({type: "popup"});
103                                         if (popupViews.length > 0) {
104                                                 for (var j = 0; j < popupViews.length; j++) {
105                                                         var popupView = popupViews[j];
106                                                         if (!popupView.removeBackupItemDiv) {
107                                                                 continue;
108                                                         }
109
110                                                         popupView.removeBackupItemDiv(deletedBackupName);
111                                                         popupView.updateStorageInfo();
112                                                 }
113                                         }
114                                 }
115                                 //
116
117                                 if (i >= numItemsToDelete) {
118                                         return;
119                                 }
120
121                                 deleteBackup (backupsList[i], loopFunc);
122                                 i++;
123                         };
124
125                         loopFunc ();
126                 }
127
128                 //for (var i = 0; i < numItemsToDelete; i++) {
129                 // TODO WARNING: I'm calling deleteBackup rapidly, while deleting is async...(I should wait for each delete to complete before deleting the next)
130                         //deleteBackup (backupsList[i], function() {
131
132                         //});
133                 //}
134
135         });
136 }
137
138 //var isCreatingBackup = false;
139
140 function backupNow(isAutomatic, backupName, callbackDone) {
141         console.log("backupNow - isAutomatic: " + isAutomatic + " name: " + backupName);
142         /*if (isCreatingBackup === true) {
143                 console.log("backupNow - already running..skipping..");
144                 return;
145         }*/
146
147         //isCreatingBackup = true;
148
149         /*if (!confirm("Perform a full backup? All windows and their tabs will be saved!")) {
150                 return;
151         }*/
152
153         var fullBackup = {
154                 windows: [],
155                 isAutomatic: isAutomatic,
156                 totNumTabs: 0
157         };
158
159         chrome.windows.getAll({populate : true}, function (window_list) {
160                 var totNumTabs = 0;
161
162                 for(var i=0;i<window_list.length;i++) {
163                         var window = window_list[i];
164
165                         //console.log ("Window " + i);
166
167                         var bkpWindow = {
168                                 state: window.state,
169                                 top: window.top,
170                                 left: window.left,
171                                 width: window.width,
172                                 height: window.height,
173                                 tabs: []
174                         };
175
176                         var windowTabs = window.tabs;
177
178                         // If it's a single window sittig at the new tab page, don't bother
179                         // saving it.  This is a nice shortcut when things crash as it will
180                         // only show a single window.
181                         if (windowTabs.length == 1) {
182                                 const tab = windowTabs[0];
183                                 if (tab.title == 'New Tab' && tab.url == 'chrome://newtab/')
184                                         continue;
185                         }
186
187                         for (var j = 0; j < windowTabs.length; j++) {
188                                 var tab = windowTabs[j];
189
190                                 //console.log("==> Tab " + j + " (" + tab.index + "): " + tabUrl);
191
192                                 var bkpTab = {
193                                         url: tab.url,
194                                         title: tab.title,
195                                         highlighted: tab.highlighted,
196                                         pinned: tab.pinned,
197                                 };
198
199                                 // Add tab to tabs arrays
200                                 bkpWindow.tabs.push(bkpTab);
201                         }
202
203                         totNumTabs += windowTabs.length;
204
205                         fullBackup.windows.push(bkpWindow);
206                 }
207
208                 if (totNumTabs == 0)
209                         return;
210
211                 fullBackup.totNumTabs = totNumTabs;
212
213                 var storageSetValues = {};
214                 storageSetValues[backupName] = fullBackup;
215
216                 // Store backup
217                 chrome.storage.local.set(storageSetValues, function () {
218                         if (chrome.runtime.lastError) {
219                                 //isCreatingBackup = false;
220                                 // TODO change icon to error..
221                                 //alert ("Error: " + chrome.runtime.lastError.message);
222                                 updateBrowserActionIcon (1);
223
224                                 callbackDone(false);
225                         } else {
226                                 console.log("backup saved");
227                                 //alert("Backup saved successfully!");
228
229                                 chrome.storage.local.get("backups_list", function(items) {
230                                         var backupsList = [];
231                                         if(items.backups_list) {
232                                                 backupsList = items.backups_list;
233                                         }
234
235                                         console.log("Updating 'backups_list' - cur. size: " + backupsList.length);
236
237                                         backupsList.push(backupName);
238
239                                         chrome.storage.local.set({"backups_list": backupsList}, function () {
240                                                 //isCreatingBackup = false;
241
242                                                 if (chrome.runtime.lastError) {
243                                                         console.log ("Error saving backups_list: " + chrome.runtime.lastError.message);
244                                                         updateBrowserActionIcon (1);
245                                                         callbackDone(false);
246                                                 } else {
247                                                         console.log("Backups list saved successfully");
248
249                                                         updateBrowserActionIcon (0);
250                                                         callbackDone(true, backupName, fullBackup);
251
252                                                         if (backupsList.length > parseInt(localStorage.prefsMaxBackupItems)) {
253                                                                 deleteOldestBackup();
254                                                         }
255                                                 }
256                                         });
257                                 });
258                         }
259                 });
260         });
261 }
262
263 /**
264  * 0 ==> OK
265  * 1 ==> ERROR
266  */
267 function updateBrowserActionIcon (status) {
268         var icon;
269         switch(status) {
270                 case 0:
271                         icon = "icon_ok.png";
272                         break;
273                 default:
274                         icon = "icon_error.png";
275                         break;
276         }
277
278         chrome.browserAction.setIcon({path: icon});
279 }
280
281 function deleteBackup (backupName, callback) {
282         console.log("Deleting backup " + backupName);
283
284         chrome.storage.local.remove(backupName, function() {
285                 //console.log ("=> Deleted backup " + backupName);
286
287                 chrome.storage.local.get("backups_list", function(items) {
288                         //console.log ("==> got backups_list " + backupName);
289
290                         if(!items.backups_list) {
291                                 callback();
292                                 return;
293                         }
294
295                         var backupsList = items.backups_list;
296
297                         var index = backupsList.indexOf(backupName);
298                         if (index >= 0) {
299                                 backupsList.splice(index, 1);
300                         }
301
302                         //console.log ("===> Updating backups_list (removing " + backupName + ")");
303
304                         chrome.storage.local.set({"backups_list": backupsList}, function() {
305                                 //console.log ("===> Updated backups_list (removed " + backupName + ")");
306
307                                 callback();
308                         });
309
310                         //console.log ("==> EXIT got backups_list " + backupName);
311                 });
312
313                 //console.log ("=> EXIT Deleted backup " + backupName);
314         });
315
316         //console.log("EXIT Deleting backup " + backupName);
317
318
319 }
320
321 function restoreNow(backupName) {
322         console.log("restoreNow");
323
324         chrome.storage.local.get(backupName, function(items) {
325                 if(!items[backupName]) {
326                         alert("No Backup found");
327                         return;
328                 }
329
330                 /*if (!confirm("Restore full backup?")) {
331                         return;
332                 }*/
333                 /*
334                 if (confirm("Would you like to close all existing windows first?")) {
335                         chrome.windows.getAll({populate : false}, function (window_list) {
336                                 for(var i=0;i<window_list.length;i++) {
337                                         var window = window_list[i];
338                                         chrome.windows.remove(window.id);
339                                 }
340                         });
341                 }*/
342
343
344                 var fullBackup = items[backupName];
345
346                 for(var i=0;i<fullBackup.windows.length;i++) {
347                         const window = fullBackup.windows[i];
348
349                         //console.log ("Window " + i);
350
351                         urlsToOpen = [];
352
353                         const windowTabs = window.tabs;
354                         for (let j = 0; j < windowTabs.length; j++) {
355                                 const tab = windowTabs[j];
356                                 const tabUrl = tab.url;
357                                 urlsToOpen.push(tabUrl);
358                         }
359
360                         const windowProperties = {
361                                 state: 'normal',
362                                 url: urlsToOpen,
363                                 top: window.top,
364                                 left: window.left,
365                                 width: window.width,
366                                 height: window.height,
367                         };
368
369                         // Create a new Window
370                         chrome.windows.create(windowProperties, function(createdWindow) {
371                                 // Chrome errors if the dimensions are set on non-normal windows.
372                                 // So we create the window first with the right settings, then
373                                 // update the window state.
374                                 if (window.state != 'normal') {
375                                         chrome.windows.update(createdWindow.id, {state: window.state});
376                                 }
377
378                                 chrome.windows.get(createdWindow.id, {populate: true}, ({tabs}) => {
379                                         for (let tabi = 0; tabi < windowTabs.length; ++tabi) {
380                                                 const oldtab = windowTabs[tabi];
381                                                 const newtab = tabs[tabi];
382                                                 chrome.tabs.update(newtab.id, {
383                                                         highlighted: oldtab.highlighted,
384                                                         pinned: oldtab.pinned,
385                                                 }, () => {
386                                                         if (!oldtab.highlighted) {
387                                                                 // If we discard a tab too fast, Chrome will completely
388                                                                 // throw it away.  Wait until it's in a stable enough
389                                                                 // state for us to discard it.
390                                                                 let retryCount = 60;
391                                                                 const checktab = (id) => {
392                                                                         if (retryCount-- < 0)
393                                                                                 return;
394                                                                         chrome.tabs.get(id, (tab) => {
395                                                                                 if (tab.pendingUrl)
396                                                                                         setTimeout(() => checktab(id), 500);
397                                                                                 else
398                                                                                         chrome.tabs.discard(id);
399                                                                         });
400                                                                 };
401                                                                 checktab(newtab.id);
402                                                         }
403                                                 });
404                                         }
405                                 });
406                         });
407                 }
408         });
409 }