Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / common / extensions / docs / examples / api / downloads / download_manager / popup.js
blob1f3712326157873220ccb2cfe379d2c83398fabd
1 // 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.
5 function 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)));
12 function setLastOpened() {
13 localStorage.popupLastOpened = (new Date()).getTime();
14 chrome.runtime.sendMessage('poll');
17 function loadI18nMessages() {
18 function setProperty(selector, prop, msg) {
19 document.querySelector(selector)[prop] = chrome.i18n.getMessage(msg);
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');
29 setProperty('#management-permission-info', 'innerText',
30 'managementPermissionInfo');
31 setProperty('#grant-management-permission', 'innerText',
32 'grantManagementPermission');
33 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');
46 document.querySelector('.progress').style.minWidth =
47 getTextWidth(formatBytes(1024 * 1024 * 1023.9) + '/' +
48 formatBytes(1024 * 1024 * 1023.9)) + 'px';
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)));
59 document.querySelector('body div.item span.time-left').style.minWidth =
60 max_time_left_width + 'px';
63 function getTextWidth(s) {
64 var probe = document.getElementById('text-width-probe');
65 probe.innerText = s;
66 return probe.offsetWidth;
69 function 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';
83 return date.getHours() + zpad_mins + 'am';
86 function formatBytes(n) {
87 if (n < 1024) {
88 return n + 'B';
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');
97 mul *= 1024;
99 return '!!!';
102 function formatTimeLeft(openWhenComplete, ms) {
103 var prefix = openWhenComplete ? 'openWhenComplete' : 'timeLeft';
104 if (ms < 1000) {
105 return chrome.i18n.getMessage(prefix + 'Finishing');
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]);
112 var minutes = parseInt(ms / (60 * 1000)) % 60;
113 if (hours) {
114 return chrome.i18n.getMessage(prefix + 'Hours', [hours, minutes]);
116 var seconds = parseInt(ms / 1000) % 60;
117 if (minutes) {
118 return chrome.i18n.getMessage(prefix + 'Minutes', [minutes, seconds]);
120 return chrome.i18n.getMessage(prefix + 'Seconds', [seconds]);
123 function ratchetWidth(w) {
124 var current = parseInt(document.body.style.minWidth) || 0;
125 document.body.style.minWidth = Math.max(w, current) + 'px';
128 function ratchetHeight(h) {
129 var current = parseInt(document.body.style.minHeight) || 0;
130 document.body.style.minHeight = Math.max(h, current) + 'px';
133 function binarySearch(array, target, cmp) {
134 var low = 0, high = array.length - 1, i, comparison;
135 while (low <= high) {
136 i = (low + high) >> 1;
137 comparison = cmp(target, array[i]);
138 if (comparison < 0) {
139 low = i + 1;
140 } else if (comparison > 0) {
141 high = i - 1;
142 } else {
143 return i;
146 return i;
149 function arrayFrom(seq) {
150 return Array.prototype.slice.apply(seq);
153 function DownloadItem(data) {
154 var item = this;
155 for (var prop in data) {
156 item[prop] = data[prop];
158 item.startTime = new Date(item.startTime);
159 if (item.canResume == undefined) {
160 DownloadItem.canResumeHack = true;
163 item.div = document.querySelector('body>div.item').cloneNode(true);
164 item.div.id = 'item' + item.id;
165 item.div.item = item;
167 var items_div = document.getElementById('items');
168 if ((items_div.childNodes.length == 0) ||
169 (item.startTime.getTime() < items_div.childNodes[
170 items_div.childNodes.length - 1].item.startTime.getTime())) {
171 items_div.appendChild(item.div);
172 } else if (item.startTime.getTime() >
173 items_div.childNodes[0].item.startTime.getTime()) {
174 items_div.insertBefore(item.div, items_div.childNodes[0]);
175 } else {
176 var adjacent_div = items_div.childNodes[
177 binarySearch(arrayFrom(items_div.childNodes),
178 item.startTime.getTime(),
179 function(target, other) {
180 return target - other.item.startTime.getTime();
181 })];
182 var adjacent_item = adjacent_div.item;
183 if (adjacent_item.startTime.getTime() < item.startTime.getTime()) {
184 items_div.insertBefore(item.div, adjacent_div);
185 } else {
186 items_div.insertBefore(item.div, adjacent_div.nextSibling);
190 item.getElement('referrer').onclick = function() {
191 chrome.tabs.create({url: item.referrer});
192 return false;
194 item.getElement('by-ext').onclick = function() {
195 chrome.tabs.create({url: 'chrome://extensions#' + item.byExtensionId});
196 return false;
198 item.getElement('open-filename').onclick = function() {
199 item.open();
200 return false;
202 item.getElement('open-filename').ondragstart = function() {
203 item.drag();
204 return false;
206 item.getElement('pause').onclick = function() {
207 item.pause();
208 return false;
210 item.getElement('cancel').onclick = function() {
211 item.cancel();
212 return false;
214 item.getElement('resume').onclick = function() {
215 item.resume();
216 return false;
218 item.getElement('show-folder').onclick = function() {
219 item.show();
220 return false;
222 item.getElement('remove-file').onclick = function() {
223 item.removeFile();
224 return false;
226 item.getElement('erase').onclick = function() {
227 item.erase();
228 return false;
231 item.more_mousemove = function(evt) {
232 var mouse = {x:evt.x, y:evt.y+document.body.scrollTop};
233 if (item.getElement('more') &&
234 (pointInElement(mouse, item.div) ||
235 pointInElement(mouse, item.getElement('more')))) {
236 return;
238 if (item.getElement('more')) {
239 item.getElement('more').hidden = true;
241 window.removeEventListener('mousemove', item.more_mousemove);
243 [item.div, item.getElement('more')].concat(
244 item.getElement('more').children).forEach(function(elem) {
245 elem.onmouseover = function() {
246 arrayFrom(items_div.children).forEach(function(other) {
247 if (other.item != item) {
248 other.item.getElement('more').hidden = true;
251 item.getElement('more').hidden = false;
252 item.getElement('more').style.top =
253 (item.div.offsetTop + item.div.offsetHeight) + 'px';
254 item.getElement('more').style.left = item.div.offsetLeft + 'px';
255 if (window.innerHeight < (parseInt(item.getElement('more').style.top) +
256 item.getElement('more').offsetHeight)) {
257 item.getElement('more').style.top = (
258 item.div.offsetTop - item.getElement('more').offsetHeight) + 'px';
260 window.addEventListener('mousemove', item.more_mousemove);
264 if (item.referrer) {
265 item.getElement('referrer').href = item.referrer;
266 } else {
267 item.getElement('referrer').hidden = true;
269 item.getElement('url').href = item.url;
270 item.getElement('url').innerText = item.url;
271 item.render();
273 DownloadItem.canResumeHack = false;
275 DownloadItem.prototype.getElement = function(name) {
276 return document.querySelector('#item' + this.id + ' .' + name);
279 DownloadItem.prototype.render = function() {
280 var item = this;
281 var now = new Date();
282 var in_progress = (item.state == 'in_progress')
283 var openable = (item.state != 'interrupted') && item.exists && !item.deleted;
285 item.startTime = new Date(item.startTime);
286 if (DownloadItem.canResumeHack) {
287 item.canResume = in_progress && item.paused;
289 if (item.filename) {
290 item.basename = item.filename.substring(Math.max(
291 item.filename.lastIndexOf('\\'),
292 item.filename.lastIndexOf('/')) + 1);
294 if (item.estimatedEndTime) {
295 item.estimatedEndTime = new Date(item.estimatedEndTime);
297 if (item.endTime) {
298 item.endTime = new Date(item.endTime);
301 if (item.filename && !item.icon_url) {
302 chrome.downloads.getFileIcon(
303 item.id,
304 {'size': 32},
305 function(icon_url) {
306 item.getElement('icon').hidden = !icon_url;
307 if (icon_url) {
308 item.icon_url = icon_url;
309 item.getElement('icon').src = icon_url;
314 item.getElement('removed').style.display = openable ? 'none' : 'inline';
315 item.getElement('open-filename').style.display = (
316 openable ? 'inline' : 'none');
317 item.getElement('in-progress').hidden = !in_progress;
318 item.getElement('pause').style.display = (
319 !in_progress || item.paused) ? 'none' : 'inline-block';
320 item.getElement('resume').style.display = (
321 !in_progress || !item.canResume) ? 'none' : 'inline-block';
322 item.getElement('cancel').style.display = (
323 !in_progress ? 'none' : 'inline-block');
324 item.getElement('remove-file').hidden = (
325 (item.state != 'complete') ||
326 !item.exists ||
327 item.deleted ||
328 !chrome.downloads.removeFile);
329 item.getElement('erase').hidden = in_progress;
331 var could_progress = in_progress || item.canResume;
332 item.getElement('progress').style.display = (
333 could_progress ? 'inline-block' : 'none');
334 item.getElement('meter').hidden = !could_progress || !item.totalBytes;
336 item.getElement('removed').innerText = item.basename;
337 item.getElement('open-filename').innerText = item.basename;
339 function setByExtension(show) {
340 if (show) {
341 item.getElement('by-ext').title = item.byExtensionName;
342 item.getElement('by-ext').href =
343 'chrome://extensions#' + item.byExtensionId;
344 item.getElement('by-ext img').src =
345 'chrome://extension-icon/' + item.byExtensionId + '/48/1';
346 } else {
347 item.getElement('by-ext').hidden = true;
350 if (item.byExtensionId && item.byExtensionName) {
351 chrome.permissions.contains({permissions: ['management']},
352 function(result) {
353 if (result) {
354 setByExtension(true);
355 } else {
356 setByExtension(false);
357 if (!localStorage.managementPermissionDenied) {
358 document.getElementById('request-management-permission').hidden =
359 false;
360 document.getElementById('grant-management-permission').onclick =
361 function() {
362 chrome.permissions.request({permissions: ['management']},
363 function(granted) {
364 setByExtension(granted);
365 if (!granted) {
366 localStorage.managementPermissionDenied = true;
369 return false;
374 } else {
375 setByExtension(false);
378 if (!item.getElement('error').hidden) {
379 if (item.error) {
380 // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is
381 // released, set minimum_chrome_version and remove the error_N messages.
382 item.getElement('error').innerText = chrome.i18n.getMessage(
383 'error_' + item.error);
384 if (!item.getElement('error').innerText) {
385 item.getElement('error').innerText = item.error;
387 } else if (!openable) {
388 item.getElement('error').innerText = chrome.i18n.getMessage(
389 'errorRemoved');
393 item.getElement('complete-size').innerText = formatBytes(
394 item.bytesReceived);
395 if (item.totalBytes && (item.state != 'complete')) {
396 item.getElement('progress').innerText = (
397 item.getElement('complete-size').innerText + '/' +
398 formatBytes(item.totalBytes));
399 item.getElement('meter').children[0].style.width = parseInt(
400 100 * item.bytesReceived / item.totalBytes) + '%';
403 if (in_progress) {
404 if (item.estimatedEndTime && !item.paused) {
405 var openWhenComplete = false;
406 try {
407 openWhenComplete = JSON.parse(localStorage.openWhenComplete).indexOf(
408 item.id) >= 0;
409 } catch (e) {
411 item.getElement('time-left').innerText = formatTimeLeft(
412 openWhenComplete, item.estimatedEndTime.getTime() - now.getTime());
413 } else {
414 item.getElement('time-left').innerText = String.fromCharCode(160);
418 if (item.startTime) {
419 item.getElement('start-time').innerText = formatDateTime(
420 item.startTime);
423 ratchetWidth(item.getElement('icon').offsetWidth +
424 item.getElement('file-url').offsetWidth +
425 item.getElement('cancel').offsetWidth +
426 item.getElement('pause').offsetWidth +
427 item.getElement('resume').offsetWidth);
428 ratchetWidth(item.getElement('more').offsetWidth);
430 this.maybeAccept();
433 DownloadItem.prototype.onChanged = function(delta) {
434 for (var key in delta) {
435 if (key != 'id') {
436 this[key] = delta[key].current;
439 this.render();
440 if (delta.state) {
441 setLastOpened();
443 if ((this.state == 'in_progress') && !this.paused) {
444 DownloadManager.startPollingProgress();
448 DownloadItem.prototype.onErased = function() {
449 window.removeEventListener('mousemove', this.more_mousemove);
450 document.getElementById('items').removeChild(this.div);
453 DownloadItem.prototype.drag = function() {
454 chrome.downloads.drag(this.id);
457 DownloadItem.prototype.show = function() {
458 chrome.downloads.show(this.id);
461 DownloadItem.prototype.open = function() {
462 if (this.state == 'complete') {
463 chrome.downloads.open(this.id);
464 return;
466 chrome.runtime.sendMessage({openWhenComplete:this.id});
469 DownloadItem.prototype.removeFile = function() {
470 chrome.downloads.removeFile(this.id);
471 this.deleted = true;
472 this.render();
475 DownloadItem.prototype.erase = function() {
476 chrome.downloads.erase({id: this.id});
479 DownloadItem.prototype.pause = function() {
480 chrome.downloads.pause(this.id);
483 DownloadItem.prototype.resume = function() {
484 chrome.downloads.resume(this.id);
487 DownloadItem.prototype.cancel = function() {
488 chrome.downloads.cancel(this.id);
491 DownloadItem.prototype.maybeAccept = function() {
492 // This function is safe to call at any time for any item, and it will always
493 // do the right thing, which is to display the danger prompt only if the item
494 // is in_progress and dangerous, and if the prompt is not already displayed.
495 if ((this.state != 'in_progress') ||
496 (this.danger == 'safe') ||
497 (this.danger == 'accepted') ||
498 DownloadItem.prototype.maybeAccept.accepting_danger) {
499 return;
501 ratchetWidth(400);
502 ratchetHeight(200);
503 DownloadItem.prototype.maybeAccept.accepting_danger = true;
504 // On Mac, window.onload is run while the popup is animating in, before it is
505 // considered "visible". Prompts will not be displayed over an invisible
506 // window, so the popup will become stuck. Just wait a little bit for the
507 // window to finish animating in. http://crbug.com/280107
508 // This has been fixed, so this setTimeout can be removed when the fix has
509 // been released to stable, and minimum_chrome_version can be set.
510 var id = this.id;
511 setTimeout(function() {
512 chrome.downloads.acceptDanger(id, function() {
513 DownloadItem.prototype.maybeAccept.accepting_danger = false;
514 arrayFrom(document.getElementById('items').childNodes).forEach(
515 function(item_div) { item_div.item.maybeAccept(); });
517 }, 500);
519 DownloadItem.prototype.maybeAccept.accepting_danger = false;
521 var DownloadManager = {};
523 DownloadManager.showingOlder = false;
525 DownloadManager.getItem = function(id) {
526 var item_div = document.getElementById('item' + id);
527 return item_div ? item_div.item : null;
530 DownloadManager.getOrCreate = function(data) {
531 var item = DownloadManager.getItem(data.id);
532 return item ? item : new DownloadItem(data);
535 DownloadManager.forEachItem = function(cb) {
536 // Calls cb(item, index) in the order that they are displayed, i.e. in order
537 // of decreasing startTime.
538 arrayFrom(document.getElementById('items').childNodes).forEach(
539 function(item_div, index) { cb(item_div.item, index); });
542 DownloadManager.startPollingProgress = function() {
543 if (DownloadManager.startPollingProgress.tid < 0) {
544 DownloadManager.startPollingProgress.tid = setTimeout(
545 DownloadManager.startPollingProgress.pollProgress,
546 DownloadManager.startPollingProgress.MS);
549 DownloadManager.startPollingProgress.MS = 200;
550 DownloadManager.startPollingProgress.tid = -1;
551 DownloadManager.startPollingProgress.pollProgress = function() {
552 DownloadManager.startPollingProgress.tid = -1;
553 chrome.downloads.search({state: 'in_progress', paused: false},
554 function(results) {
555 if (!results.length)
556 return;
557 results.forEach(function(result) {
558 var item = DownloadManager.getOrCreate(result);
559 for (var prop in result) {
560 item[prop] = result[prop];
562 item.render();
563 if ((item.state == 'in_progress') && !item.paused) {
564 DownloadManager.startPollingProgress();
570 DownloadManager.showNew = function() {
571 var any_items = (document.getElementById('items').childNodes.length > 0);
572 document.getElementById('empty').style.display =
573 any_items ? 'none' : 'inline-block';
574 document.getElementById('head').style.borderBottomWidth =
575 (any_items ? 1 : 0) + 'px';
576 document.getElementById('clear-all').hidden = !any_items;
578 var query_search = document.getElementById('q');
579 query_search.hidden = !any_items;
581 if (!any_items) {
582 return;
584 var old_ms = (new Date()).getTime() - kOldMs;
585 var any_hidden = false;
586 var any_showing = false;
587 // First show up to kShowNewMax items newer than kOldMs. If there aren't any
588 // items newer than kOldMs, then show up to kShowNewMax items of any age. If
589 // there are any hidden items, show the Show Older button.
590 DownloadManager.forEachItem(function(item, index) {
591 item.div.hidden = !DownloadManager.showingOlder && (
592 (item.startTime.getTime() < old_ms) || (index >= kShowNewMax));
593 any_hidden = any_hidden || item.div.hidden;
594 any_showing = any_showing || !item.div.hidden;
596 if (!any_showing) {
597 any_hidden = false;
598 DownloadManager.forEachItem(function(item, index) {
599 item.div.hidden = !DownloadManager.showingOlder && (index >= kShowNewMax);
600 any_hidden = any_hidden || item.div.hidden;
601 any_showing = any_showing || !item.div.hidden;
604 document.getElementById('older').hidden = !any_hidden;
606 query_search.focus();
609 DownloadManager.showOlder = function() {
610 DownloadManager.showingOlder = true;
611 var loading_older_span = document.getElementById('loading-older');
612 document.getElementById('older').hidden = true;
613 loading_older_span.hidden = false;
614 chrome.downloads.search({}, function(results) {
615 results.forEach(function(result) {
616 var item = DownloadManager.getOrCreate(result);
617 item.div.hidden = false;
619 loading_older_span.hidden = true;
623 DownloadManager.onSearch = function() {
624 // split string by space, but ignore space in quotes
625 // http://stackoverflow.com/questions/16261635
626 var query = document.getElementById('q').value.match(/(?:[^\s"]+|"[^"]*")+/g);
627 if (!query) {
628 DownloadManager.showNew();
629 document.getElementById('search-zero').hidden = true;
630 } else {
631 query = query.map(function(term) {
632 // strip quotes
633 return (term.match(/\s/) &&
634 term[0].match(/["']/) &&
635 term[term.length - 1] == term[0]) ?
636 term.substr(1, term.length - 2) : term;
638 var searching = document.getElementById('searching');
639 searching.hidden = false;
640 chrome.downloads.search({query: query}, function(results) {
641 document.getElementById('older').hidden = true;
642 DownloadManager.forEachItem(function(item) {
643 item.div.hidden = true;
645 results.forEach(function(result) {
646 DownloadManager.getOrCreate(result).div.hidden = false;
648 searching.hidden = true;
649 document.getElementById('search-zero').hidden = (results.length != 0);
654 DownloadManager.clearAll = function() {
655 DownloadManager.forEachItem(function(item) {
656 if (!item.div.hidden) {
657 item.erase();
658 // The onErased handler should circle back around to loadItems.
663 var kShowNewMax = 50;
664 var kOldMs = 1000 * 60 * 60 * 24 * 7;
666 // These settings can be tuned by modifying localStorage in dev-tools.
667 if ('kShowNewMax' in localStorage) {
668 kShowNewMax = parseInt(localStorage.kShowNewMax);
670 if ('kOldMs' in localStorage) {
671 kOldMs = parseInt(localStorage.kOldMs);
674 DownloadManager.loadItems = function() {
675 // Request up to kShowNewMax + 1, but only display kShowNewMax; the +1 is a
676 // probe to see if there are any older downloads.
677 // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is
678 // released, set minimum_chrome_version and remove this try/catch.
679 try {
680 chrome.downloads.search({
681 orderBy: ['-startTime'],
682 limit: kShowNewMax + 1},
683 function(results) {
684 DownloadManager.loadItems.items = results;
685 DownloadManager.loadItems.onLoaded();
687 } catch (exc) {
688 chrome.downloads.search({
689 orderBy: '-startTime',
690 limit: kShowNewMax + 1},
691 function(results) {
692 DownloadManager.loadItems.items = results;
693 DownloadManager.loadItems.onLoaded();
697 DownloadManager.loadItems.items = [];
698 DownloadManager.loadItems.window_loaded = false;
700 DownloadManager.loadItems.onLoaded = function() {
701 if (!DownloadManager.loadItems.window_loaded) {
702 return;
704 DownloadManager.loadItems.items.forEach(function(item) {
705 DownloadManager.getOrCreate(item);
707 DownloadManager.loadItems.items = [];
708 DownloadManager.showNew();
711 DownloadManager.loadItems.onWindowLoaded = function() {
712 DownloadManager.loadItems.window_loaded = true;
713 DownloadManager.loadItems.onLoaded();
716 // If this extension is installed on a stable-channel chrome, where the
717 // downloads API is not available, do not use the downloads API, and link to the
718 // beta channel.
719 if (chrome.downloads) {
720 // Start searching ASAP, don't wait for onload.
721 DownloadManager.loadItems();
723 chrome.downloads.onCreated.addListener(function(item) {
724 DownloadManager.getOrCreate(item);
725 DownloadManager.showNew();
726 DownloadManager.startPollingProgress();
729 chrome.downloads.onChanged.addListener(function(delta) {
730 var item = DownloadManager.getItem(delta.id);
731 if (item) {
732 item.onChanged(delta);
736 chrome.downloads.onErased.addListener(function(id) {
737 var item = DownloadManager.getItem(id);
738 if (!item) {
739 return;
741 item.onErased();
742 DownloadManager.loadItems();
745 window.onload = function() {
746 ratchetWidth(
747 document.getElementById('q-outer').offsetWidth +
748 document.getElementById('clear-all').offsetWidth +
749 document.getElementById('open-folder').offsetWidth);
750 setLastOpened();
751 loadI18nMessages();
752 DownloadManager.loadItems.onWindowLoaded();
753 document.getElementById('older').onclick = function() {
754 DownloadManager.showOlder();
755 return false;
757 document.getElementById('q').onsearch = function() {
758 DownloadManager.onSearch();
760 document.getElementById('clear-all').onclick = function() {
761 DownloadManager.clearAll();
762 return false;
764 if (chrome.downloads.showDefaultFolder) {
765 document.getElementById('open-folder').onclick = function() {
766 chrome.downloads.showDefaultFolder();
767 return false;
769 } else {
770 document.getElementById('open-folder').hidden = true;
773 } else {
774 // The downloads API is not available.
775 // TODO(benjhayden) Remove this when minimum_chrome_version is set.
776 window.onload = function() {
777 loadI18nMessages();
778 var bad_version = document.getElementById('bad-chrome-version');
779 bad_version.hidden = false;
780 bad_version.onclick = function() {
781 chrome.tabs.create({url: bad_version.href});
782 return false;
784 document.getElementById('empty').style.display = 'none';
785 document.getElementById('q').style.display = 'none';
786 document.getElementById('open-folder').style.display = 'none';
787 document.getElementById('clear-all').style.display = 'none';