This commit is contained in:
chris@h-194.office.mozilla.org 2008-06-06 17:58:02 -07:00
Родитель 31e59001d5 3e159040cb
Коммит d5a40e3690
4 изменённых файлов: 155 добавлений и 99 удалений

Просмотреть файл

@ -68,11 +68,11 @@ AsyncException.prototype = {
}
};
function Generator(object, method, onComplete, args) {
function Generator(thisArg, method, onComplete, args) {
this._log = Log4Moz.Service.getLogger("Async.Generator");
this._log.level =
Log4Moz.Level[Utils.prefs.getCharPref("log.logger.async")];
this._object = object;
this._thisArg = thisArg;
this._method = method;
this.onComplete = onComplete;
this._args = args;
@ -93,11 +93,11 @@ Generator.prototype = {
},
get listener() { return new Utils.EventListener(this.cb); },
get _object() { return this.__object; },
set _object(value) {
get _thisArg() { return this.__thisArg; },
set _thisArg(value) {
if (typeof value != "object")
throw "Generator: expected type 'object', got type '" + typeof(value) + "'";
this.__object = value;
this.__thisArg = value;
},
get _method() { return this.__method; },
@ -161,7 +161,7 @@ Generator.prototype = {
run: function AsyncGen_run() {
this._continued = false;
try {
this._generator = this._method.apply(this._object, this._args);
this._generator = this._method.apply(this._thisArg, this._args);
this.generator.next(); // must initialize before sending
this.generator.send(this);
} catch (e) {
@ -267,9 +267,9 @@ Async = {
// where fooGen is a generator function, and gen is a Generator instance
// ret is whatever the generator 'returns' via Generator.done().
run: function Async_run(object, method, onComplete /* , arg1, arg2, ... */) {
run: function Async_run(thisArg, method, onComplete /* , arg1, arg2, ... */) {
let args = Array.prototype.slice.call(arguments, 3);
let gen = new Generator(object, method, onComplete, args);
let gen = new Generator(thisArg, method, onComplete, args);
gen.run();
return gen;
},
@ -287,9 +287,9 @@ Async = {
// Note that 'this' refers to the method being called, not the
// Async object.
sugar: function Async_sugar(object, onComplete /* , arg1, arg2, ... */) {
sugar: function Async_sugar(thisArg, onComplete /* , arg1, arg2, ... */) {
let args = Array.prototype.slice.call(arguments, 1);
args.unshift(object, this);
args.unshift(thisArg, this);
Async.run.apply(Async, args);
},

Просмотреть файл

@ -649,95 +649,21 @@ Engine.prototype = {
self.done(ret);
},
_share: function Engine__share(username) {
let self = yield;
let prefix = DAV.defaultPrefix;
this._log.debug("Sharing bookmarks with " + username);
this._getSymKey.async(this, self.cb);
yield;
// copied from getSymKey
DAV.GET(this.keysFile, self.cb);
let ret = yield;
Utils.ensureStatus(ret.status, "Could not get keys file.");
let keys = this._json.decode(ret.responseText);
// get the other user's pubkey
let serverURL = Utils.prefs.getCharPref("serverURL");
try {
DAV.defaultPrefix = "user/" + username + "/"; //FIXME: very ugly!
DAV.GET("public/pubkey", self.cb);
ret = yield;
}
catch (e) { throw e; }
finally { DAV.defaultPrefix = prefix; }
Utils.ensureStatus(ret.status, "Could not get public key for " + username);
let id = new Identity();
id.pubkey = ret.responseText;
// now encrypt the symkey with their pubkey and upload the new keyring
Crypto.RSAencrypt.async(Crypto, self.cb, this._engineId.password, id);
let enckey = yield;
if (!enckey)
throw "Could not encrypt symmetric encryption key";
keys.ring[username] = enckey;
DAV.PUT(this.keysFile, this._json.encode(keys), self.cb);
ret = yield;
Utils.ensureStatus(ret.status, "Could not upload keyring file.");
this._createShare(username, username);
this._log.debug("All done sharing!");
self.done(true);
_share: function Engine__share(guid, username) {
/* This should be overridden by the engine subclass for each datatype.
Implementation should share the data node identified by guid,
and all its children, if any, with the user identified by username. */
return;
},
// FIXME: EEK bookmarks specific
_createShare: function Engine__createShare(id, title) {
let bms = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
let ans = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService);
let root;
let a = ans.getItemsWithAnnotation("weave/mounted-shares-folder", {});
if (a.length == 1)
root = a[0];
if (!root) {
root = bms.createFolder(bms.toolbarFolder, "Shared Folders",
bms.DEFAULT_INDEX);
ans.setItemAnnotation(root, "weave/mounted-shares-folder", true, 0,
ans.EXPIRE_NEVER);
}
let item;
a = ans.getItemsWithAnnotation("weave/mounted-share-id", {});
for (let i = 0; i < a.length; i++) {
if (ans.getItemAnnotation(a[i], "weave/mounted-share-id") == id) {
item = a[i];
break;
}
}
if (!item) {
let newId = bms.createFolder(root, title, bms.DEFAULT_INDEX);
ans.setItemAnnotation(newId, "weave/mounted-share-id", id, 0,
ans.EXPIRE_NEVER);
}
},
// TODO need a "stop sharing" function.
sync: function Engine_sync(onComplete) {
return this._sync.async(this, onComplete);
},
share: function Engine_share(onComplete, username) {
return this._share.async(this, onComplete, username);
share: function Engine_share(onComplete, guid, username) {
return this._share.async(this, onComplete, guid, username);
},
resetServer: function Engine_resetServer(onComplete) {

Просмотреть файл

@ -63,6 +63,108 @@ BookmarksEngine.prototype = {
}
},
// TODO modify this as neccessary since I just moved it from the engine
// superclass into BookmarkEngine.
_share: function BookmarkEngine__share(guid, username) {
let self = yield;
let prefix = DAV.defaultPrefix;
this._log.debug("Sharing bookmarks with " + username);
this._getSymKey.async(this, self.cb);
yield;
// copied from getSymKey
DAV.GET(this.keysFile, self.cb);
let ret = yield;
Utils.ensureStatus(ret.status, "Could not get keys file.");
let keys = this._json.decode(ret.responseText);
// get the other user's pubkey
let serverURL = Utils.prefs.getCharPref("serverURL");
try {
DAV.defaultPrefix = "user/" + username + "/";
DAV.GET("public/pubkey", self.cb);
ret = yield;
}
catch (e) { throw e; }
finally { DAV.defaultPrefix = prefix; }
Utils.ensureStatus(ret.status, "Could not get public key for " + username);
let id = new Identity();
id.pubkey = ret.responseText;
// now encrypt the symkey with their pubkey and upload the new keyring
Crypto.RSAencrypt.async(Crypto, self.cb, this._engineId.password, id);
let enckey = yield;
if (!enckey)
throw "Could not encrypt symmetric encryption key";
keys.ring[username] = enckey;
DAV.PUT(this.keysFile, this._json.encode(keys), self.cb);
ret = yield;
Utils.ensureStatus(ret.status, "Could not upload keyring file.");
this._createShare(guid, username, username);
this._log.debug("All done sharing!");
self.done(true);
},
_createShare: function BookmarkEngine__createShare(guid, id, title) {
/* the bookmark item identified by guid, and the whole subtree under it,
must be copied out from the main file into a separate file which is
put into the new directory and encrypted with the key in the keychain.
id is the userid of the user we're sharing with.
*/
/* TODO it appears that this just creates the folder and puts the
annotation on it; the mechanics of sharing must be done when syncing?
Or has that not been done yet at all?
Do we have to create a new Mount?
*/
let bms = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
let ans = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService);
let root;
let a = ans.getItemsWithAnnotation("weave/mounted-shares-folder", {});
if (a.length == 1)
root = a[0];
if (!root) {
root = bms.createFolder(bms.toolbarFolder, "Shared Folders",
bms.DEFAULT_INDEX);
ans.setItemAnnotation(root, "weave/mounted-shares-folder", true, 0,
ans.EXPIRE_NEVER);
}
let item;
a = ans.getItemsWithAnnotation("weave/mounted-share-id", {});
for (let i = 0; i < a.length; i++) {
if (ans.getItemAnnotation(a[i], "weave/mounted-share-id") == id) {
item = a[i];
break;
}
}
if (!item) {
let newId = bms.createFolder(root, title, bms.DEFAULT_INDEX);
ans.setItemAnnotation(newId, "weave/mounted-share-id", id, 0,
ans.EXPIRE_NEVER);
}
},
_stopShare: function BookmarkeEngine__stopShare( guid, username) {
// TODO implement this; also give a way to call it from outside
// the service.
},
_syncOneMount: function BmkEngine__syncOneMount(mountData) {
let self = yield;
let user = mountData.userid;
@ -70,10 +172,11 @@ BookmarksEngine.prototype = {
let serverURL = Utils.prefs.getCharPref("serverURL");
let snap = new SnapshotStore();
// TODO this is obviously what we want.
this._log.debug("Syncing shared folder from user " + user);
try {
DAV.defaultPrefix = "user/" + user + "/"; //FIXME: very ugly!
DAV.defaultPrefix = "user/" + user + "/";
this._getSymKey.async(this, self.cb);
yield;
@ -354,6 +457,9 @@ BookmarksStore.prototype = {
command.data.index);
break;
case "mounted-share":
// TODO this is to create the shared-items folder on another machine
// to duplicate the one that's on the first machine; we don't need that
// anymore. OR is it to create the folder on the sharee's computer?
this._log.debug(" -> creating share mountpoint \"" + command.data.title + "\"");
newId = this._bms.createFolder(parentId,
command.data.title,
@ -518,6 +624,8 @@ BookmarksStore.prototype = {
} else if (this._ans.itemHasAnnotation(node.itemId,
"weave/mounted-share-id")) {
/* TODO this is for wrapping the special shared folder created by
the old-style share command. */
item.type = "mounted-share";
item.title = node.title;
item.mountId = this._ans.getItemAnnotation(node.itemId,
@ -608,6 +716,7 @@ BookmarksStore.prototype = {
// remove any share mountpoints
for (let guid in ret.snapshot) {
// TODO decide what to do with this...
if (ret.snapshot[guid].type == "mounted-share")
delete ret.snapshot[guid];
}

Просмотреть файл

@ -561,16 +561,37 @@ WeaveSvc.prototype = {
}
},
shareBookmarks: function WeaveSync_shareBookmarks(onComplete, username) {
this._lock(this._notify("share-bookmarks",
this._shareBookmarks,
shareData: function WeaveSync_shareData(dataType,
onComplete,
guid,
username) {
/* Shares data of the specified datatype (which must correspond to
one of the registered engines) with the user specified by username.
The data node indicated by guid will be shared, along with all its
children, if it has any. onComplete is a function that will be called
when sharing is done; it takes an argument that will be true or false
to indicate whether sharing succeeded or failed.
Implementation, as well as the interpretation of what 'guid' means,
is left up to the engine for the specific dataType. */
// TODO who is listening for the share-bookmarks message?
let messageName = "share-" + dataType;
// so for instance, if dataType is "bookmarks" then a message
// "share-bookmarks" will be sent out to any observers who are listening
// for it.
this._lock(this._notify(messageName,
this._shareData,
dataType,
guid,
username)).async(this, onComplete);
},
_shareBookmarks: function WeaveSync__shareBookmarks(username) {
_shareBookmarks: function WeaveSync__shareBookmarks(dataType,
guid,
username) {
let self = yield;
if (Engines.get("bookmarks").enabled)
if (Engines.get(dataType).enabled)
return;
Engines.get("bookmarks").share(self.cb, username);
Engines.get(dataType).share(self.cb, guid, username);
let ret = yield;
self.done(ret);
}