Bug 1611178 [wpt PR 21377] - Update wpt metadata, a=testonly
[gecko.git] / toolkit / modules / FirstStartup.jsm
blobe00e5936822d430c9d90234df0abe662ced96001
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 var EXPORTED_SYMBOLS = ["FirstStartup"];
7 const { AppConstants } = ChromeUtils.import(
8   "resource://gre/modules/AppConstants.jsm"
9 );
10 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
11 const { XPCOMUtils } = ChromeUtils.import(
12   "resource://gre/modules/XPCOMUtils.jsm"
15 XPCOMUtils.defineLazyModuleGetters(this, {
16   Normandy: "resource://normandy/Normandy.jsm",
17 });
19 const PREF_TIMEOUT = "first-startup.timeout";
20 const PROBE_NAME = "firstStartup";
22 /**
23  * Service for blocking application startup, to be used on the first install. The intended
24  * use case is for `FirstStartup` to be invoked when the application is called by an installer,
25  * such as the Windows Stub Installer, to allow the application to do some first-install tasks
26  * such as performance tuning and downloading critical data.
27  *
28  * In this scenario, the installer does not exit until the first application window appears,
29  * which gives the user experience of the application starting up quickly on first install.
30  */
31 var FirstStartup = {
32   NOT_STARTED: 0,
33   IN_PROGRESS: 1,
34   TIMED_OUT: 2,
35   SUCCESS: 3,
36   UNSUPPORTED: 4,
38   _state: 0, // NOT_STARTED,
39   /**
40    * Initialize and run first-startup services. This will always run synchronously
41    * and spin the event loop until either all required services have
42    * completed, or until a timeout is reached.
43    *
44    * In the latter case, services are expected to run post-UI instead as usual.
45    */
46   init() {
47     this._state = this.IN_PROGRESS;
48     const timeout = Services.prefs.getIntPref(PREF_TIMEOUT, 30000); // default to 30 seconds
49     let startingTime = Date.now();
51     if (AppConstants.MOZ_NORMANDY) {
52       let normandyInitialized = false;
54       Normandy.init({ runAsync: false }).then(
55         () => (normandyInitialized = true)
56       );
58       this.elapsed = 0;
59       Services.tm.spinEventLoopUntil(() => {
60         this.elapsed = Date.now() - startingTime;
61         if (this.elapsed >= timeout) {
62           this._state = this.TIMED_OUT;
63           return true;
64         } else if (normandyInitialized) {
65           this._state = this.SUCCESS;
66           return true;
67         }
68         return false;
69       });
70     } else {
71       this._state = this.UNSUPPORTED;
72     }
74     Services.telemetry.scalarSet(`${PROBE_NAME}.statusCode`, this._state);
75     Services.telemetry.scalarSet(`${PROBE_NAME}.elapsed`, this.elapsed);
76   },
78   get state() {
79     return this._state;
80   },