popup.js revision 3551c9c881056c480085172ff9840cab31610854
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. 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'); 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'); 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 ratchetWidth(w) { 124 var current = parseInt(document.body.style.minWidth) || 0; 125 document.body.style.minWidth = Math.max(w, current) + 'px'; 126} 127 128function ratchetHeight(h) { 129 var current = parseInt(document.body.style.minHeight) || 0; 130 document.body.style.minHeight = Math.max(h, current) + 'px'; 131} 132 133function 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; 144 } 145 } 146 return i; 147}; 148 149function arrayFrom(seq) { 150 return Array.prototype.slice.apply(seq); 151}; 152 153function DownloadItem(data) { 154 var item = this; 155 for (var prop in data) { 156 item[prop] = data[prop]; 157 } 158 item.startTime = new Date(item.startTime); 159 if (item.canResume == undefined) { 160 DownloadItem.canResumeHack = true; 161 } 162 163 item.div = document.querySelector('body>div.item').cloneNode(true); 164 item.div.id = 'item' + item.id; 165 item.div.item = item; 166 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); 187 } 188 } 189 190 item.getElement('referrer').onclick = function() { 191 chrome.tabs.create({url: item.referrer}); 192 return false; 193 }; 194 item.getElement('by-ext').onclick = function() { 195 chrome.tabs.create({url: 'chrome://extensions#' + item.byExtensionId}); 196 return false; 197 } 198 item.getElement('open-filename').onclick = function() { 199 item.open(); 200 return false; 201 }; 202 item.getElement('open-filename').ondragstart = function() { 203 item.drag(); 204 return false; 205 }; 206 item.getElement('pause').onclick = function() { 207 item.pause(); 208 return false; 209 }; 210 item.getElement('cancel').onclick = function() { 211 item.cancel(); 212 return false; 213 }; 214 item.getElement('resume').onclick = function() { 215 item.resume(); 216 return false; 217 }; 218 item.getElement('show-folder').onclick = function() { 219 item.show(); 220 return false; 221 }; 222 item.getElement('remove-file').onclick = function() { 223 item.removeFile(); 224 return false; 225 }; 226 item.getElement('erase').onclick = function() { 227 item.erase(); 228 return false; 229 }; 230 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; 237 } 238 if (item.getElement('more')) { 239 item.getElement('more').hidden = true; 240 } 241 window.removeEventListener('mousemove', item.more_mousemove); 242 }; 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; 249 } 250 }); 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'; 259 } 260 window.addEventListener('mousemove', item.more_mousemove); 261 }; 262 }); 263 264 if (item.referrer) { 265 item.getElement('referrer').href = item.referrer; 266 } else { 267 item.getElement('referrer').hidden = true; 268 } 269 item.getElement('url').href = item.url; 270 item.getElement('url').innerText = item.url; 271 item.render(); 272} 273DownloadItem.canResumeHack = false; 274 275DownloadItem.prototype.getElement = function(name) { 276 return document.querySelector('#item' + this.id + ' .' + name); 277}; 278 279DownloadItem.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; 284 285 item.startTime = new Date(item.startTime); 286 if (DownloadItem.canResumeHack) { 287 item.canResume = in_progress && item.paused; 288 } 289 if (item.filename) { 290 item.basename = item.filename.substring(Math.max( 291 item.filename.lastIndexOf('\\'), 292 item.filename.lastIndexOf('/')) + 1); 293 } 294 if (item.estimatedEndTime) { 295 item.estimatedEndTime = new Date(item.estimatedEndTime); 296 } 297 if (item.endTime) { 298 item.endTime = new Date(item.endTime); 299 } 300 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; 310 } 311 }); 312 } 313 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; 330 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; 335 336 item.getElement('removed').innerText = item.basename; 337 item.getElement('open-filename').innerText = item.basename; 338 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; 348 } 349 } 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; 367 } 368 }); 369 return false; 370 }; 371 } 372 } 373 }); 374 } else { 375 setByExtension(false); 376 } 377 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; 386 } 387 } else if (!openable) { 388 item.getElement('error').innerText = chrome.i18n.getMessage( 389 'errorRemoved'); 390 } 391 } 392 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) + '%'; 401 } 402 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) { 410 } 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); 415 } 416 } 417 418 if (item.startTime) { 419 item.getElement('start-time').innerText = formatDateTime( 420 item.startTime); 421 } 422 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); 429 430 this.maybeAccept(); 431}; 432 433DownloadItem.prototype.onChanged = function(delta) { 434 for (var key in delta) { 435 if (key != 'id') { 436 this[key] = delta[key].current; 437 } 438 } 439 this.render(); 440 if (delta.state) { 441 setLastOpened(); 442 } 443 if ((this.state == 'in_progress') && !this.paused) { 444 DownloadManager.startPollingProgress(); 445 } 446}; 447 448DownloadItem.prototype.onErased = function() { 449 window.removeEventListener('mousemove', this.more_mousemove); 450 document.getElementById('items').removeChild(this.div); 451}; 452 453DownloadItem.prototype.drag = function() { 454 chrome.downloads.drag(this.id); 455}; 456 457DownloadItem.prototype.show = function() { 458 chrome.downloads.show(this.id); 459}; 460 461DownloadItem.prototype.open = function() { 462 if (this.state == 'complete') { 463 chrome.downloads.open(this.id); 464 return; 465 } 466 chrome.runtime.sendMessage({openWhenComplete:this.id}); 467}; 468 469DownloadItem.prototype.removeFile = function() { 470 chrome.downloads.removeFile(this.id); 471 this.deleted = true; 472 this.render(); 473}; 474 475DownloadItem.prototype.erase = function() { 476 chrome.downloads.erase({id: this.id}); 477}; 478 479DownloadItem.prototype.pause = function() { 480 chrome.downloads.pause(this.id); 481}; 482 483DownloadItem.prototype.resume = function() { 484 chrome.downloads.resume(this.id); 485}; 486 487DownloadItem.prototype.cancel = function() { 488 chrome.downloads.cancel(this.id); 489}; 490 491DownloadItem.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; 500 } 501 ratchetWidth(400); 502 ratchetHeight(200); 503 DownloadItem.prototype.maybeAccept.accepting_danger = true; 504 chrome.downloads.acceptDanger(this.id, function() { 505 DownloadItem.prototype.maybeAccept.accepting_danger = false; 506 arrayFrom(document.getElementById('items').childNodes).forEach( 507 function(item_div) { item_div.item.maybeAccept(); }); 508 }); 509}; 510DownloadItem.prototype.maybeAccept.accepting_danger = false; 511 512var DownloadManager = {}; 513 514DownloadManager.showingOlder = false; 515 516DownloadManager.getItem = function(id) { 517 var item_div = document.getElementById('item' + id); 518 return item_div ? item_div.item : null; 519}; 520 521DownloadManager.getOrCreate = function(data) { 522 var item = DownloadManager.getItem(data.id); 523 return item ? item : new DownloadItem(data); 524}; 525 526DownloadManager.forEachItem = function(cb) { 527 // Calls cb(item, index) in the order that they are displayed, i.e. in order 528 // of decreasing startTime. 529 arrayFrom(document.getElementById('items').childNodes).forEach( 530 function(item_div, index) { cb(item_div.item, index); }); 531}; 532 533DownloadManager.startPollingProgress = function() { 534 if (DownloadManager.startPollingProgress.tid < 0) { 535 DownloadManager.startPollingProgress.tid = setTimeout( 536 DownloadManager.startPollingProgress.pollProgress, 537 DownloadManager.startPollingProgress.MS); 538 } 539} 540DownloadManager.startPollingProgress.MS = 200; 541DownloadManager.startPollingProgress.tid = -1; 542DownloadManager.startPollingProgress.pollProgress = function() { 543 DownloadManager.startPollingProgress.tid = -1; 544 chrome.downloads.search({state: 'in_progress', paused: false}, 545 function(results) { 546 if (!results.length) 547 return; 548 results.forEach(function(result) { 549 var item = DownloadManager.getOrCreate(result); 550 for (var prop in result) { 551 item[prop] = result[prop]; 552 } 553 item.render(); 554 if ((item.state == 'in_progress') && !item.paused) { 555 DownloadManager.startPollingProgress(); 556 } 557 }); 558 }); 559}; 560 561DownloadManager.showNew = function() { 562 var any_items = (document.getElementById('items').childNodes.length > 0); 563 document.getElementById('empty').style.display = 564 any_items ? 'none' : 'inline-block'; 565 document.getElementById('head').style.borderBottomWidth = 566 (any_items ? 1 : 0) + 'px'; 567 document.getElementById('clear-all').hidden = !any_items; 568 569 var query_search = document.getElementById('q'); 570 query_search.hidden = !any_items; 571 572 if (!any_items) { 573 return; 574 } 575 var old_ms = (new Date()).getTime() - kOldMs; 576 var any_hidden = false; 577 var any_showing = false; 578 // First show up to kShowNewMax items newer than kOldMs. If there aren't any 579 // items newer than kOldMs, then show up to kShowNewMax items of any age. If 580 // there are any hidden items, show the Show Older button. 581 DownloadManager.forEachItem(function(item, index) { 582 item.div.hidden = !DownloadManager.showingOlder && ( 583 (item.startTime.getTime() < old_ms) || (index >= kShowNewMax)); 584 any_hidden = any_hidden || item.div.hidden; 585 any_showing = any_showing || !item.div.hidden; 586 }); 587 if (!any_showing) { 588 any_hidden = false; 589 DownloadManager.forEachItem(function(item, index) { 590 item.div.hidden = !DownloadManager.showingOlder && (index >= kShowNewMax); 591 any_hidden = any_hidden || item.div.hidden; 592 any_showing = any_showing || !item.div.hidden; 593 }); 594 } 595 document.getElementById('older').hidden = !any_hidden; 596 597 query_search.focus(); 598}; 599 600DownloadManager.showOlder = function() { 601 DownloadManager.showingOlder = true; 602 var loading_older_span = document.getElementById('loading-older'); 603 document.getElementById('older').hidden = true; 604 loading_older_span.hidden = false; 605 chrome.downloads.search({}, function(results) { 606 results.forEach(function(result) { 607 var item = DownloadManager.getOrCreate(result); 608 item.div.hidden = false; 609 }); 610 loading_older_span.hidden = true; 611 }); 612}; 613 614DownloadManager.onSearch = function() { 615 // split string by space, but ignore space in quotes 616 // http://stackoverflow.com/questions/16261635 617 var query = document.getElementById('q').value.match(/(?:[^\s"]+|"[^"]*")+/g); 618 if (!query) { 619 DownloadManager.showNew(); 620 document.getElementById('search-zero').hidden = true; 621 } else { 622 query = query.map(function(term) { 623 // strip quotes 624 return (term.match(/\s/) && 625 term[0].match(/["']/) && 626 term[term.length - 1] == term[0]) ? 627 term.substr(1, term.length - 2) : term; 628 }); 629 var searching = document.getElementById('searching'); 630 searching.hidden = false; 631 chrome.downloads.search({query: query}, function(results) { 632 document.getElementById('older').hidden = true; 633 DownloadManager.forEachItem(function(item) { 634 item.div.hidden = true; 635 }); 636 results.forEach(function(result) { 637 DownloadManager.getOrCreate(result).div.hidden = false; 638 }); 639 searching.hidden = true; 640 document.getElementById('search-zero').hidden = (results.length != 0); 641 }); 642 } 643}; 644 645DownloadManager.clearAll = function() { 646 DownloadManager.forEachItem(function(item) { 647 if (!item.div.hidden) { 648 item.erase(); 649 // The onErased handler should circle back around to loadItems. 650 } 651 }); 652}; 653 654var kShowNewMax = 50; 655var kOldMs = 1000 * 60 * 60 * 24 * 7; 656 657// These settings can be tuned by modifying localStorage in dev-tools. 658if ('kShowNewMax' in localStorage) { 659 kShowNewMax = parseInt(localStorage.kShowNewMax); 660} 661if ('kOldMs' in localStorage) { 662 kOldMs = parseInt(localStorage.kOldMs); 663} 664 665DownloadManager.loadItems = function() { 666 // Request up to kShowNewMax + 1, but only display kShowNewMax; the +1 is a 667 // probe to see if there are any older downloads. 668 // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is 669 // released, set minimum_chrome_version and remove this try/catch. 670 try { 671 chrome.downloads.search({ 672 orderBy: ['-startTime'], 673 limit: kShowNewMax + 1}, 674 function(results) { 675 DownloadManager.loadItems.items = results; 676 DownloadManager.loadItems.onLoaded(); 677 }); 678 } catch (exc) { 679 chrome.downloads.search({ 680 orderBy: '-startTime', 681 limit: kShowNewMax + 1}, 682 function(results) { 683 DownloadManager.loadItems.items = results; 684 DownloadManager.loadItems.onLoaded(); 685 }); 686 } 687}; 688DownloadManager.loadItems.items = []; 689DownloadManager.loadItems.window_loaded = false; 690 691DownloadManager.loadItems.onLoaded = function() { 692 if (!DownloadManager.loadItems.window_loaded) { 693 return; 694 } 695 DownloadManager.loadItems.items.forEach(function(item) { 696 DownloadManager.getOrCreate(item); 697 }); 698 DownloadManager.loadItems.items = []; 699 DownloadManager.showNew(); 700}; 701 702DownloadManager.loadItems.onWindowLoaded = function() { 703 DownloadManager.loadItems.window_loaded = true; 704 DownloadManager.loadItems.onLoaded(); 705}; 706 707// If this extension is installed on a stable-channel chrome, where the 708// downloads API is not available, do not use the downloads API, and link to the 709// beta channel. 710if (chrome.downloads) { 711 // Start searching ASAP, don't wait for onload. 712 DownloadManager.loadItems(); 713 714 chrome.downloads.onCreated.addListener(function(item) { 715 DownloadManager.getOrCreate(item); 716 DownloadManager.showNew(); 717 DownloadManager.startPollingProgress(); 718 }); 719 720 chrome.downloads.onChanged.addListener(function(delta) { 721 var item = DownloadManager.getItem(delta.id); 722 if (item) { 723 item.onChanged(delta); 724 } 725 }); 726 727 chrome.downloads.onErased.addListener(function(id) { 728 var item = DownloadManager.getItem(id); 729 if (!item) { 730 return; 731 } 732 item.onErased(); 733 DownloadManager.loadItems(); 734 }); 735 736 window.onload = function() { 737 ratchetWidth( 738 document.getElementById('q-outer').offsetWidth + 739 document.getElementById('clear-all').offsetWidth + 740 document.getElementById('open-folder').offsetWidth); 741 setLastOpened(); 742 loadI18nMessages(); 743 DownloadManager.loadItems.onWindowLoaded(); 744 document.getElementById('older').onclick = function() { 745 DownloadManager.showOlder(); 746 return false; 747 }; 748 document.getElementById('q').onsearch = function() { 749 DownloadManager.onSearch(); 750 }; 751 document.getElementById('clear-all').onclick = function() { 752 DownloadManager.clearAll(); 753 return false; 754 }; 755 if (chrome.downloads.showDefaultFolder) { 756 document.getElementById('open-folder').onclick = function() { 757 chrome.downloads.showDefaultFolder(); 758 return false; 759 }; 760 } else { 761 document.getElementById('open-folder').hidden = true; 762 } 763 }; 764} else { 765 // The downloads API is not available. 766 // TODO(benjhayden) Remove this when minimum_chrome_version is set. 767 window.onload = function() { 768 loadI18nMessages(); 769 var bad_version = document.getElementById('bad-chrome-version'); 770 bad_version.hidden = false; 771 bad_version.onclick = function() { 772 chrome.tabs.create({url: bad_version.href}); 773 return false; 774 }; 775 document.getElementById('empty').style.display = 'none'; 776 document.getElementById('q').style.display = 'none'; 777 document.getElementById('open-folder').style.display = 'none'; 778 document.getElementById('clear-all').style.display = 'none'; 779 }; 780} 781