summaryrefslogtreecommitdiffstats
path: root/b2g/components/Bootstraper.jsm
blob: 3d3fb37d916cb896d8f61ef617fcd34872524cef (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* 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/. */

"use strict";

this.EXPORTED_SYMBOLS = ["Bootstraper"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const CC = Components.Constructor;

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");

function debug(aMsg) {
  //dump("-*- Bootstraper: " + aMsg + "\n");
}

/**
  * This module loads the manifest for app from the --start-url enpoint and
  * ensures that it's installed as the system app.
  */
this.Bootstraper = {
  _manifestURL: null,
  _startupURL: null,

  bailout: function(aMsg) {
    dump("************************************************************\n");
    dump("* /!\\ " + aMsg + "\n");
    dump("************************************************************\n");
    let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
                       .getService(Ci.nsIAppStartup);
    appStartup.quit(appStartup.eForceQuit);
  },

  installSystemApp: function(aManifest) {
    // Get the appropriate startup url from the manifest launch_path.
    let base = Services.io.newURI(this._manifestURL, null, null);
    let origin = base.prePath;
    let helper = new ManifestHelper(aManifest, origin, this._manifestURL);
    this._startupURL = helper.fullLaunchPath();

    return new Promise((aResolve, aReject) => {
      debug("Origin is " + origin);
      let appData = {
        app: {
          installOrigin: origin,
          origin: origin,
          manifest: aManifest,
          manifestURL: this._manifestURL,
          manifestHash: AppsUtils.computeHash(JSON.stringify(aManifest)),
          appStatus: Ci.nsIPrincipal.APP_STATUS_CERTIFIED
        },
        appId: 1,
        isBrowser: false,
        isPackage: false
      };

      //DOMApplicationRegistry.confirmInstall(appData, null, aResolve);
    });
  },

  /**
    * Resolves to a json manifest.
    */
  loadManifest: function() {
    return new Promise((aResolve, aReject) => {
      debug("Loading manifest " + this._manifestURL);

      let xhr =  Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
      xhr.mozBackgroundRequest = true;
      xhr.open("GET", this._manifestURL);
      xhr.responseType = "json";
      xhr.addEventListener("load", () => {
        if (xhr.status >= 200 && xhr.status < 400) {
          debug("Success loading " + this._manifestURL);
          aResolve(xhr.response);
        } else {
          aReject("Error loading " + this._manifestURL);
        }
      });
      xhr.addEventListener("error", () => {
        aReject("Error loading " + this._manifestURL);
      });
      xhr.send(null);
    });
  },

  configure: function() {
    debug("Setting startup prefs... " + this._startupURL);
    Services.prefs.setCharPref("b2g.system_manifest_url", this._manifestURL);
    Services.prefs.setCharPref("b2g.system_startup_url", this._startupURL);
    return Promise.resolve();
  },

  /**
    * If a system app is already installed, uninstall it so that we can
    * cleanly replace it by the current one.
    */
  uninstallPreviousSystemApp: function() {
    // TODO: FIXME
    return Promise.resolve();

    let oldManifestURL;
    try{
      oldManifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
    } catch(e) {
      // No preference set, so nothing to uninstall.
      return Promise.resolve();
    }

    let id = DOMApplicationRegistry.getAppLocalIdByManifestURL(oldManifestURL);
    if (id == Ci.nsIScriptSecurityManager.NO_APP_ID) {
      return Promise.resolve();
    }
    debug("Uninstalling " + oldManifestURL);
    return DOMApplicationRegistry.uninstall(oldManifestURL);
  },

  /**
   * Check if we are already configured to run from this manifest url.
   */
  isInstallRequired: function(aManifestURL) {
    try {
      if (Services.prefs.getCharPref("b2g.system_manifest_url") == aManifestURL) {
        return false;
      }
    } catch(e) { }
    return true;
  },

  /**
    * Resolves once we have installed the app.
    */
  ensureSystemAppInstall: function(aManifestURL) {
    this._manifestURL = aManifestURL;
    debug("Installing app from " + this._manifestURL);

    if (!this.isInstallRequired(this._manifestURL)) {
      debug("Already configured for " + this._manifestURL);
      return Promise.resolve();
    }

    return new Promise((aResolve, aReject) => {
      this.uninstallPreviousSystemApp.bind(this)
          .then(this.loadManifest.bind(this))
          .then(this.installSystemApp.bind(this))
          .then(this.configure.bind(this))
          .then(aResolve)
          .catch(aReject);
    });
  }
};