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

Unified Diff: ui/file_manager/file_manager/foreground/js/file_tasks.js

Issue 1378053004: Simplify FileTasks in Files app. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 5 years, 3 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
Index: ui/file_manager/file_manager/foreground/js/file_tasks.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index 9d5a9990f3cd6e501aa3fc45caff17aa4d5108c1..644dd93309cbab93bef75e2227e01276bc6921b9 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -3,62 +3,70 @@
// found in the LICENSE file.
/**
- * This object encapsulates everything related to tasks execution.
+ * Represents a collection of available tasks to execute for a specific list
+ * of entries.
*
* @param {!VolumeManagerWrapper} volumeManager
* @param {!MetadataModel} metadataModel
* @param {!DirectoryModel} directoryModel
* @param {!FileManagerUI} ui
+ * @param {!Array<!Entry>} entries
+ * @param {!Array<?string>} mimeTypes
+ * @param {!Array<!Object>} tasks
+ * @param {Object} defaultTask
* @constructor
+ * @struct
*/
-function FileTasks(volumeManager, metadataModel, directoryModel, ui) {
+function FileTasks(volumeManager, metadataModel, directoryModel, ui, entries,
+ mimeTypes, tasks, defaultTask) {
/**
* @private {!VolumeManagerWrapper}
+ * @const
*/
this.volumeManager_ = volumeManager;
/**
* @private {!MetadataModel}
+ * @const
*/
this.metadataModel_ = metadataModel;
/**
* @private {!DirectoryModel}
+ * @const
*/
this.directoryModel_ = directoryModel;
/**
* @private {!FileManagerUI}
+ * @const
*/
this.ui_ = ui;
/**
- * @private {Array<!Object>}
+ * @private {!Array<!Entry>}
+ * @const
*/
- this.tasks_ = null;
-
- /**
- * @private {Object}
- */
- this.defaultTask_ = null;
+ this.entries_ = entries;
/**
- * @public {Array<!Entry>}
+ * @private {!Array<?string>}
+ * @const
*/
- this.entries = null;
+ this.mimeTypes_ = mimeTypes;
/**
- * @public {Array<string>}
+ * @private {!Array<!Object>}
+ * @const
*/
- this.mimeTypes = null;
+ this.tasks_ = tasks;
/**
- * List of invocations to be called once tasks are available.
- *
- * @private {Array<Object>}
+ * @private {Object}
+ * @const
*/
- this.pendingInvocations_ = [];
-}
+ this.defaultTask_ = defaultTask;
+};
/**
* Location of the Chrome Web Store.
@@ -103,6 +111,59 @@ FileTasks.TaskMenuButtonItemType = {
};
/**
+ * Creates an instance of FileTasks for the specified list of entries with mime
+ * types.
+ *
+ * @param {!VolumeManagerWrapper} volumeManager
+ * @param {!MetadataModel} metadataModel
+ * @param {!DirectoryModel} directoryModel
+ * @param {!FileManagerUI} ui
+ * @param {!Array<!Entry>} entries
+ * @param {!Array<?string>} mimeTypes
+ * @return {!Promise<!FileTasks>}
+ */
+FileTasks.create = function(volumeManager, metadataModel, directoryModel, ui,
+ entries, mimeTypes) {
+ var tasksPromise = new Promise(function(fulfill) {
+ if (entries.length === 0) {
+ fulfill([]);
+ return;
+ }
+ chrome.fileManagerPrivate.getFileTasks(entries, function(taskItems) {
+ if (chrome.runtime.lastError) {
+ console.error('Failed to fetch file tasks due to: ' +
+ chrome.runtime.lastError.message);
+ Promise.reject();
+ return;
+ }
+ fulfill(FileTasks.annotateTasks_(assert(taskItems), entries));
+ });
+ });
+
+ var defaultTaskPromise = tasksPromise.then(function(tasks) {
+ for (var i = 0; i < tasks.length; i++) {
+ if (tasks[i].isDefault) {
+ return tasks[i];
+ }
+ }
+ // If we haven't picked a default task yet, then just pick the first one
+ // which is not generic file handler.
+ for (var i = 0; i < tasks.length; i++) {
+ if (!tasks[i].isGenericFileHandler) {
+ return tasks[i];
+ }
+ }
+ return null;
+ });
+
+ return Promise.all([tasksPromise, defaultTaskPromise]).then(
+ function(args) {
+ return new FileTasks(volumeManager, metadataModel, directoryModel, ui,
+ entries, mimeTypes, args[0], args[1]);
+ });
+};
+
+/**
* Returns URL of the Chrome Web Store which show apps supporting the given
* file-extension and mime-type.
*
@@ -129,21 +190,29 @@ FileTasks.createWebStoreLink = function(extension, mimeType) {
};
/**
+ * Obtains the task items.
+ * @return {Array<!Object>}
+ */
+FileTasks.prototype.getTaskItems = function() {
+ return this.tasks_;
+};
+
+/**
* Opens the suggest file dialog.
*
- * @param {Entry} entry Entry of the file.
- * @param {?string} mimeType Mime type of the file.
* @param {function()} onSuccess Success callback.
* @param {function()} onCancelled User-cancelled callback.
* @param {function()} onFailure Failure callback.
*/
-FileTasks.prototype.openSuggestAppsDialog =
- function(entry, mimeType, onSuccess, onCancelled, onFailure) {
- if (!entry) {
+FileTasks.prototype.openSuggestAppsDialog = function(
+ onSuccess, onCancelled, onFailure) {
+ if (this.entries_.length !== 1) {
onFailure();
return;
}
+ var entry = this.entries_[0];
+ var mimeType = this.mimeTypes_[0];
var basename = entry.name;
var splitted = util.splitExtension(basename);
var extension = splitted[1];
@@ -172,62 +241,6 @@ FileTasks.prototype.openSuggestAppsDialog =
};
/**
- * Complete the initialization.
- *
- * @param {!Array<!Entry>} entries List of file entries.
- * @param {!Array<?string>} mimeTypes Mime-type specified for each entries.
- * @return {!Promise} Promise to be fulfilled when the initialization completes.
- */
-FileTasks.prototype.init = function(entries, mimeTypes) {
- this.entries_ = entries;
- this.mimeTypes_ = mimeTypes;
-
- if (entries.length > 0) {
- return new Promise(function(fulfill) {
- chrome.fileManagerPrivate.getFileTasks(entries, function(taskItems) {
- this.onTasks_(taskItems);
- fulfill();
- }.bind(this));
- }.bind(this));
- } else {
- return Promise.resolve();
- }
-};
-
-/**
- * Obtains the task items.
- * @return {Array<!Object>}
- */
-FileTasks.prototype.getTaskItems = function() {
- return this.tasks_;
-};
-
-/**
- * Returns amount of tasks.
- *
- * @return {number} amount of tasks.
- */
-FileTasks.prototype.size = function() {
- return (this.tasks_ && this.tasks_.length) || 0;
-};
-
-/**
- * Callback when tasks found.
- *
- * @param {Array<Object>} tasks The tasks.
- * @private
- */
-FileTasks.prototype.onTasks_ = function(tasks) {
- this.processTasks_(tasks);
- for (var index = 0; index < this.pendingInvocations_.length; index++) {
- var name = this.pendingInvocations_[index][0];
- var args = this.pendingInvocations_[index][1];
- this[name].apply(this, args);
- }
- this.pendingInvocations_ = [];
-};
-
-/**
* The list of known extensions to record UMA.
* Note: Because the data is recorded by the index, so new item shouldn't be
* inserted.
@@ -302,13 +315,15 @@ FileTasks.isInternalTask_ = function(taskId) {
};
/**
- * Processes internal tasks.
+ * Annotates tasks returned from the API.
*
- * @param {Array<Object>} tasks The tasks.
+ * @param {!Array<!Object>} tasks Input tasks from the API.
+ * @param {!Array<!Entry>} entries List of entries for the tasks.
+ * @return {!Array<!Object>} Annotated tasks.
* @private
*/
-FileTasks.prototype.processTasks_ = function(tasks) {
- this.tasks_ = [];
+FileTasks.annotateTasks_ = function(tasks, entries) {
+ var result = [];
var id = chrome.runtime.id;
for (var i = 0; i < tasks.length; i++) {
var task = tasks[i];
@@ -331,10 +346,10 @@ FileTasks.prototype.processTasks_ = function(tasks) {
task.iconType = 'archive';
task.title = loadTimeData.getString('MOUNT_ARCHIVE');
} else if (taskParts[2] === 'open-hosted-generic') {
- if (this.entries_.length > 1)
+ if (entries.length > 1)
task.iconType = 'generic';
else // Use specific icon.
- task.iconType = FileType.getIcon(this.entries_[0]);
+ task.iconType = FileType.getIcon(entries[0]);
task.title = loadTimeData.getString('TASK_OPEN');
} else if (taskParts[2] === 'open-hosted-gdoc') {
task.iconType = 'gdoc';
@@ -362,27 +377,13 @@ FileTasks.prototype.processTasks_ = function(tasks) {
task.title = loadTimeData.getString('TASK_VIEW');
}
}
-
if (!task.iconType && taskParts[1] === 'web-intent') {
task.iconType = 'generic';
}
-
- this.tasks_.push(task);
- if (this.defaultTask_ === null && task.isDefault) {
- this.defaultTask_ = task;
- }
- }
- if (!this.defaultTask_ && this.tasks_.length > 0) {
- // If we haven't picked a default task yet, then just pick the first one
- // which is not generic file handler.
- for (var i = 0; i < this.tasks_.length; i++) {
- var task = this.tasks_[i];
- if (!task.isGenericFileHandler) {
- this.defaultTask_ = task;
- break;
- }
- }
+ result.push(task);
}
+
+ return result;
};
/**
@@ -392,8 +393,7 @@ FileTasks.prototype.processTasks_ = function(tasks) {
* default task is executed, or the error is occurred.
* @private
*/
-FileTasks.prototype.executeDefault_ = function(opt_callback) {
- assert(this.entries_); // Set by init().
+FileTasks.prototype.executeDefault = function(opt_callback) {
FileTasks.recordViewingFileTypeUMA_(this.entries_);
this.executeDefaultInternal_(opt_callback);
};
@@ -407,20 +407,19 @@ FileTasks.prototype.executeDefault_ = function(opt_callback) {
*/
FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) {
var callback = opt_callback || function(arg1, arg2) {};
- var entries = assert(this.entries_);
if (this.defaultTask_ !== null) {
this.executeInternal_(this.defaultTask_.taskId);
- callback(true, entries);
+ callback(true, this.entries_);
return;
}
// We don't have tasks, so try to show a file in a browser tab.
// We only do that for single selection to avoid confusion.
- if (entries.length !== 1)
+ if (this.entries_.length !== 1)
return;
- var filename = entries[0].name;
+ var filename = this.entries_[0].name;
var extension = util.splitExtension(filename)[1] || null;
var mimeType = this.mimeTypes_[0] || null;
@@ -447,30 +446,32 @@ FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) {
var text = strf(textMessageId, webStoreUrl, str('NO_TASK_FOR_FILE_URL'));
var title = titleMessageId ? str(titleMessageId) : filename;
this.ui_.alertDialog.showHtml(title, text, null, null, null);
- callback(false, entries);
+ callback(false, this.entries_);
}.bind(this);
var onViewFilesFailure = function() {
- if (FileTasks.EXTENSIONS_TO_SKIP_SUGGEST_APPS_.indexOf(extension) !== -1 ||
- FileTasks.EXECUTABLE_EXTENSIONS.indexOf(extension) !== -1) {
+ if (FileTasks.EXTENSIONS_TO_SKIP_SUGGEST_APPS_.indexOf(extension) !== -1
+ || FileTasks.EXECUTABLE_EXTENSIONS.indexOf(extension) !== -1) {
showAlert();
return;
}
this.openSuggestAppsDialog(
- entries[0],
- mimeType,
function() {
- var newTasks = new FileTasks(
- this.volumeManager_, this.metadataModel_, this.directoryModel_,
- this.ui_);
- newTasks.init(assert(entries), assert(this.mimeTypes_));
- newTasks.executeDefault();
- callback(true, entries);
+ FileTasks.create(this.volumeManager_, this.metadataModel_,
+ this.directoryModel_, this.ui_, this.entries_, this.mimeTypes_)
+ .then(
+ function(tasks) {
+ tasks.executeDefault();
+ callback(true, this.entries_);
+ }.bind(this),
+ function() {
+ callback(false, this.entries_);
+ }.bind(this));
}.bind(this),
// Cancelled callback.
function() {
- callback(false, entries);
+ callback(false, this.entries_);
}.bind(this),
showAlert);
}.bind(this);
@@ -478,18 +479,19 @@ FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) {
var onViewFiles = function(result) {
switch (result) {
case 'opened':
- callback(true, entries);
+ callback(true, this.entries_);
break;
case 'message_sent':
util.isTeleported(window).then(function(teleported) {
if (teleported) {
- util.showOpenInOtherDesktopAlert(this.ui_.alertDialog, entries);
+ util.showOpenInOtherDesktopAlert(
+ this.ui_.alertDialog, this.entries_);
}
}.bind(this));
- callback(true, entries);
+ callback(true, this.entries_);
break;
case 'empty':
- callback(true, entries);
+ callback(true, this.entries_);
break;
case 'failed':
onViewFilesFailure();
@@ -499,7 +501,7 @@ FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) {
this.checkAvailability_(function() {
var taskId = chrome.runtime.id + '|file|view-in-browser';
- chrome.fileManagerPrivate.executeTask(taskId, entries, onViewFiles);
+ chrome.fileManagerPrivate.executeTask(taskId, this.entries_, onViewFiles);
}.bind(this));
};
@@ -509,8 +511,7 @@ FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) {
* @param {string} taskId Task identifier.
* @private
*/
-FileTasks.prototype.execute_ = function(taskId) {
- var entries = assert(this.entries_); // Entries set by init().
+FileTasks.prototype.execute = function(taskId) {
FileTasks.recordViewingFileTypeUMA_(this.entries_);
this.executeInternal_(taskId);
};
@@ -522,20 +523,19 @@ FileTasks.prototype.execute_ = function(taskId) {
* @private
*/
FileTasks.prototype.executeInternal_ = function(taskId) {
- var entries = assert(this.entries_);
this.checkAvailability_(function() {
if (FileTasks.isInternalTask_(taskId)) {
this.executeInternalTask_(taskId);
} else {
chrome.fileManagerPrivate.executeTask(taskId,
- assert(entries),
+ this.entries_,
function(result) {
if (result !== 'message_sent')
return;
util.isTeleported(window).then(function(teleported) {
if (teleported) {
util.showOpenInOtherDesktopAlert(
- this.ui_.alertDialog, entries);
+ this.ui_.alertDialog, this.entries_);
}
}.bind(this));
}.bind(this));
@@ -559,13 +559,11 @@ FileTasks.prototype.checkAvailability_ = function(callback) {
return props.filter(isOne).length === props.length;
};
- var entries = assert(this.entries_);
-
var isDriveOffline = this.volumeManager_.getDriveConnectionState().type ===
VolumeManagerCommon.DriveConnectionType.OFFLINE;
if (isDriveOffline) {
- this.metadataModel_.get(entries, ['availableOffline', 'hosted']).then(
+ this.metadataModel_.get(this.entries_, ['availableOffline', 'hosted']).then(
function(props) {
if (areAll(props, 'availableOffline')) {
callback();
@@ -576,11 +574,11 @@ FileTasks.prototype.checkAvailability_ = function(callback) {
loadTimeData.getString('OFFLINE_HEADER'),
props[0].hosted ?
loadTimeData.getStringF(
- entries.length === 1 ?
+ this.entries_.length === 1 ?
'HOSTED_OFFLINE_MESSAGE' :
'HOSTED_OFFLINE_MESSAGE_PLURAL') :
loadTimeData.getStringF(
- entries.length === 1 ?
+ this.entries_.length === 1 ?
'OFFLINE_MESSAGE' :
'OFFLINE_MESSAGE_PLURAL',
loadTimeData.getString('OFFLINE_COLUMN_LABEL')),
@@ -593,21 +591,21 @@ FileTasks.prototype.checkAvailability_ = function(callback) {
VolumeManagerCommon.DriveConnectionType.METERED;
if (isOnMetered) {
- this.metadataModel_.get(entries, ['availableWhenMetered', 'size']).then(
- function(props) {
+ this.metadataModel_.get(this.entries_, ['availableWhenMetered', 'size'])
+ .then(function(props) {
if (areAll(props, 'availableWhenMetered')) {
callback();
return;
}
var sizeToDownload = 0;
- for (var i = 0; i !== entries.length; i++) {
+ for (var i = 0; i !== this.entries_.length; i++) {
if (!props[i].availableWhenMetered)
sizeToDownload += props[i].size;
}
this.ui_.confirmDialog.show(
loadTimeData.getStringF(
- entries.length === 1 ?
+ this.entries_.length === 1 ?
'CONFIRM_MOBILE_DATA_USE' :
'CONFIRM_MOBILE_DATA_USE_PLURAL',
util.bytesToString(sizeToDownload)),
@@ -681,9 +679,9 @@ FileTasks.prototype.mountArchivesInternal_ = function() {
* Displays the list of tasks in a task picker combobutton.
*
* @param {cr.ui.ComboButton} combobutton The task picker element.
- * @private
+ * @public
*/
-FileTasks.prototype.display_ = function(combobutton) {
+FileTasks.prototype.display = function(combobutton) {
// If there does not exist available task, hide combobutton.
if (this.tasks_.length === 0) {
combobutton.hidden = true;
@@ -705,17 +703,16 @@ FileTasks.prototype.display_ = function(combobutton) {
}
// If there exist 2 or more available tasks, show them in context menu
- // (including defaultTask). If only one generic task is available, we also
- // show it in the context menu.
+ // (including defaultTask). If only one generic task is available, we
+ // also show it in the context menu.
var items = this.createItems_();
-
if (items.length > 1 || (items.length === 1 && this.defaultTask_ === null)) {
for (var j = 0; j < items.length; j++) {
combobutton.addDropDownItem(items[j]);
}
- // If there exist non generic task (i.e. defaultTask is set), we show an
- // item to change default task.
+ // If there exist non generic task (i.e. defaultTask is set), we show
+ // an item to change default task.
if (this.defaultTask_) {
combobutton.addSeparator();
var changeDefaultMenuItem = combobutton.addDropDownItem({
@@ -730,7 +727,8 @@ FileTasks.prototype.display_ = function(combobutton) {
/**
* Creates sorted array of available task descriptions such as title and icon.
*
- * @return {Array} created array can be used to feed combobox, menus and so on.
+ * @return {!Array<!Object>} Created array can be used to feed combobox, menus
+ * and so on.
* @private
*/
FileTasks.prototype.createItems_ = function() {
@@ -807,11 +805,10 @@ FileTasks.prototype.createCombobuttonItem_ = function(task, opt_title,
FileTasks.prototype.showTaskPicker = function(taskDialog, title, message,
onSuccess,
opt_hideGenericFileHandler) {
- var hideGenericFileHandler = opt_hideGenericFileHandler || false;
- var items = this.createItems_();
-
- if (hideGenericFileHandler)
- items = items.filter(function(item) { return !item.isGenericFileHandler; });
+ var items = !!opt_hideGenericFileHandler ? this.createItems_() :
+ this.createItems_().filter(function(item) {
+ return !item.isGenericFileHandler;
+ });
var defaultIdx = 0;
for (var j = 0; j < items.length; j++) {
@@ -827,38 +824,3 @@ FileTasks.prototype.showTaskPicker = function(taskDialog, title, message,
onSuccess(item.task);
});
};
-
-/**
- * @param {cr.ui.ComboButton} combobutton The task picker element.
- */
-FileTasks.prototype.display = function(combobutton) {
- if (this.tasks_)
- this.display_(combobutton);
- else
- this.pendingInvocations_.push(['display_', [combobutton]]);
-};
-
-/**
- * Executes a single task.
- *
- * @param {string} taskId Task identifier.
- */
-FileTasks.prototype.execute = function(taskId) {
- if (this.tasks_)
- this.execute_(taskId);
- else
- this.pendingInvocations_.push(['execute_', [taskId]]);
-};
-
-/**
- * Executes default task.
- *
- * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the
- * default task is executed, or the error is occurred.
- */
-FileTasks.prototype.executeDefault = function(opt_callback) {
- if (this.tasks_)
- this.executeDefault_(opt_callback);
- else
- this.pendingInvocations_.push(['executeDefault_', [opt_callback]]);
-};

Powered by Google App Engine
This is Rietveld 408576698