Caret/js/storage/file.js
Thomas Wilburn 12870d3b1d Revert Promises in file API to callbacks.
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.
2014-05-04 02:09:19 -07:00

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;
});