Caret/js/storage/file.js

175 lines
4.5 KiB
JavaScript
Raw Normal View History

define([
"util/manos"
], function(M) {
2013-08-20 00:53:03 +00:00
/*
Unfortunately, mimicking Node isn't really feasible given the Chrome OS security model, but we still don't want to deal with the annoying Chrome filesystem APIs. This module wraps those in a more usable File object.
2013-08-20 00:53:03 +00:00
*/
2013-11-06 20:02:20 +00:00
var noop = function() {};
var File = function(entry) {
this.entry = entry || null;
2013-11-06 20:02:20 +00:00
this.onWrite = noop;
2013-08-20 00:53:03 +00:00
};
File.prototype = {
open: function(mode, c) {
var self = this;
if (typeof mode == "function") {
c = mode;
mode = "open";
}
//mode is "open" or "save"
var modes = {
"open": "openWritableFile",
"save": "saveFile"
};
var deferred = M.deferred();
chrome.fileSystem.chooseEntry({
type: modes[mode] || "open"
}, function(entry) {
//cancelling acts like an error, but isn't.
if (!entry) return deferred.fail(chrome.runtime.lastError);
self.entry = entry;
deferred.done(self)
2013-08-20 00:53:03 +00:00
});
if (c) M.pton(deferred, c);
return deferred.promise();
2013-08-20 00:53:03 +00:00
},
2013-08-20 00:53:03 +00:00
read: function(c) {
var self = this;
var deferred = M.deferred();
if (!self.entry) {
console.error(self);
deferred.fail("File not opened");
}
var reader = new FileReader();
reader.onload = function() {
deferred.done(reader.result);
};
reader.onerror = function(err) {
console.error("File read error!");
deferred.fail(err);
};
self.entry.file(function(f) {
reader.readAsText(f);
2013-08-20 00:53:03 +00:00
});
if (c && typeof c == "function") M.pton(deferred, c);
return deferred.promise();
2013-08-20 00:53:03 +00:00
},
2013-08-22 06:35:14 +00:00
write: function(data, c) {
2013-08-20 00:53:03 +00:00
var self = this;
if (!self.entry) {
//guard against cases where we accidentally write before opening
return self.open("save").then(function() {
return self.write(data, c);
});
}
var deferred = M.deferred();
M.chain(
//check permissions
function(next) {
chrome.fileSystem.isWritableEntry(self.entry, next);
},
//if read-only, try to open as writable
function(ok, next) {
if (!ok) {
return chrome.fileSystem.getWritableEntry(self.entry, function(entry) {
if (entry) {
self.entry = entry;
next();
} else {
deferred.fail("Couldn't open file as writable");
}
});
2013-08-20 00:53:03 +00:00
}
next();
},
//write file
function() {
self.entry.createWriter(function(writer) {
writer.onerror = function(err) {
console.error(err);
deferred.fail(err);
}
writer.onwriteend = function() {
//after truncation, actually write the file
writer.onwriteend = function() {
deferred.done();
self.onWrite();
}
var blob = new Blob([data]);
writer.write(blob);
};
writer.truncate(0);
});
}
);
if (c) M.pton(deferred, c);
return deferred.promise();
2013-08-20 00:53:03 +00:00
},
2013-08-20 00:53:03 +00:00
stat: function(c) {
var self = this;
var promise = new Promise(function(ok, fail) {
if (self.entry) {
return self.entry.file(function(f) {
ok(f);
});
}
fail("No file entry");
});
if (c) M.pton(promise, c);
return promise;
2013-08-20 00:53:03 +00:00
},
2013-08-20 00:53:03 +00:00
retain: function() {
return chrome.fileSystem.retainEntry(this.entry);
},
2013-08-20 00:53:03 +00:00
restore: function(id, c) {
var self = this;
var deferred = M.deferred();
chrome.fileSystem.isRestorable(id, function(is) {
if (is) {
chrome.fileSystem.restoreEntry(id, function(entry) {
if (!entry) return fail("restoreEntry() failed for " + id);
self.entry = entry;
deferred.done();
});
} else {
deferred.fail("isRestorable() returned false for " + id);
}
2013-08-20 00:53:03 +00:00
});
if (c) M.pton(deferred, c);
return deferred.promise();
2013-11-06 15:37:34 +00:00
},
2013-11-06 15:37:34 +00:00
getPath: function(c) {
var self = this;
var promise = new Promise(function(ok, fail) {
if (!self.entry) return fail("No backing entry, cannot get path")
chrome.fileSystem.getDisplayPath(self.entry, ok);
});
if (c) M.pton(promise, c);
return promise;
2013-08-20 00:53:03 +00:00
}
};
return File;
});