tenfourfox/mobile/android/b2gdroid/components/Setup.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

271 lines
8.4 KiB
JavaScript

/* 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";
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/MessagesBridge.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppsUtils",
"resource://gre/modules/AppsUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "settings",
"@mozilla.org/settingsService;1",
"nsISettingsService");
function debug() {
dump("-*- B2GDroidSetup " + Array.slice(arguments) + "\n");
}
function B2GDroidSetup() {
this.wrappedJSObject = this;
this.isFirstRun = true;
}
B2GDroidSetup.prototype = {
classID: Components.ID('{8bc88ef2-3aab-4e94-a40c-e2c80added2c}'),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
// Returns a promise that resolves once we have set the wallpaper.image
// setting in sync with Android's wallpaper.
setWallpaper: function() {
if (!this.isFirstRun) {
return Promise.resolve();
}
debug("Getting wallpaper");
Cu.import("resource://gre/modules/Messaging.jsm");
return Messaging.sendRequestForResult({ type: "Android:GetWallpaper" })
.then(aData => {
settings.createLock().set("wallpaper.image", aData.wallpaper, null);
return Promise.resolve();
});
},
getApk: function() {
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry);
let url = registry.convertChromeURL(
Services.io.newURI("chrome://b2g/content/shell.html", null, null)).spec;
// url is something like jar:jar:file:///data/app/org.mozilla.fennec_fabrice-1.apk!/assets/omni.ja!/chrome/chrome/content/shell.html
// and we just need the apk file path.
let path = url.substring(url.indexOf("///") + 2, url.indexOf(".apk") + 4);
debug("apk path: " + path);
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(path);
return file;
},
installWebapps: function(aDir) {
debug("Extracting webapps");
let apk = this.getApk();
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Ci.nsIZipReader);
zipReader.open(apk);
// Get the target file for a zip entry, normalizing it to remove the
// assets/gaia part.
function getTargetFile(aDir, entry) {
let target = aDir.clone();
let part = 0;
entry.split("/").forEach(aPart => {
if (part > 1) {
target.append(aPart);
}
part++;
});
return target;
}
try {
// create directories first
let entries = zipReader.findEntries("assets/gaia/webapps/*");
while (entries.hasMore()) {
let entryName = entries.getNext();
let entry = zipReader.getEntry(entryName);
let target = getTargetFile(aDir, entryName);
if (!target.exists() && entry.isDirectory) {
try {
debug("Creating " + entryName);
target.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
}
catch (e) {
debug("extractFiles: failed to create directory " + target.path + " : " + e);
}
}
}
entries = zipReader.findEntries("assets/gaia/webapps/*");
while (entries.hasMore()) {
let entryName = entries.getNext();
let target = getTargetFile(aDir, entryName);
if (target.exists())
continue;
debug("Extracting " + entryName + " to " + target.path);
zipReader.extract(entryName, target);
try {
target.permissions |= FileUtils.PERMS_FILE;
}
catch (e) {
debug("Failed to set permissions " + aPermissions.toString(8) + " on " + target.path);
}
}
}
finally {
zipReader.close();
}
debug("Webapps extracted");
},
installSettings: function(aDir) {
debug("Installing default settings");
let apk = this.getApk();
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Ci.nsIZipReader);
zipReader.open(apk);
try {
let dest = aDir.clone();
dest.append("settings.json")
zipReader.extract("assets/gaia/settings.json", dest);
debug("Default settings installed to " + dest.path);
}
catch(e) {
dump("Error extracting settings.json : " + e);
}
finally {
zipReader.close();
}
},
shellStartup: function(aWindow) {
Services.androidBridge.browserApp = {
selectedTab: function() {
debug("browserApp::selectedTab");
return null;
},
getBrowserTab: function(aTabId) {
debug("browserApp::getBrowserTab " + aTabId);
return null;
},
getPreferences: function(aRequestId, aPrefNames, aCount) {
debug("browserApp::getPreferences " + uneval(aPrefNames));
let prefs = [];
for (let prefName of aPrefNames) {
let pref = {
name: prefName,
type: "",
value: null
};
try {
switch (Services.prefs.getPrefType(prefName)) {
case Ci.nsIPrefBranch.PREF_BOOL:
pref.type = "bool";
pref.value = Services.prefs.getBoolPref(prefName);
break;
case Ci.nsIPrefBranch.PREF_INT:
pref.type = "int";
pref.value = Services.prefs.getIntPref(prefName);
break;
case Ci.nsIPrefBranch.PREF_STRING:
default:
pref.type = "string";
try {
// Try in case it's a localized string (will throw an exception if not)
pref.value = Services.prefs.getComplexValue(prefName, Ci.nsIPrefLocalizedString).data;
} catch (e) {
pref.value = Services.prefs.getCharPref(prefName);
}
break;
}
} catch (e) {
debug("Error reading pref [" + prefName + "]: " + e);
// preference does not exist; do not send it
continue;
}
prefs.push(pref);
}
Messaging.sendRequest({
type: "Preferences:Data",
requestId: aRequestId, // opaque request identifier, can be any string/int/whatever
preferences: prefs
});
},
observePreferences: function(requestId, prefNames, count) {
debug("browserApp::observePreferences " + prefNames);
},
removePreferenceObservers: function(aRequestId) {
debug("browserApp::removePreferenceObservers");
},
getUITelemetryObserver: function() {
debug("browserApp:getUITelemetryObserver");
return null;
}
};
Cu.import("resource://gre/modules/Messaging.jsm");
Messaging.sendRequest({ type: "Launcher:Ready" });
Messaging.sendRequest({ type: "Gecko:Ready" });
debug("Sent Gecko:Ready");
aWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).isFirstPaint = true;
Services.androidBridge.contentDocumentChanged();
},
observe: function (aSubject, aTopic, aData) {
debug("observer notification: " + aTopic);
if (aTopic === "shell-startup") {
this.shellStartup(aSubject);
return;
}
if (aTopic !== "profile-after-change") {
return;
}
// At first run of after updates, unpack gaia.
let branch = Services.prefs.getBranch("b2gdroid");
if (!AppsUtils.isFirstRun(branch)) {
debug("No need to unpack gaia again.");
this.isFirstRun = false;
return;
}
let profile = Services.dirsvc.get("DefRt", Ci.nsIFile);
debug("profile directory is " + profile.path);
let webapps = profile.clone();
webapps.append("webapps");
webapps.append("webapps.json");
this.installWebapps(profile);
let settings = profile.clone();
settings.append("settings.json");
this.installSettings(profile);
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([B2GDroidSetup]);