blob: 6c88e3d573019b0e751f5ea71f38e845bf0566fe [file] [log] [blame]
Ben Murdochd3868032013-07-31 10:55:33 +01001// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5function pointInElement(p, elem) {
6 return ((p.x >= elem.offsetLeft) &&
7 (p.x <= (elem.offsetLeft + elem.offsetWidth)) &&
8 (p.y >= elem.offsetTop) &&
9 (p.y <= (elem.offsetTop + elem.offsetHeight)));
10};
11
12function setLastOpened() {
13 localStorage.popupLastOpened = (new Date()).getTime();
14 chrome.runtime.sendMessage('poll');
15};
16
17function loadI18nMessages() {
18 function setProperty(selector, prop, msg) {
19 document.querySelector(selector)[prop] = chrome.i18n.getMessage(msg);
20 }
21
22 setProperty('title', 'innerText', 'tabTitle');
23 setProperty('#q', 'placeholder', 'searchPlaceholder');
24 setProperty('#clear-all', 'title', 'clearAllTitle');
25 setProperty('#open-folder', 'title', 'openDownloadsFolderTitle');
26 setProperty('#empty', 'innerText', 'zeroItems');
27 setProperty('#searching', 'innerText', 'searching');
28 setProperty('#search-zero', 'innerText', 'zeroSearchResults');
Ben Murdochbb1529c2013-08-08 10:24:53 +010029 setProperty('#management-permission-info', 'innerText',
30 'managementPermissionInfo');
31 setProperty('#grant-management-permission', 'innerText',
32 'grantManagementPermission');
Ben Murdochd3868032013-07-31 10:55:33 +010033 setProperty('#older', 'innerText', 'showOlderDownloads');
34 setProperty('#loading-older', 'innerText', 'loadingOlderDownloads');
35 setProperty('.pause', 'title', 'pauseTitle');
36 setProperty('.resume', 'title', 'resumeTitle');
37 setProperty('.cancel', 'title', 'cancelTitle');
38 setProperty('.show-folder', 'title', 'showInFolderTitle');
39 setProperty('.erase', 'title', 'eraseTitle');
40 setProperty('.url', 'title', 'retryTitle');
41 setProperty('.referrer', 'title', 'referrerTitle');
42 setProperty('.open-filename', 'title', 'openTitle');
43 setProperty('#bad-chrome-version', 'innerText', 'badChromeVersion');
44 setProperty('.remove-file', 'title', 'removeFileTitle');
45
46 document.querySelector('.progress').style.minWidth =
47 getTextWidth(formatBytes(1024 * 1024 * 1023.9) + '/' +
48 formatBytes(1024 * 1024 * 1023.9)) + 'px';
49
50 // This only covers {timeLeft,openWhenComplete}{Finishing,Days}. If
51 // ...Hours/Minutes/Seconds could be longer for any locale, then this should
52 // test them.
53 var max_time_left_width = 0;
54 for (var i = 0; i < 4; ++i) {
55 max_time_left_width = Math.max(max_time_left_width, getTextWidth(
56 formatTimeLeft(0 == (i % 2),
57 (i < 2) ? 0 : ((100 * 24) + 23) * 60 * 60 * 1000)));
58 }
59 document.querySelector('body div.item span.time-left').style.minWidth =
60 max_time_left_width + 'px';
61};
62
63function getTextWidth(s) {
64 var probe = document.getElementById('text-width-probe');
65 probe.innerText = s;
66 return probe.offsetWidth;
67};
68
69function formatDateTime(date) {
70 var now = new Date();
71 var zpad_mins = ':' + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
72 if (date.getYear() != now.getYear()) {
73 return '' + (1900 + date.getYear());
74 } else if ((date.getMonth() != now.getMonth()) ||
75 (date.getDate() != now.getDate())) {
76 return date.getDate() + ' ' + chrome.i18n.getMessage(
77 'month' + date.getMonth() + 'abbr');
78 } else if (date.getHours() == 12) {
79 return '12' + zpad_mins + 'pm';
80 } else if (date.getHours() > 12) {
81 return (date.getHours() - 12) + zpad_mins + 'pm';
82 }
83 return date.getHours() + zpad_mins + 'am';
84}
85
86function formatBytes(n) {
87 if (n < 1024) {
88 return n + 'B';
89 }
90 var prefixes = 'KMGTPEZY';
91 var mul = 1024;
92 for (var i = 0; i < prefixes.length; ++i) {
93 if (n < (1024 * mul)) {
94 return (parseInt(n / mul) + '.' + parseInt(10 * ((n / mul) % 1)) +
95 prefixes[i] + 'B');
96 }
97 mul *= 1024;
98 }
99 return '!!!';
100}
101
102function formatTimeLeft(openWhenComplete, ms) {
103 var prefix = openWhenComplete ? 'openWhenComplete' : 'timeLeft';
104 if (ms < 1000) {
105 return chrome.i18n.getMessage(prefix + 'Finishing');
106 }
107 var days = parseInt(ms / (24 * 60 * 60 * 1000));
108 var hours = parseInt(ms / (60 * 60 * 1000)) % 24;
109 if (days) {
110 return chrome.i18n.getMessage(prefix + 'Days', [days, hours]);
111 }
112 var minutes = parseInt(ms / (60 * 1000)) % 60;
113 if (hours) {
114 return chrome.i18n.getMessage(prefix + 'Hours', [hours, minutes]);
115 }
116 var seconds = parseInt(ms / 1000) % 60;
117 if (minutes) {
118 return chrome.i18n.getMessage(prefix + 'Minutes', [minutes, seconds]);
119 }
120 return chrome.i18n.getMessage(prefix + 'Seconds', [seconds]);
121}
122
123function binarySearch(array, target, cmp) {
124 var low = 0, high = array.length - 1, i, comparison;
125 while (low <= high) {
126 i = (low + high) >> 1;
127 comparison = cmp(target, array[i]);
128 if (comparison < 0) {
129 low = i + 1;
130 } else if (comparison > 0) {
131 high = i - 1;
132 } else {
133 return i;
134 }
135 }
136 return i;
137};
138
139function arrayFrom(seq) {
140 return Array.prototype.slice.apply(seq);
141};
142
143function DownloadItem(data) {
144 var item = this;
145 for (var prop in data) {
146 item[prop] = data[prop];
147 }
148 item.startTime = new Date(item.startTime);
149 if (item.canResume == undefined) {
150 DownloadItem.canResumeHack = true;
151 }
152
153 item.div = document.querySelector('body>div.item').cloneNode(true);
154 item.div.id = 'item' + item.id;
155 item.div.item = item;
156
157 var items_div = document.getElementById('items');
158 if ((items_div.childNodes.length == 0) ||
159 (item.startTime.getTime() < items_div.childNodes[
160 items_div.childNodes.length - 1].item.startTime.getTime())) {
161 items_div.appendChild(item.div);
162 } else if (item.startTime.getTime() >
163 items_div.childNodes[0].item.startTime.getTime()) {
164 items_div.insertBefore(item.div, items_div.childNodes[0]);
165 } else {
166 var adjacent_div = items_div.childNodes[
167 binarySearch(arrayFrom(items_div.childNodes),
168 item.startTime.getTime(),
169 function(target, other) {
170 return target - other.item.startTime.getTime();
171 })];
172 var adjacent_item = adjacent_div.item;
173 if (adjacent_item.startTime.getTime() < item.startTime.getTime()) {
174 items_div.insertBefore(item.div, adjacent_div);
175 } else {
176 items_div.insertBefore(item.div, adjacent_div.nextSibling);
177 }
178 }
179
180 item.getElement('referrer').onclick = function() {
181 chrome.tabs.create({url: item.referrer});
182 return false;
183 };
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100184 item.getElement('by-ext').onclick = function() {
185 chrome.tabs.create({url: 'chrome://extensions#' + item.byExtensionId});
186 return false;
187 }
Ben Murdochd3868032013-07-31 10:55:33 +0100188 item.getElement('open-filename').onclick = function() {
189 item.open();
190 return false;
191 };
192 item.getElement('open-filename').ondragstart = function() {
193 item.drag();
194 return false;
195 };
196 item.getElement('pause').onclick = function() {
197 item.pause();
198 return false;
199 };
200 item.getElement('cancel').onclick = function() {
201 item.cancel();
202 return false;
203 };
204 item.getElement('resume').onclick = function() {
205 item.resume();
206 return false;
207 };
208 item.getElement('show-folder').onclick = function() {
209 item.show();
210 return false;
211 };
212 item.getElement('remove-file').onclick = function() {
213 item.removeFile();
214 return false;
215 };
216 item.getElement('erase').onclick = function() {
217 item.erase();
218 return false;
219 };
220
221 item.more_mousemove = function(evt) {
222 if (item.getElement('more') &&
223 (pointInElement(evt, item.div) ||
224 pointInElement(evt, item.getElement('more')))) {
225 return;
226 }
227 if (item.getElement('more')) {
228 item.getElement('more').hidden = true;
229 }
230 window.removeEventListener('mousemove', item.more_mousemove);
231 };
232 [item.getElement('icon'), item.getElement('more')].concat(
233 item.getElement('more').children).forEach(function(elem) {
234 elem.onmouseover = function() {
235 arrayFrom(items_div.children).forEach(function(other) {
236 if (other.item != item) {
237 other.item.getElement('more').hidden = true;
238 }
239 });
240 item.getElement('more').hidden = false;
241 item.getElement('more').style.top =
242 (item.div.offsetTop + item.div.offsetHeight) + 'px';
243 item.getElement('more').style.left = item.div.offsetLeft + 'px';
244 if (window.innerHeight < (parseInt(item.getElement('more').style.top) +
245 item.getElement('more').offsetHeight)) {
246 item.getElement('more').style.top = (
247 item.div.offsetTop - item.getElement('more').offsetHeight) + 'px';
248 }
249 window.addEventListener('mousemove', item.more_mousemove);
250 };
251 });
252
253 if (item.referrer) {
254 item.getElement('referrer').href = item.referrer;
255 } else {
256 item.getElement('referrer').hidden = true;
257 }
258 item.getElement('url').href = item.url;
259 item.getElement('url').innerText = item.url;
260 item.render();
261}
262DownloadItem.canResumeHack = false;
263
264DownloadItem.prototype.getElement = function(name) {
265 return document.querySelector('#item' + this.id + ' .' + name);
266};
267
268DownloadItem.prototype.render = function() {
269 var item = this;
270 var now = new Date();
271 var in_progress = (item.state == 'in_progress')
272 var openable = (item.state != 'interrupted') && item.exists && !item.deleted;
273
274 item.startTime = new Date(item.startTime);
275 if (DownloadItem.canResumeHack) {
276 item.canResume = in_progress && item.paused;
277 }
278 if (item.filename) {
279 item.basename = item.filename.substring(Math.max(
280 item.filename.lastIndexOf('\\'),
281 item.filename.lastIndexOf('/')) + 1);
282 }
283 if (item.estimatedEndTime) {
284 item.estimatedEndTime = new Date(item.estimatedEndTime);
285 }
286 if (item.endTime) {
287 item.endTime = new Date(item.endTime);
288 }
289
290 if (item.filename && !item.icon_url) {
291 chrome.downloads.getFileIcon(
292 item.id,
293 {'size': 32},
294 function(icon_url) {
295 item.getElement('icon').hidden = !icon_url;
296 if (icon_url) {
297 item.icon_url = icon_url;
298 item.getElement('icon').src = icon_url;
299 }
300 });
301 }
302
Ben Murdochbb1529c2013-08-08 10:24:53 +0100303 item.getElement('removed').style.display = openable ? 'none' : 'inline';
Ben Murdochd3868032013-07-31 10:55:33 +0100304 item.getElement('open-filename').style.display = (
Ben Murdochbb1529c2013-08-08 10:24:53 +0100305 openable ? 'inline' : 'none');
Ben Murdochd3868032013-07-31 10:55:33 +0100306 item.getElement('in-progress').hidden = !in_progress;
307 item.getElement('pause').style.display = (
308 !in_progress || item.paused) ? 'none' : 'inline-block';
309 item.getElement('resume').style.display = (
310 !in_progress || !item.canResume) ? 'none' : 'inline-block';
311 item.getElement('cancel').style.display = (
312 !in_progress ? 'none' : 'inline-block');
313 item.getElement('remove-file').hidden = (
314 (item.state != 'complete') ||
315 !item.exists ||
316 item.deleted ||
317 !chrome.downloads.removeFile);
318 item.getElement('erase').hidden = in_progress;
319
320 var could_progress = in_progress || item.canResume;
321 item.getElement('progress').style.display = (
322 could_progress ? 'inline-block' : 'none');
323 item.getElement('meter').hidden = !could_progress || !item.totalBytes;
324
325 item.getElement('removed').innerText = item.basename;
326 item.getElement('open-filename').innerText = item.basename;
327
Ben Murdochbb1529c2013-08-08 10:24:53 +0100328 function setByExtension(show) {
329 if (show) {
330 item.getElement('by-ext').title = item.byExtensionName;
331 item.getElement('by-ext').href =
332 'chrome://extensions#' + item.byExtensionId;
333 item.getElement('by-ext img').src =
334 'chrome://extension-icon/' + item.byExtensionId + '/48/1';
335 } else {
336 item.getElement('by-ext').hidden = true;
337 }
338 }
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100339 if (item.byExtensionId && item.byExtensionName) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100340 chrome.permissions.contains({permissions: ['management']},
341 function(result) {
342 if (result) {
343 setByExtension(true);
344 } else {
345 setByExtension(false);
346 if (!localStorage.managementPermissionDenied) {
347 document.getElementById('request-management-permission').hidden =
348 false;
349 document.getElementById('grant-management-permission').onclick =
350 function() {
351 chrome.permissions.request({permissions: ['management']},
352 function(granted) {
353 setByExtension(granted);
354 if (!granted) {
355 localStorage.managementPermissionDenied = true;
356 }
357 });
358 return false;
359 };
360 }
361 }
362 });
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100363 } else {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100364 setByExtension(false);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100365 }
366
Ben Murdochd3868032013-07-31 10:55:33 +0100367 if (!item.getElement('error').hidden) {
368 if (item.error) {
369 // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is
370 // released, set minimum_chrome_version and remove the error_N messages.
371 item.getElement('error').innerText = chrome.i18n.getMessage(
372 'error_' + item.error);
373 if (!item.getElement('error').innerText) {
374 item.getElement('error').innerText = item.error;
375 }
376 } else if (!openable) {
377 item.getElement('error').innerText = chrome.i18n.getMessage(
378 'errorRemoved');
379 }
380 }
381
382 item.getElement('complete-size').innerText = formatBytes(
383 item.bytesReceived);
384 if (item.totalBytes && (item.state != 'complete')) {
385 item.getElement('progress').innerText = (
386 item.getElement('complete-size').innerText + '/' +
387 formatBytes(item.totalBytes));
388 item.getElement('meter').children[0].style.width = parseInt(
389 100 * item.bytesReceived / item.totalBytes) + '%';
390 }
391
392 if (in_progress) {
393 if (item.estimatedEndTime && !item.paused) {
394 var openWhenComplete = false;
395 try {
396 openWhenComplete = JSON.parse(localStorage.openWhenComplete).indexOf(
397 item.id) >= 0;
398 } catch (e) {
399 }
400 item.getElement('time-left').innerText = formatTimeLeft(
401 openWhenComplete, item.estimatedEndTime.getTime() - now.getTime());
402 } else {
403 item.getElement('time-left').innerText = String.fromCharCode(160);
404 }
405 }
406
407 if (item.startTime) {
408 item.getElement('start-time').innerText = formatDateTime(
409 item.startTime);
410 }
411
412 this.maybeAccept();
413};
414
415DownloadItem.prototype.onChanged = function(delta) {
416 for (var key in delta) {
417 if (key != 'id') {
418 this[key] = delta[key].current;
419 }
420 }
421 this.render();
422 if (delta.state) {
423 setLastOpened();
424 }
425 if ((this.state == 'in_progress') && !this.paused) {
426 DownloadManager.startPollingProgress();
427 }
428};
429
430DownloadItem.prototype.onErased = function() {
431 window.removeEventListener('mousemove', this.more_mousemove);
432 document.getElementById('items').removeChild(this.div);
433};
434
435DownloadItem.prototype.drag = function() {
436 chrome.downloads.drag(this.id);
437};
438
439DownloadItem.prototype.show = function() {
440 chrome.downloads.show(this.id);
441};
442
443DownloadItem.prototype.open = function() {
444 if (this.state == 'complete') {
445 chrome.downloads.open(this.id);
446 return;
447 }
448 chrome.runtime.sendMessage({openWhenComplete:this.id});
449};
450
451DownloadItem.prototype.removeFile = function() {
452 chrome.downloads.removeFile(this.id);
453 this.deleted = true;
454 this.render();
455};
456
457DownloadItem.prototype.erase = function() {
458 chrome.downloads.erase({id: this.id});
459};
460
461DownloadItem.prototype.pause = function() {
462 chrome.downloads.pause(this.id);
463};
464
465DownloadItem.prototype.resume = function() {
466 chrome.downloads.resume(this.id);
467};
468
469DownloadItem.prototype.cancel = function() {
470 chrome.downloads.cancel(this.id);
471};
472
473DownloadItem.prototype.maybeAccept = function() {
474 // This function is safe to call at any time for any item, and it will always
475 // do the right thing, which is to display the danger prompt only if the item
476 // is in_progress and dangerous, and if the prompt is not already displayed.
477 if ((this.state != 'in_progress') ||
478 (this.danger == 'safe') ||
479 (this.danger == 'accepted') ||
480 DownloadItem.prototype.maybeAccept.accepting_danger) {
481 return;
482 }
483 DownloadItem.prototype.maybeAccept.accepting_danger = true;
484 chrome.downloads.acceptDanger(this.id, function() {
485 DownloadItem.prototype.maybeAccept.accepting_danger = false;
486 arrayFrom(document.getElementById('items').childNodes).forEach(
487 function(item_div) { item_div.item.maybeAccept(); });
488 });
489};
490DownloadItem.prototype.maybeAccept.accepting_danger = false;
491
492var DownloadManager = {};
493
494DownloadManager.showingOlder = false;
495
496DownloadManager.getItem = function(id) {
497 var item_div = document.getElementById('item' + id);
498 return item_div ? item_div.item : null;
499};
500
501DownloadManager.getOrCreate = function(data) {
502 var item = DownloadManager.getItem(data.id);
503 return item ? item : new DownloadItem(data);
504};
505
506DownloadManager.forEachItem = function(cb) {
507 // Calls cb(item, index) in the order that they are displayed, i.e. in order
508 // of decreasing startTime.
509 arrayFrom(document.getElementById('items').childNodes).forEach(
510 function(item_div, index) { cb(item_div.item, index); });
511};
512
513DownloadManager.startPollingProgress = function() {
514 if (DownloadManager.startPollingProgress.tid < 0) {
515 DownloadManager.startPollingProgress.tid = setTimeout(
516 DownloadManager.startPollingProgress.pollProgress,
517 DownloadManager.startPollingProgress.MS);
518 }
519}
520DownloadManager.startPollingProgress.MS = 200;
521DownloadManager.startPollingProgress.tid = -1;
522DownloadManager.startPollingProgress.pollProgress = function() {
523 DownloadManager.startPollingProgress.tid = -1;
524 chrome.downloads.search({state: 'in_progress', paused: false},
525 function(results) {
526 if (!results.length)
527 return;
528 results.forEach(function(result) {
529 var item = DownloadManager.getOrCreate(result);
530 for (var prop in result) {
531 item[prop] = result[prop];
532 }
533 item.render();
534 if ((item.state == 'in_progress') && !item.paused) {
535 DownloadManager.startPollingProgress();
536 }
537 });
538 });
539};
540
541DownloadManager.showNew = function() {
542 var any_items = (document.getElementById('items').childNodes.length > 0);
543 document.getElementById('empty').style.display =
544 any_items ? 'none' : 'inline-block';
Ben Murdochbb1529c2013-08-08 10:24:53 +0100545 document.getElementById('head').style.borderBottomWidth =
546 (any_items ? 1 : 0) + 'px';
Ben Murdochd3868032013-07-31 10:55:33 +0100547 document.getElementById('clear-all').hidden = !any_items;
Ben Murdochd3868032013-07-31 10:55:33 +0100548
549 var query_search = document.getElementById('q');
550 query_search.hidden = !any_items;
551
552 if (!any_items) {
553 return;
554 }
555 var old_ms = (new Date()).getTime() - kOldMs;
556 var any_hidden = false;
557 var any_showing = false;
558 // First show up to kShowNewMax items newer than kOldMs. If there aren't any
559 // items newer than kOldMs, then show up to kShowNewMax items of any age. If
560 // there are any hidden items, show the Show Older button.
561 DownloadManager.forEachItem(function(item, index) {
562 item.div.hidden = !DownloadManager.showingOlder && (
563 (item.startTime.getTime() < old_ms) || (index >= kShowNewMax));
564 any_hidden = any_hidden || item.div.hidden;
565 any_showing = any_showing || !item.div.hidden;
566 });
567 if (!any_showing) {
568 any_hidden = false;
569 DownloadManager.forEachItem(function(item, index) {
570 item.div.hidden = !DownloadManager.showingOlder && (index >= kShowNewMax);
571 any_hidden = any_hidden || item.div.hidden;
572 any_showing = any_showing || !item.div.hidden;
573 });
574 }
575 document.getElementById('older').hidden = !any_hidden;
576
577 query_search.focus();
578};
579
580DownloadManager.showOlder = function() {
581 DownloadManager.showingOlder = true;
582 var loading_older_span = document.getElementById('loading-older');
583 document.getElementById('older').hidden = true;
584 loading_older_span.hidden = false;
585 chrome.downloads.search({}, function(results) {
586 results.forEach(function(result) {
587 var item = DownloadManager.getOrCreate(result);
588 item.div.hidden = false;
589 });
590 loading_older_span.hidden = true;
591 });
592};
593
594DownloadManager.onSearch = function() {
595 // split string by space, but ignore space in quotes
596 // http://stackoverflow.com/questions/16261635
597 var query = document.getElementById('q').value.match(/(?:[^\s"]+|"[^"]*")+/g);
598 if (!query) {
599 DownloadManager.showNew();
600 document.getElementById('search-zero').hidden = true;
601 } else {
602 query = query.map(function(term) {
603 // strip quotes
604 return (term.match(/\s/) &&
605 term[0].match(/["']/) &&
606 term[term.length - 1] == term[0]) ?
607 term.substr(1, term.length - 2) : term;
608 });
609 var searching = document.getElementById('searching');
610 searching.hidden = false;
611 chrome.downloads.search({query: query}, function(results) {
612 document.getElementById('older').hidden = true;
613 DownloadManager.forEachItem(function(item) {
614 item.div.hidden = true;
615 });
616 results.forEach(function(result) {
617 DownloadManager.getOrCreate(result).div.hidden = false;
618 });
619 searching.hidden = true;
620 document.getElementById('search-zero').hidden = (results.length != 0);
621 });
622 }
623};
624
625DownloadManager.clearAll = function() {
626 DownloadManager.forEachItem(function(item) {
627 if (!item.div.hidden) {
628 item.erase();
629 // The onErased handler should circle back around to loadItems.
630 }
631 });
632};
633
634var kShowNewMax = 50;
635var kOldMs = 1000 * 60 * 60 * 24 * 7;
636
637// These settings can be tuned by modifying localStorage in dev-tools.
638if ('kShowNewMax' in localStorage) {
639 kShowNewMax = parseInt(localStorage.kShowNewMax);
640}
641if ('kOldMs' in localStorage) {
642 kOldMs = parseInt(localStorage.kOldMs);
643}
644
645DownloadManager.loadItems = function() {
646 // Request up to kShowNewMax + 1, but only display kShowNewMax; the +1 is a
647 // probe to see if there are any older downloads.
648 // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is
649 // released, set minimum_chrome_version and remove this try/catch.
650 try {
651 chrome.downloads.search({
652 orderBy: ['-startTime'],
653 limit: kShowNewMax + 1},
654 function(results) {
655 DownloadManager.loadItems.items = results;
656 DownloadManager.loadItems.onLoaded();
657 });
658 } catch (exc) {
659 chrome.downloads.search({
660 orderBy: '-startTime',
661 limit: kShowNewMax + 1},
662 function(results) {
663 DownloadManager.loadItems.items = results;
664 DownloadManager.loadItems.onLoaded();
665 });
666 }
667};
668DownloadManager.loadItems.items = [];
669DownloadManager.loadItems.window_loaded = false;
670
671DownloadManager.loadItems.onLoaded = function() {
672 if (!DownloadManager.loadItems.window_loaded) {
673 return;
674 }
675 DownloadManager.loadItems.items.forEach(function(item) {
676 DownloadManager.getOrCreate(item);
677 });
678 DownloadManager.loadItems.items = [];
679 DownloadManager.showNew();
680};
681
682DownloadManager.loadItems.onWindowLoaded = function() {
683 DownloadManager.loadItems.window_loaded = true;
684 DownloadManager.loadItems.onLoaded();
685};
686
687// If this extension is installed on a stable-channel chrome, where the
688// downloads API is not available, do not use the downloads API, and link to the
689// beta channel.
690if (chrome.downloads) {
691 // Start searching ASAP, don't wait for onload.
692 DownloadManager.loadItems();
693
694 chrome.downloads.onCreated.addListener(function(item) {
695 DownloadManager.getOrCreate(item);
696 DownloadManager.showNew();
697 DownloadManager.startPollingProgress();
698 });
699
700 chrome.downloads.onChanged.addListener(function(delta) {
701 var item = DownloadManager.getItem(delta.id);
702 if (item) {
703 item.onChanged(delta);
704 }
705 });
706
707 chrome.downloads.onErased.addListener(function(id) {
708 var item = DownloadManager.getItem(id);
709 if (!item) {
710 return;
711 }
712 item.onErased();
713 DownloadManager.loadItems();
714 });
715
716 window.onload = function() {
717 document.body.style.minWidth = (
Ben Murdochbb1529c2013-08-08 10:24:53 +0100718 document.getElementById('q-outer').offsetWidth +
Ben Murdochd3868032013-07-31 10:55:33 +0100719 document.getElementById('clear-all').offsetWidth +
720 document.getElementById('open-folder').offsetWidth) + 'px';
721 setLastOpened();
722 loadI18nMessages();
723 DownloadManager.loadItems.onWindowLoaded();
724 document.getElementById('older').onclick = function() {
725 DownloadManager.showOlder();
726 return false;
727 };
728 document.getElementById('q').onsearch = function() {
729 DownloadManager.onSearch();
730 };
731 document.getElementById('clear-all').onclick = function() {
732 DownloadManager.clearAll();
733 return false;
734 };
735 if (chrome.downloads.showDefaultFolder) {
736 document.getElementById('open-folder').onclick = function() {
737 chrome.downloads.showDefaultFolder();
738 return false;
739 };
740 } else {
741 document.getElementById('open-folder').hidden = true;
742 }
743 };
744} else {
745 // The downloads API is not available.
746 // TODO(benjhayden) Remove this when minimum_chrome_version is set.
747 window.onload = function() {
748 loadI18nMessages();
749 var bad_version = document.getElementById('bad-chrome-version');
750 bad_version.hidden = false;
751 bad_version.onclick = function() {
752 chrome.tabs.create({url: bad_version.href});
753 return false;
754 };
755 document.getElementById('empty').style.display = 'none';
756 document.getElementById('q').style.display = 'none';
757 document.getElementById('open-folder').style.display = 'none';
758 document.getElementById('clear-all').style.display = 'none';
759 };
760}