diff --git a/extensions/sroaming/Makefile.in b/extensions/sroaming/Makefile.in new file mode 100644 index 00000000000..215af261efa --- /dev/null +++ b/extensions/sroaming/Makefile.in @@ -0,0 +1,47 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Ben Bucksch of +# Beonex . +# Portions created by the Initial Developer are Copyright (C) 2003-2004 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH=../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS=src + +include $(topsrcdir)/config/rules.mk diff --git a/extensions/sroaming/README.txt b/extensions/sroaming/README.txt new file mode 100644 index 00000000000..fb66df7f6c9 --- /dev/null +++ b/extensions/sroaming/README.txt @@ -0,0 +1,43 @@ +This implements 4.x-like roaming. + +To make the implementation vastly more simple, it has been decided that no +syncing during the session happens. The design will not allow that either +(at most sync in certain intervalls). A full-blown dynamic implementation +that immediately update the server when a data change occured requires the +cooperation of the data providers (bookmarks, prefs etc.) and is thus a huge +change that I will leave to somebody else to implement independant of this +roaming support here. alecf made such proposals a longer time ago on +n.p.m.prefs, they sounded very interesting, but unfortunately, nobody +implemented them so far. + +When the users selected a profile, we will check, if it's a roaming profile +and where the data lies. If necessary, we will contact the server and +download the data as files. We will overwrite local profile files with +the downloaded ones. Then, the profile works as if it were fully local. +When the user then logs out (shuts down Mozilla or switches to another +profile), we upload the local files, overwriting those on the server. + +Following Conrad Carlen's advise, I do not hook up using nsIProfileChangeStatus, +but in nsProfile directly. That just calls |nsISessionRoaming|. +Its implementation uses various protocol handlers like |mozSRoamingCopy| to +do the upload/download. These in turn may use generic protocol handlers like +the netwerk HTTP protocol to do that. + +Also following Conrad's advise, I do not store the roaming prefs in the prefs +system (prefs.js etc.), because that it not yet initialized when I need the +data (of course - prefs.js, user.js etc. might get changed by us), but in +the Mozilla application registry. For the structure, see the comment at +the top of prefs/top.js. + + +Overview of implementation: +- transfer.js (the Transfer class and support classes) contains the + non-GUI logic to transfer files and track the progress and success. +- progressDialog.* shows the progress to the user (and also works as interface + to the C++ code) +- conflictCheck.js is the "controller", controls the overall execution flow. + It determines what has to be done (which files to transfer when etc.), + including the conflict resolution logic, and kicks off the transfers. + There is a long comment at the top describing the implementation. +- conflictResolution.* is a dialog to ask the user when we don't know which + version of a file to use. diff --git a/extensions/sroaming/jar.mn b/extensions/sroaming/jar.mn new file mode 100644 index 00000000000..3660c3c3c50 --- /dev/null +++ b/extensions/sroaming/jar.mn @@ -0,0 +1,36 @@ +sroaming.jar: + content/sroaming/contents.rdf (resources/content/contents.rdf) + content/sroaming/transfer/transfer.js (resources/content/transfer/transfer.js) + content/sroaming/transfer/utility.js (resources/content/transfer/utility.js) + content/sroaming/transfer/progressDialog.xul (resources/content/transfer/progressDialog.xul) + content/sroaming/transfer/progressDialog.js (resources/content/transfer/progressDialog.js) + content/sroaming/transfer/conflictResolve.xul (resources/content/transfer/conflictResolve.xul) + content/sroaming/transfer/conflictResolve.js (resources/content/transfer/conflictResolve.js) + content/sroaming/transfer/conflictCheck.js (resources/content/transfer/conflictCheck.js) + content/sroaming/prefs/all.js (resources/content/prefs/all.js) + content/sroaming/prefs/top.xul (resources/content/prefs/top.xul) + content/sroaming/prefs/top.js (resources/content/prefs/top.js) + content/sroaming/prefs/files.xul (resources/content/prefs/files.xul) + content/sroaming/prefs/files.js (resources/content/prefs/files.js) + content/sroaming/prefs/prefsOverlay.xul (resources/content/prefs/prefsOverlay.xul) + content/sroaming/prefs/firefox.xul (resources/content/prefs/firefox.xul) + content/sroaming/prefs/firefox.js (resources/content/prefs/firefox.js) + locale/en-US/sroaming/contents.rdf (resources/locale/en-US/contents.rdf) + locale/en-US/sroaming/transfer.properties (resources/locale/en-US/transfer.properties) + locale/en-US/sroaming/progressDialog.dtd (resources/locale/en-US/progressDialog.dtd) + locale/en-US/sroaming/conflictResolve.dtd (resources/locale/en-US/conflictResolve.dtd) + locale/en-US/sroaming/filedescr.properties (resources/locale/en-US/filedescr.properties) + locale/en-US/sroaming/prefs.dtd (resources/locale/en-US/prefs.dtd) + locale/en-US/sroaming/prefs.properties (resources/locale/en-US/prefs.properties) + skin/modern/sroaming/contents.rdf (resources/skin/modern/contents.rdf) + skin/modern/sroaming/progressDialog.css (resources/skin/modern/progressDialog.css) + skin/modern/sroaming/pending-small.gif (resources/skin/modern/pending-small.gif) + skin/modern/sroaming/busy-small.gif (resources/skin/modern/busy-small.gif) + skin/modern/sroaming/done-small.gif (resources/skin/modern/done-small.gif) + skin/modern/sroaming/failed-small.gif (resources/skin/modern/failed-small.gif) + skin/classic/sroaming/contents.rdf (resources/skin/classic/contents.rdf) + skin/classic/sroaming/progressDialog.css (resources/skin/classic/progressDialog.css) + skin/classic/sroaming/pending-small.gif (resources/skin/classic/pending-small.gif) + skin/classic/sroaming/busy-small.gif (resources/skin/classic/busy-small.gif) + skin/classic/sroaming/done-small.gif (resources/skin/classic/done-small.gif) + skin/classic/sroaming/failed-small.gif (resources/skin/classic/failed-small.gif) diff --git a/extensions/sroaming/plan.txt b/extensions/sroaming/plan.txt new file mode 100644 index 00000000000..05b4ab970eb --- /dev/null +++ b/extensions/sroaming/plan.txt @@ -0,0 +1,58 @@ +todo: +- firefox: doesn't start up after the roaming dialog closed - bug 209880 + +don't care (for now): +- conflict + - some files failed, see XXX - update: eh, where was that? +- world gone + - problem: ddump, xpcom not defined after files done and dialog closed + solution: close dialog only when done with processing. + workaround: gTimeout + - problem: cancel by user in progress dialog: xpconnect errors + solution: prevent dialog closure (even if cancel pressed) until we're done. +- listing progressmeter doesn't work +- If one file is missing on both server and client and we didn't upload, but + there is no conflict, we still show one. That's due to that commented-out + check in compareFiles(). Mind the warning there and fix it. +- no preselection in conflict dialog +- not using statusText for FTP errors (reason 'file not readable' in this case) + +Enhance +- better error dialog +- protocols + - HTTPS + - LDAP (already done by Sun?) + - IMAP +- password encrypt? +- no upload at switch profile + +roaming urls + + + Mind the number of slashes. + Servers used: wu-FTPd and Apache with mod_roaming. + + +Feedback +- why do I need to implement nsIDocShellTreeItem for a http xml file *download*? +- onStopRequest (e.g. Request: http://ben:pgpben@http.server.bucksch.org/roaming/ben/listing.xml, StatusCode: NS_OK, HTTPResponse 200) called *before* the file finished. ftp and http: onStopRequest *before* onStatus(SENDING_TO), but only for the first file + +clipboard + +undefined.message=Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIURI.password] +undefined.result=2147500037 +undefined.name=NS_ERROR_FAILURE +undefined.filename=chrome://sroaming/content/transfer/transfer.js +undefined.lineNumber=225 +undefined.columnNumber=4294967295 + +WARNING: NS_ENSURE_TRUE(!aQualifiedName.IsEmpty()) failed, file ../../../../mozilla/content/base/src/nsNodeInfoManager.cpp, line 287 + +[4] +onStatus: + Request: ftp://... + StatusCode: NET_STATUS_SENDING_TO + StatusArg: ftp.server.bucksch.org +request to change listing.xml from done (NS_OK) to busy (NET_STATUS_SENDING_TO) +SetProgressStatus(1): listing.xml, busy, NET_STATUS_SENDING_TO + Setting listing.xml from done to busy diff --git a/extensions/sroaming/resources/content/contents.rdf b/extensions/sroaming/resources/content/contents.rdf new file mode 100644 index 00000000000..43ad0ebb67e --- /dev/null +++ b/extensions/sroaming/resources/content/contents.rdf @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + chrome://sroaming/content/prefs/prefsOverlay.xul + + diff --git a/extensions/sroaming/resources/content/prefs/all.js b/extensions/sroaming/resources/content/prefs/all.js index 9f9a0f99cd6..5634afbdfb3 100644 --- a/extensions/sroaming/resources/content/prefs/all.js +++ b/extensions/sroaming/resources/content/prefs/all.js @@ -15,9 +15,9 @@ * The Original Code is Mozilla Roaming code. * * The Initial Developer of the Original Code is - * Ben Bucksch of - * Beonex - * Portions created by the Initial Developer are Copyright (C) 2002-2003 + * Ben Bucksch of + * Beonex + * Portions created by the Initial Developer are Copyright (C) 2002-2004 * the Initial Developer. All Rights Reserved. * * Contributor(s): @@ -395,11 +395,8 @@ RoamingPrefs.prototype = { try { - var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"] - .getService() - .QueryInterface(Components.interfaces.nsIStringBundleService) - .createBundle("chrome://sroaming/locale/prefs.properties"); - var dialogTitle = bundle.GetStringFromName("RoamingErrorTitle"); + var bundle = document.getElementById("bundle_roaming_prefs"); + var dialogTitle = bundle.getString("RoamingErrorTitle"); var text = dialogTitle + "\n"; if (val) text += bundle.formatStringFromName(prop, [val], 1); diff --git a/extensions/sroaming/resources/content/prefs/files.js b/extensions/sroaming/resources/content/prefs/files.js new file mode 100644 index 00000000000..57f17264ab7 --- /dev/null +++ b/extensions/sroaming/resources/content/prefs/files.js @@ -0,0 +1,195 @@ +/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Roaming code. + * + * The Initial Developer of the Original Code is + * Ben Bucksch of + * Beonex + * Portions created by the Initial Developer are Copyright (C) 2002-2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* See all.js */ + +var _elementIDs = []; // no prefs (nsIPrefBranch) needed, see above +var addedHandler = false; // see top.js + +function Load() +{ + parent.initPanel('chrome://sroaming/content/prefs/files.xul'); + + FileLabels(); + SetFiles(); + // dataManager.pageData doesn't work, because it needs to work on both panes + if (!parent.roaming) + parent.roaming = new RoamingPrefs(); + DataToUI(); + + if (parent != null && "firefox" in parent) + { + if (!parent.firefox.filesLoad) + parent.firefox.filesLoad = Load; + if (!parent.firefox.filesUnload) + parent.firefox.filesUnload = Unload; + } + + if (!addedHandler) + { + addedHandler = true; + parent.hPrefWindow.registerOKCallbackFunc(function() + { + UIToData(); + parent.roaming.okClicked(); + }); + } +} + + +// Logic + +// some files have a non-static name. set these filenames here. +function SetFiles() +{ + var prefs = Components.classes["@mozilla.org/preferences;1"] + .getService(Components.interfaces.nsIPrefBranch); + try + { + SetFile("filePassword", prefs.getCharPref("signon.SignonFileName")); + SetFile("fileWallet", prefs.getCharPref("wallet.SchemaValueFileName")); + } catch (e) {} + + // disable the nodes which are still invalid + var children = E("filesList").childNodes; + for (var i = 0; i < children.length; i++) + { + var checkbox = children[i]; + if (!("getAttribute" in checkbox) || + checkbox.getAttribute("type") != "checkbox") + continue; + if (checkbox.getAttribute("filename") == "") + checkbox.disabled = true; + } +} + +function SetFile(elementID, filename) +{ + var listitem = document.getElementById(elementID); + listitem.setAttribute("filename", filename); +} + + +// UI + +// write data to widgets +function DataToUI() +{ + var data = parent.roaming; + var filesList = E("filesList"); + + EnableTree(data.Enabled, filesList); + + // first, disable all by default + var children = filesList.childNodes; + for (var i = 0, l = children.length; i < l; i++) + { + var checkbox = children[i]; + if (!("getAttribute" in checkbox) || + checkbox.getAttribute("type") != "checkbox") + // Somebody adds unwanted nodes as children to listbox :-( + continue; + checkbox.checked = false; + } + // then check for each file in the list, if it's in the checkboxes. + // enabled it, if so, otherwise create and enable it (for files added by + // the user). + for (i = 0, l = data.Files.length; i < l; i++) + { + var file = data.Files[i]; + var found = false; + for (var i2 = 0, l2 = children.length; i2 < l2; i2++) + { + var checkbox = children[i2]; + if ("getAttribute" in checkbox + && checkbox.getAttribute("type") == "checkbox" + // Somebody adds unwanted nodes as children to listbox :-( + && checkbox.getAttribute("filename") == file) + { + checkbox.checked = true; + found = true; + } + } + if (!found) + { + var li = document.createElement("listitem"); + if (li) + { + li.setAttribute("type", "checkbox"); + li.setAttribute("id", file); + li.setAttribute("filename", file); + li.setAttribute("label", file); + li.setAttribute("checked", "true"); + filesList.appendChild(li); + } + } + } +} + +// write widget content to data +function UIToData() +{ + var data = parent.roaming; + data.Files = new Array(); // clear list + var children = E("filesList").childNodes; + for (var i = 0; i < children.length; i++) + { + var checkbox = children.item(i); + if (checkbox.checked) + data.Files.push(checkbox.getAttribute("filename")); + } + data.changed = true; // excessive +} + +/* read human-readable names for profile files from filedescr.properties + and use them as labels */ +function FileLabels() +{ + var children = E("filesList").childNodes; + for (var i = 0; i < children.length; i++) + { + var checkbox = children[i]; + if (!("getAttribute" in checkbox) || + checkbox.getAttribute("type") != "checkbox") + continue; + + checkbox.setAttribute("label", + GetFileDescription(checkbox.getAttribute("filename"), + checkbox.getAttribute("id"))); + } +} diff --git a/extensions/sroaming/resources/content/prefs/files.xul b/extensions/sroaming/resources/content/prefs/files.xul new file mode 100644 index 00000000000..d5d3e0e5a63 --- /dev/null +++ b/extensions/sroaming/resources/content/prefs/files.xul @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + +