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