Commit 5e042e9c authored by flackr@chromium.org's avatar flackr@chromium.org

Revert 133679 - Failing SelectFileDialogExtensionBrowserTest.SelectFileAndSave...

Revert 133679 - Failing SelectFileDialogExtensionBrowserTest.SelectFileAndSave on chromiumos browser_tests.

This revert made things worse, investigating.

Revert 133663 - 1. Fix JSDocs in directory_model.js.
2. Replace all getters and setters in directory_model.js with get*() and set*() methods.
Review URL: https://chromiumcodereview.appspot.com/10206015

TBR=oleg@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10201018

TBR=flackr@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10207014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133684 0039d316-1c4b-4281-b951-d872f2087c98
parent 34033b29
...@@ -50,7 +50,7 @@ function DirectoryModel(root, singleSelection, showGData, metadataCache) { ...@@ -50,7 +50,7 @@ function DirectoryModel(root, singleSelection, showGData, metadataCache) {
// The map 'name' -> callback. Callbacks are function(entry) -> boolean. // The map 'name' -> callback. Callbacks are function(entry) -> boolean.
this.filters_ = {}; this.filters_ = {};
this.filterHidden = true; this.setFilterHidden(true);
// Readonly status. // Readonly status.
this.readonly_ = false; this.readonly_ = false;
...@@ -91,136 +91,169 @@ DirectoryModel.DOWNLOADS_DIRECTORY = 'Downloads'; ...@@ -91,136 +91,169 @@ DirectoryModel.DOWNLOADS_DIRECTORY = 'Downloads';
*/ */
DirectoryModel.GDATA_DIRECTORY = 'gdata'; DirectoryModel.GDATA_DIRECTORY = 'gdata';
DirectoryModel.prototype = { /**
__proto__: cr.EventTarget.prototype, * DirectoryModel extends cr.EventTarget.
*/
DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype;
/** /**
* Files in the current directory. * @return {cr.ui.ArrayDataModel} Files in the current directory.
* @type {cr.ui.ArrayDataModel} */
*/ DirectoryModel.prototype.getFileList = function() {
get fileList() { return this.fileList_;
return this.fileList_; };
},
/** /**
* Selection in the fileList. * Sort the file list.
* @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} * @param {string} sortField Sort field.
*/ * @param {string} sortDirection "asc" or "desc".
get fileListSelection() { */
return this.fileListSelection_; DirectoryModel.prototype.sortFileList = function(sortField, sortDirection) {
}, this.fileList_.sort(sortField, sortDirection);
};
get rootType() { /**
return DirectoryModel.getRootType(this.currentEntry.fullPath); * @return {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} Selection
}, * in the fileList.
*/
DirectoryModel.prototype.getFileListSelection = function() {
return this.fileListSelection_;
};
get rootName() { /**
return DirectoryModel.getRootName(this.currentEntry.fullPath); * @return {DirectoryModel.RootType} Root type of current root.
}, */
DirectoryModel.prototype.getRootType = function() {
return DirectoryModel.getRootType(this.currentDirEntry_.fullPath);
};
/** /**
* True if current directory is read only. * @return {string} Root name.
* @type {boolean} */
*/ DirectoryModel.prototype.getRootName = function() {
get readonly() { return DirectoryModel.getRootName(this.currentDirEntry_.fullPath);
return this.readonly_; };
},
get offline() {
return this.offline_;
},
set offline(value) {
if (this.offline_ != value) {
this.offline_ = !!value;
this.updateReadonlyStatus_();
}
},
get isSystemDirectoy() {
var path = this.currentEntry.fullPath;
return path == '/' ||
path == '/' + DirectoryModel.REMOVABLE_DIRECTORY ||
path == '/' + DirectoryModel.ARCHIVE_DIRECTORY;
},
get filterHidden() {
return !!this.filters_['hidden'];
},
set filterHidden(value) {
if (value) {
this.addFilter('hidden',
function(e) {return e.name.substr(0, 1) != '.';});
} else {
this.removeFilter('hidden');
}
},
/** /**
* Current directory. * @return {boolean} True if current directory is read only.
* @type {DirectoryEntry} */
*/ DirectoryModel.prototype.isReadOnly = function() {
get currentEntry() { return this.readonly_;
return this.currentDirEntry_; };
},
set autoSelectIndex(value) { /**
this.autoSelectIndex_ = value; * @return {boolean} If offline.
}, */
DirectoryModel.prototype.isOffline = function() {
return this.offline_;
};
/** /**
* Names of selected files. * @param {boolean} value New online status.
* @type {Array.<string>} */
*/ DirectoryModel.prototype.setOffline = function(value) {
get selectedNames() { if (this.offline_ != value) {
var indexes = this.fileListSelection_.selectedIndexes; this.offline_ = !!value;
var dataModel = this.fileList_; this.updateReadonlyStatus_();
if (dataModel) { }
return indexes.map(function(i) { };
return dataModel.item(i).name;
});
}
return [];
},
set selectedNames(value) {
var indexes = [];
var dataModel = this.fileList_;
function safeKey(key) {
// The transformation must:
// 1. Never generate a reserved name ('__proto__')
// 2. Keep different keys different.
return '#' + key;
}
var hash = {}; /**
* @return {boolean} If current directory is system.
*/
DirectoryModel.prototype.isSystemDirectory = function() {
var path = this.currentDirEntry_.fullPath;
return path == '/' ||
path == '/' + DirectoryModel.REMOVABLE_DIRECTORY ||
path == '/' + DirectoryModel.ARCHIVE_DIRECTORY;
};
for (var i = 0; i < value.length; i++) /**
hash[safeKey(value[i])] = 1; * @return {boolean} If the files with names starting with "." are not shown.
*/
DirectoryModel.prototype.isFilterHiddenOn = function() {
return !!this.filters_['hidden'];
};
for (var i = 0; i < dataModel.length; i++) { /**
if (hash.hasOwnProperty(safeKey(dataModel.item(i).name))) * @param {boolean} value Whether files with leading "." are hidden.
indexes.push(i); */
} DirectoryModel.prototype.setFilterHidden = function(value) {
this.fileListSelection_.selectedIndexes = indexes; if (value) {
}, this.addFilter('hidden',
function(e) {return e.name.substr(0, 1) != '.';});
} else {
this.removeFilter('hidden');
}
};
/** /**
* Lead item file name. * @return {DirectoryEntry} Current directory.
* @type {string?} */
*/ DirectoryModel.prototype.getCurrentDirEntry = function() {
get leadName() { return this.currentDirEntry_;
var index = this.fileListSelection_.leadIndex; };
return index >= 0 && this.fileList_.item(index).name;
}, /**
* @private
set leadName(value) { * @return {Array.<string>} Names of selected files.
for (var i = 0; i < this.fileList_.length; i++) { */
if (this.fileList_.item(i).name == value) { DirectoryModel.prototype.getSelectedNames_ = function() {
this.fileListSelection_.leadIndex = i; var indexes = this.fileListSelection_.selectedIndexes;
return; var dataModel = this.fileList_;
} if (dataModel) {
return indexes.map(function(i) {
return dataModel.item(i).name;
});
}
return [];
};
/**
* @private
* @param {Array.<string>} value List of names of selected files.
*/
DirectoryModel.prototype.setSelectedNames_ = function(value) {
var indexes = [];
var dataModel = this.fileList_;
function safeKey(key) {
// The transformation must:
// 1. Never generate a reserved name ('__proto__')
// 2. Keep different keys different.
return '#' + key;
}
var hash = {};
for (var i = 0; i < value.length; i++)
hash[safeKey(value[i])] = 1;
for (var i = 0; i < dataModel.length; i++) {
if (hash.hasOwnProperty(safeKey(dataModel.item(i).name)))
indexes.push(i);
}
this.fileListSelection_.selectedIndexes = indexes;
};
/**
* @private
* @return {string} Lead item file name.
*/
DirectoryModel.prototype.getLeadName_ = function() {
var index = this.fileListSelection_.leadIndex;
return index >= 0 && this.fileList_.item(index).name;
};
/**
* @private
* @param {string} value The name of new lead index.
*/
DirectoryModel.prototype.setLeadName_ = function(value) {
for (var i = 0; i < this.fileList_.length; i++) {
if (this.fileList_.item(i).name == value) {
this.fileListSelection_.leadIndex = i;
return;
} }
} }
}; };
...@@ -334,7 +367,7 @@ DirectoryModel.prototype.rescan = function() { ...@@ -334,7 +367,7 @@ DirectoryModel.prototype.rescan = function() {
/** /**
* @private * @private
* @param {Array.<Entry>|cr.ui.ArrayDataModel} list * @param {Array.<Entry>|cr.ui.ArrayDataModel} list File list.
* @param {function} successCallback Callback on success. * @param {function} successCallback Callback on success.
* @return {DirectoryModel.Scanner} New Scanner instance. * @return {DirectoryModel.Scanner} New Scanner instance.
*/ */
...@@ -369,24 +402,24 @@ DirectoryModel.prototype.createScanner_ = function(list, successCallback) { ...@@ -369,24 +402,24 @@ DirectoryModel.prototype.createScanner_ = function(list, successCallback) {
/** /**
* @private * @private
* @param {Array.<Entry>} entries * @param {Array.<Entry>} entries List of files.
*/ */
DirectoryModel.prototype.replaceFileList_ = function(entries) { DirectoryModel.prototype.replaceFileList_ = function(entries) {
cr.dispatchSimpleEvent(this, 'begin-update-files'); cr.dispatchSimpleEvent(this, 'begin-update-files');
this.fileListSelection_.beginChange(); this.fileListSelection_.beginChange();
var selectedNames = this.selectedNames; var selectedNames = this.getSelectedNames_();
// Restore leadIndex in case leadName no longer exists. // Restore leadIndex in case leadName no longer exists.
var leadIndex = this.fileListSelection_.leadIndex; var leadIndex = this.fileListSelection_.leadIndex;
var leadName = this.leadName; var leadName = this.getLeadName_();
var spliceArgs = [].slice.call(entries); var spliceArgs = [].slice.call(entries);
spliceArgs.unshift(0, this.fileList_.length); spliceArgs.unshift(0, this.fileList_.length);
this.fileList_.splice.apply(this.fileList_, spliceArgs); this.fileList_.splice.apply(this.fileList_, spliceArgs);
this.selectedNames = selectedNames; this.setSelectedNames_(selectedNames);
this.fileListSelection_.leadIndex = leadIndex; this.fileListSelection_.leadIndex = leadIndex;
this.leadName = leadName; this.setLeadName_(leadName);
this.fileListSelection_.endChange(); this.fileListSelection_.endChange();
cr.dispatchSimpleEvent(this, 'end-update-files'); cr.dispatchSimpleEvent(this, 'end-update-files');
}; };
...@@ -433,8 +466,8 @@ DirectoryModel.prototype.scan_ = function(callback) { ...@@ -433,8 +466,8 @@ DirectoryModel.prototype.scan_ = function(callback) {
/** /**
* @private * @private
* @param {Array.<Entry>} entries * @param {Array.<Entry>} entries Files.
* @param {function} callback * @param {function} callback Callback on done.
*/ */
DirectoryModel.prototype.prefetchCacheForSorting_ = function(entries, DirectoryModel.prototype.prefetchCacheForSorting_ = function(entries,
callback) { callback) {
...@@ -480,17 +513,17 @@ DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) { ...@@ -480,17 +513,17 @@ DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) {
}; };
/** /**
* @param {string} name * @param {string} name Filename.
*/ */
DirectoryModel.prototype.onEntryChanged = function(name) { DirectoryModel.prototype.onEntryChanged = function(name) {
var currentEntry = this.currentEntry; var currentEntry = this.currentDirEntry_;
var dm = this.fileList_; var dm = this.fileList_;
var self = this; var self = this;
function onEntryFound(entry) { function onEntryFound(entry) {
self.prefetchCacheForSorting_([entry], function() { self.prefetchCacheForSorting_([entry], function() {
// Do nothing if current directory changed during async operations. // Do nothing if current directory changed during async operations.
if (self.currentEntry != currentEntry) if (self.currentDirEntry_ != currentEntry)
return; return;
var index = self.findIndexByName_(name); var index = self.findIndexByName_(name);
...@@ -503,7 +536,7 @@ DirectoryModel.prototype.onEntryChanged = function(name) { ...@@ -503,7 +536,7 @@ DirectoryModel.prototype.onEntryChanged = function(name) {
function onError(err) { function onError(err) {
// Do nothing if current directory changed during async operations. // Do nothing if current directory changed during async operations.
if (self.currentEntry != currentEntry) if (self.currentDirEntry_ != currentEntry)
return; return;
if (err.code != FileError.NOT_FOUND_ERR) { if (err.code != FileError.NOT_FOUND_ERR) {
self.rescanLater(); self.rescanLater();
...@@ -515,12 +548,12 @@ DirectoryModel.prototype.onEntryChanged = function(name) { ...@@ -515,12 +548,12 @@ DirectoryModel.prototype.onEntryChanged = function(name) {
dm.splice(index, 1); dm.splice(index, 1);
}; };
util.resolvePath(currentEntry, name, onEntryFound, onError); util.resolvePath(this.currentDirEntry_, name, onEntryFound, onError);
}; };
/** /**
* @private * @private
* @param {string} name * @param {string} name Filename.
* @return {number} The index in the fileList. * @return {number} The index in the fileList.
*/ */
DirectoryModel.prototype.findIndexByName_ = function(name) { DirectoryModel.prototype.findIndexByName_ = function(name) {
...@@ -534,7 +567,7 @@ DirectoryModel.prototype.findIndexByName_ = function(name) { ...@@ -534,7 +567,7 @@ DirectoryModel.prototype.findIndexByName_ = function(name) {
/** /**
* Rename the entry in the filesystem and update the file list. * Rename the entry in the filesystem and update the file list.
* @param {Entry} entry Entry to rename. * @param {Entry} entry Entry to rename.
* @param {string} newName * @param {string} newName New name.
* @param {function} errorCallback Called on error. * @param {function} errorCallback Called on error.
* @param {function} opt_successCallback Called on success. * @param {function} opt_successCallback Called on success.
*/ */
...@@ -554,8 +587,7 @@ DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, ...@@ -554,8 +587,7 @@ DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback,
opt_successCallback(); opt_successCallback();
}); });
} }
entry.moveTo(this.currentEntry, newName, entry.moveTo(this.currentDirEntry_, newName, onSuccess, errorCallback);
onSuccess, errorCallback);
}; };
/** /**
...@@ -566,7 +598,7 @@ DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, ...@@ -566,7 +598,7 @@ DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback,
* is true if it's a file. * is true if it's a file.
*/ */
DirectoryModel.prototype.doesExist = function(newName, callback) { DirectoryModel.prototype.doesExist = function(newName, callback) {
util.resolvePath(this.currentEntry, newName, util.resolvePath(this.currentDirEntry_, newName,
function(entry) { function(entry) {
callback(true, entry.isFile); callback(true, entry.isFile);
}, },
...@@ -576,9 +608,9 @@ DirectoryModel.prototype.doesExist = function(newName, callback) { ...@@ -576,9 +608,9 @@ DirectoryModel.prototype.doesExist = function(newName, callback) {
/** /**
* Creates directory and updates the file list. * Creates directory and updates the file list.
* *
* @param {string} name * @param {string} name Directory name.
* @param {function} successCallback * @param {function} successCallback Callback on success.
* @param {function} errorCallback * @param {function} errorCallback Callback on failure.
*/ */
DirectoryModel.prototype.createDirectory = function(name, successCallback, DirectoryModel.prototype.createDirectory = function(name, successCallback,
errorCallback) { errorCallback) {
...@@ -593,17 +625,17 @@ DirectoryModel.prototype.createDirectory = function(name, successCallback, ...@@ -593,17 +625,17 @@ DirectoryModel.prototype.createDirectory = function(name, successCallback,
self.selectEntry(name); self.selectEntry(name);
successCallback(existing[0]); successCallback(existing[0]);
} else { } else {
self.fileListSelection.beginChange(); self.fileListSelection_.beginChange();
fileList.splice(0, 0, newEntry); fileList.splice(0, 0, newEntry);
self.selectEntry(name); self.selectEntry(name);
self.fileListSelection.endChange(); self.fileListSelection_.endChange();
successCallback(newEntry); successCallback(newEntry);
} }
}); });
} }
this.currentEntry.getDirectory(name, {create: true, exclusive: true}, this.currentDirEntry_.getDirectory(name, {create: true, exclusive: true},
onSuccess, errorCallback); onSuccess, errorCallback);
}; };
/** /**
...@@ -653,7 +685,7 @@ DirectoryModel.prototype.changeDirectory = function(path, opt_OnError) { ...@@ -653,7 +685,7 @@ DirectoryModel.prototype.changeDirectory = function(path, opt_OnError) {
* @param {DirectoryEntry} dirEntry A new directory entry. * @param {DirectoryEntry} dirEntry A new directory entry.
*/ */
DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry) { DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry) {
var previous = this.currentEntry; var previous = this.currentDirEntry_;
this.currentDirEntry_ = dirEntry; this.currentDirEntry_ = dirEntry;
function onRescanComplete() { function onRescanComplete() {
// For tests that open the dialog to empty directories, everything // For tests that open the dialog to empty directories, everything
...@@ -785,30 +817,21 @@ DirectoryModel.prototype.setupPath = function(path, opt_loadedCallback, ...@@ -785,30 +817,21 @@ DirectoryModel.prototype.setupPath = function(path, opt_loadedCallback,
}; };
/** /**
* @param {function} opt_callback * @param {function} opt_callback Callback on done.
*/ */
DirectoryModel.prototype.setupDefaultPath = function(opt_callback) { DirectoryModel.prototype.setupDefaultPath = function(opt_callback) {
var overridden = false; this.setupPath(this.getDefaultDirectory(), opt_callback);
function onExternalDirChange() { overridden = true }
this.addEventListener('directory-changed', onExternalDirChange);
this.getDefaultDirectory_(function(path) {
this.removeEventListener('directory-changed', onExternalDirChange);
if (!overridden)
this.setupPath(path, opt_callback);
}.bind(this));
}; };
/** /**
* @private * @return {string} The default directory.
* @param {function} callback
*/ */
DirectoryModel.prototype.getDefaultDirectory = function() { DirectoryModel.prototype.getDefaultDirectory = function() {
return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; return '/' + DirectoryModel.DOWNLOADS_DIRECTORY;
}; };
/** /**
* @param {string} name * @param {string} name Filename.
*/ */
DirectoryModel.prototype.selectEntry = function(name) { DirectoryModel.prototype.selectEntry = function(name) {
var dm = this.fileList_; var dm = this.fileList_;
...@@ -821,7 +844,7 @@ DirectoryModel.prototype.selectEntry = function(name) { ...@@ -821,7 +844,7 @@ DirectoryModel.prototype.selectEntry = function(name) {
}; };
/** /**
* @param {number} index * @param {number} index Index of file.
*/ */
DirectoryModel.prototype.selectIndex = function(index) { DirectoryModel.prototype.selectIndex = function(index) {
// this.focusCurrentList_(); // this.focusCurrentList_();
...@@ -838,8 +861,8 @@ DirectoryModel.prototype.selectIndex = function(index) { ...@@ -838,8 +861,8 @@ DirectoryModel.prototype.selectIndex = function(index) {
* This is called by the table code before a sort happens, so that we can * This is called by the table code before a sort happens, so that we can
* go fetch data for the sort field that we may not have yet. * go fetch data for the sort field that we may not have yet.
* @private * @private
* @param {string} field * @param {string} field Sort field.
* @param {function} callback * @param {function} callback Called when done.
*/ */
DirectoryModel.prototype.prepareSort_ = function(field, callback) { DirectoryModel.prototype.prepareSort_ = function(field, callback) {
this.prepareSortEntries_(this.fileList_.slice(), field, callback); this.prepareSortEntries_(this.fileList_.slice(), field, callback);
...@@ -847,9 +870,9 @@ DirectoryModel.prototype.prepareSort_ = function(field, callback) { ...@@ -847,9 +870,9 @@ DirectoryModel.prototype.prepareSort_ = function(field, callback) {
/** /**
* @private * @private
* @param {Array.<Entry>} entries * @param {Array.<Entry>} entries Files.
* @param {string} field * @param {string} field Sort field.
* @param {function} callback * @param {function} callback Called when done.
*/ */
DirectoryModel.prototype.prepareSortEntries_ = function(entries, field, DirectoryModel.prototype.prepareSortEntries_ = function(entries, field,
callback) { callback) {
...@@ -1003,7 +1026,7 @@ DirectoryModel.prototype.updateRootsListSelection_ = function() { ...@@ -1003,7 +1026,7 @@ DirectoryModel.prototype.updateRootsListSelection_ = function() {
* @private * @private
*/ */
DirectoryModel.prototype.updateReadonlyStatus_ = function() { DirectoryModel.prototype.updateReadonlyStatus_ = function() {
switch (this.rootType) { switch (this.getRootType()) {
case DirectoryModel.RootType.REMOVABLE: case DirectoryModel.RootType.REMOVABLE:
this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly; this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly;
break; break;
...@@ -1014,7 +1037,7 @@ DirectoryModel.prototype.updateReadonlyStatus_ = function() { ...@@ -1014,7 +1037,7 @@ DirectoryModel.prototype.updateReadonlyStatus_ = function() {
this.readonly_ = false; this.readonly_ = false;
break; break;
case DirectoryModel.RootType.GDATA: case DirectoryModel.RootType.GDATA:
this.readonly_ = this.offline; this.readonly_ = this.offline_;
break; break;
default: default:
this.readonly_ = true; this.readonly_ = true;
...@@ -1048,7 +1071,7 @@ DirectoryModel.prototype.updateVolumeMetadata_ = function() { ...@@ -1048,7 +1071,7 @@ DirectoryModel.prototype.updateVolumeMetadata_ = function() {
/** /**
* Prepare the root for the unmount. * Prepare the root for the unmount.
* *
* @param {string} rootPath * @param {string} rootPath The path to the root.
*/ */
DirectoryModel.prototype.prepareUnmount = function(rootPath) { DirectoryModel.prototype.prepareUnmount = function(rootPath) {
var index = this.findRootsListItem_(rootPath); var index = this.findRootsListItem_(rootPath);
...@@ -1073,7 +1096,7 @@ DirectoryModel.prototype.prepareUnmount = function(rootPath) { ...@@ -1073,7 +1096,7 @@ DirectoryModel.prototype.prepareUnmount = function(rootPath) {
}; };
/** /**
* @param {string} path * @param {string} path Any path.
* @return {string} The root path. * @return {string} The root path.
*/ */
DirectoryModel.getRootPath = function(path) { DirectoryModel.getRootPath = function(path) {
...@@ -1097,8 +1120,8 @@ DirectoryModel.getRootPath = function(path) { ...@@ -1097,8 +1120,8 @@ DirectoryModel.getRootPath = function(path) {
}; };
/** /**
* @param {string} path * @param {string} path Any path.
* @return {string} * @return {string} The name of the root.
*/ */
DirectoryModel.getRootName = function(path) { DirectoryModel.getRootName = function(path) {
var root = DirectoryModel.getRootPath(path); var root = DirectoryModel.getRootPath(path);
...@@ -1107,7 +1130,7 @@ DirectoryModel.getRootName = function(path) { ...@@ -1107,7 +1130,7 @@ DirectoryModel.getRootName = function(path) {
}; };
/** /**
* @param {string} path Path. * @param {string} path A path.
* @return {string} A root type. * @return {string} A root type.
*/ */
DirectoryModel.getRootType = function(path) { DirectoryModel.getRootType = function(path) {
...@@ -1127,8 +1150,8 @@ DirectoryModel.getRootType = function(path) { ...@@ -1127,8 +1150,8 @@ DirectoryModel.getRootType = function(path) {
}; };
/** /**
* @param {string} path * @param {string} path A path.
* @return {boolean} * @return {boolean} True if it is a path to the root.
*/ */
DirectoryModel.isRootPath = function(path) { DirectoryModel.isRootPath = function(path) {
if (path[path.length - 1] == '/') if (path[path.length - 1] == '/')
...@@ -1193,7 +1216,7 @@ DirectoryModel.Scanner.prototype.readNextChunk_ = function() { ...@@ -1193,7 +1216,7 @@ DirectoryModel.Scanner.prototype.readNextChunk_ = function() {
/** /**
* @private * @private
* @param {Array.<Entry>} entries * @param {Array.<Entry>} entries File list.
*/ */
DirectoryModel.Scanner.prototype.onChunkComplete_ = function(entries) { DirectoryModel.Scanner.prototype.onChunkComplete_ = function(entries) {
if (this.cancelled_) if (this.cancelled_)
......
...@@ -507,7 +507,7 @@ FileManager.prototype = { ...@@ -507,7 +507,7 @@ FileManager.prototype = {
'modificationTime'; 'modificationTime';
var sortDirection = var sortDirection =
window.localStorage['sort-direction-' + this.dialogType_] || 'desc'; window.localStorage['sort-direction-' + this.dialogType_] || 'desc';
this.directoryModel_.fileList.sort(sortField, sortDirection); this.directoryModel_.sortFileList(sortField, sortDirection);
this.refocus(); this.refocus();
...@@ -519,7 +519,7 @@ FileManager.prototype = { ...@@ -519,7 +519,7 @@ FileManager.prototype = {
return self.getMetadataProvider().isInitialized(); return self.getMetadataProvider().isInitialized();
}); });
this.directoryModel_.offline = this.isOffline(); this.directoryModel_.setOffline(this.isOffline());
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) if (this.dialogType_ == FileManager.DialogType.FULL_PAGE)
this.initDataTransferOperations_(); this.initDataTransferOperations_();
...@@ -539,8 +539,8 @@ FileManager.prototype = { ...@@ -539,8 +539,8 @@ FileManager.prototype = {
this.onCopyManagerOperationComplete_.bind(this)); this.onCopyManagerOperationComplete_.bind(this));
var controller = this.fileTransferController_ = new FileTransferController( var controller = this.fileTransferController_ = new FileTransferController(
this.directoryModel_.fileList, this.directoryModel_.getFileList(),
this.directoryModel_.fileListSelection, this.directoryModel_.getFileListSelection(),
GridItem.bind(null, this), GridItem.bind(null, this),
this.copyManager_, this.copyManager_,
this.directoryModel_); this.directoryModel_);
...@@ -721,7 +721,7 @@ FileManager.prototype = { ...@@ -721,7 +721,7 @@ FileManager.prototype = {
str('ENABLE_GDATA') == '1', str('ENABLE_GDATA') == '1',
this.metadataCache_); this.metadataCache_);
var dataModel = this.directoryModel_.fileList; var dataModel = this.directoryModel_.getFileList();
var collator = this.collator_; var collator = this.collator_;
// TODO(dgozman): refactor comparison functions together with // TODO(dgozman): refactor comparison functions together with
// render/update/display. // render/update/display.
...@@ -740,12 +740,9 @@ FileManager.prototype = { ...@@ -740,12 +740,9 @@ FileManager.prototype = {
dataModel.addEventListener('permuted', dataModel.addEventListener('permuted',
this.onDataModelPermuted_.bind(this)); this.onDataModelPermuted_.bind(this));
this.directoryModel_.fileListSelection.addEventListener( this.directoryModel_.getFileListSelection().addEventListener(
'change', this.onSelectionChanged_.bind(this)); 'change', this.onSelectionChanged_.bind(this));
this.directoryModel_.autoSelectIndex =
this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE ? -1 : 0;
this.initTable_(); this.initTable_();
this.initGrid_(); this.initGrid_();
this.initRootsList_(); this.initRootsList_();
...@@ -885,7 +882,7 @@ FileManager.prototype = { ...@@ -885,7 +882,7 @@ FileManager.prototype = {
}; };
FileManager.prototype.onDataModelPermuted_ = function(event) { FileManager.prototype.onDataModelPermuted_ = function(event) {
var sortStatus = this.directoryModel_.fileList.sortStatus; var sortStatus = this.directoryModel_.getFileList().sortStatus;
window.localStorage['sort-field-' + this.dialogType_] = sortStatus.field; window.localStorage['sort-field-' + this.dialogType_] = sortStatus.field;
window.localStorage['sort-direction-' + this.dialogType_] = window.localStorage['sort-direction-' + this.dialogType_] =
sortStatus.direction; sortStatus.direction;
...@@ -1157,8 +1154,8 @@ FileManager.prototype = { ...@@ -1157,8 +1154,8 @@ FileManager.prototype = {
// style and only then set dataModel. // style and only then set dataModel.
if (type == FileManager.ListType.DETAIL) { if (type == FileManager.ListType.DETAIL) {
this.table_.dataModel = this.directoryModel_.fileList; this.table_.dataModel = this.directoryModel_.getFileList();
this.table_.selectionModel = this.directoryModel_.fileListSelection; this.table_.selectionModel = this.directoryModel_.getFileListSelection();
this.table_.style.display = ''; this.table_.style.display = '';
this.grid_.style.display = 'none'; this.grid_.style.display = 'none';
this.grid_.selectionModel = this.emptySelectionModel_; this.grid_.selectionModel = this.emptySelectionModel_;
...@@ -1171,8 +1168,8 @@ FileManager.prototype = { ...@@ -1171,8 +1168,8 @@ FileManager.prototype = {
this.dialogDom_.querySelector('div.thumbnail-view') this.dialogDom_.querySelector('div.thumbnail-view')
.removeAttribute('disabled'); .removeAttribute('disabled');
} else if (type == FileManager.ListType.THUMBNAIL) { } else if (type == FileManager.ListType.THUMBNAIL) {
this.grid_.dataModel = this.directoryModel_.fileList; this.grid_.dataModel = this.directoryModel_.getFileList();
this.grid_.selectionModel = this.directoryModel_.fileListSelection; this.grid_.selectionModel = this.directoryModel_.getFileListSelection();
this.grid_.style.display = ''; this.grid_.style.display = '';
this.table_.style.display = 'none'; this.table_.style.display = 'none';
this.table_.selectionModel = this.emptySelectionModel_; this.table_.selectionModel = this.emptySelectionModel_;
...@@ -1355,7 +1352,7 @@ FileManager.prototype = { ...@@ -1355,7 +1352,7 @@ FileManager.prototype = {
* update event). * update event).
*/ */
FileManager.prototype.onCopyManagerOperationComplete_ = function(event) { FileManager.prototype.onCopyManagerOperationComplete_ = function(event) {
var currentPath = this.directoryModel_.currentEntry.fullPath; var currentPath = this.directoryModel_.getCurrentDirEntry().fullPath;
function inCurrentDirectory(entry) { function inCurrentDirectory(entry) {
var fullPath = entry.fullPath; var fullPath = entry.fullPath;
var dirPath = fullPath.substr(0, fullPath.length - var dirPath = fullPath.substr(0, fullPath.length -
...@@ -1429,7 +1426,7 @@ FileManager.prototype = { ...@@ -1429,7 +1426,7 @@ FileManager.prototype = {
// Nothing left to do if the current directory is not changing. This happens // Nothing left to do if the current directory is not changing. This happens
// if we are exiting the Gallery. // if we are exiting the Gallery.
if (this.getPathFromUrlOrParams_() == if (this.getPathFromUrlOrParams_() ==
this.directoryModel_.currentEntry.fullPath) this.directoryModel_.getCurrentDirEntry().fullPath)
return; return;
this.setupCurrentDirectory_(true /* invokeHandler */); this.setupCurrentDirectory_(true /* invokeHandler */);
}; };
...@@ -1679,7 +1676,7 @@ FileManager.prototype = { ...@@ -1679,7 +1676,7 @@ FileManager.prototype = {
* Update check and disable states of the 'Select all' checkbox. * Update check and disable states of the 'Select all' checkbox.
*/ */
FileManager.prototype.updateSelectAllCheckboxState_ = function(checkbox) { FileManager.prototype.updateSelectAllCheckboxState_ = function(checkbox) {
var dm = this.directoryModel_.fileList; var dm = this.directoryModel_.getFileList();
checkbox.checked = this.selection && dm.length > 0 && checkbox.checked = this.selection && dm.length > 0 &&
dm.length == this.selection.totalCount; dm.length == this.selection.totalCount;
checkbox.disabled = dm.length == 0; checkbox.disabled = dm.length == 0;
...@@ -1946,8 +1943,9 @@ FileManager.prototype = { ...@@ -1946,8 +1943,9 @@ FileManager.prototype = {
var fileName = this.document_.createElement('div'); var fileName = this.document_.createElement('div');
fileName.className = 'filename-label'; fileName.className = 'filename-label';
fileName.textContent = this.directoryModel_.currentEntry.name == '' ? fileName.textContent =
this.getRootLabel_(entry.name) : entry.name; this.directoryModel_.getCurrentDirEntry().name == '' ?
this.getRootLabel_(entry.name) : entry.name;
return fileName; return fileName;
}; };
...@@ -2041,7 +2039,7 @@ FileManager.prototype = { ...@@ -2041,7 +2039,7 @@ FileManager.prototype = {
FileManager.prototype.displayDateInDiv_ = function(div, filesystemProps) { FileManager.prototype.displayDateInDiv_ = function(div, filesystemProps) {
if (!filesystemProps) return; if (!filesystemProps) return;
if (this.directoryModel_.isSystemDirectoy && if (this.directoryModel_.isSystemDirectory() &&
filesystemProps.modificationTime.getTime() == 0) { filesystemProps.modificationTime.getTime() == 0) {
// Mount points for FAT volumes have this time associated with them. // Mount points for FAT volumes have this time associated with them.
// We'd rather display nothing than this bogus date. // We'd rather display nothing than this bogus date.
...@@ -2077,7 +2075,7 @@ FileManager.prototype = { ...@@ -2077,7 +2075,7 @@ FileManager.prototype = {
}; };
FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() { FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() {
var entries = this.directoryModel_.fileList.slice(); var entries = this.directoryModel_.getFileList().slice();
this.metadataCache_.clear(entries, 'filesystem'); this.metadataCache_.clear(entries, 'filesystem');
// We don't pass callback here. When new metadata arrives, we have an // We don't pass callback here. When new metadata arrives, we have an
// observer registered to update the UI. // observer registered to update the UI.
...@@ -2089,7 +2087,7 @@ FileManager.prototype = { ...@@ -2089,7 +2087,7 @@ FileManager.prototype = {
if (this.listType_ != FileManager.ListType.DETAIL) return; if (this.listType_ != FileManager.ListType.DETAIL) return;
var items = {}; var items = {};
var dm = this.directoryModel_.fileList; var dm = this.directoryModel_.getFileList();
for (var index = 0; index < dm.length; index++) { for (var index = 0; index < dm.length; index++) {
var listItem = this.currentList_.getListItemByIndex(index); var listItem = this.currentList_.getListItemByIndex(index);
if (!listItem) continue; if (!listItem) continue;
...@@ -2121,11 +2119,11 @@ FileManager.prototype = { ...@@ -2121,11 +2119,11 @@ FileManager.prototype = {
return; return;
var dm = this.directoryModel_; var dm = this.directoryModel_;
var leadIndex = dm.fileListSelection.leadIndex; var leadIndex = dm.getFileListSelection().leadIndex;
if (leadIndex < 0) if (leadIndex < 0)
return; return;
var leadEntry = dm.fileList.item(leadIndex); var leadEntry = dm.getFileList().item(leadIndex);
if (this.renameInput_.currentEntry.fullPath != leadEntry.fullPath) if (this.renameInput_.currentEntry.fullPath != leadEntry.fullPath)
return; return;
...@@ -2194,7 +2192,7 @@ FileManager.prototype = { ...@@ -2194,7 +2192,7 @@ FileManager.prototype = {
} }
for (var i = 0; i < selection.indexes.length; i++) { for (var i = 0; i < selection.indexes.length; i++) {
var entry = this.directoryModel_.fileList.item(selection.indexes[i]); var entry = this.directoryModel_.getFileList().item(selection.indexes[i]);
if (!entry) if (!entry)
continue; continue;
...@@ -2614,7 +2612,7 @@ FileManager.prototype = { ...@@ -2614,7 +2612,7 @@ FileManager.prototype = {
console.log('ONLINE'); console.log('ONLINE');
this.dialogContainer_.removeAttribute('offline'); this.dialogContainer_.removeAttribute('offline');
} }
this.directoryModel_.offline = this.isOffline(); this.directoryModel_.setOffline(this.isOffline());
}; };
FileManager.prototype.isOnGDataOffline = function() { FileManager.prototype.isOnGDataOffline = function() {
...@@ -2622,7 +2620,7 @@ FileManager.prototype = { ...@@ -2622,7 +2620,7 @@ FileManager.prototype = {
}; };
FileManager.prototype.isOnReadonlyDirectory = function() { FileManager.prototype.isOnReadonlyDirectory = function() {
return this.directoryModel_.readonly; return this.directoryModel_.isReadOnly();
}; };
/** /**
...@@ -2651,7 +2649,7 @@ FileManager.prototype = { ...@@ -2651,7 +2649,7 @@ FileManager.prototype = {
if (this.setupCurrentDirectoryPostponed_) { if (this.setupCurrentDirectoryPostponed_) {
this.setupCurrentDirectoryPostponed_(false /* execute */); this.setupCurrentDirectoryPostponed_(false /* execute */);
} else if (this.isOnGData() && } else if (this.isOnGData() &&
this.directoryModel_.currentEntry.unmounted) { this.directoryModel_.getCurrentDirEntry().unmounted) {
// We are currently on an unmounted GData directory, force a rescan. // We are currently on an unmounted GData directory, force a rescan.
changeDirectoryTo = this.directoryModel_.getCurrentRootPath(); changeDirectoryTo = this.directoryModel_.getCurrentRootPath();
} }
...@@ -2791,9 +2789,9 @@ FileManager.prototype = { ...@@ -2791,9 +2789,9 @@ FileManager.prototype = {
FileManager.prototype.getAllUrlsInCurrentDirectory_ = function() { FileManager.prototype.getAllUrlsInCurrentDirectory_ = function() {
var urls = []; var urls = [];
var dm = this.directoryModel_.fileList; var fileList = this.directoryModel_.getFileList();
for (var i = 0; i != dm.length; i++) { for (var i = 0; i != fileList.length; i++) {
urls.push(dm.item(i).toURL()); urls.push(fileList.item(i).toURL());
} }
return urls; return urls;
}; };
...@@ -2837,7 +2835,7 @@ FileManager.prototype = { ...@@ -2837,7 +2835,7 @@ FileManager.prototype = {
selectedUrl = urls[0]; selectedUrl = urls[0];
} }
var dirPath = this.directoryModel_.currentEntry.fullPath; var dirPath = this.directoryModel_.getCurrentDirEntry().fullPath;
// Push a temporary state which will be replaced every time an individual // Push a temporary state which will be replaced every time an individual
// item is selected in the Gallery. // item is selected in the Gallery.
...@@ -2851,7 +2849,7 @@ FileManager.prototype = { ...@@ -2851,7 +2849,7 @@ FileManager.prototype = {
// Gallery shoud treat GData folder as readonly even when online // Gallery shoud treat GData folder as readonly even when online
// until we learn to save files directly to GData. // until we learn to save files directly to GData.
var readonly = self.isOnReadonlyDirectory() || self.isOnGData(); var readonly = self.isOnReadonlyDirectory() || self.isOnGData();
var currentDir = self.directoryModel_.currentEntry; var currentDir = self.directoryModel_.getCurrentDirEntry();
var downloadsDir = self.directoryModel_.getRootsList().item(0); var downloadsDir = self.directoryModel_.getRootsList().item(0);
var gallerySelection; var gallerySelection;
...@@ -2861,7 +2859,7 @@ FileManager.prototype = { ...@@ -2861,7 +2859,7 @@ FileManager.prototype = {
readonly ? readonly ?
(self.isOnGData() ? (self.isOnGData() ?
self.getRootLabel_(currentDir.fullPath) : self.getRootLabel_(currentDir.fullPath) :
self.directoryModel_.rootName) : self.directoryModel_.getRootName()) :
null, null,
saveDirEntry: readonly ? downloadsDir : currentDir, saveDirEntry: readonly ? downloadsDir : currentDir,
metadataProvider: self.getMetadataProvider(), metadataProvider: self.getMetadataProvider(),
...@@ -2892,7 +2890,7 @@ FileManager.prototype = { ...@@ -2892,7 +2890,7 @@ FileManager.prototype = {
removeChildren(bc); removeChildren(bc);
var rootPath = this.directoryModel_.getCurrentRootPath(); var rootPath = this.directoryModel_.getCurrentRootPath();
var relativePath = this.directoryModel_.currentEntry.fullPath. var relativePath = this.directoryModel_.getCurrentDirEntry().fullPath.
substring(rootPath.length).replace(/\/$/, ''); substring(rootPath.length).replace(/\/$/, '');
var pathNames = relativePath.replace(/\/$/, '').split('/'); var pathNames = relativePath.replace(/\/$/, '').split('/');
...@@ -3066,7 +3064,7 @@ FileManager.prototype = { ...@@ -3066,7 +3064,7 @@ FileManager.prototype = {
*/ */
FileManager.prototype.getCurrentDirectory = function() { FileManager.prototype.getCurrentDirectory = function() {
return this.directoryModel_ && return this.directoryModel_ &&
this.directoryModel_.currentEntry.fullPath; this.directoryModel_.getCurrentDirEntry().fullPath;
}; };
/** /**
...@@ -3074,7 +3072,7 @@ FileManager.prototype = { ...@@ -3074,7 +3072,7 @@ FileManager.prototype = {
*/ */
FileManager.prototype.getCurrentDirectoryURL = function() { FileManager.prototype.getCurrentDirectoryURL = function() {
return this.directoryModel_ && return this.directoryModel_ &&
this.directoryModel_.currentEntry.toURL(); this.directoryModel_.getCurrentDirEntry().toURL();
}; };
FileManager.prototype.deleteEntries = function(entries, force, opt_callback) { FileManager.prototype.deleteEntries = function(entries, force, opt_callback) {
...@@ -3170,7 +3168,7 @@ FileManager.prototype = { ...@@ -3170,7 +3168,7 @@ FileManager.prototype = {
}; };
FileManager.prototype.onCheckboxClick_ = function(event) { FileManager.prototype.onCheckboxClick_ = function(event) {
var sm = this.directoryModel_.fileListSelection; var sm = this.directoryModel_.getFileListSelection();
var listItem = this.findListItemForEvent_(event); var listItem = this.findListItemForEvent_(event);
sm.setIndexSelected(listItem.listIndex, event.target.checked); sm.setIndexSelected(listItem.listIndex, event.target.checked);
}; };
...@@ -3440,7 +3438,7 @@ FileManager.prototype = { ...@@ -3440,7 +3438,7 @@ FileManager.prototype = {
this.metadataCache_.removeObserver(this.metadataObserverId_); this.metadataCache_.removeObserver(this.metadataObserverId_);
this.metadataObserverId_ = this.metadataCache_.addObserver( this.metadataObserverId_ = this.metadataCache_.addObserver(
this.directoryModel_.currentEntry, this.directoryModel_.getCurrentDirEntry(),
MetadataCache.CHILDREN, MetadataCache.CHILDREN,
'filesystem', 'filesystem',
this.updateFilesystemPropertiesInUI_.bind(this)); this.updateFilesystemPropertiesInUI_.bind(this));
...@@ -3676,7 +3674,7 @@ FileManager.prototype = { ...@@ -3676,7 +3674,7 @@ FileManager.prototype = {
var defaultName = str('DEFAULT_NEW_FOLDER_NAME'); var defaultName = str('DEFAULT_NEW_FOLDER_NAME');
// Find a name that doesn't exist in the data model. // Find a name that doesn't exist in the data model.
var files = this.directoryModel_.fileList; var files = this.directoryModel_.getFileList();
var hash = {}; var hash = {};
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
var name = files.item(i).name; var name = files.item(i).name;
...@@ -3749,7 +3747,7 @@ FileManager.prototype = { ...@@ -3749,7 +3747,7 @@ FileManager.prototype = {
switch (util.getKeyModifiers(event) + event.keyCode) { switch (util.getKeyModifiers(event) + event.keyCode) {
case 'Ctrl-190': // Ctrl-. => Toggle filter files. case 'Ctrl-190': // Ctrl-. => Toggle filter files.
var dm = this.directoryModel_; var dm = this.directoryModel_;
dm.filterHidden = !dm.filterHidden; dm.setFilterHidden(!dm.getFilterHidden());
event.preventDefault(); event.preventDefault();
return; return;
...@@ -3903,7 +3901,7 @@ FileManager.prototype = { ...@@ -3903,7 +3901,7 @@ FileManager.prototype = {
if (!text) if (!text)
return; return;
var dm = this.directoryModel_.fileList; var dm = this.directoryModel_.getFileList();
for (var index = 0; index < dm.length; ++index) { for (var index = 0; index < dm.length; ++index) {
var name = dm.item(index).name; var name = dm.item(index).name;
if (name.substring(0, text.length).toLowerCase() == text) { if (name.substring(0, text.length).toLowerCase() == text) {
...@@ -4144,7 +4142,7 @@ FileManager.prototype = { ...@@ -4144,7 +4142,7 @@ FileManager.prototype = {
if (!selectedIndexes.length) if (!selectedIndexes.length)
throw new Error('Nothing selected!'); throw new Error('Nothing selected!');
var dm = this.directoryModel_.fileList; var dm = this.directoryModel_.getFileList();
for (var i = 0; i < selectedIndexes.length; i++) { for (var i = 0; i < selectedIndexes.length; i++) {
var entry = dm.item(selectedIndexes[i]); var entry = dm.item(selectedIndexes[i]);
if (!entry) { if (!entry) {
...@@ -4210,7 +4208,7 @@ FileManager.prototype = { ...@@ -4210,7 +4208,7 @@ FileManager.prototype = {
msg = str('ERROR_WHITESPACE_NAME'); msg = str('ERROR_WHITESPACE_NAME');
} else if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(name)) { } else if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(name)) {
msg = str('ERROR_RESERVED_NAME'); msg = str('ERROR_RESERVED_NAME');
} else if (this.directoryModel_.filterHidden && name[0] == '.') { } else if (this.directoryModel_.getFilterHidden() && name[0] == '.') {
msg = str('ERROR_HIDDEN_NAME'); msg = str('ERROR_HIDDEN_NAME');
} }
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* *
* Refer to chrome/test/functional/chromeos_file_browser.py for examples * Refer to chrome/test/functional/chromeos_file_browser.py for examples
* of how this API is used. * of how this API is used.
*
* TODO(olege): Fix style warnings.
*/ */
var pyautoAPI = { var pyautoAPI = {
/** /**
...@@ -18,7 +20,7 @@ var pyautoAPI = { ...@@ -18,7 +20,7 @@ var pyautoAPI = {
*/ */
addItemToSelection: function(name) { addItemToSelection: function(name) {
var entryExists = false; var entryExists = false;
var dm = fileManager.directoryModel_.fileList; var dm = fileManager.directoryModel_.getFileList();
for (var i = 0; i < dm.length; i++) { for (var i = 0; i < dm.length; i++) {
if (dm.item(i).name == name) { if (dm.item(i).name == name) {
fileManager.currentList_.selectionModel.setIndexSelected(i, true); fileManager.currentList_.selectionModel.setIndexSelected(i, true);
...@@ -39,7 +41,7 @@ var pyautoAPI = { ...@@ -39,7 +41,7 @@ var pyautoAPI = {
*/ */
listDirectory: function() { listDirectory: function() {
var list = []; var list = [];
var dm = fileManager.directoryModel_.fileList; var dm = fileManager.directoryModel_.getFileList();
for (var i = 0; i < dm.length; i++) { for (var i = 0; i < dm.length; i++) {
list.push(dm.item(i).name); list.push(dm.item(i).name);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment