12870d3b1d
Promises do not seem reliable as they are in Chrome 34. Rather than continue to implement hacks that can work around these problems, let's just go back to callbacks. Maybe we don't need to be on the cutting edge _all_ the time.
150 lines
No EOL
3.6 KiB
JavaScript
150 lines
No EOL
3.6 KiB
JavaScript
define([
|
|
"util/manos"
|
|
], function(M) {
|
|
|
|
/*
|
|
|
|
The File object provides storage backed by the local HDD via the chrome.fileSystem API.
|
|
|
|
*/
|
|
|
|
var noop = function() {};
|
|
|
|
var File = function(entry) {
|
|
this.entry = entry || null;
|
|
this.onWrite = noop;
|
|
};
|
|
|
|
File.prototype = {
|
|
open: function(mode, c) {
|
|
var self = this;
|
|
mode = mode || "open";
|
|
//mode is "open" or "save"
|
|
var modes = {
|
|
"open": "openWritableFile",
|
|
"save": "saveFile"
|
|
};
|
|
|
|
chrome.fileSystem.chooseEntry({
|
|
type: modes[mode]
|
|
}, function(entry) {
|
|
//cancelling acts like an error, but isn't.
|
|
if (!entry) return c(chrome.runtime.lastError);
|
|
self.entry = entry;
|
|
c(null, self);
|
|
});
|
|
},
|
|
|
|
read: function(c) {
|
|
var self = this;
|
|
|
|
if (!self.entry) {
|
|
console.error(self);
|
|
c("File not opened");
|
|
}
|
|
var reader = new FileReader();
|
|
reader.onload = function() {
|
|
c(null, reader.result);
|
|
};
|
|
reader.onerror = function(err) {
|
|
console.error("File read error!");
|
|
c(err);
|
|
};
|
|
self.entry.file(function(f) {
|
|
reader.readAsText(f);
|
|
});
|
|
},
|
|
|
|
write: function(data, c) {
|
|
var self = this;
|
|
c = c || function() {};
|
|
if (!self.entry) {
|
|
//guard against cases where we accidentally write before opening
|
|
return self.open("save").then(function() {
|
|
return self.write(data, c);
|
|
});
|
|
}
|
|
|
|
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 {
|
|
c("Couldn't open file as writable");
|
|
}
|
|
});
|
|
}
|
|
next();
|
|
},
|
|
//write file
|
|
function() {
|
|
self.entry.createWriter(function(writer) {
|
|
writer.onerror = function(err) {
|
|
console.error(err);
|
|
c(err);
|
|
}
|
|
writer.onwriteend = function() {
|
|
//after truncation, actually write the file
|
|
writer.onwriteend = function() {
|
|
c();
|
|
self.onWrite();
|
|
}
|
|
var blob = new Blob([data]);
|
|
writer.write(blob);
|
|
};
|
|
writer.truncate(0);
|
|
});
|
|
}
|
|
);
|
|
},
|
|
|
|
stat: function(c) {
|
|
var self = this;
|
|
if (self.entry) {
|
|
return self.entry.file(function(f) {
|
|
c(null, f);
|
|
});
|
|
}
|
|
c("No file entry");
|
|
},
|
|
|
|
retain: function() {
|
|
return chrome.fileSystem.retainEntry(this.entry);
|
|
},
|
|
|
|
restore: function(id, c) {
|
|
var self = this;
|
|
|
|
chrome.fileSystem.isRestorable(id, function(is) {
|
|
if (is) {
|
|
chrome.fileSystem.restoreEntry(id, function(entry) {
|
|
if (!entry) return c("restoreEntry() failed for " + id);
|
|
self.entry = entry;
|
|
c();
|
|
});
|
|
} else {
|
|
c("isRestorable() returned false for " + id);
|
|
}
|
|
});
|
|
},
|
|
|
|
getPath: function(c) {
|
|
var self = this;
|
|
if (!self.entry) return fail("No backing entry, cannot get path");
|
|
chrome.fileSystem.getDisplayPath(self.entry, function(path) {
|
|
c(null, path);
|
|
});
|
|
}
|
|
};
|
|
|
|
return File;
|
|
|
|
}); |