Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Unified Diff: ui/file_manager/file_manager/background/js/import_history.js

Issue 837563002: Show a little circly/arrowey badge for files that have been copied locally. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add copy support to test import_history and update media import handler test to check for copy resu… Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | ui/file_manager/file_manager/background/js/import_history_unittest.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/file_manager/file_manager/background/js/import_history.js
diff --git a/ui/file_manager/file_manager/background/js/import_history.js b/ui/file_manager/file_manager/background/js/import_history.js
index 825ebe18d87d4baee84392407abf5b9173fc478b..6bfbab0ff8f1e0abd267049a3c218b3bb9d311dd 100644
--- a/ui/file_manager/file_manager/background/js/import_history.js
+++ b/ui/file_manager/file_manager/background/js/import_history.js
@@ -16,6 +16,14 @@ importer.ImportHistory = function() {};
* @param {!FileEntry} entry
* @param {!importer.Destination} destination
* @return {!Promise.<boolean>} Resolves with true if the FileEntry
+ * was previously copied to the device.
+ */
+importer.ImportHistory.prototype.wasCopied;
+
+/**
+ * @param {!FileEntry} entry
+ * @param {!importer.Destination} destination
+ * @return {!Promise.<boolean>} Resolves with true if the FileEntry
* was previously imported to the specified destination.
*/
importer.ImportHistory.prototype.wasImported;
@@ -23,6 +31,13 @@ importer.ImportHistory.prototype.wasImported;
/**
* @param {!FileEntry} entry
* @param {!importer.Destination} destination
+ * @param {string} url
+ */
+importer.ImportHistory.prototype.markCopied;
+
+/**
+ * @param {!FileEntry} entry
+ * @param {!importer.Destination} destination
* @return {!Promise.<?>} Resolves when the operation is completed.
*/
importer.ImportHistory.prototype.markImported;
@@ -43,6 +58,7 @@ importer.ImportHistory.prototype.removeObserver;
/** @enum {string} */
importer.ImportHistory.State = {
+ 'COPIED': 'copied',
'IMPORTED': 'imported'
};
@@ -78,12 +94,24 @@ importer.DummyImportHistory.prototype.getHistory = function() {
};
/** @override */
+importer.DummyImportHistory.prototype.wasCopied =
+ function(entry, destination) {
+ return Promise.resolve(this.answer_);
+};
+
+/** @override */
importer.DummyImportHistory.prototype.wasImported =
function(entry, destination) {
return Promise.resolve(this.answer_);
};
/** @override */
+importer.DummyImportHistory.prototype.markCopied =
+ function(entry, destination, url) {
+ return Promise.resolve();
+};
+
+/** @override */
importer.DummyImportHistory.prototype.markImported =
function(entry, destination) {
return Promise.resolve();
@@ -96,6 +124,14 @@ importer.DummyImportHistory.prototype.addObserver = function(observer) {};
importer.DummyImportHistory.prototype.removeObserver = function(observer) {};
/**
+ * @private @enum {number}
+ */
+importer.RecordType_ = {
+ COPY: 0,
+ IMPORT: 1
+};
+
+/**
* An {@code ImportHistory} implementation that reads from and
* writes to a storage object.
*
@@ -111,12 +147,20 @@ importer.PersistentImportHistory = function(storage) {
this.storage_ = storage;
/**
+ * An in-memory representation of local copy history.
+ * The first value is the "key" (as generated internally
+ * from a file entry).
+ * @private {!Object.<string, !Object.<!importer.Destination, string>>}
+ */
+ this.copiedEntries_ = {};
+
+ /**
* An in-memory representation of import history.
* The first value is the "key" (as generated internally
* from a file entry).
* @private {!Object.<string, !Array.<importer.Destination>>}
*/
- this.entries_ = {};
+ this.importedEntries_ = {};
/** @private {!Array.<!importer.ImportHistory.Observer>} */
this.observers_ = [];
@@ -135,11 +179,15 @@ importer.PersistentImportHistory = function(storage) {
* @private
*/
importer.PersistentImportHistory.prototype.refresh_ = function() {
- var oldEntries = this.entries_;
- this.entries_ = {};
+ var oldCopiedEntries = this.copiedEntries_;
+ var oldImportedEntries = this.importedEntries_;
+
+ this.copiedEntries_ = {};
+ this.importedEntries_ = {};
return this.storage_.readAll()
.then(this.updateHistoryRecords_.bind(this))
- .then(this.mergeEntries_.bind(this, oldEntries))
+ .then(this.mergeCopiedEntries_.bind(this, oldCopiedEntries))
+ .then(this.mergeImportedEntries_.bind(this, oldImportedEntries))
.then(
/**
* @return {!importer.PersistentImportHistory}
@@ -151,32 +199,58 @@ importer.PersistentImportHistory.prototype.refresh_ = function() {
};
/**
- * Adds all entries not already present in history.
+ * Adds all copied entries into existing entries.
+ *
+ * @param {!Object.<string, !Object.<!importer.Destination, string>>} entries
+ * @return {!Promise.<?>} Resolves once all updates are completed.
+ * @private
+ */
+importer.PersistentImportHistory.prototype.mergeCopiedEntries_ =
+ function(entries) {
+ var promises = [];
+ for (var key in entries) {
+ for (var destination in entries[key]) {
+ // This method is only called when data is reloaded from disk.
+ // In such a situation we defend against loss of in-memory data
+ // by copying it out of the way, reloading data from disk, then
+ // merging that data back into the freshly loaded data. For that
+ // reason we will write newly created entries back to disk.
+
+ var path = entries[key][destination];
+ if (this.updateInMemoryRecord_(
+ importer.RecordType_.COPY, key, destination, path)) {
+ promises.push(this.storage_.write(
+ [importer.RecordType_.COPY, key, destination, path]));
+ }
+ }
+ }
+ return Promise.all(promises);
+};
+
+/**
+ * Adds all imported entries into existing entries.
*
* @param {!Object.<string, !Array.<string>>} entries
* @return {!Promise.<?>} Resolves once all updates are completed.
* @private
*/
-importer.PersistentImportHistory.prototype.mergeEntries_ = function(entries) {
+importer.PersistentImportHistory.prototype.mergeImportedEntries_ =
+ function(entries) {
var promises = [];
- Object.keys(entries).forEach(
- /**
- * @param {string} key
- * @this {importer.PersistentImportHistory}
- */
- function(key) {
- entries[key].forEach(
- /**
- * @param {string} key
- * @this {importer.PersistentImportHistory}
- */
- function(destination) {
- if (this.getDestinations_(key).indexOf(destination) >= 0) {
- this.updateHistoryRecord_(key, destination);
- promises.push(this.storage_.write([key, destination]));
- }
+ for (var key in entries) {
+ entries[key].forEach(
+ /**
+ * @param {string} key
+ * @this {importer.PersistentImportHistory}
+ */
+ function(destination) {
+ if (this.updateInMemoryRecord_(
+ importer.RecordType_.IMPORT, key, destination)) {
+ promises.push(this.storage_.write(
+ [importer.RecordType_.IMPORT, key, destination]));
+ }
}.bind(this));
- }.bind(this));
+ }
return Promise.all(promises);
};
@@ -212,26 +286,66 @@ importer.PersistentImportHistory.prototype.updateHistoryRecords_ =
* @this {importer.PersistentImportHistory}
*/
function(record) {
- this.updateHistoryRecord_(record[0], record[1]);
+ this.updateInMemoryRecord_(record[0], record[1], record[2], record[3]);
}.bind(this));
};
/**
* Adds a history entry to the in-memory history model.
+ * @param {!importer.RecordType_} type
* @param {string} key
- * @param {string} destination
+ * @param {!importer.Destination} destination
+ * @param {*=} opt_payload
+ * @return {boolean} True if a record was created.
* @private
*/
-importer.PersistentImportHistory.prototype.updateHistoryRecord_ =
- function(key, destination) {
- if (key in this.entries_) {
- this.entries_[key].push(destination);
- } else {
- this.entries_[key] = [destination];
+importer.PersistentImportHistory.prototype.updateInMemoryRecord_ =
+ function(type, key, destination, opt_payload) {
+
+ switch (type) {
+ case importer.RecordType_.COPY:
+ if (!this.copiedEntries_.hasOwnProperty(key)) {
+ this.copiedEntries_[key] = {};
+ }
+ if (!this.copiedEntries_[key].hasOwnProperty(destination)) {
+ this.copiedEntries_[key][destination] = /** @type {string} */ (
+ opt_payload);
+ return true;
+ }
+ break;
+ case importer.RecordType_.IMPORT:
+ if (!this.importedEntries_.hasOwnProperty(key)) {
+ this.importedEntries_[key] = [destination];
+ }
+ if (this.importedEntries_[key].indexOf(destination) === -1) {
+ this.importedEntries_[key].push(destination);
+ return true;
+ }
+ break;
+ default:
+ console.log('Ignoring record with unrecognized type: ' + type);
+ return false;
}
};
/** @override */
+importer.PersistentImportHistory.prototype.wasCopied =
+ function(entry, destination) {
+ return this.whenReady_
+ .then(this.createKey_.bind(this, entry))
+ .then(
+ /**
+ * @param {string} key
+ * @return {boolean}
+ * @this {importer.PersistentImportHistory}
+ */
+ function(key) {
+ return key in this.copiedEntries_ &&
+ destination in this.copiedEntries_[key];
+ }.bind(this));
+};
+
+/** @override */
importer.PersistentImportHistory.prototype.wasImported =
function(entry, destination) {
return this.whenReady_
@@ -239,7 +353,7 @@ importer.PersistentImportHistory.prototype.wasImported =
.then(
/**
* @param {string} key
- * @return {!Promise.<boolean>}
+ * @return {boolean}
* @this {importer.PersistentImportHistory}
*/
function(key) {
@@ -248,6 +362,30 @@ importer.PersistentImportHistory.prototype.wasImported =
};
/** @override */
+importer.PersistentImportHistory.prototype.markCopied =
+ function(entry, destination, url) {
+ return this.whenReady_
+ .then(this.createKey_.bind(this, entry))
+ .then(
+ /**
+ * @param {string} key
+ * @return {!Promise.<?>}
+ * @this {importer.ImportHistory}
+ */
+ function(key) {
+ return this.storeRecord_(
+ importer.RecordType_.COPY,
+ key,
+ destination,
+ url);
+ }.bind(this))
+ .then(this.notifyObservers_.bind(
+ this,
+ entry,
+ importer.ImportHistory.State.COPIED));
+};
+
+/** @override */
importer.PersistentImportHistory.prototype.markImported =
function(entry, destination) {
return this.whenReady_
@@ -259,9 +397,15 @@ importer.PersistentImportHistory.prototype.markImported =
* @this {importer.ImportHistory}
*/
function(key) {
- return this.addDestination_(destination, key);
+ return this.storeRecord_(
+ importer.RecordType_.IMPORT,
+ key,
+ destination);
}.bind(this))
- .then(this.notifyObservers_.bind(this, entry));
+ .then(this.notifyObservers_.bind(
+ this,
+ entry,
+ importer.ImportHistory.State.IMPORTED));
};
/** @override */
@@ -283,29 +427,34 @@ importer.PersistentImportHistory.prototype.removeObserver =
/**
* @param {!FileEntry} subject
+ * @param {!importer.ImportHistory.State} newState
* @private
*/
importer.PersistentImportHistory.prototype.notifyObservers_ =
- function(subject) {
+ function(subject, newState) {
this.observers_.forEach(
function(observer) {
observer({
- state: importer.ImportHistory.State.IMPORTED,
+ state: newState,
entry: subject
});
}.bind(this));
};
/**
- * @param {string} destination
+ * @param {!importer.RecordType_} type
* @param {string} key
+ * @param {!importer.Destination} destination
+ * @param {*=} opt_payload
* @return {!Promise.<?>} Resolves once the write has been completed.
* @private
*/
-importer.PersistentImportHistory.prototype.addDestination_ =
- function(destination, key) {
- this.updateHistoryRecord_(key, destination);
- return this.storage_.write([key, destination]);
+importer.PersistentImportHistory.prototype.storeRecord_ =
+ function(type, key, destination, opt_payload) {
+ this.updateInMemoryRecord_(type, key, destination, opt_payload);
+ return !!opt_payload ?
+ this.storage_.write([type, key, destination, opt_payload]) :
+ this.storage_.write([type, key, destination]);
};
/**
@@ -315,7 +464,7 @@ importer.PersistentImportHistory.prototype.addDestination_ =
* @private
*/
importer.PersistentImportHistory.prototype.getDestinations_ = function(key) {
- return key in this.entries_ ? this.entries_[key] : [];
+ return key in this.importedEntries_ ? this.importedEntries_[key] : [];
};
/**
@@ -476,7 +625,7 @@ importer.ChromeSyncFileEntryProvider = function() {
};
/** @private @const {string} */
-importer.ChromeSyncFileEntryProvider.FILE_NAME_ = 'import-history.data';
+importer.ChromeSyncFileEntryProvider.FILE_NAME_ = 'import-history.log';
/**
* Wraps chrome.syncFileSystem.onFileStatusChanged
@@ -678,6 +827,9 @@ importer.FileEntryRecordStorage.prototype.write = function(record) {
*/
importer.FileEntryRecordStorage.prototype.writeRecord_ =
function(record, writer) {
+ var blob = new Blob(
+ [JSON.stringify(record) + ',\n'],
+ {type: 'text/plain; charset=UTF-8'});
return new Promise(
/**
* @param {function()} resolve
@@ -685,10 +837,6 @@ importer.FileEntryRecordStorage.prototype.writeRecord_ =
* @this {importer.FileEntryRecordStorage}
*/
function(resolve, reject) {
- var blob = new Blob(
- [JSON.stringify(record) + ',\n'],
- {type: 'text/plain; charset=UTF-8'});
-
writer.onwriteend = resolve;
writer.onerror = reject;
@@ -759,31 +907,23 @@ importer.FileEntryRecordStorage.prototype.readFileAsText_ = function(file) {
* Parses the text.
*
* @param {string} text
- * @return {!Promise.<!Array.<!Array.<*>>>}
+ * @return {!Array.<!Array.<*>>}
* @private
*/
importer.FileEntryRecordStorage.prototype.parse_ = function(text) {
- return new Promise(
- /**
- * @param {function()} resolve
- * @param {function()} reject
- * @this {importer.FileEntryRecordStorage}
- */
- function(resolve, reject) {
- if (text.length === 0) {
- resolve([]);
- } else {
- // Dress up the contents of the file like an array,
- // so the JSON object can parse it using JSON.parse.
- // That means we need to both:
- // 1) Strip the trailing ',\n' from the last record
- // 2) Surround the whole string in brackets.
- // NOTE: JSON.parse is WAY faster than parsing this
- // ourselves in javascript.
- var json = '[' + text.substring(0, text.length - 2) + ']';
- resolve(JSON.parse(json));
- }
- }.bind(this));
+ if (text.length === 0) {
+ return [];
+ } else {
+ // Dress up the contents of the file like an array,
+ // so the JSON object can parse it using JSON.parse.
+ // That means we need to both:
+ // 1) Strip the trailing ',\n' from the last record
+ // 2) Surround the whole string in brackets.
+ // NOTE: JSON.parse is WAY faster than parsing this
+ // ourselves in javascript.
+ var json = '[' + text.substring(0, text.length - 2) + ']';
+ return /** @type {!Array.<!Array.<*>>} */ (JSON.parse(json));
+ }
};
/**
« no previous file with comments | « no previous file | ui/file_manager/file_manager/background/js/import_history_unittest.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698