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 |