mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 340949: error handling, refresh, startup opt, search for calendars, alarm defaults, minor cleanup
This commit is contained in:
parent
2e43231ce7
commit
1e1cf66de1
@ -37,9 +37,9 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function createWcapCalendar( calId, session )
|
||||
function createWcapCalendar( calId, session, /*optional*/calProps )
|
||||
{
|
||||
var cal = new calWcapCalendar( calId, session );
|
||||
var cal = new calWcapCalendar( calId, session, calProps );
|
||||
switch (CACHE) {
|
||||
case "memory":
|
||||
case "storage":
|
||||
@ -52,10 +52,11 @@ function createWcapCalendar( calId, session )
|
||||
return cal;
|
||||
}
|
||||
|
||||
function calWcapCalendar( calId, session ) {
|
||||
function calWcapCalendar( calId, session, /*optional*/calProps ) {
|
||||
this.wrappedJSObject = this;
|
||||
this.m_calId = calId;
|
||||
this.m_session = session;
|
||||
this.m_calProps = calProps;
|
||||
this.m_bSuppressAlarms = SUPPRESS_ALARMS;
|
||||
|
||||
// init queued calls:
|
||||
@ -71,6 +72,14 @@ function calWcapCalendar( calId, session ) {
|
||||
this, this.getItems_queued);
|
||||
this.syncChangesTo = makeQueuedCall(this.session.asyncQueue,
|
||||
this, this.syncChangesTo_queued);
|
||||
|
||||
if (LOG_LEVEL > 0 && this.m_calProps) {
|
||||
if (this.m_calId != this.getCalendarProperties(
|
||||
"X-NSCP-CALPROPS-RELATIVE_CALID", {})[0]) {
|
||||
this.notifyError("calId mismatch: " + this.m_calId +
|
||||
" vs. " + ar[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
calWcapCalendar.prototype = {
|
||||
m_ifaces: [ Components.interfaces.calIWcapCalendar,
|
||||
@ -182,10 +191,14 @@ calWcapCalendar.prototype = {
|
||||
|
||||
// calICalendar:
|
||||
get name() {
|
||||
return getCalendarManager().getCalendarPref( this, "NAME" );
|
||||
// xxx todo: mismatch
|
||||
if (this.session.isLoggedIn)
|
||||
return this.displayName;
|
||||
else
|
||||
return getCalendarManager().getCalendarPref(this, "NAME");
|
||||
},
|
||||
set name( name ) {
|
||||
getCalendarManager().setCalendarPref( this, "NAME", name );
|
||||
getCalendarManager().setCalendarPref(this, "NAME", name);
|
||||
},
|
||||
|
||||
get type() { return "wcap"; },
|
||||
@ -216,12 +229,29 @@ calWcapCalendar.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// xxx todo: will potentially vanish from calICalendar:
|
||||
get uri() { return this.session.uri; },
|
||||
set uri( thatUri ) {
|
||||
this.session.uri = thatUri;
|
||||
resetCalProps:
|
||||
function()
|
||||
{
|
||||
this.m_calProps = null;
|
||||
},
|
||||
|
||||
get uri() {
|
||||
if (this.m_calId) {
|
||||
var ret = this.session.uri.clone();
|
||||
if (LOG_LEVEL == 42) { // xxx todo: interims hack for tbe
|
||||
ret.path += ("?calid=" + encodeURIComponent(this.m_calId));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return this.session.uri;
|
||||
},
|
||||
set uri( thatUri ) {
|
||||
this.session.uri = thatUri;
|
||||
// uri changes, but calId stays constant:
|
||||
this.resetCalProps();
|
||||
},
|
||||
|
||||
notifyObservers:
|
||||
function( func, args ) {
|
||||
this.session.notifyObservers( func, args );
|
||||
@ -258,10 +288,14 @@ calWcapCalendar.prototype = {
|
||||
this.m_bSuppressAlarms = bSuppressAlarms;
|
||||
},
|
||||
|
||||
get canRefresh() { return false; },
|
||||
refresh: function() {
|
||||
// no-op
|
||||
this.log("refresh()");
|
||||
get canRefresh() { return true; },
|
||||
refresh:
|
||||
function() {
|
||||
// refresh session ticket immedidately, not queued:
|
||||
this.log("refresh!");
|
||||
this.session.logout();
|
||||
// logout sufficient, there is an upcoming getItems() call:
|
||||
// this.session.login();
|
||||
},
|
||||
|
||||
getCommandUrl:
|
||||
@ -275,7 +309,11 @@ calWcapCalendar.prototype = {
|
||||
// calIWcapCalendar:
|
||||
|
||||
m_session: null,
|
||||
get session() { return this.m_session; },
|
||||
get session() {
|
||||
if (this.m_session)
|
||||
return this.m_session;
|
||||
throw new Components.Exception("Disconnected from session!");
|
||||
},
|
||||
|
||||
// xxx todo: for now to make subscriptions context menu work,
|
||||
// will vanish when UI has been revised and every subscribed
|
||||
@ -286,7 +324,7 @@ calWcapCalendar.prototype = {
|
||||
get calId() {
|
||||
if (this.m_calId)
|
||||
return this.m_calId;
|
||||
this.session.assureLoggedIn();
|
||||
// this.session.assureLoggedIn();
|
||||
return this.session.defaultCalId;
|
||||
},
|
||||
set calId( id ) {
|
||||
@ -298,7 +336,7 @@ calWcapCalendar.prototype = {
|
||||
|
||||
get ownerId() {
|
||||
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-PRIMARY-OWNER",{});
|
||||
if (ar.length < 1 || ar[0].length == 0) {
|
||||
if (ar.length == 0) {
|
||||
var calId = this.calId;
|
||||
this.logError(
|
||||
"cannot determine primary owner of calendar " + calId );
|
||||
@ -313,7 +351,7 @@ calWcapCalendar.prototype = {
|
||||
|
||||
get description() {
|
||||
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-DESCRIPTION", {});
|
||||
if (ar.length < 1 || ar[0].length == 0) {
|
||||
if (ar.length == 0) {
|
||||
// fallback to display name:
|
||||
return this.displayName;
|
||||
}
|
||||
@ -322,11 +360,11 @@ calWcapCalendar.prototype = {
|
||||
|
||||
get displayName() {
|
||||
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-NAME", {});
|
||||
if (ar.length < 1 || ar[0].length == 0) {
|
||||
if (ar.length == 0) {
|
||||
// fallback to common name:
|
||||
ar = this.getCalendarProperties(
|
||||
"X-S1CS-CALPROPS-COMMON-NAME", {});
|
||||
if (ar.length < 1) {
|
||||
if (ar.length == 0) {
|
||||
return this.calId;
|
||||
}
|
||||
}
|
||||
@ -340,14 +378,8 @@ calWcapCalendar.prototype = {
|
||||
getCalendarProperties:
|
||||
function( propName, out_count )
|
||||
{
|
||||
var ret = [];
|
||||
var calProps = this.getCalProps_(false /* !async: waits for response*/);
|
||||
if (calProps != null) {
|
||||
var nodeList = calProps.getElementsByTagName(propName);
|
||||
for ( var i = 0; i < nodeList.length; ++i ) {
|
||||
ret.push( trimString(nodeList.item(i).textContent) );
|
||||
}
|
||||
}
|
||||
var ret = filterCalProps(
|
||||
propName, this.getCalProps_(false /* !async: waits for response*/));
|
||||
out_count.value = ret.length;
|
||||
return ret;
|
||||
},
|
||||
@ -355,7 +387,7 @@ calWcapCalendar.prototype = {
|
||||
getCalProps_:
|
||||
function( bAsync, bRefresh )
|
||||
{
|
||||
this.session.assureLoggedIn();
|
||||
// this.session.assureLoggedIn();
|
||||
try {
|
||||
if (bRefresh || !this.m_calProps) {
|
||||
var url = this.getCommandUrl( "get_calprops" );
|
||||
@ -369,10 +401,10 @@ calWcapCalendar.prototype = {
|
||||
this_.m_calProps = xml;
|
||||
}
|
||||
catch (exc) {
|
||||
// patch to read-only here, because error notification
|
||||
// call the readOnly attribute, thus we would run into
|
||||
// endless recursion here:
|
||||
this_.m_bReadOnly = true;
|
||||
// // patch to read-only here, because error notification
|
||||
// // call the readOnly attribute, thus we would run into
|
||||
// // endless recursion here:
|
||||
// this_.m_bReadOnly = true;
|
||||
// just logging here, because user may have dangling
|
||||
// users referred in his subscription list:
|
||||
this_.logError( exc );
|
||||
@ -387,9 +419,9 @@ calWcapCalendar.prototype = {
|
||||
}
|
||||
}
|
||||
catch (exc) {
|
||||
// patch to read-only here, because error notification call the
|
||||
// readOnly attribute, thus we would run into endless recursion here
|
||||
this.m_bReadOnly = true;
|
||||
// // patch to read-only here, because error notification call the
|
||||
// // readOnly attribute, thus we would run into endless recursion here
|
||||
// this.m_bReadOnly = true;
|
||||
this.logError( exc );
|
||||
if (!bAsync)
|
||||
throw exc;
|
||||
@ -399,8 +431,9 @@ calWcapCalendar.prototype = {
|
||||
|
||||
get defaultTimezone() {
|
||||
var tzid = this.getCalendarProperties("X-NSCP-CALPROPS-TZID", {});
|
||||
if (tzid.length < 1 || tzid[0].length == 0) {
|
||||
this.logError( "cannot get X-NSCP-CALPROPS-TZID!" );
|
||||
if (tzid.length == 0) {
|
||||
this.logError("cannot get X-NSCP-CALPROPS-TZID!",
|
||||
"defaultTimezone");
|
||||
return "UTC"; // fallback
|
||||
}
|
||||
return tzid[0];
|
||||
|
@ -437,40 +437,20 @@ calWcapCalendar.prototype.storeItem = function( item, oldItem, receiverFunc )
|
||||
} // else only dtend is set
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// var ar = this.session.getUserPreferences(
|
||||
// "X-NSCP-WCAP-PREF-ceDefaultAlarmStart", {});
|
||||
// if (ar.length > 0 && ar[0].length > 0) {
|
||||
// // workarounding cs duration bug, missing "T":
|
||||
// var dur = ar[0].replace(/(^P)(\d+[HMS]$)/, "$1T$2");
|
||||
// alarmStart = new CalDuration();
|
||||
// alarmStart.icalString = dur;
|
||||
// alarmStart.isNegative = !alarmStart.isNegative;
|
||||
// this.log( "setting default alarm start: " + alarmStart.icalString );
|
||||
// }
|
||||
// }
|
||||
if (alarmStart) {
|
||||
// minimal alarm server support: Alarms are currently off by default,
|
||||
// so let server at least send reminder eMails...
|
||||
var emails = "";
|
||||
if (item.hasProperty("alarmEmailAddress"))
|
||||
emails = encodeURIComponent(item.getProperty("alarmEmailAddress"));
|
||||
else {
|
||||
var ar = this.session.getUserPreferences(
|
||||
"X-NSCP-WCAP-PREF-ceDefaultAlarmEmail", {});
|
||||
if (ar.length > 0 && ar[0].length > 0) {
|
||||
for each ( var i in ar ) {
|
||||
var ars = i.split(/[;,]/);
|
||||
for each ( var j in ars ) {
|
||||
j = trimString(j);
|
||||
if (j.length > 0) {
|
||||
if (emails.length > 0)
|
||||
emails += ";";
|
||||
emails += encodeURIComponent(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// minimal alarm server support:
|
||||
// Alarms are currently off by default,
|
||||
// so let server at least send reminder eMails...
|
||||
this.session.getDefaultAlarmEmails({}).forEach(
|
||||
function(email) {
|
||||
if (emails.length > 0)
|
||||
emails += ";";
|
||||
emails += encodeURIComponent(email);
|
||||
} );
|
||||
}
|
||||
url += ("&alarmStart=" + alarmStart.icalString);
|
||||
url += ("&alarmEmails=" + emails);
|
||||
|
@ -254,14 +254,10 @@ var calWcapCalendarModule = { // nsIModule:
|
||||
return { // nsIFactory:
|
||||
lockFactory: function( lock ) {},
|
||||
createInstance: function( outer, iid ) {
|
||||
if (outer != null)
|
||||
if (outer)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
var session = new calWcapSession();
|
||||
var cal = createWcapCalendar(
|
||||
null /* calId: null indicates default calendar */,
|
||||
session );
|
||||
session.defaultCalendar = cal;
|
||||
return cal.QueryInterface( iid );
|
||||
return session.defaultCalendar.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -205,7 +205,7 @@ function issueSyncRequest( url, receiverFunc, bLogging )
|
||||
url, "" /* charset */, null /* baseURI */ );
|
||||
channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
|
||||
var stream = channel.open();
|
||||
var stream = channel.open();
|
||||
var status = channel.status;
|
||||
if (status == Components.results.NS_OK) {
|
||||
var charset = channel.contentCharset;
|
||||
|
@ -49,8 +49,10 @@ function calWcapSession() {
|
||||
this.m_calPropsTimer = new Timer();
|
||||
|
||||
// init queued calls:
|
||||
this.getFreeBusyTimes = makeQueuedCall(this.asyncQueue,
|
||||
this, this.getFreeBusyTimes_queued);
|
||||
this.getFreeBusyTimes = makeQueuedCall(
|
||||
this.asyncQueue, this, this.getFreeBusyTimes_queued);
|
||||
this.searchForCalendars = makeQueuedCall(
|
||||
this.asyncQueue, this, this.searchForCalendars_queued);
|
||||
|
||||
// listen for shutdown, being logged out:
|
||||
// network:offline-about-to-go-offline will be fired for
|
||||
@ -305,7 +307,7 @@ calWcapSession.prototype = {
|
||||
try {
|
||||
this.m_sessionId = null;
|
||||
if (timedOutSessionId) {
|
||||
this.log( "session timeout; prompting to reconnect." );
|
||||
this.log( "prompting to reconnect.", "session timeout" );
|
||||
var prompt = getWindowWatcher().getNewPrompter(null);
|
||||
var bundle = getWcapBundle();
|
||||
if (!prompt.confirm(
|
||||
@ -324,7 +326,7 @@ calWcapSession.prototype = {
|
||||
|
||||
var sessionUri = this.uri.clone();
|
||||
sessionUri.userPass = "";
|
||||
if (sessionUri.scheme.toLowerCase() != "https" &&
|
||||
if (!sessionUri.schemeIs("https") &&
|
||||
sessionUri.port == -1 /* no port specified */)
|
||||
{
|
||||
// silently probe for https support:
|
||||
@ -356,11 +358,9 @@ calWcapSession.prototype = {
|
||||
if (!timedOutSessionId) // timezones don't change that frequently
|
||||
this.getSupportedTimezones(true /* refresh */);
|
||||
|
||||
// invalidate calprops of all calendars:
|
||||
var cals = this.getSubscribedCalendars({});
|
||||
for each ( cal in cals ) {
|
||||
cal.m_calProps = null;
|
||||
}
|
||||
// reset calprops of all subscribed calendars before:
|
||||
this.getSubscribedCalendars({}).forEach(
|
||||
function(cal) { cal.resetCalProps(); } );
|
||||
|
||||
this.m_calPropsTimer.initWithCallback(
|
||||
{ // nsITimerCallback:
|
||||
@ -369,10 +369,12 @@ calWcapSession.prototype = {
|
||||
notify: function(timer_) {
|
||||
var cals = this.m_session.getSubscribedCalendars({});
|
||||
var c = (cals.length - this.m_pos);
|
||||
if (c > 5)
|
||||
c = 5;
|
||||
while (c--)
|
||||
cals[this.m_pos++].getCalProps_(true /*async*/);
|
||||
if (c > 0) {
|
||||
if (c > 5)
|
||||
c = 5;
|
||||
while (c--)
|
||||
cals[this.m_pos++].getCalProps_(true /*async*/);
|
||||
}
|
||||
if (this.m_pos >= cals.length)
|
||||
timer_.cancel();
|
||||
}
|
||||
@ -392,7 +394,7 @@ calWcapSession.prototype = {
|
||||
assureSecureLogin:
|
||||
function( sessionUri )
|
||||
{
|
||||
if (sessionUri.scheme.toLowerCase() != "https" &&
|
||||
if (!sessionUri.schemeIs("https") &&
|
||||
!confirmInsecureLogin(sessionUri)) {
|
||||
this.log( "user rejected insecure login on " + sessionUri.spec );
|
||||
throw new Components.Exception(
|
||||
@ -725,14 +727,18 @@ calWcapSession.prototype = {
|
||||
login:
|
||||
function()
|
||||
{
|
||||
this.logout(); // assure being logged out
|
||||
this.getSessionId();
|
||||
this.log("login");
|
||||
this.getSessionId(); // does *not* assure that ticket is valid
|
||||
},
|
||||
|
||||
logout:
|
||||
function()
|
||||
{
|
||||
if (this.m_sessionId != null) {
|
||||
this.log("logout");
|
||||
this.m_calPropsTimer.cancel(); // stop any timed calprops getters
|
||||
this.asyncQueue.reset(); // stop any queued actions
|
||||
|
||||
if (this.m_sessionId) {
|
||||
this.log( "attempting to log out..." );
|
||||
// although io service's offline flag is already
|
||||
// set BEFORE notification (about to go offline, nsIOService.cpp).
|
||||
@ -751,6 +757,7 @@ calWcapSession.prototype = {
|
||||
}
|
||||
this.m_sessionId = null;
|
||||
}
|
||||
|
||||
this.m_sessionUri = null;
|
||||
this.m_userId = null;
|
||||
this.m_userPrefs = null; // reread prefs
|
||||
@ -764,38 +771,39 @@ calWcapSession.prototype = {
|
||||
return wcapErrorToString(rc);
|
||||
},
|
||||
|
||||
m_defaultCalendar: null,
|
||||
get defaultCalendar() {
|
||||
return this.getCalendarByCalId(null);
|
||||
},
|
||||
set defaultCalendar(cal) {
|
||||
this.m_defaultCalendar = cal;
|
||||
if (!this.m_defaultCalendar) {
|
||||
this.m_defaultCalendar = createWcapCalendar(
|
||||
null /* calId: null indicates default calendar */, this);
|
||||
}
|
||||
return this.m_defaultCalendar;
|
||||
},
|
||||
|
||||
m_defaultCalendar: null,
|
||||
m_calIdToCalendar: {},
|
||||
getCalendarByCalId:
|
||||
function( calId )
|
||||
getCalendarByCalId_:
|
||||
function( calId, bCreate )
|
||||
{
|
||||
var ret;
|
||||
// xxx todo: for now the default calendar (calId=null)
|
||||
// is separated (own instance) from subscribed calendars
|
||||
if (calId == null /*|| this.userId == calId*/) {
|
||||
if (this.m_defaultCalendar == null) {
|
||||
this.m_defaultCalendar = createWcapCalendar(
|
||||
null/*this.userId*/, this);
|
||||
}
|
||||
ret = this.m_defaultCalendar;
|
||||
var ret = null;
|
||||
if (!calId || (LOG_LEVEL == 42 && // xxx todo: temp tbe hack
|
||||
this.defaultCalId == calId)) {
|
||||
ret = this.defaultCalendar;
|
||||
}
|
||||
else {
|
||||
var key = encodeURIComponent(calId);
|
||||
ret = this.m_calIdToCalendar[key];
|
||||
if (!ret) {
|
||||
if (!ret && bCreate) {
|
||||
ret = createWcapCalendar(calId, this);
|
||||
this.m_calIdToCalendar[key] = ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getCalendarByCalId:
|
||||
function( calId )
|
||||
{
|
||||
return this.getCalendarByCalId_(calId, true/*bCreate*/);
|
||||
},
|
||||
|
||||
getCalendars:
|
||||
function( out_count, bGetOwnedCals )
|
||||
@ -830,21 +838,19 @@ calWcapSession.prototype = {
|
||||
},
|
||||
|
||||
createCalendar:
|
||||
function( calId, name, bAllowDoubleBooking, bSetCalProps, bAddToSubscribed )
|
||||
function( calId, name )
|
||||
{
|
||||
try {
|
||||
this.assureLoggedIn();
|
||||
var url = this.getCommandUrl( "createcalendar" );
|
||||
url += ("&allowdoublebook=" + (bAllowDoubleBooking ? "1" : "0"));
|
||||
url += ("&set_calprops=" + (bSetCalProps ? "1" : "0"));
|
||||
url += ("&subscribe=" + (bAddToSubscribed ? "1" : "0"));
|
||||
// this.assureLoggedIn();
|
||||
var url = this.getCommandUrl("createcalendar");
|
||||
url += "&allowdoublebook=1&set_calprops=1&subscribe=1";
|
||||
url += ("&calid=" + encodeURIComponent(calId));
|
||||
// xxx todo: name undocumented!
|
||||
url += ("&name=" + encodeURIComponent(name));
|
||||
// xxx todo: what about categories param???
|
||||
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
|
||||
this.issueSyncRequest(url + "&fmt-out=text%2Fxml", stringToXml);
|
||||
this.m_userPrefs = null; // reread prefs
|
||||
return this.getCalendarByCalId( this.userId + ":" + calId );
|
||||
return this.getCalendarByCalId(this.userId + ":" + calId);
|
||||
}
|
||||
catch (exc) {
|
||||
this.logError( exc );
|
||||
@ -853,39 +859,53 @@ calWcapSession.prototype = {
|
||||
},
|
||||
|
||||
deleteCalendar:
|
||||
function( calId, bRemoveFromSubscribed )
|
||||
function( cal )
|
||||
{
|
||||
try {
|
||||
this.assureLoggedIn();
|
||||
var url = this.getCommandUrl( "deletecalendar" );
|
||||
url += ("&unsubscribe=" + (bRemoveFromSubscribed ? "1" : "0"));
|
||||
// this.assureLoggedIn();
|
||||
var calId = cal.calId;
|
||||
var url = this.getCommandUrl("deletecalendar");
|
||||
url += ("&calid=" + encodeURIComponent(calId));
|
||||
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
|
||||
url += "&unsubscribe=1&fmt-out=text%2Fxml";
|
||||
this.issueSyncRequest(url, stringToXml);
|
||||
this.m_userPrefs = null; // reread prefs
|
||||
// xxx todo: delete here?
|
||||
this.m_calIdToCalendar[encodeURIComponent(calId)] = null;
|
||||
cal.readOnly = true;
|
||||
}
|
||||
catch (exc) {
|
||||
this.logError( exc );
|
||||
this.logError(exc);
|
||||
throw exc;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
modifyCalendarSubscriptions:
|
||||
function( calIds, bSubscribe )
|
||||
function( cals, bSubscribe )
|
||||
{
|
||||
try {
|
||||
this.assureLoggedIn();
|
||||
// this.assureLoggedIn();
|
||||
var url = this.getCommandUrl(
|
||||
bSubscribe ? "subscribe_calendars" : "unsubscribe_calendars" );
|
||||
var calId = "";
|
||||
for ( var i = 0; i < calIds.length; ++i ) {
|
||||
if (i > 0)
|
||||
for each ( var cal in cals ) {
|
||||
if (calId.length > 0)
|
||||
calId += ";";
|
||||
calId += encodeURIComponent(calIds[i]);
|
||||
calId += encodeURIComponent(cal.calId);
|
||||
}
|
||||
url += ("&calid=" + encodeURIComponent(calId));
|
||||
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
|
||||
url += ("&calid=" + calId);
|
||||
this.issueSyncRequest(url + "&fmt-out=text%2Fxml", stringToXml);
|
||||
this.m_userPrefs = null; // reread prefs
|
||||
for each ( cal in cals ) {
|
||||
if (bSubscribe) {
|
||||
this.m_calIdToCalendar[
|
||||
encodeURIComponent(cal.calId)] = cal;
|
||||
}
|
||||
else { // remove from cached instances
|
||||
// xxx todo: delete here?
|
||||
this.m_calIdToCalendar[
|
||||
encodeURIComponent(cal.calId)] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (exc) {
|
||||
this.logError( exc );
|
||||
@ -894,15 +914,15 @@ calWcapSession.prototype = {
|
||||
},
|
||||
|
||||
subscribeToCalendars:
|
||||
function( count, calIds )
|
||||
function( count, cals )
|
||||
{
|
||||
this.modifyCalendarSubscriptions( calIds, true );
|
||||
this.modifyCalendarSubscriptions(cals, true/*bSubscribe*/);
|
||||
},
|
||||
|
||||
unsubscribeFromCalendars:
|
||||
function( count, calIds )
|
||||
{
|
||||
this.modifyCalendarSubscriptions( calIds, false );
|
||||
this.modifyCalendarSubscriptions(cals, false/*!bSubscribe*/);
|
||||
},
|
||||
|
||||
m_userPrefs: null,
|
||||
@ -910,8 +930,8 @@ calWcapSession.prototype = {
|
||||
function( prefName, out_count )
|
||||
{
|
||||
try {
|
||||
if (this.m_userPrefs == null) {
|
||||
this.assureLoggedIn();
|
||||
if (!this.m_userPrefs) {
|
||||
// this.assureLoggedIn();
|
||||
var url = this.getCommandUrl( "get_userprefs" );
|
||||
url += ("&userid=" + encodeURIComponent(this.userId));
|
||||
this.m_userPrefs = this.issueSyncRequest(
|
||||
@ -920,7 +940,8 @@ calWcapSession.prototype = {
|
||||
var ret = [];
|
||||
var nodeList = this.m_userPrefs.getElementsByTagName(prefName);
|
||||
for ( var i = 0; i < nodeList.length; ++i ) {
|
||||
ret.push( trimString(nodeList.item(i).textContent) );
|
||||
var node = nodeList.item(i);
|
||||
ret.push( trimString(node.textContent) );
|
||||
}
|
||||
out_count.value = ret.length;
|
||||
return ret;
|
||||
@ -931,6 +952,35 @@ calWcapSession.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
get defaultAlarmStart() {
|
||||
var alarmStart = null;
|
||||
var ar = this.getUserPreferences(
|
||||
"X-NSCP-WCAP-PREF-ceDefaultAlarmStart", {});
|
||||
if (ar.length > 0 && ar[0].length > 0) {
|
||||
// workarounding cs duration bug, missing "T":
|
||||
var dur = ar[0].replace(/(^P)(\d+[HMS]$)/, "$1T$2");
|
||||
alarmStart = new CalDuration();
|
||||
alarmStart.icalString = dur;
|
||||
alarmStart.isNegative = !alarmStart.isNegative;
|
||||
}
|
||||
return alarmStart;
|
||||
},
|
||||
|
||||
getDefaultAlarmEmails:
|
||||
function( out_count )
|
||||
{
|
||||
var ret = [];
|
||||
var ar = this.getUserPreferences(
|
||||
"X-NSCP-WCAP-PREF-ceDefaultAlarmEmail", {});
|
||||
if (ar.length > 0 && ar[0].length > 0) {
|
||||
for each ( var i in ar ) {
|
||||
ret = ret.concat( i.split(/[;,]/).map(trimString) );
|
||||
}
|
||||
}
|
||||
out_count.value = ret.length;
|
||||
return ret;
|
||||
},
|
||||
|
||||
getFreeBusyTimes_resp:
|
||||
function( wcapResponse, calId, listener, requestId )
|
||||
{
|
||||
@ -940,14 +990,14 @@ calWcapSession.prototype = {
|
||||
var ret = [];
|
||||
var nodeList = xml.getElementsByTagName("FB");
|
||||
for ( var i = 0; i < nodeList.length; ++i ) {
|
||||
var item = nodeList.item(i);
|
||||
var str = item.textContent;
|
||||
var node = nodeList.item(i);
|
||||
var str = node.textContent;
|
||||
var slash = str.indexOf( '/' );
|
||||
var start = getDatetimeFromIcalString(str.substr(0, slash));
|
||||
var end = getDatetimeFromIcalString(str.substr(slash + 1));
|
||||
var entry = {
|
||||
isBusyEntry:
|
||||
(item.attributes.getNamedItem("FBTYPE").nodeValue
|
||||
(node.attributes.getNamedItem("FBTYPE").nodeValue
|
||||
== "BUSY"),
|
||||
dtRangeStart: start,
|
||||
dtRangeEnd: end
|
||||
@ -970,8 +1020,8 @@ calWcapSession.prototype = {
|
||||
case calIWcapErrors.WCAP_NO_ERRNO: // workaround
|
||||
case calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR:
|
||||
case calIWcapErrors.WCAP_CALENDAR_DOES_NOT_EXIST:
|
||||
this.log( "getFreeBusyTimes_resp() ignored: " +
|
||||
errorToString(exc) ); // no error
|
||||
this.log("ignored error: " + errorToString(exc),
|
||||
"getFreeBusyTimes_resp()");
|
||||
break;
|
||||
default:
|
||||
this.notifyError( exc );
|
||||
@ -1001,7 +1051,6 @@ calWcapSession.prototype = {
|
||||
",\n\trangeEnd=" + zRangeEnd,
|
||||
"getFreeBusyTimes()" );
|
||||
|
||||
this.assureLoggedIn();
|
||||
var url = this.getCommandUrl( "get_freebusy" );
|
||||
url += ("&calid=" + encodeURIComponent(calId));
|
||||
url += ("&busyonly=" + (bBusyOnly ? "1" : "0"));
|
||||
@ -1022,6 +1071,103 @@ calWcapSession.prototype = {
|
||||
listener.onGetFreeBusyTimes( exc, requestId, calId, 0, [] );
|
||||
}
|
||||
},
|
||||
|
||||
searchForCalendars_resp:
|
||||
function( wcapResponse, listener, requestId )
|
||||
{
|
||||
try {
|
||||
var xml = wcapResponse.data; // first statement, may throw
|
||||
if (listener) {
|
||||
var ret = [];
|
||||
var nodeList = xml.getElementsByTagName("iCal");
|
||||
for ( var i = 0; i < nodeList.length; ++i ) {
|
||||
var node = nodeList.item(i);
|
||||
try {
|
||||
checkWcapXmlErrno(node);
|
||||
var ar = filterCalProps(
|
||||
"X-NSCP-CALPROPS-RELATIVE_CALID");
|
||||
if (ar.length > 0) {
|
||||
var calId = ar[0];
|
||||
// take existing one from subscribed list;
|
||||
// xxx todo assuming there is an existing instance
|
||||
// for every subscribed calendar at this point!
|
||||
var cal = this.getCalendarByCalId_(
|
||||
calId, false/*bCreate*/);
|
||||
if (!cal)
|
||||
cal = createWcapCalendar(calId, this, node);
|
||||
ret.push(cal);
|
||||
}
|
||||
}
|
||||
catch (exc) {
|
||||
const calIWcapErrors = Components.interfaces
|
||||
.calIWcapErrors;
|
||||
switch (getResultCode(exc)) {
|
||||
case calIWcapErrors.WCAP_NO_ERRNO: // workaround
|
||||
case calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR:
|
||||
this.log("ignored error: " + errorToString(exc),
|
||||
"searchForCalendars_resp()");
|
||||
break;
|
||||
default:
|
||||
this.notifyError(exc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.log("number of found calendars: " + ret.length);
|
||||
listener.onSearchForCalendarsResults(
|
||||
Components.results.NS_OK, requestId, ret.length, ret);
|
||||
}
|
||||
if (LOG_LEVEL > 0)
|
||||
this.log("search done.");
|
||||
}
|
||||
catch (exc) {
|
||||
this.notifyError(exc);
|
||||
if (listener)
|
||||
listener.onSearchForCalendarsResults(exc, requestId, 0, []);
|
||||
}
|
||||
},
|
||||
|
||||
searchForCalendars_queued:
|
||||
function( searchString, searchOptions, listener, requestId )
|
||||
{
|
||||
try {
|
||||
var url = this.getCommandUrl("search_calprops");
|
||||
url += ("&search-string=" + encodeURIComponent(searchString));
|
||||
url += ("&searchOpts=" + (searchOptions & 3).toString(10));
|
||||
const calIWcapSession = Components.interfaces.calIWcapSession;
|
||||
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_CALID)
|
||||
url += "&calid=1";
|
||||
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_NAME)
|
||||
url += "&name=1";
|
||||
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_OWNER)
|
||||
url += "&primaryOwner=1";
|
||||
url += "&fmt-out=text%2Fxml";
|
||||
|
||||
var this_ = this;
|
||||
this.issueAsyncRequest(
|
||||
url,
|
||||
// string to xml converter func without WCAP errno check:
|
||||
function(data) {
|
||||
if (!data || data == "") { // assuming time-out
|
||||
throw new Components.Exception(
|
||||
"Login failed. Invalid session ID.",
|
||||
Components.interfaces.calIWcapErrors
|
||||
.WCAP_LOGIN_FAILED );
|
||||
}
|
||||
return getDomParser().parseFromString(data, "text/xml");
|
||||
},
|
||||
// response func:
|
||||
function(wcapResponse) {
|
||||
this_.searchForCalendars_resp(
|
||||
wcapResponse, listener, requestId);
|
||||
} );
|
||||
}
|
||||
catch (exc) {
|
||||
this.notifyError(exc);
|
||||
if (listener)
|
||||
listener.onSearchForCalendarsResults(exc, requestId, 0, []);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var g_confirmedHttpLogins = null;
|
||||
|
@ -182,6 +182,19 @@ function forEachIcalComponent( icalRootComp, componentType, func, maxResult )
|
||||
}
|
||||
}
|
||||
|
||||
function filterCalProps(propName, calProps)
|
||||
{
|
||||
var ret = [];
|
||||
if (calProps) {
|
||||
var nodeList = calProps.getElementsByTagName(propName);
|
||||
for ( var i = 0; i < nodeList.length; ++i ) {
|
||||
var node = nodeList.item(i);
|
||||
ret.push( trimString(node.textContent) );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function trimString( str )
|
||||
{
|
||||
return str.replace( /(^\s+|\s+$)/g, "" );
|
||||
@ -277,6 +290,12 @@ function AsyncQueue()
|
||||
AsyncQueue.prototype = {
|
||||
m_queue: null,
|
||||
|
||||
reset:
|
||||
function()
|
||||
{
|
||||
this.m_queue = [];
|
||||
},
|
||||
|
||||
m_proxy: null,
|
||||
get proxy() {
|
||||
if (!this.m_proxy) {
|
||||
|
@ -51,6 +51,7 @@ XPIDLSRCS = calIWcapCalendar.idl \
|
||||
calIWcapErrors.idl \
|
||||
calIWcapFreeBusyEntry.idl \
|
||||
calIWcapFreeBusyListener.idl \
|
||||
calIWcapSearchListener.idl \
|
||||
calIWcapSession.idl \
|
||||
$(NULL)
|
||||
|
||||
|
@ -78,7 +78,7 @@ interface calIWcapCalendar : calICalendar
|
||||
readonly attribute string displayName;
|
||||
|
||||
/**
|
||||
* Gets or sets this calendar's (calId) default timezone.
|
||||
* Gets this calendar's (calId) default timezone.
|
||||
*/
|
||||
readonly attribute string defaultTimezone;
|
||||
|
||||
|
@ -38,7 +38,6 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "calIWcapFreeBusyEntry.idl"
|
||||
#include "calIWcapCalendar.idl"
|
||||
|
||||
[scriptable, uuid(4498E0D0-04EC-43a3-92E0-560667696CF3)]
|
||||
interface calIWcapFreeBusyListener : nsISupports
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "calIWcapCalendar.idl"
|
||||
#include "calIWcapFreeBusyListener.idl"
|
||||
#include "calIWcapSearchListener.idl"
|
||||
#include "calIDuration.idl"
|
||||
|
||||
/**
|
||||
* WCAP session.
|
||||
@ -65,10 +67,10 @@ interface calIWcapSession : nsISupports
|
||||
readonly attribute boolean isLoggedIn;
|
||||
|
||||
/**
|
||||
* Explicitly performs a session establishment.
|
||||
* Explicitly performs a session establishment if the user is not logged
|
||||
* in already.
|
||||
* Commonly not needed, because any attempt to get a calendar instance
|
||||
* will establish a session automatically.
|
||||
* If the user is already logged in, she will be logged out before.
|
||||
* UI will prompt for a userId and password.
|
||||
*/
|
||||
void login();
|
||||
@ -89,6 +91,7 @@ interface calIWcapSession : nsISupports
|
||||
* @exception NS_ERROR_INVALID_ARG
|
||||
*/
|
||||
string getWcapErrorString( in unsigned long rc );
|
||||
|
||||
|
||||
/**
|
||||
* The user's default calendar.
|
||||
@ -123,6 +126,40 @@ interface calIWcapSession : nsISupports
|
||||
out unsigned long count,
|
||||
[array, size_is(count), retval] out calIWcapCalendar subscribedCals );
|
||||
|
||||
/**
|
||||
* Specifies how to match the searchString.
|
||||
*/
|
||||
const unsigned long SEARCH_STRING_CONTAINS = 0;
|
||||
const unsigned long SEARCH_STRING_BEGINS_WITH = 1;
|
||||
const unsigned long SEARCH_STRING_ENDS_WITH = 2;
|
||||
const unsigned long SEARCH_STRING_EXACT = 3;
|
||||
/**
|
||||
* Specifies what properties to include.
|
||||
*/
|
||||
const unsigned long SEARCH_INCLUDE_CALID = 1 << 2;
|
||||
const unsigned long SEARCH_INCLUDE_NAME = 1 << 3;
|
||||
const unsigned long SEARCH_INCLUDE_OWNER = 1 << 4;
|
||||
|
||||
/* xxx todo searching: separate into own interface? */
|
||||
/**
|
||||
* Searches for calendars matching the specified searchString.
|
||||
* Results are notified to the passed listener instance.
|
||||
* An error is notified to all registered calIObservers and
|
||||
* to calIWcapSearchListener::onGetFreeBusyTimes with rc != NS_OK.
|
||||
* The returned count of calendars (with respect to Sun calendar
|
||||
* servers) is limited to 200.
|
||||
*
|
||||
* @param searchString the search string to match
|
||||
* @param searchOptions the search options
|
||||
* @param listener listener receiving results
|
||||
* @param requestId request id to distinguish asynchronous requests
|
||||
*/
|
||||
void searchForCalendars(
|
||||
in string searchString,
|
||||
in unsigned long searchOptions,
|
||||
in calIWcapSearchListener listener,
|
||||
in unsigned long requestId );
|
||||
|
||||
/**
|
||||
* Creates a new calendar for the session's user.
|
||||
*
|
||||
@ -136,51 +173,37 @@ interface calIWcapSession : nsISupports
|
||||
* - Underscore (_)
|
||||
* - Period (.)
|
||||
* @param name calendar's name, e.g. "My Work Cal"
|
||||
* @param bAllowDoubleBooking whether double booking (events/todos) is
|
||||
* allowed
|
||||
* @param bSetCalProps whether properties of the new calendar are set
|
||||
* @param bAddToSubscribed allows a user to specify if the newly
|
||||
* created calendar should be added to the
|
||||
* user’s subscribed calendar list
|
||||
* @return created calendar
|
||||
*/
|
||||
calIWcapCalendar createCalendar(
|
||||
in string calId,
|
||||
in string name,
|
||||
in boolean bAllowDoubleBooking,
|
||||
in boolean bSetCalProps,
|
||||
in boolean bAddToSubscribed );
|
||||
calIWcapCalendar createCalendar( in string calId, in string name );
|
||||
|
||||
/**
|
||||
* Deletes a calendar.
|
||||
* Deletes a calendar. Don't do any further calls on the deleted instance.
|
||||
*
|
||||
* @param calId full calId (incl. "<user>:")
|
||||
* @param bRemoveFromSubscribed whether calendar ought to be removed
|
||||
* from subscription list
|
||||
* @param cal calendar to be deleted
|
||||
*/
|
||||
void deleteCalendar(
|
||||
in string calId,
|
||||
in boolean bRemoveFromSubscribed );
|
||||
void deleteCalendar( in calIWcapCalendar cal );
|
||||
|
||||
/**
|
||||
* Subscribe to calendar(s).
|
||||
*
|
||||
* @param count number of calIds
|
||||
* @param calIds array of calIds (calid or "mailto:rfc822addr")
|
||||
* @param count length of cals
|
||||
* @param calendars array of cals
|
||||
*/
|
||||
void subscribeToCalendars(
|
||||
in unsigned long count,
|
||||
[array, size_is(count)] in string calIds );
|
||||
[array, size_is(count)] in calIWcapCalendar cals );
|
||||
|
||||
/**
|
||||
* Unsubscribe from calendar(s).
|
||||
*
|
||||
* @param count number of calIds
|
||||
* @param calIds array of calIds (calid or "mailto:rfc822addr")
|
||||
* @param count length of cals
|
||||
* @param calendars array of cals
|
||||
*/
|
||||
void unsubscribeFromCalendars(
|
||||
in unsigned long count,
|
||||
[array, size_is(count)] in string calIds );
|
||||
[array, size_is(count)] in calIWcapCalendar cals );
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's preferences.
|
||||
@ -193,10 +216,23 @@ interface calIWcapSession : nsISupports
|
||||
out unsigned long count,
|
||||
[array, size_is(count), retval] out string properties );
|
||||
|
||||
/**
|
||||
* Gets this user's default alarm start.
|
||||
*/
|
||||
readonly attribute calIDuration defaultAlarmStart;
|
||||
|
||||
/**
|
||||
* Gets this user's default alarm eMail addresses.
|
||||
*/
|
||||
void getDefaultAlarmEmails(
|
||||
out unsigned long count,
|
||||
[array, size_is(count), retval] out string emails );
|
||||
|
||||
|
||||
/* xxx todo freebusy: separate into own interface? */
|
||||
/**
|
||||
* Gets free-busy entries for calid.
|
||||
* Results are notified to passed listener instance.
|
||||
* Results are notified to the passed listener instance.
|
||||
* An error is notified to all registered calIObservers and
|
||||
* to calIWcapFreeBusyListener::onGetFreeBusyTimes with rc != NS_OK.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user