mirror of https://github.com/roytam1/boc-uxp.git
parent
15f970504b
commit
6e71b0dfbe
801 changed files with 177041 additions and 1 deletions
@ -0,0 +1,474 @@ |
||||
"use strict"; |
||||
|
||||
module.exports = { |
||||
"extends": [ |
||||
"../mozilla/toolkit/.eslintrc.js" |
||||
], |
||||
"rules": { |
||||
// Enforce one true brace style (opening brace on the same line)
|
||||
// Allow single line (for now) because of the vast number of changes needed
|
||||
"brace-style": [2, "1tbs", { allowSingleLine: true }], |
||||
|
||||
// Enforce newline at the end of file, with no multiple empty lines.
|
||||
"eol-last": 2, |
||||
|
||||
// Disallow using variables outside the blocks they are defined
|
||||
"block-scoped-var": 2, |
||||
|
||||
// Allow trailing commas for easy list extension. Having them does not
|
||||
// impair readability, but also not required either.
|
||||
"comma-dangle": 0, |
||||
|
||||
// Enforce spacing before and after comma
|
||||
"comma-spacing": [2, { before: false, after: true }], |
||||
|
||||
// Enforce one true comma style.
|
||||
"comma-style": [2, "last"], |
||||
|
||||
// Enforce curly brace conventions for all control statements.
|
||||
"curly": 2, |
||||
|
||||
// Enforce the spacing around the * in generator functions.
|
||||
"generator-star-spacing": [2, "after"], |
||||
|
||||
// Require space before/after arrow function's arrow
|
||||
"arrow-spacing": [2, { before: true, after: true }], |
||||
|
||||
// Enforces spacing between keys and values in object literal properties.
|
||||
"key-spacing": [2, { beforeColon: false, afterColon: true, mode: "minimum" }], |
||||
|
||||
// Disallow the omission of parentheses when invoking a constructor with no
|
||||
// arguments.
|
||||
"new-parens": 2, |
||||
|
||||
// Disallow use of the Array constructor.
|
||||
"no-array-constructor": 2, |
||||
|
||||
// disallow use of the Object constructor
|
||||
"no-new-object": 2, |
||||
|
||||
// Disallow Primitive Wrapper Instances
|
||||
"no-new-wrappers": 2, |
||||
|
||||
// Disallow the catch clause parameter name being the same as a variable in
|
||||
// the outer scope, to avoid confusion.
|
||||
"no-catch-shadow": 2, |
||||
|
||||
// Disallow assignment in conditional expressions.
|
||||
"no-cond-assign": 2, |
||||
|
||||
// Disallow use of debugger.
|
||||
"no-debugger": 2, |
||||
|
||||
// Disallow deletion of variables (deleting properties is fine).
|
||||
"no-delete-var": 2, |
||||
|
||||
// Disallow duplicate arguments in functions.
|
||||
"no-dupe-args": 2, |
||||
|
||||
// Disallow duplicate keys when creating object literals.
|
||||
"no-dupe-keys": 2, |
||||
|
||||
// Disallow a duplicate case label.
|
||||
"no-duplicate-case": 2, |
||||
|
||||
// Disallow the use of empty character classes in regular expressions.
|
||||
"no-empty-character-class": 2, |
||||
|
||||
// Disallow assigning to the exception in a catch block.
|
||||
"no-ex-assign": 2, |
||||
|
||||
// Disallow adding to native types
|
||||
"no-extend-native": 2, |
||||
|
||||
// Disallow double-negation boolean casts in a boolean context.
|
||||
"no-extra-boolean-cast": 2, |
||||
|
||||
// Disallow unnecessary semicolons.
|
||||
"no-extra-semi": 2, |
||||
|
||||
// Disallow mixed spaces and tabs for indentation.
|
||||
"no-mixed-spaces-and-tabs": 2, |
||||
|
||||
// Disallow reassignments of native objects.
|
||||
"no-native-reassign": 2, |
||||
|
||||
// Disallow nested ternary expressions, they make the code hard to read.
|
||||
"no-nested-ternary": 2, |
||||
|
||||
// Disallow use of octal literals.
|
||||
"no-octal": 2, |
||||
|
||||
// Disallow comparisons where both sides are exactly the same.
|
||||
"no-self-compare": 2, |
||||
|
||||
// Disallow sparse arrays, eg. let arr = [,,2].
|
||||
// Array destructuring is fine though:
|
||||
// for (let [, breakpointPromise] of aPromises)
|
||||
"no-sparse-arrays": 2, |
||||
|
||||
// Disallow trailing whitespace at the end of lines.
|
||||
"no-trailing-spaces": 2, |
||||
|
||||
// Disallow use of the with statement.
|
||||
"no-with": 2, |
||||
|
||||
// Disallow comparisons with the value NaN.
|
||||
"use-isnan": 2, |
||||
|
||||
// Ensure that the results of typeof are compared against a valid string.
|
||||
"valid-typeof": 2, |
||||
|
||||
// disallow the use of object properties of the global object (Math and
|
||||
// JSON) as functions
|
||||
"no-obj-calls": 2, |
||||
|
||||
// disallow use of octal escape sequences in string literals, such as
|
||||
// var foo = "Copyright \251";
|
||||
"no-octal-escape": 2, |
||||
|
||||
// disallow use of void operator
|
||||
"no-void": 2, |
||||
|
||||
// Disallow Yoda conditions (where literal value comes first).
|
||||
"yoda": 2, |
||||
|
||||
// Require a space immediately following the // in a line comment.
|
||||
"spaced-comment": [2, "always"], |
||||
|
||||
// Require use of the second argument for parseInt().
|
||||
"radix": 2, |
||||
|
||||
// Require spaces before/after unary operators (words on by default,
|
||||
// nonwords off by default).
|
||||
"space-unary-ops": [2, { words: true, nonwords: false }], |
||||
|
||||
// Enforce spacing after semicolons.
|
||||
"semi-spacing": [2, { before: false, after: true }], |
||||
|
||||
// Disallow the use of Boolean literals in conditional expressions.
|
||||
"no-unneeded-ternary": 2, |
||||
|
||||
// Disallow use of multiple spaces (sometimes used to align const values,
|
||||
// array or object items, etc.). It's hard to maintain and doesn't add that
|
||||
// much benefit.
|
||||
"no-multi-spaces": 2, |
||||
|
||||
// Require spaces around operators, except for a|0.
|
||||
// Disabled for now given eslint doesn't support default args yet
|
||||
// "space-infix-ops": [2, { "int32Hint": true }],
|
||||
|
||||
// Require a space around all keywords.
|
||||
"keyword-spacing": 2, |
||||
|
||||
// Disallow space between function identifier and application.
|
||||
"no-spaced-func": 2, |
||||
|
||||
// Disallow shadowing of names such as arguments.
|
||||
"no-shadow-restricted-names": 2, |
||||
|
||||
// Disallow use of comma operator.
|
||||
"no-sequences": 2, |
||||
|
||||
// Disallow use of assignment in return statement. It is preferable for a
|
||||
// single line of code to have only one easily predictable effect.
|
||||
"no-return-assign": 2, |
||||
|
||||
// Require return statements to either always or never specify values
|
||||
"consistent-return": 2, |
||||
|
||||
// Disallow padding within blocks.
|
||||
"padded-blocks": [2, "never"], |
||||
|
||||
// Disallow spaces inside parentheses.
|
||||
"space-in-parens": [2, "never"], |
||||
|
||||
// Require space after keyword for anonymous functions, but disallow space
|
||||
// after name of named functions.
|
||||
"space-before-function-paren": [2, { anonymous: "never", named: "never" }], |
||||
|
||||
// Disallow unreachable statements after a return, throw, continue, or break
|
||||
// statement.
|
||||
"no-unreachable": 2, |
||||
|
||||
// Always require use of semicolons wherever they are valid.
|
||||
"semi": [2, "always"], |
||||
|
||||
// Disallow empty statements. This will report an error for:
|
||||
// try { something(); } catch (e) {}
|
||||
// but will not report it for:
|
||||
// try { something(); } catch (e) { /* Silencing the error because ...*/ }
|
||||
// which is a valid use case.
|
||||
"no-empty": 2, |
||||
|
||||
// Disallow declaring the same variable more than once (we use let anyway).
|
||||
"no-redeclare": 2, |
||||
|
||||
// Warn about declaration of variables already declared in the outer scope.
|
||||
// This isn't an error because it sometimes is useful to use the same name
|
||||
// in a small helper function rather than having to come up with another
|
||||
// random name. Still, making this a warning can help people avoid being
|
||||
// confused.
|
||||
"no-shadow": 2, |
||||
|
||||
// We use var-only-at-top-level instead of no-var as we allow top level
|
||||
// vars.
|
||||
"no-var": 0, |
||||
"mozilla/var-only-at-top-level": 1, |
||||
|
||||
// Disallow global and local variables that aren't used, but allow unused function arguments.
|
||||
"no-unused-vars": [2, { vars: "all", args: "none", varsIgnorePattern: "EXPORTED_SYMBOLS" }], |
||||
|
||||
"mozilla/mark-test-function-used": 1, |
||||
|
||||
// Require padding inside curly braces
|
||||
"object-curly-spacing": [2, "always"], |
||||
|
||||
// Disallow spaces inside of brackets
|
||||
"array-bracket-spacing": [2, "never"], |
||||
|
||||
// Disallow control characters in regular expressions
|
||||
"no-control-regex": 2, |
||||
|
||||
// Disallow invalid regular expression strings in RegExp constructors
|
||||
"no-invalid-regexp": 2, |
||||
|
||||
// Disallow multiple spaces in regular expression literals
|
||||
"no-regex-spaces": 2, |
||||
|
||||
// Disallow irregular whitespace
|
||||
"no-irregular-whitespace": 2, |
||||
|
||||
// Disallow negating the left operand in `in` expressions
|
||||
"no-negated-in-lhs": 2, |
||||
|
||||
// Allow constant expressions in conditions
|
||||
// With 2.11.0 we can enable this with checkLoops: false
|
||||
"no-constant-condition": [2, { checkLoops: false }], |
||||
|
||||
// Disallow Regexs That Look Like Division
|
||||
"no-div-regex": 2, |
||||
|
||||
// Disallow Iterator (using __iterator__)
|
||||
"no-iterator": 2, |
||||
|
||||
// Enforce consistent linebreak style
|
||||
"linebreak-style": [2, "unix"], |
||||
|
||||
// Enforces return statements in callbacks of array's methods
|
||||
"array-callback-return": 2, |
||||
|
||||
// Verify super() calls in constructors
|
||||
"constructor-super": 2, |
||||
|
||||
// Disallow modifying variables of class declarations
|
||||
"no-class-assign": 2, |
||||
|
||||
// Disallow modifying variables that are declared using const
|
||||
"no-const-assign": 2, |
||||
|
||||
// Disallow duplicate name in class members
|
||||
"no-dupe-class-members": 2, |
||||
|
||||
// Disallow use of this/super before calling super() in constructors
|
||||
"no-this-before-super": 2, |
||||
|
||||
// Disallow duplicate imports
|
||||
"no-duplicate-imports": 2, |
||||
|
||||
// Disallow empty destructuring patterns
|
||||
"no-empty-pattern": 2, |
||||
|
||||
// Disallow Labeled Statements
|
||||
"no-labels": 2, |
||||
|
||||
// Disallow Multiline Strings
|
||||
"no-multi-str": 2, |
||||
|
||||
// Disallow Symbol Constructor
|
||||
"no-new-symbol": 2, |
||||
|
||||
// Disallow Initializing to undefined
|
||||
"no-undef-init": 2, |
||||
|
||||
// Disallow control flow statements in finally blocks
|
||||
"no-unsafe-finally": 2, |
||||
|
||||
// Disallow Unused Labels
|
||||
"no-unused-labels": 2, |
||||
|
||||
// Disallow unnecessary computed property keys on objects
|
||||
"no-useless-computed-key": 2, |
||||
|
||||
// Disallow unnecessary constructor
|
||||
"no-useless-constructor": 2, |
||||
|
||||
// Disallow renaming import, export, and destructured assignments to the
|
||||
// same name
|
||||
"no-useless-rename": 2, |
||||
|
||||
// Enforce spacing between rest and spread operators and their expressions
|
||||
"rest-spread-spacing": [2, "never"], |
||||
|
||||
// Disallow usage of spacing in template string expressions
|
||||
"template-curly-spacing": [2, "never"], |
||||
|
||||
// Disallow the Unicode Byte Order Mark
|
||||
"unicode-bom": [2, "never"], |
||||
|
||||
// Enforce spacing around the * in yield* expressions
|
||||
"yield-star-spacing": [2, "after"], |
||||
|
||||
// Disallow Implied eval
|
||||
"no-implied-eval": 2, |
||||
|
||||
// Disallow unnecessary function binding
|
||||
"no-extra-bind": 2, |
||||
|
||||
// Disallow new For Side Effects
|
||||
"no-new": 2, |
||||
|
||||
// Disallow Self Assignment
|
||||
"no-self-assign": 2, |
||||
|
||||
// Disallow confusing multiline expressions
|
||||
"no-unexpected-multiline": 2, |
||||
|
||||
// Require IIFEs to be Wrapped
|
||||
"wrap-iife": [2, "inside"], |
||||
|
||||
// Disallow Unused Expressions
|
||||
"no-unused-expressions": 2, |
||||
|
||||
// Disallow function or var declarations in nested blocks
|
||||
"no-inner-declarations": 2, |
||||
|
||||
// Enforce newline before and after dot
|
||||
"dot-location": [2, "property"], |
||||
|
||||
// Disallow Use of caller/callee
|
||||
"no-caller": 2, |
||||
|
||||
// Disallow Case Statement Fallthrough
|
||||
"no-fallthrough": 2, |
||||
|
||||
// Disallow Floating Decimals
|
||||
"no-floating-decimal": 2, |
||||
|
||||
// Require Space Before Blocks
|
||||
"space-before-blocks": 2, |
||||
|
||||
// Operators always before the line break
|
||||
"operator-linebreak": [2, "after", { overrides: { ":": "before", "?": "ignore" } }], |
||||
|
||||
// Restricts the use of parentheses to only where they are necessary
|
||||
// Disabled for now since this also removes parens around assignments, e.g. let foo = bar == baz
|
||||
// "no-extra-parens": [2, "all", { "conditionalAssign": false, "returnAssign": false, "nestedBinaryExpressions": false }],
|
||||
|
||||
// Double quotes should be used.
|
||||
"quotes": [2, "double", { avoidEscape: true }], |
||||
|
||||
// Disallow if as the only statement in an else block.
|
||||
"no-lonely-if": 2, |
||||
|
||||
// Not more than two empty lines with in the file, and no extra lines at
|
||||
// beginning or end of file.
|
||||
"no-multiple-empty-lines": [2, { max: 2, maxEOF: 0, maxBOF: 0 }], |
||||
|
||||
// Make sure all setters have a corresponding getter
|
||||
"accessor-pairs": 2, |
||||
|
||||
// Enforce spaces inside of single line blocks
|
||||
"block-spacing": [2, "always"], |
||||
|
||||
// Disallow spaces inside of computed properties
|
||||
"computed-property-spacing": [2, "never"], |
||||
|
||||
// Require consistent this (using |self|)
|
||||
"consistent-this": [2, "self"], |
||||
|
||||
// Disallow unnecessary .call() and .apply()
|
||||
"no-useless-call": 2, |
||||
|
||||
// Require dot notation when accessing properties
|
||||
"dot-notation": 2, |
||||
|
||||
// Disallow named function expressions
|
||||
"func-names": [2, "never"], |
||||
|
||||
// Enforce placing object properties on separate lines
|
||||
"object-property-newline": [2, { allowMultiplePropertiesPerLine: true }], |
||||
|
||||
// Enforce consistent line breaks inside braces
|
||||
"object-curly-newline": [2, { multiline: true }], |
||||
|
||||
// Disallow whitespace before properties
|
||||
"no-whitespace-before-property": 2, |
||||
|
||||
// Disallow unnecessary escape usage
|
||||
"no-useless-escape": 2, |
||||
|
||||
// Disallow mixes of different operators, but allow simple math operations.
|
||||
"no-mixed-operators": [2, { |
||||
groups: [ |
||||
/* ["+", "-", "*", "/", "%", "**"], */ |
||||
["&", "|", "^", "~", "<<", ">>", ">>>"], |
||||
["==", "!=", "===", "!==", ">", ">=", "<", "<="], |
||||
["&&", "||"], |
||||
["in", "instanceof"] |
||||
] |
||||
}], |
||||
|
||||
// Disallow unnecessary concatenation of strings
|
||||
"no-useless-concat": 2, |
||||
|
||||
// Disallow unmodified conditions of loops
|
||||
"no-unmodified-loop-condition": 2, |
||||
|
||||
// Suggest using arrow functions as callbacks
|
||||
"prefer-arrow-callback": [2, { allowNamedFunctions: true }], |
||||
|
||||
// Suggest using the spread operator instead of .apply()
|
||||
"prefer-spread": 2, |
||||
|
||||
// Quoting style for property names
|
||||
"quote-props": [2, "consistent-as-needed", { keywords: true }], |
||||
|
||||
// Disallow negated conditions
|
||||
"no-negated-condition": 2, |
||||
|
||||
// Enforce a maximum number of statements allowed per line
|
||||
"max-statements-per-line": [2, { max: 2 }], |
||||
|
||||
// Disallow arrow functions where they could be confused with comparisons
|
||||
"no-confusing-arrow": 2, |
||||
|
||||
// Disallow Unnecessary Nested Blocks
|
||||
"no-lone-blocks": 2, |
||||
|
||||
// Enforce minimum identifier length
|
||||
"id-length": [2, { |
||||
min: 3, |
||||
exceptions: [ |
||||
/* sorting */ "a", "b", |
||||
/* exceptions */ "e", "ex", |
||||
/* loop indices */ "i", "j", "k", "n", |
||||
/* coordinates */ "x", "y", |
||||
/* regexes */ "re", |
||||
/* known words */ "rc", "rv", "id", "OS", "os", "db", |
||||
/* mail/calendar words */ "to", "cc", |
||||
/* Components */ "Ci", "Cc", "Cu", "Cr", |
||||
] |
||||
}], |
||||
|
||||
// Disallow lexical declarations in case/default clauses
|
||||
"no-case-declarations": 2, |
||||
|
||||
// Enforce consistent indentation (4-space)
|
||||
"indent": [2, 4, { SwitchCase: 1 }], |
||||
|
||||
// The following rules will not be enabled currently, but are kept here for
|
||||
// easier updates in the future.
|
||||
"no-else-return": 0, |
||||
} |
||||
}; |
@ -0,0 +1,81 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
|
||||
function calBackendLoader() { |
||||
this.wrappedJSObject = this; |
||||
try { |
||||
this.loadBackend(); |
||||
} catch (e) { |
||||
dump("### Error loading backend: " + e + "\n"); |
||||
} |
||||
} |
||||
|
||||
var calBackendLoaderClassID = Components.ID("{0314c271-7168-40fa-802e-83c8c46a557e}"); |
||||
var calBackendLoaderInterfaces = [Components.interfaces.nsIObserver]; |
||||
calBackendLoader.prototype = { |
||||
classID: calBackendLoaderClassID, |
||||
QueryInterface: XPCOMUtils.generateQI(calBackendLoaderInterfaces), |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
classID: calBackendLoaderClassID, |
||||
contractID: "@mozilla.org/calendar/backend-loader;1", |
||||
classDescription: "Calendar Backend Loader", |
||||
interfaces: calBackendLoaderInterfaces, |
||||
flags: Components.interfaces.nsIClassInfo.SINGLETON |
||||
}), |
||||
|
||||
loaded: false, |
||||
|
||||
observe: function() { |
||||
// Nothing to do here, just need the entry so this is instanciated
|
||||
}, |
||||
|
||||
loadBackend: function() { |
||||
if (this.loaded) { |
||||
return; |
||||
} |
||||
|
||||
if (Services.prefs.getBoolPref("calendar.icaljs")) { |
||||
let contracts = [ |
||||
"@mozilla.org/calendar/datetime;1", |
||||
"@mozilla.org/calendar/duration;1", |
||||
"@mozilla.org/calendar/ics-service;1", |
||||
"@mozilla.org/calendar/period;1", |
||||
"@mozilla.org/calendar/recurrence-rule;1" |
||||
]; |
||||
|
||||
// Unregister libical components
|
||||
let registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); |
||||
for (let contractId of contracts) { |
||||
let classobj = Components.classes[contractId]; |
||||
let factory = Components.manager.getClassObject(classobj, Components.interfaces.nsIFactory); |
||||
let classId = registrar.contractIDToCID(contractId); |
||||
registrar.unregisterFactory(classId, factory); |
||||
} |
||||
|
||||
// Now load ical.js backend
|
||||
let uri = Services.io.getProtocolHandler("resource") |
||||
.QueryInterface(Components.interfaces.nsIResProtocolHandler) |
||||
.getSubstitution("calendar"); |
||||
|
||||
let file = Services.io.getProtocolHandler("file") |
||||
.QueryInterface(Components.interfaces.nsIFileProtocolHandler) |
||||
.getFileFromURLSpec(uri.spec); |
||||
file.append("components"); |
||||
file.append("icaljs-manifest"); |
||||
|
||||
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar) |
||||
.autoRegister(file); |
||||
dump("[calBackendLoader] Using icaljs backend at " + file.path + "\n"); |
||||
} else { |
||||
dump("[calBackendLoader] Using Thunderbird's builtin libical backend\n"); |
||||
} |
||||
|
||||
this.loaded = true; |
||||
} |
||||
}; |
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([calBackendLoader]); |
@ -0,0 +1,3 @@ |
||||
component {0314c271-7168-40fa-802e-83c8c46a557e} calBackendLoader.js |
||||
contract @mozilla.org/calendar/backend-loader;1 {0314c271-7168-40fa-802e-83c8c46a557e} |
||||
category profile-after-change calendar-backend-loader @mozilla.org/calendar/backend-loader;1 |
@ -0,0 +1,136 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://calendar/modules/ical.js"); |
||||
Components.utils.import("resource://calendar/modules/calUtils.jsm"); |
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
var UNIX_TIME_TO_PRTIME = 1000000; |
||||
|
||||
function calDateTime(innerObject) { |
||||
this.wrappedJSObject = this; |
||||
this.innerObject = innerObject || ICAL.Time.epochTime.clone(); |
||||
} |
||||
|
||||
var calDateTimeInterfaces = [Components.interfaces.calIDateTime]; |
||||
var calDateTimeClassID = Components.ID("{36783242-ec94-4d8a-9248-d2679edd55b9}"); |
||||
calDateTime.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI(calDateTimeInterfaces), |
||||
classID: calDateTimeClassID, |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
contractID: "@mozilla.org/calendar/datetime;1", |
||||
classDescription: "Describes a Date/Time Object", |
||||
classID: calDateTimeClassID, |
||||
interfaces: calDateTimeInterfaces |
||||
}), |
||||
|
||||
isMutable: true, |
||||
makeImmutable: function() { this.isMutable = false; }, |
||||
clone: function() { return new calDateTime(this.innerObject.clone()); }, |
||||
|
||||
isValid: true, |
||||
innerObject: null, |
||||
|
||||
get nativeTime() { return this.innerObject.toUnixTime() * UNIX_TIME_TO_PRTIME; }, |
||||
set nativeTime(val) { this.innerObject.fromUnixTime(val / UNIX_TIME_TO_PRTIME); }, |
||||
|
||||
get year() { return this.innerObject.year; }, |
||||
set year(val) { this.innerObject.year = val; }, |
||||
|
||||
get month() { return this.innerObject.month - 1; }, |
||||
set month(val) { this.innerObject.month = val + 1; }, |
||||
|
||||
get day() { return this.innerObject.day; }, |
||||
set day(val) { this.innerObject.day = val; }, |
||||
|
||||
get hour() { return this.innerObject.hour; }, |
||||
set hour(val) { this.innerObject.hour = val; }, |
||||
|
||||
get minute() { return this.innerObject.minute; }, |
||||
set minute(val) { this.innerObject.minute = val; }, |
||||
|
||||
get second() { return this.innerObject.second; }, |
||||
set second(val) { this.innerObject.second = val; }, |
||||
|
||||
get timezone() { return new calICALJSTimezone(this.innerObject.zone); }, |
||||
set timezone(rawval) { |
||||
unwrapSetter(ICAL.Timezone, rawval, function(val) { |
||||
this.innerObject.zone = val; |
||||
return val; |
||||
}, this); |
||||
}, |
||||
|
||||
resetTo: function(year, month, day, hour, minute, second, timezone) { |
||||
this.innerObject.fromData({ |
||||
year: year, |
||||
month: month + 1, |
||||
day: day, |
||||
hour: hour, |
||||
minute: minute, |
||||
second: second, |
||||
}); |
||||
this.timezone = timezone; |
||||
}, |
||||
|
||||
reset: function() { this.innerObject.reset(); }, |
||||
|
||||
get timezoneOffset() { return this.innerObject.utcOffset(); }, |
||||
get isDate() { return this.innerObject.isDate; }, |
||||
set isDate(val) { this.innerObject.isDate = val; }, |
||||
|
||||
get weekday() { return this.innerObject.dayOfWeek() - 1; }, |
||||
get yearday() { return this.innerObject.dayOfYear(); }, |
||||
|
||||
toString: function() { return this.innerObject.toString(); }, |
||||
|
||||
getInTimezone: unwrap(ICAL.Timezone, function(val) { |
||||
return new calDateTime(this.innerObject.convertToZone(val)); |
||||
}), |
||||
|
||||
addDuration: unwrap(ICAL.Duration, function(val) { |
||||
this.innerObject.addDuration(val); |
||||
}), |
||||
|
||||
subtractDate: unwrap(ICAL.Time, function(val) { |
||||
return new calDuration(this.innerObject.subtractDateTz(val)); |
||||
}), |
||||
|
||||
compare: unwrap(ICAL.Time, function(val) { |
||||
let a = this.innerObject; |
||||
let b = val; |
||||
|
||||
// If either this or aOther is floating, both objects are treated
|
||||
// as floating for the comparison.
|
||||
if (a.zone == ICAL.Timezone.localTimezone || b.zone == ICAL.Timezone.localTimezone) { |
||||
a = a.convertToZone(ICAL.Timezone.localTimezone); |
||||
b = b.convertToZone(ICAL.Timezone.localTimezone); |
||||
} |
||||
|
||||
if (a.isDate || b.isDate) { |
||||
// Lightning expects 20120101 and 20120101T010101 to be equal
|
||||
return a.compareDateOnlyTz(b, a.zone); |
||||
} else { |
||||
// If both are dates or date-times, then just do the normal compare
|
||||
return a.compare(b); |
||||
} |
||||
}), |
||||
|
||||
get startOfWeek() { return new calDateTime(this.innerObject.startOfWeek()); }, |
||||
get endOfWeek() { return new calDateTime(this.innerObject.endOfWeek()); }, |
||||
get startOfMonth() { return new calDateTime(this.innerObject.startOfMonth()); }, |
||||
get endOfMonth() { return new calDateTime(this.innerObject.endOfMonth()); }, |
||||
get startOfYear() { return new calDateTime(this.innerObject.startOfYear()); }, |
||||
get endOfYear() { return new calDateTime(this.innerObject.endOfYear()); }, |
||||
|
||||
get icalString() { return this.innerObject.toICALString(); }, |
||||
set icalString(val) { |
||||
let jcalString; |
||||
if (val.length > 10) { |
||||
jcalString = ICAL.design.icalendar.value["date-time"].fromICAL(val); |
||||
} else { |
||||
jcalString = ICAL.design.icalendar.value.date.fromICAL(val); |
||||
} |
||||
this.innerObject = ICAL.Time.fromString(jcalString); |
||||
} |
||||
}; |
@ -0,0 +1,67 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://calendar/modules/ical.js"); |
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
function calDuration(innerObject) { |
||||
this.innerObject = innerObject || new ICAL.Duration(); |
||||
this.wrappedJSObject = this; |
||||
} |
||||
|
||||
var calDurationInterfaces = [Components.interfaces.calIDuration]; |
||||
var calDurationClassID = Components.ID("{7436f480-c6fc-4085-9655-330b1ee22288}"); |
||||
calDuration.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI(calDurationInterfaces), |
||||
classID: calDurationClassID, |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
contractID: "@mozilla.org/calendar/duration;1", |
||||
classDescription: "Calendar Duration Object", |
||||
classID: calDurationClassID, |
||||
interfaces: calDurationInterfaces |
||||
}), |
||||
|
||||
get icalDuration() { return this.innerObject; }, |
||||
set icalDuration(val) { this.innerObject = val; }, |
||||
|
||||
isMutable: true, |
||||
makeImmutable: function() { this.isMutable = false; }, |
||||
clone: function() { return new calDuration(this.innerObject.clone()); }, |
||||
|
||||
get isNegative() { return this.innerObject.isNegative; }, |
||||
set isNegative(val) { this.innerObject.isNegative = val; }, |
||||
|
||||
get weeks() { return this.innerObject.weeks; }, |
||||
set weeks(val) { this.innerObject.weeks = val; }, |
||||
|
||||
get days() { return this.innerObject.days; }, |
||||
set days(val) { this.innerObject.days = val; }, |
||||
|
||||
get hours() { return this.innerObject.hours; }, |
||||
set hours(val) { this.innerObject.hours = val; }, |
||||
|
||||
get minutes() { return this.innerObject.minutes; }, |
||||
set minutes(val) { this.innerObject.minutes = val; }, |
||||
|
||||
get seconds() { return this.innerObject.seconds; }, |
||||
set seconds(val) { this.innerObject.seconds = val; }, |
||||
|
||||
get inSeconds() { return this.innerObject.toSeconds(); }, |
||||
set inSeconds(val) { this.innerObject.fromSeconds(val); }, |
||||
|
||||
addDuration: unwrap(ICAL.Duration, function(val) { |
||||
this.innerObject.fromSeconds(this.innerObject.toSeconds() + val.toSeconds()); |
||||
}), |
||||
|
||||
compare: unwrap(ICAL.Duration, function(val) { |
||||
return this.innerObject.compare(val); |
||||
}), |
||||
|
||||
reset: function() { this.innerObject.reset(); }, |
||||
normalize: function() { this.innerObject.normalize(); }, |
||||
toString: function() { return this.innerObject.toString(); }, |
||||
|
||||
get icalString() { return this.innerObject.toString(); }, |
||||
set icalString(val) { this.innerObject = ICAL.Duration.fromString(val); } |
||||
}; |
@ -0,0 +1,28 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://calendar/modules/calUtils.jsm"); |
||||
|
||||
var scriptLoadOrder = [ |
||||
"calTimezone.js", |
||||
"calDateTime.js", |
||||
"calDuration.js", |
||||
"calICSService.js", |
||||
"calPeriod.js", |
||||
"calRecurrenceRule.js", |
||||
]; |
||||
|
||||
function getComponents() { |
||||
return [ |
||||
calDateTime, |
||||
calDuration, |
||||
calIcalComponent, |
||||
calIcalProperty, |
||||
calICSService, |
||||
calPeriod, |
||||
calRecurrenceRule, |
||||
]; |
||||
} |
||||
|
||||
this.NSGetFactory = cal.loadingNSGetFactory(scriptLoadOrder, getComponents, this); |
@ -0,0 +1,22 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/** |
||||
* ChromeWorker for parseICSAsync method in calICSService.js |
||||
*/ |
||||
|
||||
var NS_OK = 0; |
||||
var NS_ERROR_FAILURE = 2147500037; |
||||
|
||||
importScripts("resource://calendar/modules/ical.js"); |
||||
|
||||
onmessage = function(event) { |
||||
try { |
||||
let comp = ICAL.parse(event.data); |
||||
postMessage({ rc: NS_OK, data: comp }); |
||||
} catch (e) { |
||||
postMessage({ rc: NS_ERROR_FAILURE, data: "Exception occurred: " + e }); |
||||
} |
||||
close(); |
||||
}; |
@ -0,0 +1,520 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://calendar/modules/ical.js"); |
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
Components.utils.import("resource://calendar/modules/calUtils.jsm"); |
||||
|
||||
function calIcalProperty(innerObject) { |
||||
this.innerObject = innerObject || new ICAL.Property(); |
||||
this.wrappedJSObject = this; |
||||
} |
||||
|
||||
var calIcalPropertyInterfaces = [Components.interfaces.calIIcalProperty]; |
||||
var calIcalPropertyClassID = Components.ID("{423ac3f0-f612-48b3-953f-47f7f8fd705b}"); |
||||
calIcalProperty.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI(calIcalPropertyInterfaces), |
||||
classID: calIcalPropertyClassID, |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
contractID: "@mozilla.org/calendar/ical-property;1", |
||||
classDescription: "Wrapper for a libical property", |
||||
classID: calIcalPropertyClassID, |
||||
interfaces: calIcalPropertyInterfaces |
||||
}), |
||||
|
||||
get icalString() { return this.innerObject.toICALString() + ICAL.newLineChar; }, |
||||
get icalProperty() { return this.innerObject; }, |
||||
set icalProperty(val) { this.innerObject = val; }, |
||||
|
||||
get parent() { return this.innerObject.parent; }, |
||||
toString: function() { return this.innerObject.toICAL(); }, |
||||
|
||||
get value() { |
||||
// Unescaped value for properties of TEXT, escaped otherwise.
|
||||
if (this.innerObject.type == "text") { |
||||
return this.innerObject.getValues().join(","); |
||||
} |
||||
return this.valueAsIcalString; |
||||
}, |
||||
set value(val) { |
||||
// Unescaped value for properties of TEXT, escaped otherwise.
|
||||
if (this.innerObject.type == "text") { |
||||
this.innerObject.setValue(val); |
||||
return val; |
||||
} |
||||
this.valueAsIcalString = val; |
||||
return val; |
||||
}, |
||||
|
||||
get valueAsIcalString() { |
||||
let type = this.innerObject.type; |
||||
return this.innerObject.getValues().map(val => { |
||||
if (type == "text") { |
||||
return ICAL.stringify.value(val, type, ICAL.design.icalendar); |
||||
} else if (typeof val == "number" || typeof val == "string") { |
||||
return val; |
||||
} else if ("toICALString" in val) { |
||||
return val.toICALString(); |
||||
} else { |
||||
return val.toString(); |
||||
} |
||||
}).join(","); |
||||
}, |
||||
set valueAsIcalString(val) { |
||||
let mockLine = this.propertyName + ":" + val; |
||||
let prop = ICAL.Property.fromString(mockLine, ICAL.design.icalendar); |
||||
|
||||
if (this.innerObject.isMultiValue) { |
||||
this.innerObject.setValues(prop.getValues()); |
||||
} else { |
||||
this.innerObject.setValue(prop.getFirstValue()); |
||||
} |
||||
return val; |
||||
}, |
||||
|
||||
get valueAsDatetime() { |
||||
let val = this.innerObject.getFirstValue(); |
||||
let isIcalTime = val && (typeof val == "object") && |
||||
("icalclass" in val) && val.icalclass == "icaltime"; |
||||
return (isIcalTime ? new calDateTime(val) : null); |
||||
}, |
||||
set valueAsDatetime(rawval) { |
||||
unwrapSetter(ICAL.Time, rawval, function(val) { |
||||
if (val && val.zone && |
||||
val.zone != ICAL.Timezone.utcTimezone && |
||||
val.zone != ICAL.Timezone.localTimezone) { |
||||
this.innerObject.setParameter("TZID", val.zone.tzid); |
||||
if (this.parent) { |
||||
let tzref = wrapGetter(calICALJSTimezone, val.zone); |
||||
this.parent.addTimezoneReference(tzref); |
||||
} |
||||
} else { |
||||
this.innerObject.removeParameter("TZID"); |
||||
} |
||||
this.innerObject.setValue(val); |
||||
}, this); |
||||
}, |
||||
|
||||
get propertyName() { return this.innerObject.name.toUpperCase(); }, |
||||
|
||||
getParameter: function(name) { |
||||
// Unfortuantely getting the "VALUE" parameter won't work, since in
|
||||
// jCal it has been translated to the value type id.
|
||||
if (name == "VALUE") { |
||||
let defaultType = this.innerObject.getDefaultType(); |
||||
if (this.innerObject.type != defaultType) { |
||||
// Default type doesn't match object type, so we have a VALUE
|
||||
// parameter
|
||||
return this.innerObject.type.toUpperCase(); |
||||
} |
||||
} |
||||
|
||||
return this.innerObject.getParameter(name.toLowerCase()); |
||||
}, |
||||
setParameter: function(name, value) { |
||||
// Similar problems for setting the value parameter. Lightning code
|
||||
// expects setting the value parameter to just change the value type
|
||||
// and attempt to use the previous value as the new one. To do this in
|
||||
// ICAL.js we need to save the value, reset the type and then try to
|
||||
// set the value again.
|
||||
if (name == "VALUE") { |
||||
let oldValues; |
||||
let type = this.innerObject.type; |
||||
let designSet = this.innerObject._designSet; |
||||
|
||||
let wasMultiValue = this.innerObject.isMultiValue; |
||||
if (wasMultiValue) { |
||||
oldValues = this.innerObject.getValues(); |
||||
} else { |
||||
let oldValue = this.innerObject.getFirstValue(); |
||||
oldValues = oldValue ? [oldValue] : []; |
||||
} |
||||
|
||||
this.innerObject.resetType(value.toLowerCase()); |
||||
try { |
||||
oldValues = oldValues.map(oldValue => { |
||||
let strvalue = ICAL.stringify.value(oldValue.toString(), type, designSet); |
||||
return ICAL.parse._parseValue(strvalue, value, designSet); |
||||
}); |
||||
} catch (e) { |
||||
// If there was an error reparsing the value, then just keep it
|
||||
// empty.
|
||||
oldValues = null; |
||||
} |
||||
|
||||
if (oldValues && oldValues.length) { |
||||
if (wasMultiValue && this.innerObject.isMultiValue) { |
||||
this.innerObject.setValues(oldValues); |
||||
} else { |
||||
this.innerObject.setValue(oldValues.join(",")); |
||||
} |
||||
} |
||||
} else { |
||||
this.innerObject.setParameter(name.toLowerCase(), value); |
||||
} |
||||
}, |
||||
removeParameter: function(name) { |
||||
// Again, VALUE needs special handling. Removing the value parameter is
|
||||
// kind of like resetting it to the default type. So find out the
|
||||
// default type and then set the value parameter to it.
|
||||
if (name == "VALUE") { |
||||
let propname = this.innerObject.name.toLowerCase(); |
||||
if (propname in ICAL.design.icalendar.property) { |
||||
let details = ICAL.design.icalendar.property[propname]; |
||||
if ("defaultType" in details) { |
||||
this.setParameter("VALUE", details.defaultType); |
||||
} |
||||
} |
||||
} else { |
||||
this.innerObject.removeParameter(name.toLowerCase()); |
||||
} |
||||
}, |
||||
|
||||
clearXParameters: function() { |
||||
cal.WARN("calIICSService::clearXParameters is no longer implemented, " + |
||||
"please use removeParameter"); |
||||
}, |
||||
|
||||
paramIterator: null, |
||||
getFirstParameterName: function() { |
||||
let innerObject = this.innerObject; |
||||
this.paramIterator = (function* () { |
||||
let defaultType = innerObject.getDefaultType(); |
||||
if (defaultType != innerObject.type) { |
||||
yield "VALUE"; |
||||
} |
||||
|
||||
let paramNames = Object.keys(innerObject.jCal[1] || {}); |
||||
for (let name of paramNames) { |
||||
yield name.toUpperCase(); |
||||
} |
||||
})(); |
||||
return this.getNextParameterName(); |
||||
}, |
||||
|
||||
getNextParameterName: function() { |
||||
if (this.paramIterator) { |
||||
let next = this.paramIterator.next(); |
||||
if (next.done) { |
||||
this.paramIterator = null; |
||||
} |
||||
|
||||
return next.value; |
||||
} else { |
||||
return this.getFirstParameterName(); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
function calIcalComponent(innerObject) { |
||||
this.innerObject = innerObject || new ICAL.Component(); |
||||
this.wrappedJSObject = this; |
||||
this.mReferencedZones = {}; |
||||
} |
||||
|
||||
var calIcalComponentInterfaces = [Components.interfaces.calIIcalComponent]; |
||||
var calIcalComponentClassID = Components.ID("{51ac96fd-1279-4439-a85b-6947b37f4cea}"); |
||||
calIcalComponent.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI(calIcalComponentInterfaces), |
||||
classID: calIcalComponentClassID, |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
contractID: "@mozilla.org/calendar/ical-component;1", |
||||
classDescription: "Wrapper for a icaljs component", |
||||
classID: calIcalComponentClassID, |
||||
interfaces: calIcalComponentInterfaces |
||||
}), |
||||
|
||||
clone: function() { return new calIcalComponent(new ICAL.Component(this.innerObject.toJSON())); }, |
||||
|
||||
get parent() { return wrapGetter(calIcalComponent, this.innerObject.parent); }, |
||||
|
||||
get icalTimezone() { return this.innerObject.name == "vtimezone" ? this.innerObject : null; }, |
||||
get icalComponent() { return this.innerObject; }, |
||||
set icalComponent(val) { this.innerObject = val; }, |
||||
|
||||
componentIterator: null, |
||||
getFirstSubcomponent: function(kind) { |
||||
if (kind == "ANY") { |
||||
kind = null; |
||||
} else if (kind) { |
||||
kind = kind.toLowerCase(); |
||||
} |
||||
let innerObject = this.innerObject; |
||||
this.componentIterator = (function* () { |
||||
let comps = innerObject.getAllSubcomponents(kind); |
||||
if (comps) { |
||||
for (let comp of comps) { |
||||
yield new calIcalComponent(comp); |
||||
} |
||||
} |
||||
})(); |
||||
return this.getNextSubcomponent(kind); |
||||
}, |
||||
getNextSubcomponent: function(kind) { |
||||
if (this.componentIterator) { |
||||
let next = this.componentIterator.next(); |
||||
if (next.done) { |
||||
this.componentIterator = null; |
||||
} |
||||
|
||||
return next.value; |
||||
} else { |
||||
return this.getFirstSubcomponent(kind); |
||||
} |
||||
}, |
||||
|
||||
get componentType() { return this.innerObject.name.toUpperCase(); }, |
||||
|
||||
get uid() { return this.innerObject.getFirstPropertyValue("uid"); }, |
||||
set uid(val) { this.innerObject.updatePropertyWithValue("uid", val); }, |
||||
|
||||
get prodid() { return this.innerObject.getFirstPropertyValue("prodid"); }, |
||||
set prodid(val) { this.innerObject.updatePropertyWithValue("prodid", val); }, |
||||
|
||||
get version() { return this.innerObject.getFirstPropertyValue("version"); }, |
||||
set version(val) { this.innerObject.updatePropertyWithValue("version", val); }, |
||||
|
||||
get method() { return this.innerObject.getFirstPropertyValue("method"); }, |
||||
set method(val) { this.innerObject.updatePropertyWithValue("method", val); }, |
||||
|
||||
get status() { return this.innerObject.getFirstPropertyValue("status"); }, |
||||
set status(val) { this.innerObject.updatePropertyWithValue("status", val); }, |
||||
|
||||
get summary() { return this.innerObject.getFirstPropertyValue("summary"); }, |
||||
set summary(val) { this.innerObject.updatePropertyWithValue("summary", val); }, |
||||
|
||||
get description() { return this.innerObject.getFirstPropertyValue("description"); }, |
||||
set description(val) { this.innerObject.updatePropertyWithValue("description", val); }, |
||||
|
||||
get location() { return this.innerObject.getFirstPropertyValue("location"); }, |
||||
set location(val) { this.innerObject.updatePropertyWithValue("location", val); }, |
||||
|
||||
get categories() { return this.innerObject.getFirstPropertyValue("categories"); }, |
||||
set categories(val) { this.innerObject.updatePropertyWithValue("categories", val); }, |
||||
|
||||
get URL() { return this.innerObject.getFirstPropertyValue("url"); }, |
||||
set URL(val) { this.innerObject.updatePropertyWithValue("url", val); }, |
||||
|
||||
get priority() { |
||||
// If there is no value for this integer property, then we must return
|
||||
// the designated INVALID_VALUE.
|
||||
const INVALID_VALUE = Components.interfaces.calIIcalComponent.INVALID_VALUE; |
||||
let prop = this.innerObject.getFirstProperty("priority"); |
||||
let val = prop ? prop.getFirstValue() : null; |
||||
return (val === null ? INVALID_VALUE : val); |
||||
}, |
||||
set priority(val) { this.innerObject.updatePropertyWithValue("priority", val); }, |
||||
|
||||
_setTimeAttr: function(propName, val) { |
||||
let prop = this.innerObject.updatePropertyWithValue(propName, val); |
||||
if (val && val.zone && |
||||
val.zone != ICAL.Timezone.utcTimezone && |
||||
val.zone != ICAL.Timezone.localTimezone) { |
||||
prop.setParameter("TZID", val.zone.tzid); |
||||
this.addTimezoneReference(wrapGetter(calICALJSTimezone, val.zone)); |
||||
} else { |
||||
prop.removeParameter("TZID"); |
||||
} |
||||
}, |
||||
|
||||
get startTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("dtstart")); }, |
||||
set startTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "dtstart"), this); }, |
||||
|
||||
get endTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("dtend")); }, |
||||
set endTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "dtend"), this); }, |
||||
|
||||
get duration() { return wrapGetter(calDuration, this.innerObject.getFirstPropertyValue("duration")); }, |
||||
|
||||
get dueTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("due")); }, |
||||
set dueTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "due"), this); }, |
||||
|
||||
get stampTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("dtstamp")); }, |
||||
set stampTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "dtstamp"), this); }, |
||||
|
||||
get createdTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("created")); }, |
||||
set createdTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "created"), this); }, |
||||
|
||||
get completedTime() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("completed")); }, |
||||
set completedTime(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "completed"), this); }, |
||||
|
||||
get lastModified() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("last-modified")); }, |
||||
set lastModified(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "last-modified"), this); }, |
||||
|
||||
get recurrenceId() { return wrapGetter(calDateTime, this.innerObject.getFirstPropertyValue("recurrence-id")); }, |
||||
set recurrenceId(val) { unwrapSetter(ICAL.Time, val, this._setTimeAttr.bind(this, "recurrence-id"), this); }, |
||||
|
||||
serializeToICS: function() { return this.innerObject.toString() + ICAL.newLineChar; }, |
||||
toString: function() { return this.innerObject.toString(); }, |
||||
|
||||
addSubcomponent: function(comp) { |
||||
comp.getReferencedTimezones({}).forEach(this.addTimezoneReference, this); |
||||
let jscomp = unwrapSingle(ICAL.Component, comp); |
||||
this.innerObject.addSubcomponent(jscomp); |
||||
}, |
||||
|
||||
propertyIterator: null, |
||||
getFirstProperty: function(kind) { |
||||
if (kind == "ANY") { |
||||
kind = null; |
||||
} else if (kind) { |
||||
kind = kind.toLowerCase(); |
||||
} |
||||
let innerObject = this.innerObject; |
||||
this.propertyIterator = (function* () { |
||||
let props = innerObject.getAllProperties(kind); |
||||
if (!props) { |
||||
return; |
||||
} |
||||
for (let prop of props) { |
||||
let hell = prop.getValues(); |
||||
if (hell.length > 1) { |
||||
// Uh oh, multiple property values. Our code expects each as one
|
||||
// property. I hate API incompatibility!
|
||||
for (let devil of hell) { |
||||
let thisprop = new ICAL.Property(prop.toJSON(), |
||||
prop.parent); |
||||
thisprop.removeAllValues(); |
||||
thisprop.setValue(devil); |
||||
yield new calIcalProperty(thisprop); |
||||
} |
||||
} else { |
||||
yield new calIcalProperty(prop); |
||||
} |
||||
} |
||||
})(); |
||||
|
||||
return this.getNextProperty(kind); |
||||
}, |
||||
|
||||
getNextProperty: function(kind) { |
||||
if (this.propertyIterator) { |
||||
let next = this.propertyIterator.next(); |
||||
if (next.done) { |
||||
this.propertyIterator = null; |
||||
} |
||||
|
||||
return next.value; |
||||
} else { |
||||
return this.getFirstProperty(kind); |
||||
} |
||||
}, |
||||
|
||||
_getNextParentVCalendar: function() { |
||||
let vcalendar = this; // eslint-disable-line consistent-this
|
||||
while (vcalendar && vcalendar.componentType != "VCALENDAR") { |
||||
vcalendar = vcalendar.parent; |
||||
} |
||||
return vcalendar || this; |
||||
}, |
||||
|
||||
addProperty: function(prop) { |
||||
try { |
||||
let datetime = prop.valueAsDatetime; |
||||
if (datetime && datetime.timezone) { |
||||
this._getNextParentVCalendar().addTimezoneReference(datetime.timezone); |
||||
} |
||||
} catch (e) { |
||||
// If there is an issue adding the timezone reference, don't make
|
||||
// that break adding the property.
|
||||
} |
||||
|
||||
let jsprop = unwrapSingle(ICAL.Property, prop); |
||||
this.innerObject.addProperty(jsprop); |
||||
}, |
||||
|
||||
addTimezoneReference: function(timezone) { |
||||
if (timezone) { |
||||
if (!(timezone.tzid in this.mReferencedZones) && |
||||
this.componentType == "VCALENDAR") { |
||||
let comp = timezone.icalComponent; |
||||
if (comp) { |
||||
this.addSubcomponent(comp); |
||||
} |
||||
} |
||||
|
||||
this.mReferencedZones[timezone.tzid] = timezone; |
||||
} |
||||
}, |
||||
|
||||
getReferencedTimezones: function(aCount) { |
||||
let vals = Object.keys(this.mReferencedZones).map(timezone => this.mReferencedZones[timezone]); |
||||
aCount.value = vals.length; |
||||
return vals; |
||||
}, |
||||
|
||||
serializeToICSStream: function() { |
||||
let unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"] |
||||
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter); |
||||
unicodeConverter.charset = "UTF-8"; |
||||
return unicodeConverter.convertToInputStream(this.innerObject.toString()); |
||||
} |
||||
}; |
||||
|
||||
function calICSService() { |
||||
this.wrappedJSObject = this; |
||||
} |
||||
|
||||
var calICSServiceInterfaces = [Components.interfaces.calIICSService]; |
||||
var calICSServiceClassID = Components.ID("{c61cb903-4408-41b3-bc22-da0b27efdfe1}"); |
||||
calICSService.prototype = { |
||||
QueryInterface: XPCOMUtils.generateQI(calICSServiceInterfaces), |
||||
classID: calICSServiceClassID, |
||||
classInfo: XPCOMUtils.generateCI({ |
||||
contractID: "@mozilla.org/calendar/ics-service;1", |
||||
classDescription: "ICS component and property service", |
||||
classID: calICSServiceClassID, |
||||
interfaces: [Components.interfaces.calIICSService] |
||||
}), |
||||
|
||||
parseICS: function(serialized, tzProvider) { |
||||
// TODO ical.js doesn't support tz providers, but this is usually null
|
||||
// or our timezone service anyway.
|
||||
let comp = ICAL.parse(serialized); |
||||
return new calIcalComponent(new ICAL.Component(comp)); |
||||
}, |
||||
|
||||
parseICSAsync: function(serialized, tzProvider, listener) { |
||||
// There are way too many error checking messages here, but I had so
|
||||
// much pain with this method that I don't want it to break again.
|
||||
try { |
||||
let worker = new ChromeWorker("resource://calendar/calendar-js/calICSService-worker.js"); |
||||
worker.onmessage = function(event) { |
||||
let rc = Components.results.NS_ERROR_FAILURE; |
||||
let icalComp = null; |
||||
try { |
||||
rc = event.data.rc; |
||||
icalComp = new calIcalComponent(new ICAL.Component(event.data.data)); |
||||
if (!Components.isSuccessCode(rc)) { |
||||
cal.ERROR("[calICSService] Error in parser worker: " + data); |
||||
} |
||||
} catch (e) { |
||||
cal.ERROR("[calICSService] Exception parsing item: " + e); |
||||
} |
||||
|
||||
listener.onParsingComplete(rc, icalComp); |
||||
}; |
||||
worker.onerror = function(event) { |
||||
cal.ERROR("[calICSService] Error in parser worker: " + event.message); |
||||
listener.onParsingComplete(Components.results.NS_ERROR_FAILURE, null); |
||||
}; |
||||
worker.postMessage(serialized); |
||||