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
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');
66 return probe
.offsetWidth
;
69 function formatDateTime(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
) {
90 var prefixes
= 'KMGTPEZY';
92 for (var i
= 0; i
< prefixes
.length
; ++i
) {
93 if (n
< (1024 * mul
)) {
94 return (parseInt(n
/ mul
) + '.' + parseInt(10 * ((n
/ mul
) % 1)) +
102 function formatTimeLeft(openWhenComplete
, ms
) {
103 var prefix
= openWhenComplete
? 'openWhenComplete' : 'timeLeft';
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;
110 return chrome
.i18n
.getMessage(prefix
+ 'Days', [days
, hours
]);
112 var minutes
= parseInt(ms
/ (60 * 1000)) % 60;
114 return chrome
.i18n
.getMessage(prefix
+ 'Hours', [hours
, minutes
]);
116 var seconds
= parseInt(ms
/ 1000) % 60;
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) {
140 } else if (comparison
> 0) {
149 function arrayFrom(seq
) {
150 return Array
.prototype.slice
.apply(seq
);
153 function DownloadItem(data
) {
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]);
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();
182 var adjacent_item
= adjacent_div
.item
;
183 if (adjacent_item
.startTime
.getTime() < item
.startTime
.getTime()) {
184 items_div
.insertBefore(item
.div
, adjacent_div
);
186 items_div
.insertBefore(item
.div
, adjacent_div
.nextSibling
);
190 item
.getElement('referrer').onclick = function() {
191 chrome
.tabs
.create({url
: item
.referrer
});
194 item
.getElement('by-ext').onclick = function() {
195 chrome
.tabs
.create({url
: 'chrome://extensions#' + item
.byExtensionId
});
198 item
.getElement('open-filename').onclick = function() {
202 item
.getElement('open-filename').ondragstart = function() {
206 item
.getElement('pause').onclick = function() {
210 item
.getElement('cancel').onclick = function() {
214 item
.getElement('resume').onclick = function() {
218 item
.getElement('show-folder').onclick = function() {
222 item
.getElement('remove-file').onclick = function() {
226 item
.getElement('erase').onclick = function() {
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')))) {
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
);
265 item
.getElement('referrer').href
= item
.referrer
;
267 item
.getElement('referrer').hidden
= true;
269 item
.getElement('url').href
= item
.url
;
270 item
.getElement('url').innerText
= item
.url
;
273 DownloadItem
.canResumeHack
= false;
275 DownloadItem
.prototype.getElement = function(name
) {
276 return document
.querySelector('#item' + this.id
+ ' .' + name
);
279 DownloadItem
.prototype.render = function() {
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
;
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
);
298 item
.endTime
= new Date(item
.endTime
);
301 if (item
.filename
&& !item
.icon_url
) {
302 chrome
.downloads
.getFileIcon(
306 item
.getElement('icon').hidden
= !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') ||
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
) {
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';
347 item
.getElement('by-ext').hidden
= true;
350 if (item
.byExtensionId
&& item
.byExtensionName
) {
351 chrome
.permissions
.contains({permissions
: ['management']},
354 setByExtension(true);
356 setByExtension(false);
357 if (!localStorage
.managementPermissionDenied
) {
358 document
.getElementById('request-management-permission').hidden
=
360 document
.getElementById('grant-management-permission').onclick
=
362 chrome
.permissions
.request({permissions
: ['management']},
364 setByExtension(granted
);
366 localStorage
.managementPermissionDenied
= true;
375 setByExtension(false);
378 if (!item
.getElement('error').hidden
) {
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(
393 item
.getElement('complete-size').innerText
= formatBytes(
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
) + '%';
404 if (item
.estimatedEndTime
&& !item
.paused
) {
405 var openWhenComplete
= false;
407 openWhenComplete
= JSON
.parse(localStorage
.openWhenComplete
).indexOf(
411 item
.getElement('time-left').innerText
= formatTimeLeft(
412 openWhenComplete
, item
.estimatedEndTime
.getTime() - now
.getTime());
414 item
.getElement('time-left').innerText
= String
.fromCharCode(160);
418 if (item
.startTime
) {
419 item
.getElement('start-time').innerText
= formatDateTime(
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
);
433 DownloadItem
.prototype.onChanged = function(delta
) {
434 for (var key
in delta
) {
436 this[key
] = delta
[key
].current
;
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
);
466 chrome
.runtime
.sendMessage({openWhenComplete
:this.id
});
469 DownloadItem
.prototype.removeFile = function() {
470 chrome
.downloads
.removeFile(this.id
);
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
) {
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.
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(); });
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},
557 results
.forEach(function(result
) {
558 var item
= DownloadManager
.getOrCreate(result
);
559 for (var prop
in result
) {
560 item
[prop
] = result
[prop
];
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
;
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
;
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);
628 DownloadManager
.showNew();
629 document
.getElementById('search-zero').hidden
= true;
631 query
= query
.map(function(term
) {
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
) {
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.
680 chrome
.downloads
.search({
681 orderBy
: ['-startTime'],
682 limit
: kShowNewMax
+ 1},
684 DownloadManager
.loadItems
.items
= results
;
685 DownloadManager
.loadItems
.onLoaded();
688 chrome
.downloads
.search({
689 orderBy
: '-startTime',
690 limit
: kShowNewMax
+ 1},
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
) {
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
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
);
732 item
.onChanged(delta
);
736 chrome
.downloads
.onErased
.addListener(function(id
) {
737 var item
= DownloadManager
.getItem(id
);
742 DownloadManager
.loadItems();
745 window
.onload = function() {
747 document
.getElementById('q-outer').offsetWidth
+
748 document
.getElementById('clear-all').offsetWidth
+
749 document
.getElementById('open-folder').offsetWidth
);
752 DownloadManager
.loadItems
.onWindowLoaded();
753 document
.getElementById('older').onclick = function() {
754 DownloadManager
.showOlder();
757 document
.getElementById('q').onsearch = function() {
758 DownloadManager
.onSearch();
760 document
.getElementById('clear-all').onclick = function() {
761 DownloadManager
.clearAll();
764 if (chrome
.downloads
.showDefaultFolder
) {
765 document
.getElementById('open-folder').onclick = function() {
766 chrome
.downloads
.showDefaultFolder();
770 document
.getElementById('open-folder').hidden
= true;
774 // The downloads API is not available.
775 // TODO(benjhayden) Remove this when minimum_chrome_version is set.
776 window
.onload = function() {
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
});
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';