Bug 1673280 Comment 0 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

Calendars created in add-ons have a probability of being displayed as hidden after restarts.

## STR:
0. Clean Profile, Thunderbird 78.4.0
1. Install the Birthday Calendar Add-on from https://github.com/rsjtdrjgfuzkfg/thunderbird-birthdaycalendar/releases/download/v0.2/birthdaycalendar.xpi
2. Observe that two calendars were created (for the default address books), which are visible
3. Quit Thunderbird through the menu bar (Alt to show, then File | Quit)
4. Start Thunderbird again and look in the calendar tab

## Expected:
Both calendars remain enabled

## Actual:
Both calendars are disabled (not certain if this STR is reliable in all configurations, if in doubt try Linux x64 with the official build of 78.4.0)

## Cause:
[CalCompositeCalendar.jsm line 176ff](https://searchfox.org/comm-esr78/source/calendar/providers/composite/CalCompositeCalendar.jsm#176)
```
   if (newCalendars.length != this.mCalendars) {
      this.mCalendars = newCalendars;
      if (this.mPrefPrefix) {
        aCalendar.deleteProperty(this.mActivePref);
        aCalendar.deleteProperty(this.mDefaultPref);
```
The comparison does not make sense (should probably be `newCalendars.length != this.mCalendars.length`), but that is not the cause for the bug.

The issue is that unregistered calendars (that were indeed part of the composite calendar) will loose their visibility properties. Removing the deletions fixes the issue and does not seem to cause leakage or any other issues in my tests, but they could be important for some edge cases.

I can provide patches removing the property deletions if necessary, but want some feedback first – anybody remember what the deletion's original purpose was? Was there a time when properties were not cleared when a calendar is deleted?
Calendars created in add-ons have a probability of being displayed as hidden after restarts.

## STR:
0. Clean Profile, Thunderbird 78.4.0
1. Install the Birthday Calendar Add-on from https://github.com/rsjtdrjgfuzkfg/thunderbird-birthdaycalendar/releases/download/v0.2/birthdaycalendar.xpi
2. Observe that two calendars were created (for the default address books), which are visible
3. Quit Thunderbird through the menu bar (Alt to show, then File | Quit)
4. Start Thunderbird again and look in the calendar tab
5. Update the add-on (just reinstall the same thing) and look in the calendar tab

## Expected:
Both calendars remain enabled throughout.

## Actual:
Both calendars are disabled in step 4 (not certain if this STR is reliable in all configurations, if in doubt try Linux x64 with the official build of 78.4.0) and re-enabled in step 5.

## Cause:
While calendars registered before startup re-use their previous visibility, dummy calendars are force-disabled, while newly registered calendar types are force-enabled. The following section gives a step-by-step rundown on what happens:

On shutdown, there is a chance that the add-on is unloaded before Thunderbird exits. In that case, it is removed from the composite calendar
([CalCompositeCalendar.jsm line 176ff](https://searchfox.org/comm-esr78/source/calendar/providers/composite/CalCompositeCalendar.jsm#176)):
```
   if (newCalendars.length != this.mCalendars) {
      this.mCalendars = newCalendars;
      if (this.mPrefPrefix) {
        aCalendar.deleteProperty(this.mActivePref);
```
The comparison does not make sense (should probably be `newCalendars.length != this.mCalendars.length`), but that has nothing to do with  the issue. Important to note is that the active property gets cleared.

The calendar is then not re-added, as its replacement is a disabled dummy calendar (compare [calendar-management.js line 449ff](https://searchfox.org/comm-esr78/source/calendar/base/content/calendar-management.js#449), quoted in the last step).

After the restart, the calendar is registered before the composite calendar loaded. It is then added as invisible, as its active property is still `null` ([CalCompositeCalendar.jsm line 136ff](https://searchfox.org/comm-esr78/source/calendar/providers/composite/CalCompositeCalendar.jsm#136)):
```
    cals.forEach(function(calendar) {
      if (calendar.getProperty(this.mActivePref)) {
        this.addCalendar(calendar);
```

Reloading the add-on replaces the calendar with a dummy (still invisible) and the new implementation (now becoming visible, as the calendar is no longer disabled, [calendar-management.js line 449ff](https://searchfox.org/comm-esr78/source/calendar/base/content/calendar-management.js#449)):
```
      let inComposite = calendar.getProperty("calendar-main-in-composite");
      if (inComposite === null && !calendar.getProperty("disabled")) {
        compositeCalendar.addCalendar(calendar);
```

## Potential fixes

I'm unsure how to fix this properly. The best option I came up with would be to update the calendar manager to copy visibility information to a different property before unregistering a calendar type, and restoring it after re-registering. The same approach could also be used from an WebExtension Experiment as a workaround.
The visibility of Calendars created in add-ons may change on restarts and updates.

## STR
0. Thunderbird 102.10.0, clean profile
1. Install the birthday calendar add-on from https://github.com/rsjtdrjgfuzkfg/thunderbird-birthdaycalendar/releases/download/v1.1/birthdaycalendar.xpi
2. Observe that two calendars were created (for the default address books), which are visible
3. Hide one of the two calendars observed in step 2
4. Quit Thunderbird by closing the main window
5. Start Thunderbird again and look in the calendar tab
6. Hide the calendar observed in step 2, which was not hidden in step 3
7. Update the add-on (just reinstall the same thing) and look in the calendar tab

## Expected:
In steps 5 one calendar is hidden, in step 7 two calendars are hidden.

## Actual:
In steps 5 and 7, both calendars are visible.


## Original STR / Analysis

The following information applies to the original version of the bug that also had a probability to switch the visibility from visible to invisible, but seems to no longer reproduce (at least in the few test runs I did) and has been worked around in all current add-ons.

**Information below this line might be outdated!**

### STR:
0. Clean Profile, Thunderbird 78.4.0
1. Install the Birthday Calendar Add-on from https://github.com/rsjtdrjgfuzkfg/thunderbird-birthdaycalendar/releases/download/v0.2/birthdaycalendar.xpi
2. Observe that two calendars were created (for the default address books), which are visible
3. Quit Thunderbird through the menu bar (Alt to show, then File | Quit)
4. Start Thunderbird again and look in the calendar tab
5. Update the add-on (just reinstall the same thing) and look in the calendar tab

### Expected:
Both calendars remain enabled throughout.

### Actual:
Both calendars are disabled in step 4 (not certain if this STR is reliable in all configurations, if in doubt try Linux x64 with the official build of 78.4.0) and re-enabled in step 5.

### Cause:
While calendars registered before startup re-use their previous visibility, dummy calendars are force-disabled, while newly registered calendar types are force-enabled. The following section gives a step-by-step rundown on what happens:

On shutdown, there is a chance that the add-on is unloaded before Thunderbird exits. In that case, it is removed from the composite calendar
([CalCompositeCalendar.jsm line 176ff](https://searchfox.org/comm-esr78/source/calendar/providers/composite/CalCompositeCalendar.jsm#176)):
```
   if (newCalendars.length != this.mCalendars) {
      this.mCalendars = newCalendars;
      if (this.mPrefPrefix) {
        aCalendar.deleteProperty(this.mActivePref);
```
The comparison does not make sense (should probably be `newCalendars.length != this.mCalendars.length`), but that has nothing to do with  the issue. Important to note is that the active property gets cleared.

The calendar is then not re-added, as its replacement is a disabled dummy calendar (compare [calendar-management.js line 449ff](https://searchfox.org/comm-esr78/source/calendar/base/content/calendar-management.js#449), quoted in the last step).

After the restart, the calendar is registered before the composite calendar loaded. It is then added as invisible, as its active property is still `null` ([CalCompositeCalendar.jsm line 136ff](https://searchfox.org/comm-esr78/source/calendar/providers/composite/CalCompositeCalendar.jsm#136)):
```
    cals.forEach(function(calendar) {
      if (calendar.getProperty(this.mActivePref)) {
        this.addCalendar(calendar);
```

Reloading the add-on replaces the calendar with a dummy (still invisible) and the new implementation (now becoming visible, as the calendar is no longer disabled, [calendar-management.js line 449ff](https://searchfox.org/comm-esr78/source/calendar/base/content/calendar-management.js#449)):
```
      let inComposite = calendar.getProperty("calendar-main-in-composite");
      if (inComposite === null && !calendar.getProperty("disabled")) {
        compositeCalendar.addCalendar(calendar);
```

### Potential fixes

I'm unsure how to fix this properly. The best option I came up with would be to update the calendar manager to copy visibility information to a different property before unregistering a calendar type, and restoring it after re-registering. The same approach could also be used from an WebExtension Experiment as a workaround.

Back to Bug 1673280 Comment 0