mobile/android/chrome/content/WebappRT.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/chrome/content/WebappRT.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,222 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +let Cc = Components.classes;
     1.8 +let Ci = Components.interfaces;
     1.9 +let Cu = Components.utils;
    1.10 +
    1.11 +Cu.import("resource://gre/modules/Services.jsm");
    1.12 +Cu.import("resource://gre/modules/FileUtils.jsm");
    1.13 +Cu.import("resource://gre/modules/NetUtil.jsm");
    1.14 +Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
    1.15 +Cu.import("resource://gre/modules/PermissionPromptHelper.jsm");
    1.16 +Cu.import("resource://gre/modules/ContactService.jsm");
    1.17 +#ifdef MOZ_ANDROID_SYNTHAPKS
    1.18 +Cu.import("resource://gre/modules/AppsUtils.jsm");
    1.19 +
    1.20 +XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
    1.21 +#endif
    1.22 +
    1.23 +function pref(name, value) {
    1.24 +  return {
    1.25 +    name: name,
    1.26 +    value: value
    1.27 +  }
    1.28 +}
    1.29 +
    1.30 +let WebappRT = {
    1.31 +  DEFAULT_PREFS_FILENAME: "default-prefs.js",
    1.32 +
    1.33 +  prefs: [
    1.34 +    // Disable all add-on locations other than the profile (which can't be disabled this way)
    1.35 +    pref("extensions.enabledScopes", 1),
    1.36 +    // Auto-disable any add-ons that are "dropped in" to the profile
    1.37 +    pref("extensions.autoDisableScopes", 1),
    1.38 +    // Disable add-on installation via the web-exposed APIs
    1.39 +    pref("xpinstall.enabled", false),
    1.40 +    // Set a future policy version to avoid the telemetry prompt.
    1.41 +    pref("toolkit.telemetry.prompted", 999),
    1.42 +    pref("toolkit.telemetry.notifiedOptOut", 999),
    1.43 +    pref("media.useAudioChannelService", true),
    1.44 +    pref("dom.mozTCPSocket.enabled", true),
    1.45 +    // Don't check for updates in webapp processes to avoid duplicate notifications.
    1.46 +    pref("browser.webapps.checkForUpdates", 0),
    1.47 +  ],
    1.48 +
    1.49 +  init: function(aStatus, aUrl, aCallback) {
    1.50 +    this.deck = document.getElementById("browsers");
    1.51 +    this.deck.addEventListener("click", this, false, true);
    1.52 +
    1.53 +    // on first run, update any prefs
    1.54 +    if (aStatus == "new") {
    1.55 +      this.getDefaultPrefs().forEach(this.addPref);
    1.56 +
    1.57 +      // update the blocklist url to use a different app id
    1.58 +      let blocklist = Services.prefs.getCharPref("extensions.blocklist.url");
    1.59 +      blocklist = blocklist.replace(/%APP_ID%/g, "webapprt-mobile@mozilla.org");
    1.60 +      Services.prefs.setCharPref("extensions.blocklist.url", blocklist);
    1.61 +    }
    1.62 +
    1.63 +    // On firstrun, set permissions to their default values.
    1.64 +    // When the webapp runtime is updated, update the permissions.
    1.65 +    if (aStatus == "new" || aStatus == "upgrade") {
    1.66 +      this.getManifestFor(aUrl, function (aManifest, aApp) {
    1.67 +        if (aManifest) {
    1.68 +          PermissionsInstaller.installPermissions(aApp, true);
    1.69 +        }
    1.70 +      });
    1.71 +    }
    1.72 +
    1.73 +#ifdef MOZ_ANDROID_SYNTHAPKS
    1.74 +    // If the app is in debug mode, configure and enable the remote debugger.
    1.75 +    sendMessageToJava({ type: "NativeApp:IsDebuggable" }, (response) => {
    1.76 +      if (response.isDebuggable) {
    1.77 +        this._enableRemoteDebugger(aUrl);
    1.78 +      }
    1.79 +    });
    1.80 +#endif
    1.81 +
    1.82 +    this.findManifestUrlFor(aUrl, aCallback);
    1.83 +  },
    1.84 +
    1.85 +  getManifestFor: function (aUrl, aCallback) {
    1.86 +    DOMApplicationRegistry.registryReady.then(() => {
    1.87 +      let request = navigator.mozApps.mgmt.getAll();
    1.88 +      request.onsuccess = function() {
    1.89 +        let apps = request.result;
    1.90 +        for (let i = 0; i < apps.length; i++) {
    1.91 +          let app = apps[i];
    1.92 +          let manifest = new ManifestHelper(app.manifest, app.origin);
    1.93 +
    1.94 +          // if this is a path to the manifest, or the launch path, then we have a hit.
    1.95 +          if (app.manifestURL == aUrl || manifest.fullLaunchPath() == aUrl) {
    1.96 +            aCallback(manifest, app);
    1.97 +            return;
    1.98 +          }
    1.99 +        }
   1.100 +
   1.101 +        // Otherwise, once we loop through all of them, we have a miss.
   1.102 +        aCallback(undefined);
   1.103 +      };
   1.104 +
   1.105 +      request.onerror = function() {
   1.106 +        // Treat an error like a miss. We can't find the manifest.
   1.107 +        aCallback(undefined);
   1.108 +      };
   1.109 +    });
   1.110 +  },
   1.111 +
   1.112 +  findManifestUrlFor: function(aUrl, aCallback) {
   1.113 +    this.getManifestFor(aUrl, function(aManifest, aApp) {
   1.114 +      if (!aManifest) {
   1.115 +        // we can't find the manifest, so open it like a web page
   1.116 +        aCallback(aUrl);
   1.117 +        return;
   1.118 +      }
   1.119 +
   1.120 +      BrowserApp.manifest = aManifest;
   1.121 +      BrowserApp.manifestUrl = aApp.manifestURL;
   1.122 +
   1.123 +      aCallback(aManifest.fullLaunchPath());
   1.124 +    });
   1.125 +  },
   1.126 +
   1.127 +  getDefaultPrefs: function() {
   1.128 +    // read default prefs from the disk
   1.129 +    try {
   1.130 +      let defaultPrefs = [];
   1.131 +      try {
   1.132 +          defaultPrefs = this.readDefaultPrefs(FileUtils.getFile("ProfD", [this.DEFAULT_PREFS_FILENAME]));
   1.133 +      } catch(ex) {
   1.134 +          // this can throw if the defaultprefs.js file doesn't exist
   1.135 +      }
   1.136 +      for (let i = 0; i < defaultPrefs.length; i++) {
   1.137 +        this.prefs.push(defaultPrefs[i]);
   1.138 +      }
   1.139 +    } catch(ex) {
   1.140 +      console.log("Error reading defaultPrefs file: " + ex);
   1.141 +    }
   1.142 +    return this.prefs;
   1.143 +  },
   1.144 +
   1.145 +  readDefaultPrefs: function webapps_readDefaultPrefs(aFile) {
   1.146 +    let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
   1.147 +    fstream.init(aFile, -1, 0, 0);
   1.148 +    let prefsString = NetUtil.readInputStreamToString(fstream, fstream.available(), {});
   1.149 +    return JSON.parse(prefsString);
   1.150 +  },
   1.151 +
   1.152 +  addPref: function(aPref) {
   1.153 +    switch (typeof aPref.value) {
   1.154 +      case "string":
   1.155 +        Services.prefs.setCharPref(aPref.name, aPref.value);
   1.156 +        break;
   1.157 +      case "boolean":
   1.158 +        Services.prefs.setBoolPref(aPref.name, aPref.value);
   1.159 +        break;
   1.160 +      case "number":
   1.161 +        Services.prefs.setIntPref(aPref.name, aPref.value);
   1.162 +        break;
   1.163 +    }
   1.164 +  },
   1.165 +
   1.166 +#ifdef MOZ_ANDROID_SYNTHAPKS
   1.167 +  _enableRemoteDebugger: function(aUrl) {
   1.168 +    // Skip the connection prompt in favor of notifying the user below.
   1.169 +    Services.prefs.setBoolPref("devtools.debugger.prompt-connection", false);
   1.170 +
   1.171 +    // Automagically find a free port and configure the debugger to use it.
   1.172 +    let serv = Cc['@mozilla.org/network/server-socket;1'].createInstance(Ci.nsIServerSocket);
   1.173 +    serv.init(-1, true, -1);
   1.174 +    let port = serv.port;
   1.175 +    serv.close();
   1.176 +    Services.prefs.setIntPref("devtools.debugger.remote-port", port);
   1.177 +
   1.178 +    Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
   1.179 +
   1.180 +    // Notify the user that we enabled the debugger and which port it's using
   1.181 +    // so they can use the DevTools Connect… dialog to connect the client to it.
   1.182 +    DOMApplicationRegistry.registryReady.then(() => {
   1.183 +      let name;
   1.184 +      let app = DOMApplicationRegistry.getAppByManifestURL(aUrl);
   1.185 +      if (app) {
   1.186 +        name = app.name;
   1.187 +      } else {
   1.188 +        name = Strings.browser.GetStringFromName("remoteNotificationGenericName");
   1.189 +      }
   1.190 +
   1.191 +      Notifications.create({
   1.192 +        title: Strings.browser.formatStringFromName("remoteNotificationTitle", [name], 1),
   1.193 +        message: Strings.browser.formatStringFromName("remoteNotificationMessage", [port], 1),
   1.194 +        icon: "drawable://warning_doorhanger",
   1.195 +      });
   1.196 +    });
   1.197 +  },
   1.198 +#endif
   1.199 +
   1.200 +  handleEvent: function(event) {
   1.201 +    let target = event.target;
   1.202 +
   1.203 +    // walk up the tree to find the nearest link tag
   1.204 +    while (target && !(target instanceof HTMLAnchorElement)) {
   1.205 +      target = target.parentNode;
   1.206 +    }
   1.207 +
   1.208 +    if (!target || target.getAttribute("target") != "_blank") {
   1.209 +      return;
   1.210 +    }
   1.211 +
   1.212 +    let uri = Services.io.newURI(target.href, target.ownerDocument.characterSet, null);
   1.213 +
   1.214 +    // Direct the URL to the browser.
   1.215 +    Cc["@mozilla.org/uriloader/external-protocol-service;1"].
   1.216 +      getService(Ci.nsIExternalProtocolService).
   1.217 +      getProtocolHandlerInfo(uri.scheme).
   1.218 +      launchWithURI(uri);
   1.219 +
   1.220 +    // Prevent the runtime from loading the URL.  We do this after directing it
   1.221 +    // to the browser to give the runtime a shot at handling the URL if we fail
   1.222 +    // to direct it to the browser for some reason.
   1.223 +    event.preventDefault();
   1.224 +  }
   1.225 +}

mercurial