| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // TODO(jhawkins): Use hidden instead of showInline* and display:none. | 5 // TODO(jhawkins): Use hidden instead of showInline* and display:none. |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The type of the download object. The definition is based on |
| 9 * chrome/browser/ui/webui/downloads_dom_handler.cc:CreateDownloadItemValue() |
| 10 * @typedef {{by_ext_id: (string|undefined), |
| 11 * by_ext_name: (string|undefined), |
| 12 * danger_type: (string|undefined), |
| 13 * date_string: string, |
| 14 * file_externally_removed: boolean, |
| 15 * file_name: string, |
| 16 * file_path: string, |
| 17 * file_url: string, |
| 18 * id: string, |
| 19 * last_reason_text: (string|undefined), |
| 20 * otr: boolean, |
| 21 * percent: (number|undefined), |
| 22 * progress_status_text: (string|undefined), |
| 23 * received: (number|undefined), |
| 24 * resume: boolean, |
| 25 * retry: boolean, |
| 26 * since_string: string, |
| 27 * started: number, |
| 28 * state: string, |
| 29 * total: number, |
| 30 * url: string}} |
| 31 */ |
| 32 var BackendDownloadObject; |
| 33 |
| 34 /** |
| 8 * Sets the display style of a node. | 35 * Sets the display style of a node. |
| 9 * @param {!Element} node The target element to show or hide. | 36 * @param {!Element} node The target element to show or hide. |
| 10 * @param {boolean} isShow Should the target element be visible. | 37 * @param {boolean} isShow Should the target element be visible. |
| 11 */ | 38 */ |
| 12 function showInline(node, isShow) { | 39 function showInline(node, isShow) { |
| 13 node.style.display = isShow ? 'inline' : 'none'; | 40 node.style.display = isShow ? 'inline' : 'none'; |
| 14 } | 41 } |
| 15 | 42 |
| 16 /** | 43 /** |
| 17 * Sets the display style of a node. | 44 * Sets the display style of a node. |
| 18 * @param {!Element} node The target element to show or hide. | 45 * @param {!Element} node The target element to show or hide. |
| 19 * @param {boolean} isShow Should the target element be visible. | 46 * @param {boolean} isShow Should the target element be visible. |
| 20 */ | 47 */ |
| 21 function showInlineBlock(node, isShow) { | 48 function showInlineBlock(node, isShow) { |
| 22 node.style.display = isShow ? 'inline-block' : 'none'; | 49 node.style.display = isShow ? 'inline-block' : 'none'; |
| 23 } | 50 } |
| 24 | 51 |
| 25 /** | 52 /** |
| 26 * Creates a link with a specified onclick handler and content. | 53 * Creates a link with a specified onclick handler and content. |
| 27 * @param {function()} onclick The onclick handler. | 54 * @param {function()} onclick The onclick handler. |
| 28 * @param {string} value The link text. | 55 * @param {string} value The link text. |
| 29 * @return {Element} The created link element. | 56 * @return {!Element} The created link element. |
| 30 */ | 57 */ |
| 31 function createLink(onclick, value) { | 58 function createLink(onclick, value) { |
| 32 var link = document.createElement('a'); | 59 var link = document.createElement('a'); |
| 33 link.onclick = onclick; | 60 link.onclick = onclick; |
| 34 link.href = '#'; | 61 link.href = '#'; |
| 35 link.textContent = value; | 62 link.textContent = value; |
| 36 link.oncontextmenu = function() { return false; }; | 63 link.oncontextmenu = function() { return false; }; |
| 37 return link; | 64 return link; |
| 38 } | 65 } |
| 39 | 66 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 51 return button; | 78 return button; |
| 52 } | 79 } |
| 53 | 80 |
| 54 /////////////////////////////////////////////////////////////////////////////// | 81 /////////////////////////////////////////////////////////////////////////////// |
| 55 // Downloads | 82 // Downloads |
| 56 /** | 83 /** |
| 57 * Class to hold all the information about the visible downloads. | 84 * Class to hold all the information about the visible downloads. |
| 58 * @constructor | 85 * @constructor |
| 59 */ | 86 */ |
| 60 function Downloads() { | 87 function Downloads() { |
| 88 /** |
| 89 * @type {!Object.<string, Download>} |
| 90 * @private |
| 91 */ |
| 61 this.downloads_ = {}; | 92 this.downloads_ = {}; |
| 62 this.node_ = $('downloads-display'); | 93 this.node_ = $('downloads-display'); |
| 63 this.summary_ = $('downloads-summary-text'); | 94 this.summary_ = $('downloads-summary-text'); |
| 64 this.searchText_ = ''; | 95 this.searchText_ = ''; |
| 65 | 96 |
| 66 // Keep track of the dates of the newest and oldest downloads so that we | 97 // Keep track of the dates of the newest and oldest downloads so that we |
| 67 // know where to insert them. | 98 // know where to insert them. |
| 68 this.newestTime_ = -1; | 99 this.newestTime_ = -1; |
| 69 | 100 |
| 70 // Icon load request queue. | 101 // Icon load request queue. |
| 71 this.iconLoadQueue_ = []; | 102 this.iconLoadQueue_ = []; |
| 72 this.isIconLoading_ = false; | 103 this.isIconLoading_ = false; |
| 73 } | 104 } |
| 74 | 105 |
| 75 /** | 106 /** |
| 76 * Called when a download has been updated or added. | 107 * Called when a download has been updated or added. |
| 77 * @param {Object} download A backend download object (see downloads_ui.cc) | 108 * @param {BackendDownloadObject} download A backend download object |
| 78 */ | 109 */ |
| 79 Downloads.prototype.updated = function(download) { | 110 Downloads.prototype.updated = function(download) { |
| 80 var id = download.id; | 111 var id = download.id; |
| 81 if (!!this.downloads_[id]) { | 112 if (!!this.downloads_[id]) { |
| 82 this.downloads_[id].update(download); | 113 this.downloads_[id].update(download); |
| 83 } else { | 114 } else { |
| 84 this.downloads_[id] = new Download(download); | 115 this.downloads_[id] = new Download(download); |
| 85 // We get downloads in display order, so we don't have to worry about | 116 // We get downloads in display order, so we don't have to worry about |
| 86 // maintaining correct order - we can assume that any downloads not in | 117 // maintaining correct order - we can assume that any downloads not in |
| 87 // display order are new ones and so we can add them to the top of the | 118 // display order are new ones and so we can add them to the top of the |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 | 153 |
| 123 var hasDownloads = false; | 154 var hasDownloads = false; |
| 124 for (var i in this.downloads_) { | 155 for (var i in this.downloads_) { |
| 125 hasDownloads = true; | 156 hasDownloads = true; |
| 126 break; | 157 break; |
| 127 } | 158 } |
| 128 }; | 159 }; |
| 129 | 160 |
| 130 /** | 161 /** |
| 131 * Returns the number of downloads in the model. Used by tests. | 162 * Returns the number of downloads in the model. Used by tests. |
| 132 * @return {integer} Returns the number of downloads shown on the page. | 163 * @return {number} Returns the number of downloads shown on the page. |
| 133 */ | 164 */ |
| 134 Downloads.prototype.size = function() { | 165 Downloads.prototype.size = function() { |
| 135 return Object.keys(this.downloads_).length; | 166 return Object.keys(this.downloads_).length; |
| 136 }; | 167 }; |
| 137 | 168 |
| 138 /** | 169 /** |
| 139 * Update the date visibility in our nodes so that no date is | 170 * Update the date visibility in our nodes so that no date is |
| 140 * repeated. | 171 * repeated. |
| 141 * @private | 172 * @private |
| 142 */ | 173 */ |
| 143 Downloads.prototype.updateDateDisplay_ = function() { | 174 Downloads.prototype.updateDateDisplay_ = function() { |
| 144 var dateContainers = document.getElementsByClassName('date-container'); | 175 var dateContainers = document.getElementsByClassName('date-container'); |
| 145 var displayed = {}; | 176 var displayed = {}; |
| 146 for (var i = 0, container; container = dateContainers[i]; i++) { | 177 for (var i = 0, container; container = dateContainers[i]; i++) { |
| 147 var dateString = container.getElementsByClassName('date')[0].innerHTML; | 178 var dateString = container.getElementsByClassName('date')[0].innerHTML; |
| 148 if (!!displayed[dateString]) { | 179 if (!!displayed[dateString]) { |
| 149 container.style.display = 'none'; | 180 container.style.display = 'none'; |
| 150 } else { | 181 } else { |
| 151 displayed[dateString] = true; | 182 displayed[dateString] = true; |
| 152 container.style.display = 'block'; | 183 container.style.display = 'block'; |
| 153 } | 184 } |
| 154 } | 185 } |
| 155 }; | 186 }; |
| 156 | 187 |
| 157 /** | 188 /** |
| 158 * Remove a download. | 189 * Remove a download. |
| 159 * @param {number} id The id of the download to remove. | 190 * @param {string} id The id of the download to remove. |
| 160 */ | 191 */ |
| 161 Downloads.prototype.remove = function(id) { | 192 Downloads.prototype.remove = function(id) { |
| 162 this.node_.removeChild(this.downloads_[id].node); | 193 this.node_.removeChild(this.downloads_[id].node); |
| 163 delete this.downloads_[id]; | 194 delete this.downloads_[id]; |
| 164 this.updateDateDisplay_(); | 195 this.updateDateDisplay_(); |
| 165 }; | 196 }; |
| 166 | 197 |
| 167 /** | 198 /** |
| 168 * Clear all downloads and reset us back to a null state. | 199 * Clear all downloads and reset us back to a null state. |
| 169 */ | 200 */ |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 if (!this.downloads_[downloads[i].id]) | 257 if (!this.downloads_[downloads[i].id]) |
| 227 return true; | 258 return true; |
| 228 } | 259 } |
| 229 return false; | 260 return false; |
| 230 }; | 261 }; |
| 231 | 262 |
| 232 /////////////////////////////////////////////////////////////////////////////// | 263 /////////////////////////////////////////////////////////////////////////////// |
| 233 // Download | 264 // Download |
| 234 /** | 265 /** |
| 235 * A download and the DOM representation for that download. | 266 * A download and the DOM representation for that download. |
| 236 * @param {Object} download A backend download object (see downloads_ui.cc) | 267 * @param {BackendDownloadObject} download A backend download object |
| 237 * @constructor | 268 * @constructor |
| 238 */ | 269 */ |
| 239 function Download(download) { | 270 function Download(download) { |
| 240 // Create DOM | 271 // Create DOM |
| 241 this.node = createElementWithClassName( | 272 this.node = createElementWithClassName( |
| 242 'div', 'download' + (download.otr ? ' otr' : '')); | 273 'div', 'download' + (download.otr ? ' otr' : '')); |
| 243 | 274 |
| 244 // Dates | 275 // Dates |
| 245 this.dateContainer_ = createElementWithClassName('div', 'date-container'); | 276 this.dateContainer_ = createElementWithClassName('div', 'date-container'); |
| 246 this.node.appendChild(this.dateContainer_); | 277 this.node.appendChild(this.dateContainer_); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 loadTimeData.getString('danger_discard')); | 411 loadTimeData.getString('danger_discard')); |
| 381 this.danger_.appendChild(this.dangerDiscard_); | 412 this.danger_.appendChild(this.dangerDiscard_); |
| 382 | 413 |
| 383 // Update member vars. | 414 // Update member vars. |
| 384 this.update(download); | 415 this.update(download); |
| 385 } | 416 } |
| 386 | 417 |
| 387 /** | 418 /** |
| 388 * The states a download can be in. These correspond to states defined in | 419 * The states a download can be in. These correspond to states defined in |
| 389 * DownloadsDOMHandler::CreateDownloadItemValue | 420 * DownloadsDOMHandler::CreateDownloadItemValue |
| 421 * @enum {string} |
| 390 */ | 422 */ |
| 391 Download.States = { | 423 Download.States = { |
| 392 IN_PROGRESS: 'IN_PROGRESS', | 424 IN_PROGRESS: 'IN_PROGRESS', |
| 393 CANCELLED: 'CANCELLED', | 425 CANCELLED: 'CANCELLED', |
| 394 COMPLETE: 'COMPLETE', | 426 COMPLETE: 'COMPLETE', |
| 395 PAUSED: 'PAUSED', | 427 PAUSED: 'PAUSED', |
| 396 DANGEROUS: 'DANGEROUS', | 428 DANGEROUS: 'DANGEROUS', |
| 397 INTERRUPTED: 'INTERRUPTED', | 429 INTERRUPTED: 'INTERRUPTED', |
| 398 }; | 430 }; |
| 399 | 431 |
| 400 /** | 432 /** |
| 401 * Explains why a download is in DANGEROUS state. | 433 * Explains why a download is in DANGEROUS state. |
| 434 * @enum {string} |
| 402 */ | 435 */ |
| 403 Download.DangerType = { | 436 Download.DangerType = { |
| 404 NOT_DANGEROUS: 'NOT_DANGEROUS', | 437 NOT_DANGEROUS: 'NOT_DANGEROUS', |
| 405 DANGEROUS_FILE: 'DANGEROUS_FILE', | 438 DANGEROUS_FILE: 'DANGEROUS_FILE', |
| 406 DANGEROUS_URL: 'DANGEROUS_URL', | 439 DANGEROUS_URL: 'DANGEROUS_URL', |
| 407 DANGEROUS_CONTENT: 'DANGEROUS_CONTENT', | 440 DANGEROUS_CONTENT: 'DANGEROUS_CONTENT', |
| 408 UNCOMMON_CONTENT: 'UNCOMMON_CONTENT', | 441 UNCOMMON_CONTENT: 'UNCOMMON_CONTENT', |
| 409 DANGEROUS_HOST: 'DANGEROUS_HOST', | 442 DANGEROUS_HOST: 'DANGEROUS_HOST', |
| 410 POTENTIALLY_UNWANTED: 'POTENTIALLY_UNWANTED', | 443 POTENTIALLY_UNWANTED: 'POTENTIALLY_UNWANTED', |
| 411 }; | 444 }; |
| 412 | 445 |
| 413 /** | 446 /** |
| 414 * @param {number} a Some float. | 447 * @param {number} a Some float. |
| 415 * @param {number} b Some float. | 448 * @param {number} b Some float. |
| 416 * @param {number} opt_pct Percent of min(a,b). | 449 * @param {number=} opt_pct Percent of min(a,b). |
| 417 * @return {boolean} true if a is within opt_pct percent of b. | 450 * @return {boolean} true if a is within opt_pct percent of b. |
| 418 */ | 451 */ |
| 419 function floatEq(a, b, opt_pct) { | 452 function floatEq(a, b, opt_pct) { |
| 420 return Math.abs(a - b) < (Math.min(a, b) * (opt_pct || 1.0) / 100.0); | 453 return Math.abs(a - b) < (Math.min(a, b) * (opt_pct || 1.0) / 100.0); |
| 421 } | 454 } |
| 422 | 455 |
| 423 /** | 456 /** |
| 424 * Constants and "constants" for the progress meter. | 457 * Constants and "constants" for the progress meter. |
| 425 */ | 458 */ |
| 426 Download.Progress = { | 459 Download.Progress = { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 442 Download.Progress.height = Download.Progress.SIDE * Download.Progress.scale; | 475 Download.Progress.height = Download.Progress.SIDE * Download.Progress.scale; |
| 443 Download.Progress.radius = Download.Progress.HALF * Download.Progress.scale; | 476 Download.Progress.radius = Download.Progress.HALF * Download.Progress.scale; |
| 444 Download.Progress.centerX = Download.Progress.HALF * Download.Progress.scale; | 477 Download.Progress.centerX = Download.Progress.HALF * Download.Progress.scale; |
| 445 Download.Progress.centerY = Download.Progress.HALF * Download.Progress.scale; | 478 Download.Progress.centerY = Download.Progress.HALF * Download.Progress.scale; |
| 446 } | 479 } |
| 447 computeDownloadProgress(); | 480 computeDownloadProgress(); |
| 448 | 481 |
| 449 // Listens for when device-pixel-ratio changes between any zoom level. | 482 // Listens for when device-pixel-ratio changes between any zoom level. |
| 450 [0.3, 0.4, 0.6, 0.7, 0.8, 0.95, 1.05, 1.2, 1.4, 1.6, 1.9, 2.2, 2.7, 3.5, 4.5 | 483 [0.3, 0.4, 0.6, 0.7, 0.8, 0.95, 1.05, 1.2, 1.4, 1.6, 1.9, 2.2, 2.7, 3.5, 4.5 |
| 451 ].forEach(function(scale) { | 484 ].forEach(function(scale) { |
| 452 matchMedia('(-webkit-min-device-pixel-ratio:' + scale + ')').addListener( | 485 var media = '(-webkit-min-device-pixel-ratio:' + scale + ')'; |
| 453 function() { | 486 window.matchMedia(media).addListener(computeDownloadProgress); |
| 454 computeDownloadProgress(); | |
| 455 }); | |
| 456 }); | 487 }); |
| 457 | 488 |
| 458 var ImageCache = {}; | 489 var ImageCache = {}; |
| 459 function getCachedImage(src) { | 490 function getCachedImage(src) { |
| 460 if (!ImageCache[src]) { | 491 if (!ImageCache[src]) { |
| 461 ImageCache[src] = new Image(); | 492 ImageCache[src] = new Image(); |
| 462 ImageCache[src].src = src; | 493 ImageCache[src].src = src; |
| 463 } | 494 } |
| 464 return ImageCache[src]; | 495 return ImageCache[src]; |
| 465 } | 496 } |
| 466 | 497 |
| 467 /** | 498 /** |
| 468 * Updates the download to reflect new data. | 499 * Updates the download to reflect new data. |
| 469 * @param {Object} download A backend download object (see downloads_ui.cc) | 500 * @param {BackendDownloadObject} download A backend download object |
| 470 */ | 501 */ |
| 471 Download.prototype.update = function(download) { | 502 Download.prototype.update = function(download) { |
| 472 this.id_ = download.id; | 503 this.id_ = download.id; |
| 473 this.filePath_ = download.file_path; | 504 this.filePath_ = download.file_path; |
| 474 this.fileUrl_ = download.file_url; | 505 this.fileUrl_ = download.file_url; |
| 475 this.fileName_ = download.file_name; | 506 this.fileName_ = download.file_name; |
| 476 this.url_ = download.url; | 507 this.url_ = download.url; |
| 477 this.state_ = download.state; | 508 this.state_ = download.state; |
| 478 this.fileExternallyRemoved_ = download.file_externally_removed; | 509 this.fileExternallyRemoved_ = download.file_externally_removed; |
| 479 this.dangerType_ = download.danger_type; | 510 this.dangerType_ = download.danger_type; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 // danger_url_desc is also used by DANGEROUS_CONTENT. | 739 // danger_url_desc is also used by DANGEROUS_CONTENT. |
| 709 var desc = this.dangerType_ == Download.DangerType.DANGEROUS_FILE ? | 740 var desc = this.dangerType_ == Download.DangerType.DANGEROUS_FILE ? |
| 710 'danger_file_desc' : 'danger_url_desc'; | 741 'danger_file_desc' : 'danger_url_desc'; |
| 711 return loadTimeData.getString(desc); | 742 return loadTimeData.getString(desc); |
| 712 case Download.States.INTERRUPTED: | 743 case Download.States.INTERRUPTED: |
| 713 return this.lastReasonDescription_; | 744 return this.lastReasonDescription_; |
| 714 case Download.States.COMPLETE: | 745 case Download.States.COMPLETE: |
| 715 return this.fileExternallyRemoved_ ? | 746 return this.fileExternallyRemoved_ ? |
| 716 loadTimeData.getString('status_removed') : ''; | 747 loadTimeData.getString('status_removed') : ''; |
| 717 } | 748 } |
| 749 assertNotReached(); |
| 750 return ''; |
| 718 }; | 751 }; |
| 719 | 752 |
| 720 /** | 753 /** |
| 721 * Tells the backend to initiate a drag, allowing users to drag | 754 * Tells the backend to initiate a drag, allowing users to drag |
| 722 * files from the download page and have them appear as native file | 755 * files from the download page and have them appear as native file |
| 723 * drags. | 756 * drags. |
| 724 * @return {boolean} Returns false to prevent the default action. | 757 * @return {boolean} Returns false to prevent the default action. |
| 725 * @private | 758 * @private |
| 726 */ | 759 */ |
| 727 Download.prototype.drag_ = function() { | 760 Download.prototype.drag_ = function() { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 openDownloadsFolderLink.oncontextmenu = function() { return false; }; | 892 openDownloadsFolderLink.oncontextmenu = function() { return false; }; |
| 860 | 893 |
| 861 $('search-link').onclick = function(e) { | 894 $('search-link').onclick = function(e) { |
| 862 setSearch(''); | 895 setSearch(''); |
| 863 e.preventDefault(); | 896 e.preventDefault(); |
| 864 $('term').value = ''; | 897 $('term').value = ''; |
| 865 return false; | 898 return false; |
| 866 }; | 899 }; |
| 867 | 900 |
| 868 $('term').onsearch = function(e) { | 901 $('term').onsearch = function(e) { |
| 869 setSearch(this.value); | 902 setSearch($('term').value); |
| 870 }; | 903 }; |
| 871 } | 904 } |
| 872 | 905 |
| 873 function setSearch(searchText) { | 906 function setSearch(searchText) { |
| 874 fifoResults.length = 0; | 907 fifoResults.length = 0; |
| 875 downloads.setSearchText(searchText); | 908 downloads.setSearchText(searchText); |
| 876 searchText = searchText.toString().match(/(?:[^\s"]+|"[^"]*")+/g); | 909 searchText = searchText.toString().match(/(?:[^\s"]+|"[^"]*")+/g); |
| 877 if (searchText) { | 910 if (searchText) { |
| 878 searchText = searchText.map(function(term) { | 911 searchText = searchText.map(function(term) { |
| 879 // strip quotes | 912 // strip quotes |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 if (Date.now() - start > 50) { | 975 if (Date.now() - start > 50) { |
| 943 clearTimeout(resultsTimeout); | 976 clearTimeout(resultsTimeout); |
| 944 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); | 977 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); |
| 945 break; | 978 break; |
| 946 } | 979 } |
| 947 } | 980 } |
| 948 } | 981 } |
| 949 | 982 |
| 950 // Add handlers to HTML elements. | 983 // Add handlers to HTML elements. |
| 951 window.addEventListener('DOMContentLoaded', load); | 984 window.addEventListener('DOMContentLoaded', load); |
| OLD | NEW |