Port downloads.ItemView to a Polymer component.
This results in a very ugly, somewhat functional MD chrome://downloads.
[email protected]
BUG=425626
NOPRESUBMIT=true
Review URL: https://codereview.chromium.org/1224623013
Cr-Commit-Position: refs/heads/master@{#338221}
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index c2f4cedd..6faddb66 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -25,9 +25,8 @@
<structure name="IDR_APP_LIST_START_PAGE_JS" file="resources\app_list\start_page.js" flattenhtml="true" type="chrome_html" />
</if>
<if expr="not is_android">
- <structure name="IDR_DOWNLOADS_HTML" file="resources\downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
- <!-- TODO(dbeam): remove flattening from all new MD UIs. -->
- <structure name="IDR_MD_DOWNLOADS_HTML" file="resources\md_downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
+ <structure name="IDR_DOWNLOADS_DOWNLOADS_HTML" file="resources\downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
+ <structure name="IDR_MD_DOWNLOADS_DOWNLOADS_HTML" file="resources\md_downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
</if>
<if expr="enable_extensions">
<structure name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="chrome_html" />
@@ -126,13 +125,19 @@
<include name="IDR_DOMAIN_RELIABILITY_INTERNALS_CSS" file="resources\domain_reliability_internals.css" type="BINDATA" />
<include name="IDR_DOMAIN_RELIABILITY_INTERNALS_JS" file="resources\domain_reliability_internals.js" type="BINDATA" />
<if expr="not is_android">
- <include name="IDR_DOWNLOAD_CONSTANTS_JS" file="resources\downloads\constants.js" type="BINDATA" />
- <include name="IDR_DOWNLOAD_FOCUS_ROW_JS" file="resources\downloads\focus_row.js" type="BINDATA" />
- <include name="IDR_DOWNLOAD_ITEM_VIEW_JS" file="resources\downloads\item_view.js" type="BINDATA" />
- <include name="IDR_DOWNLOAD_MANAGER_JS" file="resources\downloads\manager.js" type="BINDATA" />
- <include name="IDR_DOWNLOAD_THROTTLED_ICON_LOADER_HTML" file="resources\downloads\throttled_icon_loader.html" type="BINDATA" />
- <include name="IDR_DOWNLOAD_THROTTLED_ICON_LOADER_JS" file="resources\downloads\throttled_icon_loader.js" type="BINDATA" />
- <include name="IDR_MD_DOWNLOAD_MANAGER_JS" file="resources\md_downloads\manager.js" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_CONSTANTS_HTML" file="resources\downloads\constants.html" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_CONSTANTS_JS" file="resources\downloads\constants.js" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_FOCUS_ROW_JS" file="resources\downloads\focus_row.js" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_ITEM_VIEW_JS" file="resources\downloads\item_view.js" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_MANAGER_JS" file="resources\downloads\manager.js" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_THROTTLED_ICON_LOADER_HTML" file="resources\downloads\throttled_icon_loader.html" type="BINDATA" />
+ <include name="IDR_DOWNLOADS_THROTTLED_ICON_LOADER_JS" file="resources\downloads\throttled_icon_loader.js" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_DOWNLOADS_CSS" file="resources\md_downloads\downloads.css" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_ITEM_VIEW_HTML" file="resources\md_downloads\item_view.html" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_ITEM_VIEW_JS" file="resources\md_downloads\item_view.js" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_MANAGER_HTML" file="resources\md_downloads\manager.html" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_MANAGER_JS" file="resources\md_downloads\manager.js" type="BINDATA" />
+ <include name="IDR_MD_DOWNLOADS_STRINGS_HTML" file="resources\md_downloads\strings.html" type="BINDATA" />
</if>
<if expr="enable_extensions">
<include name="IDR_EXTENSION_COMMAND_LIST_JS" file="resources\extensions\extension_command_list.js" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/resources/downloads/compiled_resources2.gyp b/chrome/browser/resources/downloads/compiled_resources2.gyp
index 7a7fafb..af609c9d 100644
--- a/chrome/browser/resources/downloads/compiled_resources2.gyp
+++ b/chrome/browser/resources/downloads/compiled_resources2.gyp
@@ -37,10 +37,9 @@
{
'target_name': 'manager',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:action_link',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:event_tracker',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
diff --git a/chrome/browser/resources/downloads/constants.html b/chrome/browser/resources/downloads/constants.html
new file mode 100644
index 0000000..0ac6c26b
--- /dev/null
+++ b/chrome/browser/resources/downloads/constants.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://downloads/constants.js"></script>
diff --git a/chrome/browser/resources/downloads/downloads.html b/chrome/browser/resources/downloads/downloads.html
index e389e04..96dedb5 100644
--- a/chrome/browser/resources/downloads/downloads.html
+++ b/chrome/browser/resources/downloads/downloads.html
@@ -16,7 +16,7 @@
<script src="chrome://resources/js/event_tracker.js"></script>
<script src="chrome://resources/js/cr/ui/focus_row.js"></script>
<script src="chrome://resources/js/cr/ui/focus_grid.js"></script>
- <script src="chrome://downloads/constants.js"></script>
+ <link rel="import" href="chrome://downloads/constants.html">
<link rel="import" href="chrome://downloads/throttled_icon_loader.html">
<script src="chrome://downloads/item_view.js"></script>
<script src="chrome://downloads/focus_row.js"></script>
diff --git a/chrome/browser/resources/md_downloads/compiled_resources.gyp b/chrome/browser/resources/md_downloads/compiled_resources.gyp
index b615a89..75e200f2 100644
--- a/chrome/browser/resources/md_downloads/compiled_resources.gyp
+++ b/chrome/browser/resources/md_downloads/compiled_resources.gyp
@@ -14,6 +14,9 @@
'../../../../ui/webui/resources/js/cr/ui.js',
'../../../../ui/webui/resources/js/cr/ui/command.js',
'../../../../ui/webui/resources/js/util.js',
+ '../downloads/constants.js',
+ '../downloads/throttled_icon_loader.js',
+ 'item_view.js',
],
'externs': [
'<(EXTERNS_DIR)/chrome_send.js',
diff --git a/chrome/browser/resources/md_downloads/compiled_resources2.gyp b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
index 7f74d88..7b4afb7 100644
--- a/chrome/browser/resources/md_downloads/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
@@ -4,15 +4,25 @@
{
'targets': [
{
+ 'target_name': 'item_view',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '../downloads/compiled_resources2.gyp:constants',
+ '../downloads/compiled_resources2.gyp:throttled_icon_loader',
+ '../downloads/compiled_resources2.gyp:externs',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'manager',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:action_link',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
'<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:command',
+ 'item_view',
'<(EXTERNS_GYP):chrome_send',
'../downloads/compiled_resources2.gyp:externs',
],
diff --git a/chrome/browser/resources/md_downloads/downloads.html b/chrome/browser/resources/md_downloads/downloads.html
index aeb638d0..00cf7c9 100644
--- a/chrome/browser/resources/md_downloads/downloads.html
+++ b/chrome/browser/resources/md_downloads/downloads.html
@@ -4,28 +4,19 @@
<meta charset="utf-8">
<title i18n-content="title"></title>
+ <link rel="import" href="chrome://resources/html/action_link.html">
+ <link rel="import" href="chrome://resources/html/polymer_config.html">
<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
-
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html">
- <link rel="import" href="chrome://resources/html/action_link.html">
- <link rel="import" href="chrome://resources/html/assert.html">
- <link rel="import" href="chrome://resources/html/cr.html">
-
- <script src="chrome://resources/js/util.js"></script>
- <script src="chrome://resources/js/load_time_data.js"></script>
- <script src="chrome://resources/js/cr/ui.js"></script>
- <script src="chrome://resources/js/cr/ui/command.js"></script>
-
- <script src="chrome://downloads/constants.js"></script>
- <script src="chrome://downloads/manager.js"></script>
+ <link rel="import" href="chrome://downloads/manager.html">
<link rel="stylesheet" href="chrome://resources/css/roboto.css">
- <link rel="stylesheet" href="downloads.css">
+ <link rel="stylesheet" href="chrome://downloads/downloads.css">
</head>
<body class="fullbleed">
@@ -59,8 +50,9 @@
<command id="undo-command" shortcut="Ctrl-U+005A"><!-- Ctrl+Z -->
</if>
- <script src="chrome://downloads/strings.js"></script>
- <script src="chrome://resources/js/i18n_template.js"></script>
+ <link rel="import" href="chrome://resources/html/load_time_data.html">
+ <link rel="import" href="chrome://downloads/strings.html">
+ <link rel="import" href="chrome://resources/html/i18n_template.html"></script>
</body>
</html>
diff --git a/chrome/browser/resources/md_downloads/item_view.html b/chrome/browser/resources/md_downloads/item_view.html
new file mode 100644
index 0000000..279b9ba
--- /dev/null
+++ b/chrome/browser/resources/md_downloads/item_view.html
@@ -0,0 +1,58 @@
+<dom-module id="item-view">
+ <template>
+ <div id="date-container" hidden$="{{hideDate}}">
+ <div id="since"></div>
+ <div id="date"></div>
+ </div>
+
+ <div id="safe" hidden$="{{isDangerous}}">
+ <div id="progress"></div>
+ <img id="safe-icon" alt="">
+ <div id="title-area">
+ <a is="action-link" id="file-link" column-type="name"></a>
+ <span id="name"></span>
+ <span id="status"></span>
+ </div>
+ <div>
+ <a id="src-url" target="_blank" column-type="url"></a>
+ </div>
+ <div>
+ <a is="action-link" id="show" column-type="show"
+ i18n-content="control_showinfolder"></a>
+ <a id="retry" column-type="retry" i18n-content="control_retry"
+ download></a>
+ <a is="action-link" id="pause" column-type="pause"
+ i18n-content="control_pause"></a>
+ <a is="action-link" id="resume" column-type="resume"
+ i18n-content="control_resume"></a>
+ <a is="action-link" id="safe-remove" column-type="remove"
+ i18n-content="control_removefromlist"></a>
+ <a is="action-link" id="cancel" column-type="cancel"
+ i18n-content="control_cancel"></a>
+ <span id="controlled-by"
+ i18n-values=".innerHTML:control_by_extension"></span>
+ </div>
+ </div>
+
+ <div id="dangerous" hidden$="{{!isDangerous}}">
+ <img id="dangerous-icon" alt="">
+ <div id="description"></div>
+ <div id="malware-controls" hidden$="{{!isMalware}}">
+ <a is="action-link" id="restore" column-type="save"
+ i18n-content="danger_restore"></a>
+ <a is="action-link" id="dangerous-remove" column-type="discard"
+ i18n-content="control_removefromlist"></a>
+ </div>
+ <button id="save" column-type="save" i18n-content="danger_save"
+ hidden$="{{isMalware}}"></button>
+ <button id="discard" column-type="discard" i18n-content="danger_discard"
+ hidden$="{{isMalware}}"></button>
+ </div>
+ </template>
+ <link rel="import" href="chrome://resources/html/cr.html">
+ <link rel="import" href="chrome://resources/html/load_time_data.html">
+ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+ <link rel="import" href="chrome://downloads/constants.html">
+ <link rel="import" href="chrome://downloads/throttled_icon_loader.html">
+ <script src="chrome://downloads/item_view.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/md_downloads/item_view.js b/chrome/browser/resources/md_downloads/item_view.js
new file mode 100644
index 0000000..d0b7490
--- /dev/null
+++ b/chrome/browser/resources/md_downloads/item_view.js
@@ -0,0 +1,250 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('downloads', function() {
+ var ItemView = Polymer({
+ is: 'item-view',
+
+ /** @param {!downloads.ThrottledIconLoader} iconLoader */
+ factoryImpl: function(iconLoader) {
+ /** @private {!downloads.ThrottledIconLoader} */
+ this.iconLoader_ = iconLoader;
+ },
+
+ properties: {
+ hideDate: {type: Boolean, value: false},
+ isDangerous: {type: Boolean, value: false},
+ // Only use |isMalware| if |isDangerous| is true.
+ isMalware: Boolean,
+ },
+
+ ready: function() {
+ this.$.safe.ondragstart = this.onSafeDragstart_.bind(this);
+ this.$['file-link'].onclick = this.onFileLinkClick_.bind(this);
+ this.$.show.onclick = this.onShowClick_.bind(this);
+ this.$.pause.onclick = this.onPauseClick_.bind(this);
+ this.$.resume.onclick = this.onResumeClick_.bind(this);
+ this.$['safe-remove'].onclick = this.onSafeRemoveClick_.bind(this);
+ this.$.cancel.onclick = this.onCancelClick_.bind(this);
+ this.$.restore.onclick = this.onRestoreClick_.bind(this);
+ this.$.save.onclick = this.onSaveClick_.bind(this);
+ this.$['dangerous-remove'].onclick = this.onDangerRemoveClick_.bind(this);
+ this.$.discard.onclick = this.onDiscardClick_.bind(this);
+ },
+
+ /** @param {!downloads.Data} data */
+ update: function(data) {
+ assert(!this.id_ || data.id == this.id_);
+ this.id_ = data.id; // This is the only thing saved from |data|.
+
+ this.classList.toggle('otr', data.otr);
+
+ this.ensureTextIs_(this.$.since, data.since_string);
+ this.ensureTextIs_(this.$.date, data.date_string);
+
+ var dangerText = this.getDangerText_(data);
+ this.isDangerous = !!dangerText;
+
+ if (dangerText) {
+ this.ensureTextIs_(this.$.description, dangerText);
+
+ var dangerType = data.danger_type;
+ var dangerousFile = dangerType == downloads.DangerType.DANGEROUS_FILE;
+ this.$.description.classList.toggle('malware', !dangerousFile);
+
+ var idr = dangerousFile ? 'IDR_WARNING' : 'IDR_SAFEBROWSING_WARNING';
+ var iconUrl = 'chrome://theme/' + idr;
+ this.iconLoader_.loadScaledIcon(this.$['dangerous-icon'], iconUrl);
+
+ this.isMalware =
+ dangerType == downloads.DangerType.DANGEROUS_CONTENT ||
+ dangerType == downloads.DangerType.DANGEROUS_HOST ||
+ dangerType == downloads.DangerType.DANGEROUS_URL ||
+ dangerType == downloads.DangerType.POTENTIALLY_UNWANTED;
+ } else {
+ var iconUrl = 'chrome://fileicon/' + encodeURIComponent(data.file_path);
+ this.iconLoader_.loadScaledIcon(this.$['safe-icon'], iconUrl);
+
+ /** @const */ var isInProgress =
+ data.state == downloads.States.IN_PROGRESS;
+ this.classList.toggle('in-progress', isInProgress);
+
+ /** @const */ var completelyOnDisk =
+ data.state == downloads.States.COMPLETE &&
+ !data.file_externally_removed;
+
+ this.$['file-link'].href = data.url;
+ this.ensureTextIs_(this.$['file-link'], data.file_name);
+ this.$['file-link'].hidden = !completelyOnDisk;
+
+ /** @const */ var isInterrupted =
+ data.state == downloads.States.INTERRUPTED;
+ this.$.name.classList.toggle('interrupted', isInterrupted);
+ this.ensureTextIs_(this.$.name, data.file_name);
+ this.$.name.hidden = completelyOnDisk;
+
+ this.$.show.hidden = !completelyOnDisk;
+
+ this.$.retry.href = data.url;
+ this.$.retry.hidden = !data.retry;
+
+ this.$.pause.hidden = !isInProgress;
+
+ this.$.resume.hidden = !data.resume;
+
+ /** @const */ var isPaused = data.state == downloads.States.PAUSED;
+ /** @const */ var showCancel = isPaused || isInProgress;
+ this.$.cancel.hidden = !showCancel;
+
+ this.$['safe-remove'].hidden = showCancel ||
+ !loadTimeData.getBoolean('allow_deleting_history');
+
+ /** @const */ var controlledByExtension = data.by_ext_id &&
+ data.by_ext_name;
+ this.$['controlled-by'].hidden = !controlledByExtension;
+ if (controlledByExtension) {
+ var link = this.$['controlled-by'].querySelector('a');
+ link.href = 'chrome://extensions#' + data.by_ext_id;
+ link.setAttribute('column-type', 'controlled-by');
+ link.textContent = data.by_ext_name;
+ }
+
+ this.ensureTextIs_(this.$['src-url'], data.url);
+ this.$['src-url'].href = data.url;
+ this.ensureTextIs_(this.$.status, this.getStatusText_(data));
+
+ this.$.progress.hidden = !isInProgress;
+
+ // TODO(dbeam): implement progress.
+ }
+ },
+
+ /**
+ * Overwrite |el|'s textContent if it differs from |text|.
+ * @param {!Element} el
+ * @param {string} text
+ * @private
+ */
+ ensureTextIs_: function(el, text) {
+ if (el.textContent != text)
+ el.textContent = text;
+ },
+
+ /**
+ * @param {!downloads.Data} data
+ * @return {string} Text describing the danger of a download. Empty if not
+ * dangerous.
+ */
+ getDangerText_: function(data) {
+ switch (data.danger_type) {
+ case downloads.DangerType.DANGEROUS_FILE:
+ return loadTimeData.getStringF('danger_file_desc', data.file_name);
+ case downloads.DangerType.DANGEROUS_URL:
+ return loadTimeData.getString('danger_url_desc');
+ case downloads.DangerType.DANGEROUS_CONTENT: // Fall through.
+ case downloads.DangerType.DANGEROUS_HOST:
+ return loadTimeData.getStringF('danger_content_desc', data.file_name);
+ case downloads.DangerType.UNCOMMON_CONTENT:
+ return loadTimeData.getStringF('danger_uncommon_desc',
+ data.file_name);
+ case downloads.DangerType.POTENTIALLY_UNWANTED:
+ return loadTimeData.getStringF('danger_settings_desc',
+ data.file_name);
+ default:
+ return '';
+ }
+ },
+
+ /**
+ * @param {!downloads.Data} data
+ * @return {string} User-visible status update text.
+ * @private
+ */
+ getStatusText_: function(data) {
+ switch (data.state) {
+ case downloads.States.IN_PROGRESS:
+ case downloads.States.PAUSED: // Fallthrough.
+ assert(typeof data.progress_status_text == 'string');
+ return data.progress_status_text;
+ case downloads.States.CANCELLED:
+ return loadTimeData.getString('status_cancelled');
+ case downloads.States.DANGEROUS:
+ break; // Intentionally hit assertNotReached(); at bottom.
+ case downloads.States.INTERRUPTED:
+ assert(typeof data.last_reason_text == 'string');
+ return data.last_reason_text;
+ case downloads.States.COMPLETE:
+ return data.file_externally_removed ?
+ loadTimeData.getString('status_removed') : '';
+ }
+ assertNotReached();
+ return '';
+ },
+
+ /**
+ * @private
+ * @param {Event} e
+ */
+ onSafeDragstart_: function(e) {
+ e.preventDefault();
+ chrome.send('drag', [this.id_]);
+ },
+
+ /**
+ * @param {Event} e
+ * @private
+ */
+ onFileLinkClick_: function(e) {
+ e.preventDefault();
+ chrome.send('openFile', [this.id_]);
+ },
+
+ /** @private */
+ onShowClick_: function() {
+ chrome.send('show', [this.id_]);
+ },
+
+ /** @private */
+ onPauseClick_: function() {
+ chrome.send('pause', [this.id_]);
+ },
+
+ /** @private */
+ onResumeClick_: function() {
+ chrome.send('resume', [this.id_]);
+ },
+
+ /** @private */
+ onSafeRemoveClick_: function() {
+ chrome.send('remove', [this.id_]);
+ },
+
+ /** @private */
+ onCancelClick_: function() {
+ chrome.send('cancel', [this.id_]);
+ },
+
+ /** @private */
+ onRestoreClick_: function() {
+ this.onSaveClick_();
+ },
+
+ /** @private */
+ onSaveClick_: function() {
+ chrome.send('saveDangerous', [this.id_]);
+ },
+
+ /** @private */
+ onDangerRemoveClick_: function() {
+ this.onDiscardClick_();
+ },
+
+ /** @private */
+ onDiscardClick_: function() {
+ chrome.send('discardDangerous', [this.id_]);
+ },
+ });
+
+ return {ItemView: ItemView};
+});
diff --git a/chrome/browser/resources/md_downloads/manager.html b/chrome/browser/resources/md_downloads/manager.html
new file mode 100644
index 0000000..53b11d38
--- /dev/null
+++ b/chrome/browser/resources/md_downloads/manager.html
@@ -0,0 +1,8 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
+<link rel="import" href="chrome://resources/html/cr/ui.html">
+<link rel="import" href="chrome://resources/html/cr/ui/command.html">
+<link rel="import" href="chrome://resources/html/util.html">
+<link rel="import" href="chrome://downloads/constants.html">
+<link rel="import" href="chrome://downloads/item_view.html">
+<script src="chrome://downloads/manager.js"></script>
diff --git a/chrome/browser/resources/md_downloads/manager.js b/chrome/browser/resources/md_downloads/manager.js
index 16caf24..99c3547 100644
--- a/chrome/browser/resources/md_downloads/manager.js
+++ b/chrome/browser/resources/md_downloads/manager.js
@@ -32,13 +32,78 @@
},
/**
+ * @return {number} A guess at how many items could be visible at once.
+ * @private
+ */
+ guesstimateNumberOfVisibleItems_: function() {
+ var toolbarHeight = $('downloads-toolbar').offsetHeight;
+ var summaryHeight = $('downloads-summary').offsetHeight;
+ var nonItemSpace = toolbarHeight + summaryHeight;
+ return Math.floor((window.innerHeight - nonItemSpace) / 46) + 1;
+ },
+
+ /**
* Called when all items need to be updated.
* @param {!Array<!downloads.Data>} list A list of new download data.
* @private
*/
updateAll_: function(list) {
- /** @private {!Array} */
- this.items_ = list;
+ var oldIdMap = this.idMap_ || {};
+
+ /** @private {!Object<!downloads.ItemView>} */
+ this.idMap_ = {};
+
+ /** @private {!Array<!downloads.ItemView>} */
+ this.items_ = [];
+
+ if (!this.iconLoader_) {
+ var guesstimate = Math.max(this.guesstimateNumberOfVisibleItems_(), 1);
+ /** @private {downloads.ThrottledIconLoader} */
+ this.iconLoader_ = new downloads.ThrottledIconLoader(guesstimate);
+ }
+
+ for (var i = 0; i < list.length; ++i) {
+ var data = list[i];
+ var id = data.id;
+
+ // Re-use old items when possible (saves work, preserves focus).
+ var item = oldIdMap[id] || new downloads.ItemView(this.iconLoader_);
+
+ this.idMap_[id] = item; // Associated by ID for fast lookup.
+ this.items_.push(item); // Add to sorted list for order.
+
+ // Render |item| but don't actually add to the DOM yet. |this.items_|
+ // must be fully created to be able to find the right spot to insert.
+ item.update(data);
+
+ // Collapse redundant dates.
+ var prev = list[i - 1];
+ item.hideDate = !!prev && prev.date_string == data.date_string;
+
+ delete oldIdMap[id];
+ }
+
+ // Remove stale, previously rendered items from the DOM.
+ for (var id in oldIdMap) {
+ if (oldIdMap[id].parentNode)
+ oldIdMap[id].parentNode.removeChild(oldIdMap[id]);
+ delete oldIdMap[id];
+ }
+
+ for (var i = 0; i < this.items_.length; ++i) {
+ var item = this.items_[i];
+ if (item.parentNode) // Already in the DOM; skip.
+ continue;
+
+ var before = null;
+ // Find the next rendered item after this one, and insert before it.
+ for (var j = i + 1; !before && j < this.items_.length; ++j) {
+ if (this.items_[j].parentNode)
+ before = this.items_[j];
+ }
+ // If |before| is null, |item| will just get added at the end.
+ this.node_.insertBefore(item, before);
+ }
var noDownloadsOrResults = $('no-downloads-or-results');
noDownloadsOrResults.textContent = loadTimeData.getString(
@@ -53,6 +118,14 @@
},
/**
+ * @param {!downloads.Data} data
+ * @private
+ */
+ updateItem_: function(data) {
+ this.idMap_[data.id].update(data);
+ },
+
+ /**
* @return {number} The number of downloads shown on the page.
* @private
*/
@@ -139,7 +212,9 @@
Manager.getInstance().updateAll_(list);
};
- Manager.updateItem = function(item) {};
+ Manager.updateItem = function(item) {
+ Manager.getInstance().updateItem_(item);
+ };
Manager.setSearchText = function(searchText) {
Manager.getInstance().setSearchText_(searchText);
@@ -156,4 +231,4 @@
return {Manager: Manager};
});
-window.addEventListener('DOMContentLoaded', downloads.Manager.onLoad);
+window.addEventListener('load', downloads.Manager.onLoad);
diff --git a/chrome/browser/resources/md_downloads/strings.html b/chrome/browser/resources/md_downloads/strings.html
new file mode 100644
index 0000000..ecbe002
--- /dev/null
+++ b/chrome/browser/resources/md_downloads/strings.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/load_time_data.html">
+<script src="chrome://downloads/strings.js"></script>
diff --git a/chrome/browser/ui/webui/downloads_ui.cc b/chrome/browser/ui/webui/downloads_ui.cc
index 1b51926..8fc489e 100644
--- a/chrome/browser/ui/webui/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads_ui.cc
@@ -90,20 +90,26 @@
!profile->IsSupervised());
source->SetJsonPath("strings.js");
- source->AddResourcePath("constants.js", IDR_DOWNLOAD_CONSTANTS_JS);
+ source->AddResourcePath("constants.html", IDR_DOWNLOADS_CONSTANTS_HTML);
+ source->AddResourcePath("constants.js", IDR_DOWNLOADS_CONSTANTS_JS);
source->AddResourcePath("throttled_icon_loader.html",
- IDR_DOWNLOAD_THROTTLED_ICON_LOADER_HTML);
+ IDR_DOWNLOADS_THROTTLED_ICON_LOADER_HTML);
source->AddResourcePath("throttled_icon_loader.js",
- IDR_DOWNLOAD_THROTTLED_ICON_LOADER_JS);
+ IDR_DOWNLOADS_THROTTLED_ICON_LOADER_JS);
if (switches::MdDownloadsEnabled()) {
- source->AddResourcePath("manager.js", IDR_MD_DOWNLOAD_MANAGER_JS);
- source->SetDefaultResource(IDR_MD_DOWNLOADS_HTML);
+ source->AddResourcePath("downloads.css", IDR_MD_DOWNLOADS_DOWNLOADS_CSS);
+ source->AddResourcePath("item_view.html", IDR_MD_DOWNLOADS_ITEM_VIEW_HTML);
+ source->AddResourcePath("item_view.js", IDR_MD_DOWNLOADS_ITEM_VIEW_JS);
+ source->AddResourcePath("manager.html", IDR_MD_DOWNLOADS_MANAGER_HTML);
+ source->AddResourcePath("manager.js", IDR_MD_DOWNLOADS_MANAGER_JS);
+ source->AddResourcePath("strings.html", IDR_MD_DOWNLOADS_STRINGS_HTML);
+ source->SetDefaultResource(IDR_MD_DOWNLOADS_DOWNLOADS_HTML);
} else {
- source->AddResourcePath("item_view.js", IDR_DOWNLOAD_ITEM_VIEW_JS);
- source->AddResourcePath("focus_row.js", IDR_DOWNLOAD_FOCUS_ROW_JS);
- source->AddResourcePath("manager.js", IDR_DOWNLOAD_MANAGER_JS);
- source->SetDefaultResource(IDR_DOWNLOADS_HTML);
+ source->AddResourcePath("item_view.js", IDR_DOWNLOADS_ITEM_VIEW_JS);
+ source->AddResourcePath("focus_row.js", IDR_DOWNLOADS_FOCUS_ROW_JS);
+ source->AddResourcePath("manager.js", IDR_DOWNLOADS_MANAGER_JS);
+ source->SetDefaultResource(IDR_DOWNLOADS_DOWNLOADS_HTML);
}
return source;