summaryrefslogtreecommitdiffhomepage
path: root/desktop/packages/mullvad-vpn/src/main/version.ts
blob: f6ea72cc8361226d2085fc8931d081b0702c6f42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { app } from 'electron';

import { IAppVersionInfo } from '../shared/daemon-rpc-types';
import { ICurrentAppVersionInfo } from '../shared/ipc-types';
import log from '../shared/logging';
import {
  InconsistentVersionNotificationProvider,
  SystemNotificationCategory,
  UnsupportedVersionNotificationProvider,
  UpdateAvailableNotificationProvider,
} from '../shared/notifications';
import { DaemonRpc } from './daemon-rpc';
import { IpcMainEventChannel } from './ipc-event-channel';
import { NotificationSender } from './notification-controller';

export const GUI_VERSION = app.getVersion().replace('.0', '');
/// Mirrors the beta check regex in the daemon. Matches only well formed beta versions
const IS_BETA = /^(\d{4})\.(\d+)-beta(\d+)$/;

export default class Version {
  private currentVersionData: ICurrentAppVersionInfo = {
    daemon: undefined,
    gui: GUI_VERSION,
    isConsistent: true,
    isBeta: IS_BETA.test(GUI_VERSION),
  };

  private upgradeVersionData: IAppVersionInfo = {
    supported: true,
    suggestedUpgrade: undefined,
  };

  public constructor(
    private delegate: NotificationSender,
    private daemonRpc: DaemonRpc,
    private updateNotificationDisabled: boolean,
  ) {}

  public get currentVersion() {
    return this.currentVersionData;
  }

  public get upgradeVersion() {
    return this.upgradeVersionData;
  }

  public setDaemonVersion(daemonVersion: string) {
    const versionInfo = {
      ...this.currentVersionData,
      daemon: daemonVersion,
      isConsistent: daemonVersion === this.currentVersionData.gui,
    };

    this.currentVersionData = versionInfo;

    if (!versionInfo.isConsistent) {
      log.info('Inconsistent version', {
        guiVersion: versionInfo.gui,
        daemonVersion: versionInfo.daemon,
      });
    }

    // notify user about inconsistent version
    const notificationProvider = new InconsistentVersionNotificationProvider({
      consistent: versionInfo.isConsistent,
    });
    if (notificationProvider.mayDisplay()) {
      this.delegate.notify(notificationProvider.getSystemNotification());
    } else {
      this.delegate.closeNotificationsInCategory(SystemNotificationCategory.inconsistentVersion);
    }

    // notify renderer
    IpcMainEventChannel.currentVersion.notify?.(versionInfo);
  }

  public setLatestVersion(latestVersionInfo: IAppVersionInfo) {
    if (this.updateNotificationDisabled) {
      return;
    }

    const suggestedIsBeta =
      latestVersionInfo.suggestedUpgrade !== undefined &&
      IS_BETA.test(latestVersionInfo.suggestedUpgrade.version);

    const upgradeVersion = {
      ...latestVersionInfo,
      suggestedIsBeta,
    };

    this.upgradeVersionData = upgradeVersion;

    // notify user to update the app if it became unsupported
    const notificationProviders = [
      new UnsupportedVersionNotificationProvider({
        supported: latestVersionInfo.supported,
        consistent: this.currentVersionData.isConsistent,
        suggestedUpgrade: latestVersionInfo.suggestedUpgrade,
        suggestedIsBeta,
      }),
      new UpdateAvailableNotificationProvider({
        suggestedUpgrade: latestVersionInfo.suggestedUpgrade,
        suggestedIsBeta,
      }),
    ];
    const notificationProvider = notificationProviders.find((notificationProvider) =>
      notificationProvider.mayDisplay(),
    );
    if (notificationProvider) {
      this.delegate.notify(notificationProvider.getSystemNotification());
    } else {
      this.delegate.closeNotificationsInCategory(SystemNotificationCategory.newVersion);
    }

    IpcMainEventChannel.upgradeVersion.notify?.(upgradeVersion);
  }

  public async fetchLatestVersion() {
    try {
      this.setLatestVersion(await this.daemonRpc.getVersionInfo());
    } catch (e) {
      const error = e as Error;
      log.error(`Failed to request the version info: ${error.message}`);
    }
  }
}