mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
Exterminate WebAppRT - Part 1: Remove webapprt application directory
This commit is contained in:
@@ -1,110 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function CommandLineHandler() {}
|
||||
|
||||
CommandLineHandler.prototype = {
|
||||
classID: Components.ID("{6d69c782-40a3-469b-8bfd-3ee366105a4a}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
|
||||
handle: function handle(cmdLine) {
|
||||
let args = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
let inTestMode = this._handleTestMode(cmdLine, args);
|
||||
|
||||
let debugPort = this._handleDebugMode(cmdLine);
|
||||
if (!isNaN(debugPort)) {
|
||||
Cu.import("resource://webapprt/modules/RemoteDebugger.jsm");
|
||||
RemoteDebugger.init(debugPort);
|
||||
}
|
||||
|
||||
if (inTestMode) {
|
||||
// Open the mochitest shim window, which configures the runtime for tests.
|
||||
Services.ww.openWindow(null,
|
||||
"chrome://webapprt/content/mochitest.xul",
|
||||
"_blank",
|
||||
"chrome,dialog=no",
|
||||
args);
|
||||
} else {
|
||||
// We're opening the window here in order to show it as soon as possible.
|
||||
let window = Services.ww.openWindow(null,
|
||||
"chrome://webapprt/content/webapp.xul",
|
||||
"_blank",
|
||||
"chrome,dialog=no,resizable,scrollbars,centerscreen",
|
||||
null);
|
||||
// Load the module to start up the app
|
||||
Cu.import("resource://webapprt/modules/Startup.jsm");
|
||||
startup(window).then(null, function (aError) {
|
||||
dump("Error: " + aError + "\n");
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle debug command line option.
|
||||
*
|
||||
* @param cmdLine A nsICommandLine object.
|
||||
*
|
||||
* @returns the port number if it's specified, the default port number if
|
||||
* the debug option is specified, NaN if the debug option isn't
|
||||
* specified or the port number isn't valid.
|
||||
*/
|
||||
_handleDebugMode: function(cmdLine) {
|
||||
// -debug [port]
|
||||
let idx = cmdLine.findFlag("debug", true);
|
||||
if (idx < 0) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
let port;
|
||||
let portIdx = idx + 1;
|
||||
if (portIdx < cmdLine.length) {
|
||||
port = parseInt(cmdLine.getArgument(portIdx));
|
||||
if (port != NaN) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
return Services.prefs.getIntPref('devtools.debugger.remote-port');
|
||||
},
|
||||
|
||||
_handleTestMode: function _handleTestMode(cmdLine, args) {
|
||||
// -test-mode [url]
|
||||
let idx = cmdLine.findFlag("test-mode", true);
|
||||
if (idx < 0)
|
||||
return false;
|
||||
let url;
|
||||
let urlIdx = idx + 1;
|
||||
if (urlIdx < cmdLine.length) {
|
||||
let potentialURL = cmdLine.getArgument(urlIdx);
|
||||
if (potentialURL && potentialURL[0] != "-") {
|
||||
try {
|
||||
url = Services.io.newURI(potentialURL, null, null);
|
||||
} catch (err) {
|
||||
throw Components.Exception(
|
||||
"-test-mode argument is not a valid URL: " + potentialURL,
|
||||
Components.results.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
cmdLine.removeArguments(urlIdx, urlIdx);
|
||||
args.setProperty("url", url.spec);
|
||||
}
|
||||
}
|
||||
cmdLine.removeArguments(idx, idx);
|
||||
return true;
|
||||
},
|
||||
|
||||
helpInfo : "",
|
||||
};
|
||||
|
||||
let components = [CommandLineHandler];
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
@@ -1,118 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const UNKNOWN_FAIL = ["geolocation", "desktop-notification"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
function ContentPermission() {}
|
||||
|
||||
ContentPermission.prototype = {
|
||||
classID: Components.ID("{07ef5b2e-88fb-47bd-8cec-d3b0bef11ac4}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
|
||||
|
||||
_getChromeWindow: function(aWindow) {
|
||||
return aWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
},
|
||||
|
||||
prompt: function(request) {
|
||||
// Only allow exactly one permission request here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
// Reuse any remembered permission preferences
|
||||
let result =
|
||||
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
perm.type);
|
||||
|
||||
// We used to use the name "geo" for the geolocation permission, now we're
|
||||
// using "geolocation". We need to check both to support existing
|
||||
// installations.
|
||||
if ((result == Ci.nsIPermissionManager.UNKNOWN_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) &&
|
||||
perm.type == "geolocation") {
|
||||
let geoResult = Services.perms.testExactPermission(request.principal.URI,
|
||||
"geo");
|
||||
// We override the result only if the "geo" permission was allowed or
|
||||
// denied.
|
||||
if (geoResult == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
geoResult == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
result = geoResult;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return;
|
||||
} else if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
(result == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
UNKNOWN_FAIL.indexOf(perm.type) >= 0)) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Display a prompt at the top level
|
||||
let {name} = WebappRT.localeManifest;
|
||||
let requestingWindow = request.window.top;
|
||||
let chromeWin = this._getChromeWindow(requestingWindow);
|
||||
let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
|
||||
|
||||
// Construct a prompt with share/don't and remember checkbox
|
||||
let remember = {value: false};
|
||||
let choice = Services.prompt.confirmEx(
|
||||
chromeWin,
|
||||
bundle.formatStringFromName(perm.type + ".title", [name], 1),
|
||||
bundle.GetStringFromName(perm.type + ".description"),
|
||||
// Set both buttons to strings with the cancel button being default
|
||||
Ci.nsIPromptService.BUTTON_POS_1_DEFAULT |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0 |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1,
|
||||
bundle.GetStringFromName(perm.type + ".allow"),
|
||||
bundle.GetStringFromName(perm.type + ".deny"),
|
||||
null,
|
||||
bundle.GetStringFromName(perm.type + ".remember"),
|
||||
remember);
|
||||
|
||||
let action = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
if (choice != 0) {
|
||||
action = Ci.nsIPermissionManager.DENY_ACTION;
|
||||
}
|
||||
|
||||
if (remember.value) {
|
||||
// Persist the choice if the user wants to remember
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, action);
|
||||
} else {
|
||||
// Otherwise allow the permission for the current session
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, action,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
}
|
||||
|
||||
// Trigger the selected choice
|
||||
if (choice == 0) {
|
||||
request.allow();
|
||||
}
|
||||
else {
|
||||
request.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermission]);
|
||||
@@ -1,56 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const WEBAPP_REGISTRY_DIR = "WebappRegD";
|
||||
const NS_APP_CHROME_DIR_LIST = "AChromDL";
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function DirectoryProvider() {}
|
||||
|
||||
DirectoryProvider.prototype = {
|
||||
classID: Components.ID("{e1799fda-4b2f-4457-b671-e0641d95698d}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider,
|
||||
Ci.nsIDirectoryServiceProvider2]),
|
||||
|
||||
getFile: function(prop, persistent) {
|
||||
if (prop == WEBAPP_REGISTRY_DIR) {
|
||||
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
dir.initWithPath(WebappRT.config.registryDir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
// We return null to show failure instead of throwing an error,
|
||||
// which works with the way the interface is called (per bug 529077).
|
||||
return null;
|
||||
},
|
||||
|
||||
getFiles: function(prop, persistent) {
|
||||
if (prop == NS_APP_CHROME_DIR_LIST) {
|
||||
return {
|
||||
_done: false,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
|
||||
hasMoreElements: function() {
|
||||
return !this._done;
|
||||
},
|
||||
getNext: function() {
|
||||
this._done = true;
|
||||
return FileUtils.getDir("AppRegD", ["chrome"], false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DirectoryProvider]);
|
||||
@@ -1,35 +0,0 @@
|
||||
/* 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 = ["DownloadView"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Downloads.jsm");
|
||||
|
||||
this.DownloadView = {
|
||||
init: function() {
|
||||
Downloads.getList(Downloads.ALL)
|
||||
.then(list => list.addView(this))
|
||||
.catch(Cu.reportError);
|
||||
},
|
||||
|
||||
onDownloadAdded: function(aDownload) {
|
||||
let dmWindow = Services.wm.getMostRecentWindow("Download:Manager");
|
||||
if (dmWindow) {
|
||||
dmWindow.focus();
|
||||
} else {
|
||||
Services.ww.openWindow(null,
|
||||
"chrome://webapprt/content/downloads/downloads.xul",
|
||||
"Download:Manager",
|
||||
"chrome,dialog=no,resizable",
|
||||
null);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
DownloadView.init();
|
||||
@@ -1,22 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
# Include config.mk explicitly so we can override FINAL_TARGET.
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET))
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'resource webapprt ./')
|
||||
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
|
||||
webapprt.ini: application.ini.in $(DEPTH)/config/buildid $(topsrcdir)/config/milestone.txt
|
||||
$(call py_action,preprocessor,$(DEFINES) $< -o $@)
|
||||
|
||||
libs:: webapprt.ini
|
||||
$(INSTALL) webapprt.ini $(FINAL_TARGET)
|
||||
|
||||
GARBAGE += webapprt.ini
|
||||
@@ -1,148 +0,0 @@
|
||||
/* 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";
|
||||
|
||||
const { interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
function paymentSuccess(aRequestId) {
|
||||
return function(aResult) {
|
||||
closePaymentWindow(aRequestId, function() {
|
||||
cpmm.sendAsyncMessage("Payment:Success", { requestId: aRequestId,
|
||||
result: aResult });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function paymentFailed(aRequestId) {
|
||||
return function(aErrorMsg) {
|
||||
closePaymentWindow(aRequestId, function() {
|
||||
cpmm.sendAsyncMessage("Payment:Failed", { requestId: aRequestId,
|
||||
errorMsg: aErrorMsg });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let payments = {};
|
||||
|
||||
function closePaymentWindow(aId, aCallback) {
|
||||
if (payments[aId]) {
|
||||
payments[aId].handled = true;
|
||||
payments[aId].win.close();
|
||||
payments[aId] = null;
|
||||
}
|
||||
|
||||
aCallback();
|
||||
}
|
||||
|
||||
function PaymentUI() {}
|
||||
|
||||
PaymentUI.prototype = {
|
||||
classID: Components.ID("{ede1124f-72e8-4a31-9567-3270d46f21fb}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue]),
|
||||
|
||||
confirmPaymentRequest: function(aRequestId, aRequests, aSuccessCb, aErrorCb) {
|
||||
// If there's only one payment provider that will work, just move on
|
||||
// without prompting the user.
|
||||
if (aRequests.length == 1) {
|
||||
aSuccessCb.onresult(aRequestId, aRequests[0].type);
|
||||
return;
|
||||
}
|
||||
|
||||
let items = [];
|
||||
|
||||
// Otherwise, let the user select a payment provider from a list.
|
||||
for (let i = 0; i < aRequests.length; i++) {
|
||||
let request = aRequests[i];
|
||||
let requestText = request.providerName;
|
||||
if (request.productPrice && Array.isArray(request.productPrice)) {
|
||||
// We should guess the user currency and use that instead.
|
||||
requestText += " (" + request.productPrice[0].amount + " " +
|
||||
request.productPrice[0].currency + ")";
|
||||
}
|
||||
items.push(requestText);
|
||||
}
|
||||
|
||||
let selected = {};
|
||||
|
||||
let bundle = Services.strings.
|
||||
createBundle("chrome://webapprt/locale/webapp.properties");
|
||||
let result = Services.prompt.
|
||||
select(null, bundle.GetStringFromName("paymentDialog.title"),
|
||||
bundle.GetStringFromName("paymentDialog.message"),
|
||||
items.length, items, selected);
|
||||
if (result) {
|
||||
aSuccessCb.onresult(aRequestId,
|
||||
aRequests[selected.value].type);
|
||||
} else {
|
||||
aErrorCb.onresult(aRequestId, "USER_CANCELLED");
|
||||
}
|
||||
},
|
||||
|
||||
showPaymentFlow: function(aRequestId, aPaymentFlowInfo, aErrorCb) {
|
||||
let win = Services.ww.
|
||||
openWindow(null,
|
||||
"chrome://webapprt/content/webapp.xul",
|
||||
"_blank",
|
||||
"chrome,dialog=no,resizable,scrollbars,centerscreen",
|
||||
null);
|
||||
|
||||
// Store a reference to the window so that we can close it when the payment
|
||||
// succeeds or fails.
|
||||
payments[aRequestId] = { win: win, handled: false };
|
||||
|
||||
// Inject paymentSuccess and paymentFailed methods into the document after
|
||||
// its loaded.
|
||||
win.addEventListener("DOMContentLoaded", function onDOMContentLoaded() {
|
||||
win.removeEventListener("DOMContentLoaded", onDOMContentLoaded);
|
||||
|
||||
let browserElement = win.document.getElementById("content");
|
||||
browserElement.
|
||||
setAttribute("src", aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt);
|
||||
|
||||
browserElement.addEventListener("DOMWindowCreated",
|
||||
function onDOMWindowCreated() {
|
||||
browserElement.removeEventListener("DOMWindowCreated",
|
||||
onDOMWindowCreated);
|
||||
|
||||
|
||||
win.document.getElementById("content").contentDocument.defaultView
|
||||
.wrappedJSObject.mozPaymentProvider = {
|
||||
__exposedProps__: {
|
||||
paymentSuccess: 'r',
|
||||
paymentFailed: 'r'
|
||||
},
|
||||
paymentSuccess: paymentSuccess(aRequestId),
|
||||
paymentFailed: paymentFailed(aRequestId)
|
||||
};
|
||||
}, true);
|
||||
});
|
||||
|
||||
let winObserver = function(aClosedWin, aTopic) {
|
||||
if (aTopic == "domwindowclosed") {
|
||||
// Fail the payment if the window is closed.
|
||||
if (aClosedWin == win) {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
if (payments[aRequestId] && !payments[aRequestId].handled) {
|
||||
aErrorCb.onresult(aRequestId, "USER_CANCELLED");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
},
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);
|
||||
@@ -1,28 +0,0 @@
|
||||
/* 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 = ["RemoteDebugger"];
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
|
||||
|
||||
this.RemoteDebugger = {
|
||||
init: function(port) {
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors("webapprt:webapp");
|
||||
DebuggerServer.addActors("chrome://webapprt/content/dbg-webapp-actors.js");
|
||||
}
|
||||
let listener = DebuggerServer.createListener();
|
||||
listener.portOrPath = port;
|
||||
listener.open();
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
/* This module is imported at the startup of an application. It takes care of
|
||||
* permissions installation, application url loading, security settings. Put
|
||||
* stuff here that you want to happen once on startup before the webapp is
|
||||
* loaded. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["startup"];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
/* We load here modules that are needed to perform the application startup.
|
||||
* We lazily load modules that aren't needed on every startup.
|
||||
* We load modules that aren't used here but that need to perform some
|
||||
* initialization steps later in the startup function. */
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
// Lazily load these modules because we don't need them at every
|
||||
// startup, but only during first run or runtime update.
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsInstaller",
|
||||
"resource://gre/modules/PermissionsInstaller.jsm");
|
||||
|
||||
const PROFILE_DIR = OS.Constants.Path.profileDir;
|
||||
|
||||
function isFirstRunOrUpdate() {
|
||||
let savedBuildID = null;
|
||||
try {
|
||||
savedBuildID = Services.prefs.getCharPref("webapprt.buildID");
|
||||
} catch (e) {}
|
||||
|
||||
let ourBuildID = Services.appinfo.platformBuildID;
|
||||
|
||||
if (ourBuildID != savedBuildID) {
|
||||
Services.prefs.setCharPref("webapprt.buildID", ourBuildID);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function writeFile(aPath, aData) {
|
||||
return Task.spawn(function() {
|
||||
let data = new TextEncoder().encode(aData);
|
||||
yield OS.File.writeAtomic(aPath, data, { tmpPath: aPath + ".tmp" });
|
||||
});
|
||||
}
|
||||
|
||||
function createBrandingFiles() {
|
||||
return Task.spawn(function() {
|
||||
let manifest = WebappRT.localeManifest;
|
||||
let name = WebappRT.localeManifest.name;
|
||||
let developer = " ";
|
||||
if (WebappRT.localeManifest.developer) {
|
||||
developer = WebappRT.localeManifest.developer.name;
|
||||
}
|
||||
|
||||
let brandDTDContent = '<!ENTITY brandShortName "' + name + '">\n\
|
||||
<!ENTITY brandFullName "' + name + '">\n\
|
||||
<!ENTITY vendorShortName "' + developer + '">\n\
|
||||
<!ENTITY trademarkInfo.part1 " ">';
|
||||
|
||||
yield writeFile(OS.Path.join(PROFILE_DIR, "brand.dtd"), brandDTDContent);
|
||||
|
||||
let brandPropertiesContent = 'brandShortName=' + name + '\n\
|
||||
brandFullName=' + name + '\n\
|
||||
vendorShortName=' + developer;
|
||||
|
||||
yield writeFile(OS.Path.join(PROFILE_DIR, "brand.properties"),
|
||||
brandPropertiesContent);
|
||||
});
|
||||
}
|
||||
|
||||
// Observes all the events needed to actually launch an application.
|
||||
// It waits for XUL window and webapps registry loading.
|
||||
this.startup = function(window) {
|
||||
return Task.spawn(function () {
|
||||
// Observe XUL window loading.
|
||||
// For tests, it could be already loaded.
|
||||
let deferredWindowLoad = Promise.defer();
|
||||
if (window.document && window.document.getElementById("content")) {
|
||||
deferredWindowLoad.resolve();
|
||||
} else {
|
||||
window.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
window.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
deferredWindowLoad.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
let appUpdated = false;
|
||||
let updatePending = yield WebappRT.isUpdatePending();
|
||||
if (updatePending) {
|
||||
appUpdated = yield WebappRT.applyUpdate();
|
||||
}
|
||||
|
||||
yield WebappRT.configPromise;
|
||||
|
||||
let appData = WebappRT.config.app;
|
||||
|
||||
// Initialize DOMApplicationRegistry by importing Webapps.jsm.
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
// Initialize window-independent handling of webapps- notifications.
|
||||
Cu.import("resource://webapprt/modules/WebappManager.jsm");
|
||||
|
||||
// Wait for webapps registry loading.
|
||||
yield DOMApplicationRegistry.registryStarted;
|
||||
// Add the currently running app to the registry.
|
||||
yield DOMApplicationRegistry.addInstalledApp(appData, appData.manifest,
|
||||
appData.updateManifest);
|
||||
|
||||
let manifestURL = appData.manifestURL;
|
||||
if (manifestURL) {
|
||||
// On firstrun, set permissions to their default values.
|
||||
// When the webapp runtime is updated, update the permissions.
|
||||
if (isFirstRunOrUpdate(Services.prefs) || appUpdated) {
|
||||
PermissionsInstaller.installPermissions(appData, true);
|
||||
yield createBrandingFiles();
|
||||
}
|
||||
}
|
||||
|
||||
// Branding substitution
|
||||
let aliasFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsIFile);
|
||||
aliasFile.initWithPath(PROFILE_DIR);
|
||||
|
||||
let aliasURI = Services.io.newFileURI(aliasFile);
|
||||
|
||||
Services.io.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsIResProtocolHandler)
|
||||
.setSubstitution("webappbranding", aliasURI);
|
||||
|
||||
// Wait for XUL window loading
|
||||
yield deferredWindowLoad.promise;
|
||||
|
||||
// Load these modules here because they aren't needed right at startup,
|
||||
// but they need to be loaded to perform some initialization steps.
|
||||
Cu.import("resource://gre/modules/Payment.jsm");
|
||||
Cu.import("resource://gre/modules/AlarmService.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebRTCHandler.jsm");
|
||||
Cu.import("resource://webapprt/modules/DownloadView.jsm");
|
||||
|
||||
// Get the <browser> element in the webapp.xul window.
|
||||
let appBrowser = window.document.getElementById("content");
|
||||
|
||||
// Set the principal to the correct appID and launch the application.
|
||||
appBrowser.docShell.setIsApp(WebappRT.appID);
|
||||
appBrowser.setAttribute("src", WebappRT.launchURI);
|
||||
|
||||
if (appData.manifest.fullscreen) {
|
||||
appBrowser.addEventListener("load", function onLoad() {
|
||||
appBrowser.removeEventListener("load", onLoad, true);
|
||||
appBrowser.contentDocument.
|
||||
documentElement.mozRequestFullScreen();
|
||||
}, true);
|
||||
}
|
||||
|
||||
WebappRT.startUpdateService();
|
||||
});
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/* 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 = [];
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function handleRequest(aSubject, aTopic, aData) {
|
||||
let { windowID, callID } = aSubject;
|
||||
let constraints = aSubject.getConstraints();
|
||||
let contentWindow = Services.wm.getOuterWindowWithId(windowID);
|
||||
|
||||
contentWindow.navigator.mozGetUserMediaDevices(
|
||||
constraints,
|
||||
function (devices) {
|
||||
prompt(contentWindow, callID, constraints.audio,
|
||||
constraints.video || constraints.picture,
|
||||
devices);
|
||||
},
|
||||
function (error) {
|
||||
denyRequest(callID, error);
|
||||
});
|
||||
}
|
||||
|
||||
function prompt(aWindow, aCallID, aAudioRequested, aVideoRequested, aDevices) {
|
||||
let audioDevices = [];
|
||||
let videoDevices = [];
|
||||
for (let device of aDevices) {
|
||||
device = device.QueryInterface(Ci.nsIMediaDevice);
|
||||
switch (device.type) {
|
||||
case "audio":
|
||||
if (aAudioRequested) {
|
||||
audioDevices.push(device);
|
||||
}
|
||||
break;
|
||||
|
||||
case "video":
|
||||
if (aVideoRequested) {
|
||||
videoDevices.push(device);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (audioDevices.length == 0 && videoDevices.length == 0) {
|
||||
denyRequest(aCallID);
|
||||
return;
|
||||
}
|
||||
|
||||
let params = {
|
||||
videoDevices: videoDevices,
|
||||
audioDevices: audioDevices,
|
||||
out: null
|
||||
};
|
||||
aWindow.openDialog("chrome://webapprt/content/getUserMediaDialog.xul", "",
|
||||
"chrome, dialog, modal", params).focus();
|
||||
|
||||
if (!params.out) {
|
||||
denyRequest(aCallID);
|
||||
return;
|
||||
}
|
||||
|
||||
let allowedDevices = Cc["@mozilla.org/supports-array;1"].
|
||||
createInstance(Ci.nsISupportsArray);
|
||||
let videoIndex = params.out.video;
|
||||
let audioIndex = params.out.audio;
|
||||
|
||||
if (videoIndex != -1) {
|
||||
allowedDevices.AppendElement(videoDevices[videoIndex]);
|
||||
}
|
||||
|
||||
if (audioIndex != -1) {
|
||||
allowedDevices.AppendElement(audioDevices[audioIndex]);
|
||||
}
|
||||
|
||||
if (allowedDevices.Count()) {
|
||||
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow",
|
||||
aCallID);
|
||||
} else {
|
||||
denyRequest(aCallID);
|
||||
}
|
||||
}
|
||||
|
||||
function denyRequest(aCallID, aError) {
|
||||
let msg = null;
|
||||
if (aError) {
|
||||
msg = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
msg.data = aError;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(msg, "getUserMedia:response:deny", aCallID);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(handleRequest, "getUserMedia:request", false);
|
||||
@@ -1,142 +0,0 @@
|
||||
/* 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 = ["WebappManager"];
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NativeApp.jsm");
|
||||
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
|
||||
this.WebappManager = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let data = JSON.parse(aData);
|
||||
data.mm = aSubject;
|
||||
|
||||
let chromeWin;
|
||||
switch (aTopic) {
|
||||
case "webapps-ask-install":
|
||||
chromeWin = Services.wm.getOuterWindowWithId(data.oid);
|
||||
if (chromeWin)
|
||||
this.doInstall(data, chromeWin);
|
||||
break;
|
||||
case "webapps-ask-uninstall":
|
||||
chromeWin = Services.wm.getOuterWindowWithId(data.windowId);
|
||||
if (chromeWin) {
|
||||
this.doUninstall(data, chromeWin);
|
||||
}
|
||||
break;
|
||||
case "webapps-launch":
|
||||
WebappOSUtils.launch(data);
|
||||
break;
|
||||
case "webapps-uninstall":
|
||||
WebappOSUtils.uninstall(data).then(null, Cu.reportError);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
update: function(aApp, aManifest, aZipPath) {
|
||||
let nativeApp = new NativeApp(aApp, aManifest,
|
||||
WebappRT.config.app.categories,
|
||||
WebappRT.config.registryDir);
|
||||
nativeApp.prepareUpdate(aApp, aManifest, aZipPath);
|
||||
},
|
||||
|
||||
doInstall: function(data, window) {
|
||||
let jsonManifest = data.isPackage ? data.app.updateManifest : data.app.manifest;
|
||||
let manifest =
|
||||
new ManifestHelper(jsonManifest, data.app.origin, data.app.manifestURL);
|
||||
let name = manifest.name;
|
||||
let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
|
||||
|
||||
let choice = Services.prompt.confirmEx(
|
||||
window,
|
||||
bundle.formatStringFromName("webapps.install.title", [name], 1),
|
||||
bundle.formatStringFromName("webapps.install.description", [name], 1),
|
||||
// Set both buttons to strings with the cancel button being default
|
||||
Ci.nsIPromptService.BUTTON_POS_1_DEFAULT |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0 |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1,
|
||||
bundle.GetStringFromName("webapps.install.install"),
|
||||
bundle.GetStringFromName("webapps.install.dontinstall"),
|
||||
null,
|
||||
null,
|
||||
{});
|
||||
|
||||
// Perform the install if the user allows it
|
||||
if (choice == 0) {
|
||||
let nativeApp = new NativeApp(data.app, jsonManifest,
|
||||
data.app.categories,
|
||||
WebappRT.config.registryDir);
|
||||
let localDir;
|
||||
try {
|
||||
localDir = nativeApp.createProfile();
|
||||
} catch (ex) {
|
||||
DOMApplicationRegistry.denyInstall(data);
|
||||
return;
|
||||
}
|
||||
|
||||
DOMApplicationRegistry.confirmInstall(data, localDir,
|
||||
Task.async(function*(aApp, aManifest, aZipPath) {
|
||||
yield nativeApp.install(aApp, aManifest, aZipPath);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
DOMApplicationRegistry.denyInstall(data);
|
||||
}
|
||||
},
|
||||
|
||||
doUninstall: function(aData, aWindow) {
|
||||
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
|
||||
let manifest = new ManifestHelper(jsonManifest, aData.app.origin,
|
||||
aData.app.manifestURL);
|
||||
let name = manifest.name;
|
||||
let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
|
||||
|
||||
let choice = Services.prompt.confirmEx(
|
||||
aWindow,
|
||||
bundle.formatStringFromName("webapps.uninstall.title", [name], 1),
|
||||
bundle.formatStringFromName("webapps.uninstall.description", [name], 1),
|
||||
// Set both buttons to strings with the cancel button being default
|
||||
Ci.nsIPromptService.BUTTON_POS_1_DEFAULT |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0 |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1,
|
||||
bundle.GetStringFromName("webapps.uninstall.uninstall"),
|
||||
bundle.GetStringFromName("webapps.uninstall.dontuninstall"),
|
||||
null,
|
||||
null,
|
||||
{});
|
||||
|
||||
// Perform the uninstall if the user allows it
|
||||
if (choice == 0) {
|
||||
DOMApplicationRegistry.confirmUninstall(aData).then((aApp) => {
|
||||
WebappOSUtils.uninstall(aApp).then(null, Cu.reportError);
|
||||
});
|
||||
} else {
|
||||
DOMApplicationRegistry.denyUninstall(aData);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
|
||||
Services.obs.addObserver(WebappManager, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(WebappManager, "webapps-ask-uninstall", false);
|
||||
Services.obs.addObserver(WebappManager, "webapps-launch", false);
|
||||
Services.obs.addObserver(WebappManager, "webapps-uninstall", false);
|
||||
Services.obs.addObserver(WebappManager, "webapps-update", false);
|
||||
|
||||
DOMApplicationRegistry.registerUpdateHandler(WebappManager.update);
|
||||
@@ -1,143 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["WebappRT"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'NativeApp',
|
||||
'resource://gre/modules/NativeApp.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
this.WebappRT = {
|
||||
_configPromise: null,
|
||||
|
||||
get configPromise() {
|
||||
if (!this._configPromise) {
|
||||
this._configPromise = Task.spawn(function*() {
|
||||
let webappJson = OS.Path.join(Services.dirsvc.get("AppRegD", Ci.nsIFile).path,
|
||||
"webapp.json");
|
||||
|
||||
WebappRT.config = yield AppsUtils.loadJSONAsync(webappJson);
|
||||
});
|
||||
}
|
||||
|
||||
return this._configPromise;
|
||||
},
|
||||
|
||||
get launchURI() {
|
||||
return this.localeManifest.fullLaunchPath();
|
||||
},
|
||||
|
||||
get localeManifest() {
|
||||
return new ManifestHelper(this.config.app.manifest,
|
||||
this.config.app.origin,
|
||||
this.config.app.manifestURL);
|
||||
},
|
||||
|
||||
get appID() {
|
||||
let manifestURL = this.config.app.manifestURL;
|
||||
if (!manifestURL) {
|
||||
return Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
}
|
||||
|
||||
return appsService.getAppLocalIdByManifestURL(manifestURL);
|
||||
},
|
||||
|
||||
isUpdatePending: Task.async(function*() {
|
||||
let webappJson = OS.Path.join(Services.dirsvc.get("AppRegD", Ci.nsIFile).path,
|
||||
"update", "webapp.json");
|
||||
|
||||
if (!(yield OS.File.exists(webappJson))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}),
|
||||
|
||||
applyUpdate: Task.async(function*() {
|
||||
let webappJson = OS.Path.join(Services.dirsvc.get("AppRegD", Ci.nsIFile).path,
|
||||
"update", "webapp.json");
|
||||
let config = yield AppsUtils.loadJSONAsync(webappJson);
|
||||
|
||||
let nativeApp = new NativeApp(config.app, config.app.manifest,
|
||||
config.app.categories,
|
||||
config.registryDir);
|
||||
try {
|
||||
yield nativeApp.applyUpdate(config.app);
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The update has been applied successfully, the new config file
|
||||
// is the config file that was in the update directory.
|
||||
this.config = config;
|
||||
this._configPromise = Promise.resolve();
|
||||
|
||||
return true;
|
||||
}),
|
||||
|
||||
startUpdateService: function() {
|
||||
let manifestURL = this.config.app.manifestURL;
|
||||
// We used to install apps without storing their manifest URL.
|
||||
// Now we can't update them.
|
||||
if (!manifestURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for updates once a day.
|
||||
let timerManager = Cc["@mozilla.org/updates/timer-manager;1"].
|
||||
getService(Ci.nsIUpdateTimerManager);
|
||||
timerManager.registerTimer("updateTimer", () => {
|
||||
let window = Services.wm.getMostRecentWindow("webapprt:webapp");
|
||||
window.navigator.mozApps.mgmt.getAll().onsuccess = function() {
|
||||
let thisApp = null;
|
||||
for (let app of this.result) {
|
||||
if (app.manifestURL == manifestURL) {
|
||||
thisApp = app;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This shouldn't happen if the app is installed.
|
||||
if (!thisApp) {
|
||||
Cu.reportError("Couldn't find the app in the webapps registry");
|
||||
return;
|
||||
}
|
||||
|
||||
thisApp.ondownloadavailable = () => {
|
||||
// Download available, download it!
|
||||
thisApp.download();
|
||||
};
|
||||
|
||||
thisApp.ondownloadsuccess = () => {
|
||||
// Update downloaded, apply it!
|
||||
window.navigator.mozApps.mgmt.applyDownload(thisApp);
|
||||
};
|
||||
|
||||
thisApp.ondownloadapplied = () => {
|
||||
// Application updated, nothing to do.
|
||||
};
|
||||
|
||||
thisApp.checkForUpdate();
|
||||
}
|
||||
}, Services.prefs.getIntPref("webapprt.app_update_interval"));
|
||||
},
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
#if 0
|
||||
; 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/.
|
||||
#endif
|
||||
|
||||
#filter substitution
|
||||
|
||||
[App]
|
||||
ID=webapprt@mozilla.org
|
||||
Vendor=Mozilla
|
||||
; Note: the Windows stub executable sets nsXREAppData::name to the webapp
|
||||
; origin, overriding the value below, to make the app runner treat webapps
|
||||
; as distinct products, per bug 747409.
|
||||
Name=Webapp Runtime
|
||||
Version=@GRE_MILESTONE@
|
||||
BuildID=@GRE_BUILDID@
|
||||
UAName=@MOZ_APP_BASENAME@
|
||||
|
||||
[Goanna]
|
||||
MinVersion=@GRE_MILESTONE@
|
||||
MaxVersion=@GRE_MILESTONE@
|
||||
|
||||
[Crash Reporter]
|
||||
#if MOZILLA_OFFICIAL
|
||||
Enabled=1
|
||||
#endif
|
||||
ServerURL=https://crash-reports.mozilla.com/submit?id=webapprt@mozilla.org&version=@GRE_MILESTONE@&buildid=@GRE_BUILDID@
|
||||
@@ -1,17 +0,0 @@
|
||||
# CommandLineHandler.js
|
||||
component {6d69c782-40a3-469b-8bfd-3ee366105a4a} CommandLineHandler.js
|
||||
contract @mozilla.org/webapprt/clh;1 {6d69c782-40a3-469b-8bfd-3ee366105a4a}
|
||||
category command-line-handler x-default @mozilla.org/webapprt/clh;1
|
||||
|
||||
# ContentPermission.js
|
||||
component {07ef5b2e-88fb-47bd-8cec-d3b0bef11ac4} ContentPermission.js
|
||||
contract @mozilla.org/content-permission/prompt;1 {07ef5b2e-88fb-47bd-8cec-d3b0bef11ac4}
|
||||
|
||||
# DirectoryProvider.js
|
||||
component {e1799fda-4b2f-4457-b671-e0641d95698d} DirectoryProvider.js
|
||||
contract @mozilla.org/webapprt/directory-provider;1 {e1799fda-4b2f-4457-b671-e0641d95698d}
|
||||
category xpcom-directory-providers webapprt-directory-provider @mozilla.org/webapprt/directory-provider;1
|
||||
|
||||
# PaymentUIGlue.js
|
||||
component {ede1124f-72e8-4a31-9567-3270d46f21fb} PaymentUIGlue.js
|
||||
contract @mozilla.org/payment/ui-glue;1 {ede1124f-72e8-4a31-9567-3270d46f21fb}
|
||||
@@ -1,130 +0,0 @@
|
||||
/* 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';
|
||||
|
||||
const { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { BrowserTabActor, BrowserTabList, allAppShellDOMWindows,
|
||||
sendShutdownEvent } = devtools.require("devtools/server/actors/webbrowser");
|
||||
const { RootActor } = devtools.require("devtools/server/actors/root");
|
||||
|
||||
/**
|
||||
* WebappRT-specific actors.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Construct a root actor appropriate for use in a server running in the webapp
|
||||
* runtime. The returned root actor:
|
||||
* - respects the factories registered with DebuggerServer.addGlobalActor,
|
||||
* - uses a WebappTabList to supply tab actors,
|
||||
* - sends all webapprt:webapp window documents a Debugger:Shutdown event
|
||||
* when it exits.
|
||||
*
|
||||
* * @param connection DebuggerServerConnection
|
||||
* The conection to the client.
|
||||
*/
|
||||
function createRootActor(connection)
|
||||
{
|
||||
let parameters = {
|
||||
tabList: new WebappTabList(connection),
|
||||
globalActorFactories: DebuggerServer.globalActorFactories,
|
||||
onShutdown: sendShutdownEvent
|
||||
};
|
||||
return new RootActor(connection, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* A live list of BrowserTabActors representing the current webapp windows,
|
||||
* to be provided to the root actor to answer 'listTabs' requests. In the
|
||||
* webapp runtime, only a single tab per window is ever present.
|
||||
*
|
||||
* @param connection DebuggerServerConnection
|
||||
* The connection in which this list's tab actors may participate.
|
||||
*
|
||||
* @see BrowserTabList for more a extensive description of how tab list objects
|
||||
* work.
|
||||
*/
|
||||
function WebappTabList(connection)
|
||||
{
|
||||
BrowserTabList.call(this, connection);
|
||||
}
|
||||
|
||||
WebappTabList.prototype = Object.create(BrowserTabList.prototype);
|
||||
|
||||
WebappTabList.prototype.constructor = WebappTabList;
|
||||
|
||||
WebappTabList.prototype.getList = function() {
|
||||
let topXULWindow = Services.wm.getMostRecentWindow(this._windowType);
|
||||
|
||||
// As a sanity check, make sure all the actors presently in our map get
|
||||
// picked up when we iterate over all windows.
|
||||
let initialMapSize = this._actorByBrowser.size;
|
||||
let foundCount = 0;
|
||||
|
||||
// To avoid mysterious behavior if windows are closed or opened mid-iteration,
|
||||
// we update the map first, and then make a second pass over it to yield
|
||||
// the actors. Thus, the sequence yielded is always a snapshot of the
|
||||
// actors that were live when we began the iteration.
|
||||
|
||||
// Iterate over all webapprt:webapp XUL windows.
|
||||
for (let win of allAppShellDOMWindows(this._windowType)) {
|
||||
let browser = win.document.getElementById("content");
|
||||
if (!browser) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do we have an existing actor for this browser? If not, create one.
|
||||
let actor = this._actorByBrowser.get(browser);
|
||||
if (actor) {
|
||||
foundCount++;
|
||||
} else {
|
||||
actor = new WebappTabActor(this._connection, browser);
|
||||
this._actorByBrowser.set(browser, actor);
|
||||
}
|
||||
|
||||
actor.selected = (win == topXULWindow);
|
||||
}
|
||||
|
||||
if (this._testing && initialMapSize !== foundCount) {
|
||||
throw Error("_actorByBrowser map contained actors for dead tabs");
|
||||
}
|
||||
|
||||
this._mustNotify = true;
|
||||
this._checkListening();
|
||||
|
||||
return Promise.resolve([actor for ([_, actor] of this._actorByBrowser)]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a tab actor for handling requests to the single tab, like
|
||||
* attaching and detaching. WebappTabActor respects the actor factories
|
||||
* registered with DebuggerServer.addTabActor.
|
||||
*
|
||||
* We override the title of the XUL window in content/webapp.js so here
|
||||
* we need to override the title property to avoid confusion to the user.
|
||||
* We won't return the title of the contained browser, but the title of
|
||||
* the webapp window.
|
||||
*
|
||||
* @param connection DebuggerServerConnection
|
||||
* The conection to the client.
|
||||
* @param browser browser
|
||||
* The browser instance that contains this tab.
|
||||
*/
|
||||
function WebappTabActor(connection, browser)
|
||||
{
|
||||
BrowserTabActor.call(this, connection, browser);
|
||||
}
|
||||
|
||||
WebappTabActor.prototype.constructor = WebappTabActor;
|
||||
|
||||
WebappTabActor.prototype = Object.create(BrowserTabActor.prototype);
|
||||
|
||||
Object.defineProperty(WebappTabActor.prototype, "title", {
|
||||
get: function() {
|
||||
return this.browser.ownerDocument.defaultView.document.title;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
@@ -1,328 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % downloadDTD SYSTEM "chrome://webapprt/locale/downloads/downloads.dtd" >
|
||||
%downloadDTD;
|
||||
]>
|
||||
|
||||
<bindings id="downloadBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="download-base" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
|
||||
<resources>
|
||||
<stylesheet src="chrome://webapprt/skin/downloads/downloads.css"/>
|
||||
</resources>
|
||||
<implementation>
|
||||
<property name="paused">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return parseInt(this.getAttribute("state")) == Components.interfaces.nsIDownloadManager.DOWNLOAD_PAUSED;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<property name="openable">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return parseInt(this.getAttribute("state")) == Components.interfaces.nsIDownloadManager.DOWNLOAD_FINISHED;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<property name="inProgress">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var state = parseInt(this.getAttribute("state"));
|
||||
const dl = Components.interfaces.nsIDownloadManager;
|
||||
return state == dl.DOWNLOAD_NOTSTARTED ||
|
||||
state == dl.DOWNLOAD_QUEUED ||
|
||||
state == dl.DOWNLOAD_DOWNLOADING ||
|
||||
state == dl.DOWNLOAD_PAUSED ||
|
||||
state == dl.DOWNLOAD_SCANNING;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<property name="removable">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var state = parseInt(this.getAttribute("state"));
|
||||
const dl = Components.interfaces.nsIDownloadManager;
|
||||
return state == dl.DOWNLOAD_FINISHED ||
|
||||
state == dl.DOWNLOAD_CANCELED ||
|
||||
state == dl.DOWNLOAD_BLOCKED_PARENTAL ||
|
||||
state == dl.DOWNLOAD_BLOCKED_POLICY ||
|
||||
state == dl.DOWNLOAD_DIRTY ||
|
||||
state == dl.DOWNLOAD_FAILED;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<property name="buttons">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var startEl = document.getAnonymousNodes(this);
|
||||
if (!startEl.length) {
|
||||
startEl = [this];
|
||||
}
|
||||
|
||||
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
return startEl[0].getElementsByTagNameNS(XULNS, "button");
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="download-starting" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" class="name"/>
|
||||
<xul:progressmeter mode="normal" value="0" flex="1"
|
||||
anonid="progressmeter"/>
|
||||
<xul:label value="&starting.label;" class="status"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="center">
|
||||
<xul:button class="cancel mini-button" tooltiptext="&cmd.cancel.label;"
|
||||
cmd="cmd_cancel" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_cancel', this);"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-downloading" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1" class="downloadContentBox">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="2" class="name"/>
|
||||
<xul:hbox>
|
||||
<xul:vbox flex="1">
|
||||
<xul:progressmeter mode="normal" value="0" flex="1"
|
||||
anonid="progressmeter"
|
||||
xbl:inherits="value=progress,mode=progressmode"/>
|
||||
</xul:vbox>
|
||||
<xul:button class="pause mini-button" tooltiptext="&cmd.pause.label;"
|
||||
cmd="cmd_pause" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_pause', this);"/>
|
||||
<xul:button class="cancel mini-button" tooltiptext="&cmd.cancel.label;"
|
||||
cmd="cmd_cancel" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_cancel', this);"/>
|
||||
</xul:hbox>
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip" flex="1"
|
||||
crop="right" class="status"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-paused" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="2" class="name"/>
|
||||
<xul:hbox>
|
||||
<xul:vbox flex="1">
|
||||
<xul:progressmeter mode="normal" value="0" flex="1"
|
||||
anonid="progressmeter"
|
||||
xbl:inherits="value=progress,mode=progressmode"/>
|
||||
</xul:vbox>
|
||||
<xul:button class="resume mini-button" tooltiptext="&cmd.resume.label;"
|
||||
cmd="cmd_resume" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_resume', this);"/>
|
||||
<xul:button class="cancel mini-button" tooltiptext="&cmd.cancel.label;"
|
||||
cmd="cmd_cancel" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_cancel', this);"/>
|
||||
</xul:hbox>
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip" flex="1"
|
||||
crop="right" class="status"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-done" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-canceled" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
<xul:button class="retry mini-button" tooltiptext="&cmd.retry.label;"
|
||||
cmd="cmd_retry" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_retry', this);"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-failed" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
<xul:button class="retry mini-button" tooltiptext="&cmd.retry.label;"
|
||||
cmd="cmd_retry" ondblclick="event.stopPropagation();"
|
||||
oncommand="gDownloadList.performCommand('cmd_retry', this);"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-blocked-parental" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon blockedIcon"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-blocked-policy" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon blockedIcon"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-scanning" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon" validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="2" class="name"/>
|
||||
<xul:hbox>
|
||||
<xul:vbox flex="1">
|
||||
<xul:progressmeter mode="undetermined" flex="1" />
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
<xul:label value="&scanning.label;" class="status"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="download-dirty" extends="chrome://webapprt/content/downloads/download.xml#download-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox pack="center">
|
||||
<xul:image class="downloadTypeIcon blockedIcon"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start" flex="1">
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=target,tooltiptext=target"
|
||||
crop="center" flex="1" class="name"/>
|
||||
<xul:label xbl:inherits="value=dateTime,tooltiptext=dateTimeTip"
|
||||
class="dateTime"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox align="center" flex="1">
|
||||
<xul:label xbl:inherits="value=status,tooltiptext=statusTip"
|
||||
crop="end" flex="1" class="status"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
@@ -1,50 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
richlistitem[type="download"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-starting');
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="0"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-downloading');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="1"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-done');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="2"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-failed');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="3"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-canceled');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="4"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-paused');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="6"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-blocked-parental');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="7"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-scanning');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="8"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-dirty');
|
||||
}
|
||||
|
||||
richlistitem[type="download"][state="9"] {
|
||||
-moz-binding: url('chrome://webapprt/content/downloads/download.xml#download-blocked-policy');
|
||||
}
|
||||
|
||||
/* Only focus buttons in the selected item*/
|
||||
richlistitem[type="download"]:not([selected="true"]) button {
|
||||
-moz-user-focus: none;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
# 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/.
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#ifndef XP_MACOSX
|
||||
#define XP_GNOME 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://webapprt/content/downloads/downloads.css"?>
|
||||
<?xml-stylesheet href="chrome://webapprt/skin/downloads/downloads.css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % downloadManagerDTD SYSTEM "chrome://webapprt/locale/downloads/downloads.dtd">
|
||||
%downloadManagerDTD;
|
||||
<!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
|
||||
%editMenuOverlayDTD;
|
||||
]>
|
||||
|
||||
<window xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="downloadManager" windowtype="Download:Manager"
|
||||
orient="vertical" title="&downloads.title;" statictitle="&downloads.title;"
|
||||
width="&window.width2;" height="&window.height;" screenX="10" screenY="10"
|
||||
persist="width height screenX screenY sizemode"
|
||||
onload="Startup();" onunload="Shutdown();"
|
||||
onclose="return closeWindow(false);">
|
||||
|
||||
<script type="application/javascript" src="chrome://webapprt/content/downloads/downloads.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||
|
||||
<stringbundleset id="downloadSet">
|
||||
<stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
|
||||
<stringbundle id="downloadStrings" src="chrome://mozapps/locale/downloads/downloads.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<!-- Use this commandset for command which do not depened on focus or selection -->
|
||||
<commandset id="generalCommands">
|
||||
<command id="cmd_findDownload" oncommand="gDownloadList.setSearchboxFocus();"/>
|
||||
<command id="cmd_selectAllDownloads" oncommand="gDownloadList.selectAll();"/>
|
||||
<command id="cmd_clearList" oncommand="gDownloadList.clearList();"/>
|
||||
</commandset>
|
||||
|
||||
<keyset id="downloadKeys">
|
||||
<key keycode="VK_RETURN" oncommand="gDownloadList.doDefaultForSelected();"/>
|
||||
<key id="key_pauseResume" key=" " oncommand="gDownloadList.performCommand('cmd_pauseResume');"/>
|
||||
<key id="key_removeFromList" keycode="VK_DELETE" oncommand="gDownloadList.performCommand('cmd_removeFromList');"/>
|
||||
#ifdef XP_MACOSX
|
||||
<key id="key_removeFromList2" keycode="VK_BACK" oncommand="gDownloadList.performCommand('cmd_removeFromList');"/>
|
||||
#endif
|
||||
<key id="key_close" key="&cmd.close.commandKey;" oncommand="closeWindow(true);" modifiers="accel"/>
|
||||
#ifdef XP_GNOME
|
||||
<key id="key_close2" key="&cmd.close2Unix.commandKey;" oncommand="closeWindow(true);" modifiers="accel,shift"/>
|
||||
#else
|
||||
<key id="key_close2" key="&cmd.close2.commandKey;" oncommand="closeWindow(true);" modifiers="accel"/>
|
||||
#endif
|
||||
<key keycode="VK_ESCAPE" oncommand="closeWindow(true);"/>
|
||||
|
||||
<key id="key_findDownload"
|
||||
key="&cmd.find.commandKey;"
|
||||
modifiers="accel"
|
||||
command="cmd_findDownload"/>
|
||||
<key id="key_findDownload2"
|
||||
key="&cmd.search.commandKey;"
|
||||
modifiers="accel"
|
||||
command="cmd_findDownload"/>
|
||||
<key id="key_selectAllDownloads"
|
||||
key="&selectAllCmd.key;"
|
||||
modifiers="accel"
|
||||
command="cmd_selectAllDownloads"/>
|
||||
<key id="pasteKey"
|
||||
key="V"
|
||||
modifiers="accel"
|
||||
oncommand="gDownloadList.pasteHandler();"/>
|
||||
</keyset>
|
||||
|
||||
<vbox id="contextMenuPalette" hidden="true">
|
||||
<menuitem id="menuitem_pause"
|
||||
label="&cmd.pause.label;" accesskey="&cmd.pause.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_pause');"
|
||||
cmd="cmd_pause"/>
|
||||
<menuitem id="menuitem_resume"
|
||||
label="&cmd.resume.label;" accesskey="&cmd.resume.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_resume');"
|
||||
cmd="cmd_resume"/>
|
||||
<menuitem id="menuitem_cancel"
|
||||
label="&cmd.cancel.label;" accesskey="&cmd.cancel.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_cancel');"
|
||||
cmd="cmd_cancel"/>
|
||||
|
||||
<menuitem id="menuitem_open" default="true"
|
||||
label="&cmd.open.label;" accesskey="&cmd.open.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_open');"
|
||||
cmd="cmd_open"/>
|
||||
<menuitem id="menuitem_show"
|
||||
#ifdef XP_MACOSX
|
||||
label="&cmd.showMac.label;"
|
||||
accesskey="&cmd.showMac.accesskey;"
|
||||
#else
|
||||
label="&cmd.show.label;"
|
||||
accesskey="&cmd.show.accesskey;"
|
||||
#endif
|
||||
oncommand="gDownloadList.performCommand('cmd_show');"
|
||||
cmd="cmd_show"/>
|
||||
|
||||
<menuitem id="menuitem_retry" default="true"
|
||||
label="&cmd.retry.label;" accesskey="&cmd.retry.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_retry');"
|
||||
cmd="cmd_retry"/>
|
||||
|
||||
<menuitem id="menuitem_removeFromList"
|
||||
label="&cmd.removeFromList.label;" accesskey="&cmd.removeFromList.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_removeFromList');"
|
||||
cmd="cmd_removeFromList"/>
|
||||
|
||||
<menuseparator id="menuseparator"/>
|
||||
|
||||
<menuitem id="menuitem_openReferrer"
|
||||
label="&cmd.goToDownloadPage.label;"
|
||||
accesskey="&cmd.goToDownloadPage.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_openReferrer');"
|
||||
cmd="cmd_openReferrer"/>
|
||||
|
||||
<menuitem id="menuitem_copyLocation"
|
||||
label="&cmd.copyDownloadLink.label;"
|
||||
accesskey="&cmd.copyDownloadLink.accesskey;"
|
||||
oncommand="gDownloadList.performCommand('cmd_copyLocation');"
|
||||
cmd="cmd_copyLocation"/>
|
||||
|
||||
<menuitem id="menuitem_selectAll"
|
||||
label="&selectAllCmd.label;"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
command="cmd_selectAllDownloads"/>
|
||||
</vbox>
|
||||
|
||||
<menupopup id="downloadContextMenu" onpopupshowing="return gDownloadList.buildContextMenu(event);"/>
|
||||
|
||||
<richlistbox id="downloadView" seltype="multiple" flex="1"
|
||||
context="downloadContextMenu"
|
||||
ondblclick="gDownloadList.onDownloadDblClick(event);"
|
||||
ondragstart="gDownloadList.onDragStart(event);"
|
||||
ondragover="gDownloadList.onDragOver(event);"
|
||||
ondrop="gDownloadList.onDrop(event)">
|
||||
</richlistbox>
|
||||
|
||||
<windowdragbox id="search" align="center">
|
||||
<button id="clearListButton" command="cmd_clearList"
|
||||
label="&cmd.clearList.label;"
|
||||
accesskey="&cmd.clearList.accesskey;"
|
||||
tooltiptext="&cmd.clearList.tooltip;"/>
|
||||
<spacer flex="1"/>
|
||||
<textbox type="search" id="searchbox" class="compact"
|
||||
aria-controls="downloadView"
|
||||
oncommand="gDownloadList.buildList();" placeholder="&searchBox.label;"/>
|
||||
</windowdragbox>
|
||||
|
||||
</window>
|
||||
@@ -1,38 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
function onOK() {
|
||||
window.arguments[0].out = {
|
||||
video: document.getElementById("video").selectedItem.value,
|
||||
audio: document.getElementById("audio").selectedItem.value
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
let videoDevices = window.arguments[0].videoDevices;
|
||||
if (videoDevices.length) {
|
||||
let videoMenu = document.getElementById("video");
|
||||
for (let i = 0; i < videoDevices.length; i++) {
|
||||
videoMenu.appendItem(videoDevices[i].name, i);
|
||||
}
|
||||
videoMenu.selectedIndex = 1;
|
||||
} else {
|
||||
document.getElementById("videoGroup").hidden = true;
|
||||
}
|
||||
|
||||
let audioDevices = window.arguments[0].audioDevices;
|
||||
if (audioDevices.length) {
|
||||
let audioMenu = document.getElementById("audio");
|
||||
for (let i = 0; i < audioDevices.length; i++) {
|
||||
audioMenu.appendItem(audioDevices[i].name, i);
|
||||
}
|
||||
audioMenu.selectedIndex = 1;
|
||||
} else {
|
||||
document.getElementById("audioGroup").hidden = true;
|
||||
}
|
||||
|
||||
window.sizeToContent();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog [
|
||||
<!ENTITY % gum-askDTD SYSTEM "chrome://webapprt/locale/getUserMediaDialog.dtd">
|
||||
%gum-askDTD;
|
||||
]>
|
||||
|
||||
<dialog id="getUserMediaDialog" title="&getUserMediaDialog.title;"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
buttons="accept,cancel"
|
||||
buttonlabelaccept="&getUserMediaDialog.button.accept.label;"
|
||||
buttonaccesskeyaccept="&getUserMediaDialog.button.accept.accesskey;"
|
||||
onload="onLoad()"
|
||||
ondialogaccept="return onOK()"
|
||||
buttonlabelcancel="&getUserMediaDialog.button.cancel.label;"
|
||||
buttonaccesskeycancel="&getUserMediaDialog.button.cancel.accesskey;">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://webapprt/content/getUserMediaDialog.js"/>
|
||||
|
||||
<groupbox id="videoGroup" flex="1">
|
||||
<caption label="&getUserMediaDialog.video.label;"/>
|
||||
<menulist id="video">
|
||||
<menupopup>
|
||||
<menuitem label="&getUserMediaDialog.video.noVideo;" value="-1"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="audioGroup" flex="1">
|
||||
<caption label="&getUserMediaDialog.audio.label;"/>
|
||||
<menulist id="audio">
|
||||
<menupopup>
|
||||
<menuitem label="&getUserMediaDialog.audio.noAudio;" value="-1"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</groupbox>
|
||||
|
||||
</dialog>
|
||||
@@ -1,91 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
/* Note: this script is loaded by both mochitest.js and head.js, so make sure
|
||||
* the code you put here can be evaluated by both! */
|
||||
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
// When WebappsHandler opens an install confirmation dialog for apps we install,
|
||||
// close it, which will be seen as the equivalent of cancelling the install.
|
||||
// This doesn't prevent us from installing those apps, as we listen for the same
|
||||
// notification as WebappsHandler and do the install ourselves. It just
|
||||
// prevents the modal installation confirmation dialogs from hanging tests.
|
||||
Services.ww.registerNotification({
|
||||
observe: function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
// Wait for load because the window is not yet sufficiently initialized.
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
if (win.location == "chrome://global/content/commonDialog.xul" &&
|
||||
win.opener == window) {
|
||||
win.close();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Transmogrify the runtime session into one for the given webapp.
|
||||
*
|
||||
* @param {String} manifestURL
|
||||
* The URL of the webapp's manifest, relative to the base URL.
|
||||
* Note that the base URL points to the *chrome* WebappRT mochitests,
|
||||
* so you must supply an absolute URL to manifests elsewhere.
|
||||
* @param {Object} parameters
|
||||
* The value to pass as the "parameters" argument to
|
||||
* mozIDOMApplicationRegistry.install, e.g., { receipts: ... }.
|
||||
* Use undefined to pass nothing.
|
||||
* @param {Function} onBecome
|
||||
* The callback to call once the transmogrification is complete.
|
||||
*/
|
||||
function becomeWebapp(manifestURL, parameters, onBecome) {
|
||||
let observeInstall = Task.async(function*(subj, topic, data) {
|
||||
Services.obs.removeObserver(observeInstall, "webapps-ask-install");
|
||||
|
||||
// Step 2: Configure the runtime session to represent the app.
|
||||
// We load DOMApplicationRegistry into a local scope to avoid appearing
|
||||
// to leak it.
|
||||
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/Webapps.jsm", scope);
|
||||
Cu.import("resource://webapprt/modules/Startup.jsm", scope);
|
||||
yield scope.DOMApplicationRegistry.confirmInstall(JSON.parse(data));
|
||||
|
||||
let installRecord = JSON.parse(data);
|
||||
installRecord.mm = subj;
|
||||
installRecord.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
|
||||
WebappRT.config = installRecord;
|
||||
WebappRT._configPromise = new Promise((resolve) => resolve());
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("webapprt:webapp");
|
||||
if (!win) {
|
||||
win = Services.ww.openWindow(null,
|
||||
"chrome://webapprt/content/webapp.xul",
|
||||
"_blank",
|
||||
"chrome,dialog=no,resizable,scrollbars,centerscreen",
|
||||
null);
|
||||
}
|
||||
|
||||
// During chrome tests, we use the same window to load all the tests. We
|
||||
// need to change the buildID so that the permissions for the currently
|
||||
// tested application get installed.
|
||||
Services.prefs.setCharPref("webapprt.buildID", WebappRT.config.app.manifestURL);
|
||||
|
||||
// During tests, the webapps registry is already loaded,
|
||||
// but SystemMessageInternal expects to be notified when the registry
|
||||
// start and then when it's ready, so we do that now.
|
||||
Services.obs.notifyObservers(this, "webapps-registry-start", null);
|
||||
Services.obs.notifyObservers(this, "webapps-registry-ready", null);
|
||||
|
||||
yield scope.startup(win);
|
||||
onBecome();
|
||||
});
|
||||
Services.obs.addObserver(observeInstall, "webapps-ask-install", false);
|
||||
|
||||
// Step 1: Install the app at the URL specified by the manifest.
|
||||
navigator.mozApps.install(manifestURL, parameters);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
Services.scriptloader
|
||||
.loadSubScript("chrome://webapprt/content/mochitest-shared.js", this);
|
||||
|
||||
// In test mode, the runtime isn't configured until we tell it to become
|
||||
// an app, which requires us to use DOMApplicationRegistry to install one.
|
||||
// But DOMApplicationRegistry needs to know the location of its registry dir,
|
||||
// so we need to configure the runtime with at least that information.
|
||||
WebappRT.config = {
|
||||
registryDir: Services.dirsvc.get("ProfD", Ci.nsIFile).path,
|
||||
};
|
||||
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
|
||||
becomeWebapp("http://mochi.test:8888/webapprtContent/webapprt/test/content/test.webapp",
|
||||
undefined, function onBecome() {
|
||||
if (window.arguments && window.arguments[0]) {
|
||||
let testUrl = window.arguments[0].QueryInterface(Ci.nsIPropertyBag2).get("url");
|
||||
|
||||
if (testUrl) {
|
||||
let win = Services.wm.getMostRecentWindow("webapprt:webapp");
|
||||
win.document.getElementById("content").setAttribute("src", testUrl);
|
||||
}
|
||||
}
|
||||
|
||||
window.close();
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window id="browserTestHarness"
|
||||
windowtype="webapprt:mochitest"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://webapprt/content/mochitest.js"/>
|
||||
|
||||
<description value="WebappRT Test Shim"/>
|
||||
|
||||
</window>
|
||||
@@ -1,238 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAppBrowser",
|
||||
function() document.getElementById("content"));
|
||||
|
||||
function isSameOrigin(url) {
|
||||
let origin = Services.io.newURI(url, null, null).prePath;
|
||||
return (origin == WebappRT.config.app.origin);
|
||||
}
|
||||
|
||||
let progressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
onLocationChange: function onLocationChange(progress, request, location,
|
||||
flags) {
|
||||
|
||||
// Close tooltip (code adapted from /browser/base/content/browser.js)
|
||||
let pageTooltip = document.getElementById("contentAreaTooltip");
|
||||
let tooltipNode = pageTooltip.triggerNode;
|
||||
if (tooltipNode) {
|
||||
// Optimise for the common case
|
||||
if (progress.isTopLevel) {
|
||||
pageTooltip.hidePopup();
|
||||
}
|
||||
else {
|
||||
for (let tooltipWindow = tooltipNode.ownerDocument.defaultView;
|
||||
tooltipWindow != tooltipWindow.parent;
|
||||
tooltipWindow = tooltipWindow.parent) {
|
||||
if (tooltipWindow == progress.DOMWindow) {
|
||||
pageTooltip.hidePopup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the title of the window to the name of the webapp, adding the origin
|
||||
// of the page being loaded if it's from a different origin than the app
|
||||
// (per security bug 741955, which specifies that other-origin pages loaded
|
||||
// in runtime windows must be identified in chrome).
|
||||
let title = WebappRT.localeManifest.name;
|
||||
if (!isSameOrigin(location.spec)) {
|
||||
title = location.prePath + " - " + title;
|
||||
}
|
||||
document.documentElement.setAttribute("title", title);
|
||||
},
|
||||
|
||||
onStateChange: function onStateChange(aProgress, aRequest, aFlags, aStatus) {
|
||||
if (aRequest instanceof Ci.nsIChannel &&
|
||||
aFlags & Ci.nsIWebProgressListener.STATE_START &&
|
||||
aFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onOpenWindow(event) {
|
||||
let name = event.detail.name;
|
||||
|
||||
if (name == "_blank") {
|
||||
let uri = Services.io.newURI(event.detail.url, null, null);
|
||||
|
||||
// Direct the URL to the browser.
|
||||
Cc["@mozilla.org/uriloader/external-protocol-service;1"].
|
||||
getService(Ci.nsIExternalProtocolService).
|
||||
getProtocolHandlerInfo(uri.scheme).
|
||||
launchWithURI(uri);
|
||||
} else {
|
||||
let win = window.openDialog("chrome://webapprt/content/webapp.xul",
|
||||
name,
|
||||
"chrome,dialog=no,resizable," + event.detail.features);
|
||||
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
|
||||
#ifndef XP_WIN
|
||||
#ifndef XP_MACOSX
|
||||
if (isSameOrigin(event.detail.url)) {
|
||||
// On non-Windows platforms, we open new windows in fullscreen mode
|
||||
// if the opener window is in fullscreen mode, so we hide the menubar;
|
||||
// but on Mac we don't need to hide the menubar.
|
||||
if (document.mozFullScreenElement) {
|
||||
win.document.getElementById("main-menubar").style.display = "none";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
win.document.getElementById("content").docShell.setIsApp(WebappRT.appID);
|
||||
win.document.getElementById("content").setAttribute("src", event.detail.url);
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
window.removeEventListener("load", onLoad, false);
|
||||
|
||||
gAppBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION |
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
|
||||
updateMenuItems();
|
||||
|
||||
gAppBrowser.addEventListener("mozbrowseropenwindow", onOpenWindow);
|
||||
}
|
||||
window.addEventListener("load", onLoad, false);
|
||||
|
||||
function onUnload() {
|
||||
gAppBrowser.removeProgressListener(progressListener);
|
||||
gAppBrowser.removeEventListener("mozbrowseropenwindow", onOpenWindow);
|
||||
}
|
||||
window.addEventListener("unload", onUnload, false);
|
||||
|
||||
// Fullscreen handling.
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
document.addEventListener('mozfullscreenchange', function() {
|
||||
if (document.mozFullScreenElement) {
|
||||
document.getElementById("main-menubar").style.display = "none";
|
||||
} else {
|
||||
document.getElementById("main-menubar").style.display = "";
|
||||
}
|
||||
}, false);
|
||||
#endif
|
||||
|
||||
// On Mac, we dynamically create the label for the Quit menuitem, using
|
||||
// a string property to inject the name of the webapp into it.
|
||||
let updateMenuItems = Task.async(function*() {
|
||||
#ifdef XP_MACOSX
|
||||
yield WebappRT.configPromise;
|
||||
|
||||
let manifest = WebappRT.localeManifest;
|
||||
let bundle =
|
||||
Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
|
||||
let quitLabel = bundle.formatStringFromName("quitApplicationCmdMac.label",
|
||||
[manifest.name], 1);
|
||||
let hideLabel = bundle.formatStringFromName("hideApplicationCmdMac.label",
|
||||
[manifest.name], 1);
|
||||
document.getElementById("menu_FileQuitItem").setAttribute("label", quitLabel);
|
||||
document.getElementById("menu_mac_hide_app").setAttribute("label", hideLabel);
|
||||
#endif
|
||||
});
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
let gEditUIVisible = true;
|
||||
#endif
|
||||
|
||||
function updateEditUIVisibility() {
|
||||
#ifndef XP_MACOSX
|
||||
let editMenuPopupState = document.getElementById("menu_EditPopup").state;
|
||||
let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
|
||||
|
||||
// The UI is visible if the Edit menu is opening or open, if the context menu
|
||||
// is open, or if the toolbar has been customized to include the Cut, Copy,
|
||||
// or Paste toolbar buttons.
|
||||
gEditUIVisible = editMenuPopupState == "showing" ||
|
||||
editMenuPopupState == "open" ||
|
||||
contextMenuPopupState == "showing" ||
|
||||
contextMenuPopupState == "open";
|
||||
|
||||
// If UI is visible, update the edit commands' enabled state to reflect
|
||||
// whether or not they are actually enabled for the current focus/selection.
|
||||
if (gEditUIVisible) {
|
||||
goUpdateGlobalEditMenuItems();
|
||||
}
|
||||
|
||||
// Otherwise, enable all commands, so that keyboard shortcuts still work,
|
||||
// then lazily determine their actual enabled state when the user presses
|
||||
// a keyboard shortcut.
|
||||
else {
|
||||
goSetCommandEnabled("cmd_undo", true);
|
||||
goSetCommandEnabled("cmd_redo", true);
|
||||
goSetCommandEnabled("cmd_cut", true);
|
||||
goSetCommandEnabled("cmd_copy", true);
|
||||
goSetCommandEnabled("cmd_paste", true);
|
||||
goSetCommandEnabled("cmd_selectAll", true);
|
||||
goSetCommandEnabled("cmd_delete", true);
|
||||
goSetCommandEnabled("cmd_switchTextDirection", true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Context menu handling code.
|
||||
// At the moment there isn't any built-in menu, we only support HTML5 custom
|
||||
// menus.
|
||||
|
||||
let gContextMenu = null;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
||||
return new tmp.PageMenu();
|
||||
});
|
||||
|
||||
function showContextMenu(aEvent, aXULMenu) {
|
||||
if (aEvent.target != aXULMenu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
gContextMenu = new nsContextMenu(aXULMenu);
|
||||
if (gContextMenu.shouldDisplay) {
|
||||
updateEditUIVisibility();
|
||||
}
|
||||
|
||||
return gContextMenu.shouldDisplay;
|
||||
}
|
||||
|
||||
function hideContextMenu(aEvent, aXULMenu) {
|
||||
if (aEvent.target != aXULMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
gContextMenu = null;
|
||||
|
||||
updateEditUIVisibility();
|
||||
}
|
||||
|
||||
function nsContextMenu(aXULMenu) {
|
||||
this.initMenu(aXULMenu);
|
||||
}
|
||||
|
||||
nsContextMenu.prototype = {
|
||||
initMenu: function(aXULMenu) {
|
||||
this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(document.popupNode,
|
||||
aXULMenu);
|
||||
this.shouldDisplay = this.hasPageMenu;
|
||||
},
|
||||
};
|
||||
@@ -1,168 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % webappDTD SYSTEM "chrome://webapprt/locale/webapp.dtd">
|
||||
%webappDTD;
|
||||
]>
|
||||
|
||||
<window windowtype="webapprt:webapp"
|
||||
id="default"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
width="1024" height="768"
|
||||
fullscreenbutton="true"
|
||||
persist="screenX screenY width height sizemode"
|
||||
>
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||
<script type="application/javascript" src="chrome://webapprt/content/webapp.js"/>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<command id="cmd_quitApplication" oncommand="goQuitApplication()"/>
|
||||
<commandset id="editMenuCommands"/>
|
||||
</commandset>
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key id="key_undo"
|
||||
key="&undoCmd.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/>
|
||||
<key id="key_cut"
|
||||
key="&cutCmd.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_copy"
|
||||
key="©Cmd.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_paste"
|
||||
key="&pasteCmd.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
|
||||
<key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
|
||||
<key id="key_quitApplication"
|
||||
key="&quitApplicationCmdUnix.key;"
|
||||
command="cmd_quitApplication"
|
||||
modifiers="accel"/>
|
||||
<key id="key_hideThisAppCmdMac"
|
||||
key="&hideThisAppCmdMac.key;"
|
||||
modifiers="accel"/>
|
||||
<key id="key_hideOtherAppsCmdMac"
|
||||
key="&hideOtherAppsCmdMac.key;"
|
||||
modifiers="accel,alt"/>
|
||||
</keyset>
|
||||
|
||||
<menubar id="main-menubar">
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
<!-- On Mac, the Quit item gets moved to the Application menu by nsMenuBarX.
|
||||
- And right now it's the only item in the File menu. So if we put it
|
||||
- into that menu on Mac, the File menu shows up empty on that OS.
|
||||
- To work around that problem, we put the item into the Edit menu on Mac
|
||||
- (from which nsMenuBarX still moves it properly), and we don't create
|
||||
- the File menu in the first place on that OS.
|
||||
-
|
||||
- But if you are adding a persistent item to the File menu on Mac,
|
||||
- then that workaround is no longer necessary, and you can move the Quit
|
||||
- item up here. -->
|
||||
<menu id="file-menu" label="&fileMenu.label;"
|
||||
accesskey="&fileMenu.accesskey;">
|
||||
<menupopup id="menu_FilePopup">
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
#ifdef XP_WIN
|
||||
label="&quitApplicationCmdWin.label;"
|
||||
accesskey="&quitApplicationCmdWin.accesskey;"
|
||||
#else
|
||||
label="&quitApplicationCmd.label;"
|
||||
accesskey="&quitApplicationCmd.accesskey;"
|
||||
#endif
|
||||
#ifdef XP_UNIX
|
||||
key="key_quitApplication"
|
||||
#endif
|
||||
command="cmd_quitApplication"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
#endif
|
||||
|
||||
<menu id="edit-menu" label="&editMenu.label;"
|
||||
accesskey="&editMenu.accesskey;">
|
||||
<menupopup id="menu_EditPopup"
|
||||
onpopupshowing="updateEditUIVisibility()"
|
||||
onpopuphidden="updateEditUIVisibility()">
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
<!-- These items get moved to the Application menu by nsMenuBarX.
|
||||
- They can live in any menu.
|
||||
-
|
||||
- See the comment on the File menu above for why the Quit item is
|
||||
- here, and note that JavaScript code dynamically updates the labels
|
||||
- of the Quit and Hide items, which include the name of the app. -->
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
label="&quitApplicationCmd.label;"
|
||||
key="key_quitApplication"
|
||||
command="cmd_quitApplication"/>
|
||||
<menuitem id="menu_mac_hide_app"
|
||||
key="key_hideThisAppCmdMac"/>
|
||||
<menuitem id="menu_mac_hide_others"
|
||||
label="&hideOtherAppsCmdMac.label;"
|
||||
key="key_hideOtherAppsCmdMac"/>
|
||||
<menuitem id="menu_mac_show_all" label="&showAllAppsCmdMac.label;"/>
|
||||
#endif
|
||||
|
||||
<menuitem id="menu_undo"
|
||||
label="&undoCmd.label;"
|
||||
key="key_undo"
|
||||
accesskey="&undoCmd.accesskey;"
|
||||
command="cmd_undo"/>
|
||||
<menuitem id="menu_redo"
|
||||
label="&redoCmd.label;"
|
||||
key="key_redo"
|
||||
accesskey="&redoCmd.accesskey;"
|
||||
command="cmd_redo"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_cut"
|
||||
label="&cutCmd.label;"
|
||||
key="key_cut"
|
||||
accesskey="&cutCmd.accesskey;"
|
||||
command="cmd_cut"/>
|
||||
<menuitem id="menu_copy"
|
||||
label="©Cmd.label;"
|
||||
key="key_copy"
|
||||
accesskey="©Cmd.accesskey;"
|
||||
command="cmd_copy"/>
|
||||
<menuitem id="menu_paste"
|
||||
label="&pasteCmd.label;"
|
||||
key="key_paste"
|
||||
accesskey="&pasteCmd.accesskey;"
|
||||
command="cmd_paste"/>
|
||||
<menuitem id="menu_delete"
|
||||
label="&deleteCmd.label;"
|
||||
key="key_delete"
|
||||
accesskey="&deleteCmd.accesskey;"
|
||||
command="cmd_delete"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_selectAll"
|
||||
label="&selectAllCmd.label;"
|
||||
key="key_selectAll"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
command="cmd_selectAll"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
<browser type="content-primary" id="content" flex="1" context="contentAreaContextMenu" tooltip="contentAreaTooltip" />
|
||||
|
||||
<popupset>
|
||||
<menupopup id="contentAreaContextMenu" pagemenu="start"
|
||||
onpopupshowing="return showContextMenu(event, this)"
|
||||
onpopuphiding="hideContextMenu(event, this)">
|
||||
</menupopup>
|
||||
<tooltip id="contentAreaTooltip" page="true" />
|
||||
</popupset>
|
||||
|
||||
</window>
|
||||
@@ -1 +0,0 @@
|
||||
XPI_ROOT_APPID=webapprt@mozilla.org
|
||||
@@ -1,14 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
NSDISTMODE = copy
|
||||
|
||||
PROGRAMS_DEST = $(DIST)/bin
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
|
||||
webapprt.$(OBJ_SUFFIX): $(DEPTH)/config/buildid
|
||||
@@ -1,28 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
# mozglue is statically linked into GoannaPrograms on gtk builds, so
|
||||
# we can use GoannaProgram, contrary to other platforms.
|
||||
GoannaProgram('webapprt-stub')
|
||||
|
||||
SOURCES += [
|
||||
'webapprt.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
GENERATED_INCLUDES += ['/build']
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/xre',
|
||||
'/xpcom/base',
|
||||
'/xpcom/build',
|
||||
]
|
||||
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
OS_LIBS += CONFIG['TK_LIBS']
|
||||
@@ -1,408 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/* 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/. */
|
||||
|
||||
// GTK headers
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
// Linux headers
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
// Mozilla headers
|
||||
#include "nsIFile.h"
|
||||
#include "nsINIParser.h"
|
||||
#include "nsXPCOMGlue.h"
|
||||
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "BinaryPath.h"
|
||||
|
||||
const char kAPP_INI[] = "application.ini";
|
||||
const char kWEBAPP_INI[] = "webapp.ini";
|
||||
const char kWEBAPP_JSON[] = "webapp.json";
|
||||
const char kWEBAPP_PACKAGE[] = "application.zip";
|
||||
const char kWEBAPPRT_INI[] = "webapprt.ini";
|
||||
const char kWEBAPPRT_PATH[] = "webapprt";
|
||||
const char kAPP_ENV_VAR[] = "XUL_APP_FILE";
|
||||
const char kAPP_RT[] = "webapprt-stub";
|
||||
|
||||
int* pargc;
|
||||
char*** pargv;
|
||||
char profile[MAXPATHLEN];
|
||||
bool isProfileOverridden = false;
|
||||
|
||||
XRE_GetFileFromPathType XRE_GetFileFromPath;
|
||||
XRE_CreateAppDataType XRE_CreateAppData;
|
||||
XRE_FreeAppDataType XRE_FreeAppData;
|
||||
XRE_mainType XRE_main;
|
||||
|
||||
const nsDynamicFunctionLoad kXULFuncs[] = {
|
||||
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
|
||||
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
|
||||
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
|
||||
{ "XRE_main", (NSFuncPtr*) &XRE_main },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
class ScopedLogging
|
||||
{
|
||||
public:
|
||||
ScopedLogging() { NS_LogInit(); }
|
||||
~ScopedLogging() { NS_LogTerm(); }
|
||||
};
|
||||
|
||||
// Copied from toolkit/xre/nsAppData.cpp.
|
||||
void SetAllocatedString(const char *&str, const char *newvalue)
|
||||
{
|
||||
NS_Free(const_cast<char*>(str));
|
||||
if (newvalue) {
|
||||
str = NS_strdup(newvalue);
|
||||
}
|
||||
else {
|
||||
str = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to open a dialog box displaying the message provided
|
||||
void ErrorDialog(const char* message)
|
||||
{
|
||||
gtk_init(pargc, pargv);
|
||||
|
||||
GtkWidget* dialog = gtk_message_dialog_new(nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
|
||||
gtk_window_set_title(GTK_WINDOW(dialog), "Error launching webapp");
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), false);
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
// Function to get the parent dir of a file
|
||||
void GetDirFromPath(char* parentDir, char* filePath)
|
||||
{
|
||||
char* base = strrchr(filePath, '/');
|
||||
|
||||
if (!base) {
|
||||
strcpy(parentDir, ".");
|
||||
}
|
||||
else {
|
||||
while (base > filePath && *base == '/')
|
||||
base--;
|
||||
|
||||
int len = 1 + base - filePath;
|
||||
strncpy(parentDir, filePath, len);
|
||||
parentDir[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyFile(const char* inputFile, const char* outputFile)
|
||||
{
|
||||
// Open input file
|
||||
int inputFD = open(inputFile, O_RDONLY);
|
||||
if (!inputFD)
|
||||
return false;
|
||||
|
||||
// Open output file
|
||||
int outputFD = creat(outputFile, S_IRWXU);
|
||||
if (!outputFD)
|
||||
return false;
|
||||
|
||||
// Copy file
|
||||
char buf[BUFSIZ];
|
||||
ssize_t bytesRead;
|
||||
|
||||
while ((bytesRead = read(inputFD, buf, BUFSIZ)) > 0) {
|
||||
ssize_t bytesWritten = write(outputFD, buf, bytesRead);
|
||||
if (bytesWritten < 0) {
|
||||
bytesRead = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close file descriptors
|
||||
close(inputFD);
|
||||
close(outputFD);
|
||||
|
||||
return (bytesRead >= 0);
|
||||
}
|
||||
|
||||
bool GRELoadAndLaunch(const char* firefoxDir, bool silentFail)
|
||||
{
|
||||
char xpcomDllPath[MAXPATHLEN];
|
||||
snprintf(xpcomDllPath, MAXPATHLEN, "%s/%s", firefoxDir, XPCOM_DLL);
|
||||
|
||||
if (silentFail && access(xpcomDllPath, F_OK) != 0)
|
||||
return false;
|
||||
|
||||
if (NS_FAILED(XPCOMGlueStartup(xpcomDllPath))) {
|
||||
ErrorDialog("Couldn't load the XPCOM library");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_FAILED(XPCOMGlueLoadXULFunctions(kXULFuncs))) {
|
||||
ErrorDialog("Couldn't load libxul");
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: The GRE has successfully loaded, so we can use XPCOM now
|
||||
{ // Scope for any XPCOM stuff we create
|
||||
ScopedLogging log;
|
||||
|
||||
// Get the path to the runtime
|
||||
char rtPath[MAXPATHLEN];
|
||||
snprintf(rtPath, MAXPATHLEN, "%s/%s", firefoxDir, kWEBAPPRT_PATH);
|
||||
|
||||
// Get the path to the runtime's INI file
|
||||
char rtIniPath[MAXPATHLEN];
|
||||
snprintf(rtIniPath, MAXPATHLEN, "%s/%s", rtPath, kWEBAPPRT_INI);
|
||||
|
||||
// Load the runtime's INI from its path
|
||||
nsCOMPtr<nsIFile> rtINI;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtIniPath, getter_AddRefs(rtINI)))) {
|
||||
ErrorDialog("Couldn't load the runtime INI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exists;
|
||||
nsresult rv = rtINI->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists) {
|
||||
ErrorDialog("The runtime INI doesn't exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsXREAppData *webShellAppData;
|
||||
if (NS_FAILED(XRE_CreateAppData(rtINI, &webShellAppData))) {
|
||||
ErrorDialog("Couldn't read WebappRT application.ini");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isProfileOverridden) {
|
||||
SetAllocatedString(webShellAppData->profile, profile);
|
||||
// nsXREAppData::name is used for the class name part of the WM_CLASS
|
||||
// property. Set it so that the DE can match our window to the correct
|
||||
// launcher.
|
||||
char programClass[MAXPATHLEN];
|
||||
snprintf(programClass, MAXPATHLEN, "owa-%s", profile);
|
||||
SetAllocatedString(webShellAppData->name, programClass);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtPath, getter_AddRefs(directory)))) {
|
||||
ErrorDialog("Couldn't open runtime directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> xreDir;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(firefoxDir, getter_AddRefs(xreDir)))) {
|
||||
ErrorDialog("Couldn't open XRE directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
xreDir.forget(&webShellAppData->xreDirectory);
|
||||
NS_IF_RELEASE(webShellAppData->directory);
|
||||
directory.forget(&webShellAppData->directory);
|
||||
|
||||
XRE_main(*pargc, *pargv, webShellAppData, 0);
|
||||
|
||||
XRE_FreeAppData(webShellAppData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyAndRelaunch(const char* firefoxDir, const char* curExePath)
|
||||
{
|
||||
char newExePath[MAXPATHLEN];
|
||||
snprintf(newExePath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_RT);
|
||||
|
||||
if (unlink(curExePath) == -1) {
|
||||
ErrorDialog("Couldn't remove the old webapprt-stub executable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CopyFile(newExePath, curExePath)) {
|
||||
ErrorDialog("Couldn't copy the new webapprt-stub executable");
|
||||
return;
|
||||
}
|
||||
|
||||
execv(curExePath, *pargv);
|
||||
|
||||
ErrorDialog("Couldn't execute the new webapprt-stub executable");
|
||||
}
|
||||
|
||||
void RemoveApplication(nsINIParser& parser, const char* curExeDir, const char* profile) {
|
||||
if (!isProfileOverridden) {
|
||||
// Remove the desktop entry file.
|
||||
char desktopEntryFilePath[MAXPATHLEN];
|
||||
|
||||
char* dataDir = getenv("XDG_DATA_HOME");
|
||||
|
||||
if (dataDir && *dataDir) {
|
||||
snprintf(desktopEntryFilePath, MAXPATHLEN, "%s/applications/owa-%s.desktop", dataDir, profile);
|
||||
} else {
|
||||
char* home = getenv("HOME");
|
||||
snprintf(desktopEntryFilePath, MAXPATHLEN, "%s/.local/share/applications/owa-%s.desktop", home, profile);
|
||||
}
|
||||
|
||||
unlink(desktopEntryFilePath);
|
||||
}
|
||||
|
||||
// Remove the files from the installation directory.
|
||||
char webAppIniPath[MAXPATHLEN];
|
||||
snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI);
|
||||
unlink(webAppIniPath);
|
||||
|
||||
char curExePath[MAXPATHLEN];
|
||||
snprintf(curExePath, MAXPATHLEN, "%s/%s", curExeDir, kAPP_RT);
|
||||
unlink(curExePath);
|
||||
|
||||
char webAppJsonPath[MAXPATHLEN];
|
||||
snprintf(webAppJsonPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_JSON);
|
||||
unlink(webAppJsonPath);
|
||||
|
||||
char iconPath[MAXPATHLEN];
|
||||
snprintf(iconPath, MAXPATHLEN, "%s/icon.png", curExeDir);
|
||||
unlink(iconPath);
|
||||
|
||||
char packagePath[MAXPATHLEN];
|
||||
snprintf(packagePath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_PACKAGE);
|
||||
unlink(packagePath);
|
||||
|
||||
char appName[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Name", appName, MAXPATHLEN))) {
|
||||
strcpy(appName, profile);
|
||||
}
|
||||
|
||||
char uninstallMsg[MAXPATHLEN];
|
||||
if (NS_SUCCEEDED(parser.GetString("Webapp", "UninstallMsg", uninstallMsg, MAXPATHLEN))) {
|
||||
/**
|
||||
* The only difference between libnotify.so.4 and libnotify.so.1 for these symbols
|
||||
* is that notify_notification_new takes three arguments in libnotify.so.4 and
|
||||
* four in libnotify.so.1.
|
||||
* Passing the fourth argument as nullptr is binary compatible.
|
||||
*/
|
||||
typedef void (*notify_init_t)(const char*);
|
||||
typedef void* (*notify_notification_new_t)(const char*, const char*, const char*, const char*);
|
||||
typedef void (*notify_notification_show_t)(void*, void**);
|
||||
|
||||
void *handle = dlopen("libnotify.so.4", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
handle = dlopen("libnotify.so.1", RTLD_LAZY);
|
||||
if (!handle)
|
||||
return;
|
||||
}
|
||||
|
||||
notify_init_t nn_init = (notify_init_t)(uintptr_t)dlsym(handle, "notify_init");
|
||||
notify_notification_new_t nn_new = (notify_notification_new_t)(uintptr_t)dlsym(handle, "notify_notification_new");
|
||||
notify_notification_show_t nn_show = (notify_notification_show_t)(uintptr_t)dlsym(handle, "notify_notification_show");
|
||||
if (!nn_init || !nn_new || !nn_show) {
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_init(appName);
|
||||
|
||||
void* n = nn_new(uninstallMsg, nullptr, "dialog-information", nullptr);
|
||||
|
||||
nn_show(n, nullptr);
|
||||
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pargc = &argc;
|
||||
pargv = &argv;
|
||||
|
||||
// Get current executable path
|
||||
char curExePath[MAXPATHLEN];
|
||||
if (NS_FAILED(mozilla::BinaryPath::Get(argv[0], curExePath))) {
|
||||
ErrorDialog("Couldn't read current executable path");
|
||||
return 255;
|
||||
}
|
||||
char curExeDir[MAXPATHLEN];
|
||||
GetDirFromPath(curExeDir, curExePath);
|
||||
|
||||
bool removeApp = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-profile") || !strcmp(argv[i], "--profile")) {
|
||||
isProfileOverridden = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-remove") || !strcmp(argv[i], "--remove")) {
|
||||
removeApp = true;
|
||||
}
|
||||
}
|
||||
|
||||
char firefoxDir[MAXPATHLEN];
|
||||
|
||||
// Check if Firefox is in the same directory as the webapp runtime.
|
||||
// This is the case for webapprt chrome and content tests.
|
||||
if (GRELoadAndLaunch(curExeDir, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set up webAppIniPath with path to webapp.ini
|
||||
char webAppIniPath[MAXPATHLEN];
|
||||
snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI);
|
||||
|
||||
// Open webapp.ini as an INI file
|
||||
nsINIParser parser;
|
||||
if (NS_FAILED(parser.Init(webAppIniPath))) {
|
||||
ErrorDialog("Couldn't open webapp.ini");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set up our environment to know where webapp.ini was loaded from
|
||||
if (setenv(kAPP_ENV_VAR, webAppIniPath, 1) == -1) {
|
||||
ErrorDialog("Couldn't set up app environment");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Get profile dir from webapp.ini
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't retrieve profile from web app INI file");
|
||||
return 255;
|
||||
}
|
||||
|
||||
if (removeApp) {
|
||||
RemoveApplication(parser, curExeDir, profile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the location of Firefox from our webapp.ini
|
||||
if (NS_FAILED(parser.GetString("WebappRT", "InstallDir", firefoxDir, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't find your Firefox install directory.");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set up appIniPath with path to application.ini.
|
||||
// This is in the Firefox installation directory.
|
||||
char appIniPath[MAXPATHLEN];
|
||||
snprintf(appIniPath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_INI);
|
||||
|
||||
if (NS_FAILED(parser.Init(appIniPath))) {
|
||||
ErrorDialog("This app requires that Firefox version 16 or above is installed."
|
||||
" Firefox 16+ has not been detected.");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Get buildid of Firefox we're trying to load (MAXPATHLEN only for convenience)
|
||||
char buildid[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("App", "BuildID", buildid, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't read BuildID from Firefox application.ini");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// If WebAppRT version == Firefox version, load XUL and execute the application
|
||||
if (!strcmp(buildid, NS_STRINGIFY(GRE_BUILDID))) {
|
||||
if (GRELoadAndLaunch(firefoxDir, false))
|
||||
return 0;
|
||||
}
|
||||
// Else, copy WebAppRT from Firefox installation and re-execute the process
|
||||
else
|
||||
CopyAndRelaunch(firefoxDir, curExePath);
|
||||
|
||||
return 255;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
webapprt.jar:
|
||||
% content webapprt %content/
|
||||
* content/webapp.js (content/webapp.js)
|
||||
* content/webapp.xul (content/webapp.xul)
|
||||
content/getUserMediaDialog.xul (content/getUserMediaDialog.xul)
|
||||
content/getUserMediaDialog.js (content/getUserMediaDialog.js)
|
||||
content/mochitest-shared.js (content/mochitest-shared.js)
|
||||
content/mochitest.js (content/mochitest.js)
|
||||
content/mochitest.xul (content/mochitest.xul)
|
||||
content/dbg-webapp-actors.js (content/dbg-webapp-actors.js)
|
||||
* content/downloads/downloads.xul (content/downloads/downloads.xul)
|
||||
content/downloads/downloads.js (content/downloads/downloads.js)
|
||||
content/downloads/downloads.css (content/downloads/downloads.css)
|
||||
content/downloads/download.xml (content/downloads/download.xml)
|
||||
@@ -1,10 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE: This file must be saved as UTF8
|
||||
# LOCALIZATION NOTE: $AppName will be replaced with the (already localized)
|
||||
# name of the webapp being uninstalled.
|
||||
|
||||
^UninstallCaption=$AppName Uninstall
|
||||
UN_CONFIRM_UNINSTALL=$AppName will be uninstalled from your computer.
|
||||
@@ -1,52 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE (window.width2, window.height): These values should be
|
||||
close to the golden ratio (1.618:1) while making sure it's wide enough for long
|
||||
file names and tall enough to hint that there are more downloads in the list -->
|
||||
<!ENTITY window.width2 "485">
|
||||
<!ENTITY window.height "300">
|
||||
|
||||
<!ENTITY starting.label "Starting…">
|
||||
<!ENTITY scanning.label "Scanning for viruses…">
|
||||
|
||||
<!ENTITY downloads.title "Downloads">
|
||||
|
||||
<!ENTITY cmd.pause.label "Pause">
|
||||
<!ENTITY cmd.pause.accesskey "P">
|
||||
<!ENTITY cmd.resume.label "Resume">
|
||||
<!ENTITY cmd.resume.accesskey "R">
|
||||
<!ENTITY cmd.cancel.label "Cancel">
|
||||
<!ENTITY cmd.cancel.accesskey "C">
|
||||
<!ENTITY cmd.show.label "Open Containing Folder">
|
||||
<!ENTITY cmd.show.accesskey "F">
|
||||
<!ENTITY cmd.showMac.label "Show in Finder">
|
||||
<!ENTITY cmd.showMac.accesskey "F">
|
||||
<!ENTITY cmd.open.label "Open">
|
||||
<!ENTITY cmd.open.accesskey "O">
|
||||
<!ENTITY cmd.openWith.label "Open With…">
|
||||
<!ENTITY cmd.openWith.accesskey "h">
|
||||
<!ENTITY cmd.retry.label "Retry">
|
||||
<!ENTITY cmd.retry.accesskey "R">
|
||||
<!ENTITY cmd.goToDownloadPage.label "Go to Download Page">
|
||||
<!ENTITY cmd.goToDownloadPage.accesskey "G">
|
||||
<!ENTITY cmd.copyDownloadLink.label "Copy Download Link">
|
||||
<!ENTITY cmd.copyDownloadLink.accesskey "L">
|
||||
<!ENTITY cmd.removeFromList.label "Remove From List">
|
||||
<!ENTITY cmd.removeFromList.accesskey "e">
|
||||
|
||||
<!ENTITY cmd.close.commandKey "w">
|
||||
<!ENTITY cmd.close2.commandKey "j">
|
||||
<!ENTITY cmd.close2Unix.commandKey "y">
|
||||
<!ENTITY cmd.clearList.label "Clear List">
|
||||
<!ENTITY cmd.clearList.tooltip "Removes completed, canceled, and failed downloads from the list">
|
||||
<!ENTITY cmd.clearList.accesskey "C">
|
||||
<!ENTITY cmd.find.commandKey "f">
|
||||
<!ENTITY cmd.search.commandKey "k">
|
||||
|
||||
<!ENTITY closeWhenDone.label "Close when downloads complete">
|
||||
<!ENTITY closeWhenDone.tooltip "Closes the Downloads window when all files are done downloading">
|
||||
|
||||
<!ENTITY showFolder.label "Show this Folder">
|
||||
<!ENTITY searchBox.label "Search…">
|
||||
@@ -1,17 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE: These are localized strings for the getUserMedia dialog
|
||||
- to ask permissions in the webapp runtime. -->
|
||||
|
||||
<!ENTITY getUserMediaDialog.title "Media Sharing">
|
||||
<!ENTITY getUserMediaDialog.button.accept.label "Share">
|
||||
<!ENTITY getUserMediaDialog.button.accept.accesskey "S">
|
||||
<!ENTITY getUserMediaDialog.button.cancel.label "Cancel">
|
||||
<!ENTITY getUserMediaDialog.button.cancel.accesskey "n">
|
||||
|
||||
<!ENTITY getUserMediaDialog.video.label "Select camera">
|
||||
<!ENTITY getUserMediaDialog.video.noVideo "No video">
|
||||
<!ENTITY getUserMediaDialog.audio.label "Select microphone">
|
||||
<!ENTITY getUserMediaDialog.audio.noAudio "No audio">
|
||||
@@ -1,36 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
malformedURI=The URL is not valid and cannot be loaded.
|
||||
fileNotFound=The file %S cannot be found. Please check the location and try again.
|
||||
dnsNotFound=%S could not be found. Please check the name and try again.
|
||||
unknownProtocolFound=One of the following %S is not a registered protocol or is not allowed in this context.
|
||||
connectionFailure=The connection was refused when attempting to contact %S.
|
||||
netInterrupt=The connection to %S has terminated unexpectedly. Some data may have been transferred.
|
||||
netTimeout=The operation timed out when attempting to contact %S.
|
||||
redirectLoop=A server is redirecting a request in a way that will never complete.
|
||||
confirmRepostPrompt=To continue, the application must send information that will repeat an action (such as a search or order confirmation) that was performed earlier.
|
||||
resendButton.label=Resend
|
||||
unknownSocketType=The application doesn't know how to communicate with the server.
|
||||
netReset=The connection to the server was reset while the application was loading.
|
||||
notCached=The application requested a document which is no longer available.
|
||||
netOffline=The application is currently in offline mode and can't access the network.
|
||||
isprinting=The document cannot change while Printing or in Print Preview.
|
||||
deniedPortAccess=The application tried to access a network port that it should not have access to. The application has canceled the request for your protection.
|
||||
proxyResolveFailure=The application is configured to use a proxy server that can't be found.
|
||||
proxyConnectFailure=The application is configured to use a proxy server that is refusing connections.
|
||||
contentEncodingError=The application received a response from a server which used an invalid or unsupported form of compression.
|
||||
unsafeContentType=The application cannot continue because it accessed a file type that may not be safe to open. Please contact the application authors to inform them of this problem.
|
||||
externalProtocolTitle=External Protocol Request
|
||||
externalProtocolPrompt=An external application must be launched to handle %1$S: links.\n\n\nRequested link:\n\n%2$S\n\nApplication: %3$S\n\n\nIf you were not expecting this request it may be an attempt to exploit a weakness in that other program. Cancel this request unless you are sure it is not malicious.\n
|
||||
#LOCALIZATION NOTE (externalProtocolUnknown): The following string is shown if the application name can't be determined
|
||||
externalProtocolUnknown=<Unknown>
|
||||
externalProtocolChkMsg=Remember my choice for all links of this type.
|
||||
externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspBlocked=This application tried to access a resource that has a content security policy that prevents it from being loaded in this way.
|
||||
corruptedContentError=The application cannot continue loading because an error in the data transmission was detected.
|
||||
remoteXUL=This application tried to use an unsupported technology that is no longer available.
|
||||
sslv3Used=This application cannot guarantee the safety of your data on %S because it uses SSLv3, a broken security protocol.
|
||||
@@ -1,154 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
KillScriptTitle=Warning: Unresponsive script
|
||||
KillScriptMessage=A script may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete.
|
||||
KillScriptWithDebugMessage=A script may be busy, or it may have stopped responding. You can stop the script now, open the script in the debugger, or let the script continue.
|
||||
KillScriptLocation=Script: %S
|
||||
StopScriptButton=Stop script
|
||||
DebugScriptButton=Debug script
|
||||
WaitForScriptButton=Continue
|
||||
DontAskAgain=&Don't ask me again
|
||||
JSURLLoadBlockedWarning=Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager.
|
||||
WindowCloseBlockedWarning=Scripts may not close windows that were not opened by script.
|
||||
OnBeforeUnloadTitle=Are you sure?
|
||||
OnBeforeUnloadMessage=This application is asking you to confirm that you want to leave - data you have entered may not be saved.
|
||||
OnBeforeUnloadStayButton=Stay
|
||||
OnBeforeUnloadLeaveButton=Leave
|
||||
UnexpectedCanvasVariantStyle=canvas: an attempt to set strokeStyle or fillStyle to a value that is neither a string, a CanvasGradient, or a CanvasPattern was ignored.
|
||||
EmptyGetElementByIdParam=Empty string passed to getElementById().
|
||||
LowMemoryTitle=Warning: Low memory
|
||||
LowMemoryMessage=An application script has been stopped due to a low memory condition.
|
||||
SpeculationFailed=An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
|
||||
DocumentWriteIgnored=A call to document.write() from an asynchronously-loaded external script was ignored.
|
||||
FormValidationTextTooLong=Please shorten this text to %S characters or less (you are currently using %S characters).
|
||||
FormValidationValueMissing=Please fill out this field.
|
||||
FormValidationCheckboxMissing=Please check this box if you want to proceed.
|
||||
FormValidationRadioMissing=Please select one of these options.
|
||||
FormValidationFileMissing=Please select a file.
|
||||
FormValidationSelectMissing=Please select an item in the list.
|
||||
FormValidationInvalidEmail=Please enter an email address.
|
||||
FormValidationInvalidURL=Please enter a URL.
|
||||
FormValidationPatternMismatch=Please match the requested format.
|
||||
# LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value.
|
||||
FormValidationPatternMismatchWithTitle=Please match the requested format: %S.
|
||||
# LOCALIZATION NOTE (FormValidationNumberRangeOverflow): %S is a number.
|
||||
FormValidationNumberRangeOverflow=Please select a value that is no more than %S.
|
||||
# LOCALIZATION NOTE (FormValidationDateRangeOverflow): %S is a date.
|
||||
FormValidationDateRangeOverflow=Please select a value that is no earlier than %S.
|
||||
# LOCALIZATION NOTE (FormValidationTimeRangeOverflow): %S is a time.
|
||||
FormValidationTimeRangeOverflow=Please select a value that is no earlier than %S.
|
||||
# LOCALIZATION NOTE (FormValidationNumberRangeUnderflow): %S is a number.
|
||||
FormValidationNumberRangeUnderflow=Please select a value that is no less than %S.
|
||||
# LOCALIZATION NOTE (FormValidationDateRangeUnderflow): %S is a date.
|
||||
FormValidationDateRangeUnderflow=Please select a value that is no later than %S.
|
||||
# LOCALIZATION NOTE (FormValidationTimeRangeUnderflow): %S is a time.
|
||||
FormValidationTimeRangeUnderflow=Please select a value that is no later than %S.
|
||||
# LOCALIZATION NOTE (FormValidationStepMismatch): both %S can be a number, a date or a time.
|
||||
FormValidationStepMismatch=Please select a valid value. The two nearest valid values are %S and %S.
|
||||
# LOCALIZATION NOTE (FormValidationStepMismatchOneValue): %S can be a number, a date or a time. This is called instead of FormValidationStepMismatch when the second value is the same as the first.
|
||||
FormValidationStepMismatchOneValue=Please select a valid value. The nearest valid value is %S.
|
||||
FormValidationBadInputNumber=Please enter a number.
|
||||
GetAttributeNodeWarning=Use of getAttributeNode() is deprecated. Use getAttribute() instead.
|
||||
SetAttributeNodeWarning=Use of setAttributeNode() is deprecated. Use setAttribute() instead.
|
||||
GetAttributeNodeNSWarning=Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.
|
||||
SetAttributeNodeNSWarning=Use of setAttributeNodeNS() is deprecated. Use setAttributeNS() instead.
|
||||
RemoveAttributeNodeWarning=Use of removeAttributeNode() is deprecated. Use removeAttribute() instead.
|
||||
CreateAttributeWarning=Use of document.createAttribute() is deprecated. Use element.setAttribute() instead.
|
||||
CreateAttributeNSWarning=Use of document.createAttributeNS() is deprecated. Use element.setAttributeNS() instead.
|
||||
OwnerElementWarning=Use of attributes' ownerElement attribute is deprecated.
|
||||
NodeValueWarning=Use of attributes' nodeValue attribute is deprecated. Use value instead.
|
||||
TextContentWarning=Use of attributes' textContent attribute is deprecated. Use value instead.
|
||||
EnablePrivilegeWarning=Use of enablePrivilege is deprecated. Please use code that runs with the system principal (e.g. an extension) instead.
|
||||
nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated. Please use JSON.parse instead.
|
||||
nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated. Please use JSON.stringify instead.
|
||||
nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
|
||||
InputEncodingWarning=Use of inputEncoding is deprecated.
|
||||
# LOCALIZATION NOTE: Do not translate "MozBeforePaint" and "mozRequestAnimationFrame"
|
||||
MozBeforePaintWarning=MozBeforePaint events are no longer supported. mozRequestAnimationFrame must be passed a non-null callback argument.
|
||||
FullScreenDeniedBlocked=Request for full-screen was denied because this domain has been blocked from full-screen by user.
|
||||
FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
|
||||
FullScreenDeniedFocusedPlugin=Request for full-screen was denied because a windowed plugin is focused.
|
||||
FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
|
||||
FullScreenDeniedIframeNotAllowed=Request for full-screen was denied because at least one of the document's containing iframes does not have an "allowfullscreen" attribute.
|
||||
FullScreenDeniedNotInputDriven=Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler.
|
||||
FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
|
||||
FullScreenDeniedMovedDocument=Request for full-screen was denied because requesting element has moved document.
|
||||
FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
|
||||
FullScreenDeniedSubDocFullScreen=Request for full-screen was denied because a subdocument of the document requesting full-screen is already full-screen.
|
||||
FullScreenDeniedNotDescendant=Request for full-screen was denied because requesting element is not a descendant of the current full-screen element.
|
||||
FullScreenDeniedNotFocusedTab=Request for full-screen was denied because requesting element is not in the currently focused tab.
|
||||
FullScreenDeniedContentOnly=Request for full-screen was denied because requesting element is in the chrome document and the fullscreen API is configured for content only.
|
||||
RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
|
||||
FocusedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was focused.
|
||||
HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
|
||||
InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
|
||||
ResponseTypeSyncXHRWarning=Use of XMLHttpRequest's responseType attribute is no longer supported in the synchronous mode in window context.
|
||||
WithCredentialsSyncXHRWarning=Use of XMLHttpRequest's withCredentials attribute is no longer supported in the synchronous mode in window context.
|
||||
TimeoutSyncXHRWarning=Use of XMLHttpRequest's timeout attribute is not supported in the synchronous mode in window context.
|
||||
JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
|
||||
# LOCALIZATION NOTE: Do not translate AudioBufferSourceNode
|
||||
MediaBufferSourceNodeResampleOutOfMemory=Insufficient memory to resample the AudioBufferSourceNode for playback.
|
||||
# LOCALIZATION NOTE: Do not translate decodeAudioData.
|
||||
MediaDecodeAudioDataUnknownContentType=The buffer passed to decodeAudioData contains an unknown content type.
|
||||
# LOCALIZATION NOTE: Do not translate decodeAudioData.
|
||||
MediaDecodeAudioDataUnknownError=An unknown error occured while processing decodeAudioData.
|
||||
# LOCALIZATION NOTE: Do not translate decodeAudioData.
|
||||
MediaDecodeAudioDataInvalidContent=The buffer passed to decodeAudioData contains invalid content which cannot be decoded successfully.
|
||||
# LOCALIZATION NOTE: Do not translate decodeAudioData.
|
||||
MediaDecodeAudioDataNoAudio=The buffer passed to decodeAudioData does not contain any audio.
|
||||
MediaLoadExhaustedCandidates=All candidate resources failed to load. Media load paused.
|
||||
MediaLoadSourceMissingSrc=<source> element has no "src" attribute. Media resource load failed.
|
||||
# LOCALIZATION NOTE: %1$S is the Http error code the server returned (e.g. 404, 500, etc), %2$S is the URL of the media resource which failed to load.
|
||||
MediaLoadHttpError=HTTP load failed with status %1$S. Load of media resource %2$S failed.
|
||||
# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load.
|
||||
MediaLoadInvalidURI=Invalid URI. Load of media resource %S failed.
|
||||
# LOCALIZATION NOTE: %1$S is the media resource's format/codec type (basically equivalent to the file type, e.g. MP4,AVI,WMV,MOV etc), %2$S is the URL of the media resource which failed to load.
|
||||
MediaLoadUnsupportedTypeAttribute=Specified "type" attribute of "%1$S" is not supported. Load of media resource %2$S failed.
|
||||
# LOCALIZATION NOTE: %1$S is the "media" attribute value of the <source> element. It is a media query. %2$S is the URL of the media resource which failed to load.
|
||||
MediaLoadSourceMediaNotMatched=Specified "media" attribute of "%1$S" does not match the environment. Load of media resource %2$S failed.
|
||||
# LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
|
||||
MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
|
||||
# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
|
||||
MediaLoadDecodeError=Media resource %S could not be decoded.
|
||||
# LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name"
|
||||
DOMExceptionCodeWarning=Use of DOMException's code attribute is deprecated. Use name instead.
|
||||
# LOCALIZATION NOTE: Do not translate "__exposedProps__"
|
||||
NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedProps__ is insecure and deprecated. See https://developer.mozilla.org/en/XPConnect_wrappers for more information.
|
||||
# LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver"
|
||||
MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead.
|
||||
# LOCALIZATION NOTE: Do not translate "Components"
|
||||
ComponentsWarning=The Components object is deprecated. It will soon be removed.
|
||||
PluginHangUITitle=Warning: Unresponsive plugin
|
||||
PluginHangUIMessage=%S may be busy, or it may have stopped responding. You can stop the plugin now, or you can continue to see if the plugin will complete.
|
||||
PluginHangUIWaitButton=Continue
|
||||
PluginHangUIStopButton=Stop plugin
|
||||
# LOCALIZATION NOTE: Do not translate "mozHidden", "mozVisibilityState", "hidden", or "visibilityState"
|
||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||
# LOCALIZATION NOTE: Do not translate "NodeIterator" or "detach()".
|
||||
NodeIteratorDetachWarning=Calling detach() on a NodeIterator no longer has an effect.
|
||||
# LOCALIZATION NOTE: Do not translate "LenientThis" and "this"
|
||||
LenientThisWarning=Ignoring get or set of property that has [LenientThis] because the "this" object is incorrect.
|
||||
# LOCALIZATION NOTE: Do not translate "nsIDOMWindowUtils", "getWindowWithOuterId", or "nsIWindowMediator"
|
||||
GetWindowWithOuterIdWarning=Use of nsIDOMWindowUtils.getOuterWindowWithId() is deprecated. Instead, use the nsIWindowMediator method of the same name.
|
||||
# LOCALIZATION NOTE: Do not translate "getPreventDefault" or "defaultPrevented".
|
||||
GetPreventDefaultWarning=Use of getPreventDefault() is deprecated. Use defaultPrevented instead.
|
||||
# LOCALIZATION NOTE: Do not translate "getUserData", "setUserData", "WeakMap", or "element.dataset".
|
||||
GetSetUserDataWarning=Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead.
|
||||
# LOCALIZATION NOTE: Do not translate "mozGetAsFile" or "toBlob"
|
||||
MozGetAsFileWarning=The non-standard mozGetAsFile method is deprecated and will soon be removed. Use the standard toBlob method instead.
|
||||
# LOCALIZATION NOTE: Do not translate "captureEvents()" or "addEventListener()"
|
||||
UseOfCaptureEventsWarning=Use of captureEvents() is deprecated. To upgrade your code, use the DOM 2 addEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.addEventListener
|
||||
# LOCALIZATION NOTE: Do not translate "releaseEvents()" or "removeEventListener()"
|
||||
UseOfReleaseEventsWarning=Use of releaseEvents() is deprecated. To upgrade your code, use the DOM 2 removeEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.removeEventListener
|
||||
# LOCALIZATION NOTE: Do not translate "document.load()" or "XMLHttpRequest"
|
||||
UseOfDOM3LoadMethodWarning=Use of document.load() is deprecated. To upgrade your code, use the DOM XMLHttpRequest object. For more help https://developer.mozilla.org/en/XMLHttpRequest
|
||||
# LOCALIZATION NOTE: Do not translate "window.showModalDialog()" or "window.open()"
|
||||
ShowModalDialogWarning=Use of window.showModalDialog() is deprecated. Use window.open() instead. For more help https://developer.mozilla.org/en-US/docs/Web/API/Window.open
|
||||
# LOCALIZATION NOTE: Do not translate "window._content" or "window.content"
|
||||
Window_ContentWarning=window._content is deprecated. Please use window.content instead.
|
||||
# LOCALIZATION NOTE: Do not translate "XMLHttpRequest"
|
||||
SyncXMLHttpRequestWarning=Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/
|
||||
# LOCALIZATION NOTE: Do not translate "DataContainerEvent" or "CustomEvent"
|
||||
DataContainerEventWarning=Use of DataContainerEvent is deprecated. Use CustomEvent instead.
|
||||
@@ -1,51 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE: These are localized strings for the webapp runtime,
|
||||
- which loads a webapp in a separate process from Firefox. Webapps loaded
|
||||
- in this way have very little application chrome, but the runtime does
|
||||
- provide them with some default functionality, like the standard OS
|
||||
- menus/menuitems. -->
|
||||
|
||||
<!ENTITY fileMenu.label "File">
|
||||
<!ENTITY fileMenu.accesskey "F">
|
||||
|
||||
<!ENTITY quitApplicationCmdWin.label "Exit">
|
||||
<!ENTITY quitApplicationCmdWin.accesskey "x">
|
||||
<!ENTITY quitApplicationCmd.label "Quit">
|
||||
<!ENTITY quitApplicationCmd.accesskey "Q">
|
||||
<!-- On Mac, we create the Quit and Hide command labels dynamically,
|
||||
- using properties in window.properties, in order to include the name
|
||||
- of the webapp in the labels without creating a DTD file for it. -->
|
||||
<!ENTITY hideThisAppCmdMac.key "H">
|
||||
<!ENTITY hideOtherAppsCmdMac.label "Hide Others">
|
||||
<!ENTITY hideOtherAppsCmdMac.key "H">
|
||||
<!ENTITY showAllAppsCmdMac.label "Show All">
|
||||
|
||||
<!-- LOCALIZATION NOTE(quitApplicationCmdUnix.key): This keyboard shortcut is used by both Linux and OSX -->
|
||||
<!ENTITY quitApplicationCmdUnix.key "Q">
|
||||
|
||||
<!ENTITY editMenu.label "Edit">
|
||||
<!ENTITY editMenu.accesskey "E">
|
||||
<!ENTITY undoCmd.label "Undo">
|
||||
<!ENTITY undoCmd.key "Z">
|
||||
<!ENTITY undoCmd.accesskey "U">
|
||||
<!ENTITY redoCmd.label "Redo">
|
||||
<!ENTITY redoCmd.key "Y">
|
||||
<!ENTITY redoCmd.accesskey "R">
|
||||
<!ENTITY cutCmd.label "Cut">
|
||||
<!ENTITY cutCmd.key "X">
|
||||
<!ENTITY cutCmd.accesskey "t">
|
||||
<!ENTITY copyCmd.label "Copy">
|
||||
<!ENTITY copyCmd.key "C">
|
||||
<!ENTITY copyCmd.accesskey "C">
|
||||
<!ENTITY pasteCmd.label "Paste">
|
||||
<!ENTITY pasteCmd.key "V">
|
||||
<!ENTITY pasteCmd.accesskey "P">
|
||||
<!ENTITY deleteCmd.label "Delete">
|
||||
<!ENTITY deleteCmd.key "D">
|
||||
<!ENTITY deleteCmd.accesskey "D">
|
||||
<!ENTITY selectAllCmd.label "Select All">
|
||||
<!ENTITY selectAllCmd.key "A">
|
||||
<!ENTITY selectAllCmd.accesskey "A">
|
||||
@@ -1,53 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE: These are localized strings for the webapp runtime,
|
||||
# which loads a webapp in a separate process from Firefox. Webapps loaded
|
||||
# in this way have very little application chrome, but the runtime does
|
||||
# provide them with some default functionality, like the standard OS
|
||||
# menus/menuitems.
|
||||
|
||||
# LOCALIZATION NOTE (quitApplicationCmdMac.label): %S will be replaced with
|
||||
# the name of the webapp.
|
||||
quitApplicationCmdMac.label=Quit %S
|
||||
|
||||
# LOCALIZATION NOTE (hideApplicationCmdMac.label): %S will be replaced with
|
||||
# the name of the webapp.
|
||||
hideApplicationCmdMac.label=Hide %S
|
||||
|
||||
# LOCALIZATION NOTE (geolocation.title): %S will be replaced with the name of
|
||||
# the webapp.
|
||||
geolocation.title=%S - Share Location
|
||||
geolocation.description=Do you want to share your location?
|
||||
geolocation.allow=Share Location
|
||||
geolocation.deny=Don't Share
|
||||
geolocation.remember=Remember my choice
|
||||
|
||||
# LOCALIZATION NOTE (desktop-notification.title): %S will be replaced with the
|
||||
# name of the webapp.
|
||||
desktop-notification.title=%S - Show notifications
|
||||
desktop-notification.description=Do you want to allow notifications?
|
||||
desktop-notification.allow=Show
|
||||
desktop-notification.deny=Don't show
|
||||
desktop-notification.remember=Remember my choice
|
||||
|
||||
# LOCALIZATION NOTE (webapps.install.title): %S will be replaced with the name
|
||||
# of the webapp being installed.
|
||||
webapps.install.title=Install %S
|
||||
# LOCALIZATION NOTE (webapps.install.description): %S will be replaced with the
|
||||
# name of the webapp being installed.
|
||||
webapps.install.description=Do you want to install %S?
|
||||
webapps.install.install=Install App
|
||||
webapps.install.dontinstall=Don't Install
|
||||
# LOCALIZATION NOTE (webapps.uninstall.title): %S will be replaced with the name
|
||||
# of the webapp being uninstalled.
|
||||
webapps.uninstall.title=Uninstall %S
|
||||
# LOCALIZATION NOTE (webapps.uninstall.description): %S will be replaced with the
|
||||
# name of the webapp being uninstalled.
|
||||
webapps.uninstall.description=Do you want to uninstall %S?
|
||||
webapps.uninstall.uninstall=Uninstall App
|
||||
webapps.uninstall.dontuninstall=Don't Uninstall
|
||||
|
||||
paymentDialog.title=Payment
|
||||
paymentDialog.message=Which payment provider do you want to use?
|
||||
@@ -1,19 +0,0 @@
|
||||
#filter substitution
|
||||
# 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/.
|
||||
|
||||
@AB_CD@.jar:
|
||||
% locale webapprt @AB_CD@ %locale/webapprt/
|
||||
locale/webapprt/webapp.dtd (%webapprt/webapp.dtd)
|
||||
locale/webapprt/webapp.properties (%webapprt/webapp.properties)
|
||||
locale/webapprt/getUserMediaDialog.dtd (%webapprt/getUserMediaDialog.dtd)
|
||||
locale/webapprt/appstrings.properties (%webapprt/overrides/appstrings.properties)
|
||||
locale/webapprt/dom.properties (%webapprt/overrides/dom.properties)
|
||||
locale/webapprt/downloads/downloads.dtd (%webapprt/downloads/downloads.dtd)
|
||||
|
||||
|
||||
% locale branding @AB_CD@ resource://webappbranding/
|
||||
|
||||
% override chrome://global/locale/appstrings.properties chrome://webapprt/locale/appstrings.properties
|
||||
% override chrome://global/locale/dom/dom.properties chrome://webapprt/locale/dom.properties
|
||||
@@ -1,9 +0,0 @@
|
||||
; 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/.
|
||||
|
||||
[general]
|
||||
depth = ../..
|
||||
|
||||
[compare]
|
||||
dirs = webapprt
|
||||
@@ -1,6 +0,0 @@
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
@@ -1,16 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
# This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that
|
||||
# shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
|
||||
NSDISTMODE = copy
|
||||
|
||||
PROGRAMS_DEST = $(DIST)/bin
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
|
||||
webapprt.$(OBJ_SUFFIX): $(DEPTH)/config/buildid
|
||||
@@ -1,31 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
# Can't use GoannaProgram, because we don't want to create a dependency on
|
||||
# mozglue, which is impossible (difficult?) to dynamically link into our
|
||||
# executable, as we copy it to arbitrary locations.
|
||||
Program('webapprt-stub')
|
||||
|
||||
SOURCES += [
|
||||
'webapprt.mm',
|
||||
]
|
||||
|
||||
DEFINES['XPCOM_GLUE'] = True
|
||||
|
||||
GENERATED_INCLUDES += ['/build']
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/xre',
|
||||
'/xpcom/base',
|
||||
'/xpcom/build',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'xpcomglue',
|
||||
]
|
||||
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
@@ -1,400 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
//PLAN:
|
||||
|
||||
// open my bundle, check for an override binary signature
|
||||
// find the newest firefox. open its bundle, get the version number.
|
||||
// if the firefox version is different than ours:
|
||||
// delete our own binary,
|
||||
// copy the newer webapprt binary from Firefox
|
||||
// exec it, and quit
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include "nsXPCOMGlue.h"
|
||||
#include "nsINIParser.h"
|
||||
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "mozilla/AppData.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
const char WEBAPPRT_EXECUTABLE[] = "webapprt-stub";
|
||||
const char FXAPPINI_NAME[] = "application.ini";
|
||||
const char WEBAPPINI_NAME[] = "webapp.ini";
|
||||
const char WEBRTINI_NAME[] = "webapprt.ini";
|
||||
|
||||
//need the correct relative path here
|
||||
const char APP_MACOS_PATH[] = "/Contents/MacOS/";
|
||||
const char APP_RESOURCES_PATH[] = "/Contents/Resources/";
|
||||
|
||||
//the path to the WebappRT subdir within the Firefox app contents dir
|
||||
const char WEBAPPRT_PATH[] = "webapprt/";
|
||||
|
||||
void ExecNewBinary(NSString* launchPath);
|
||||
|
||||
NSString *PathToWebRT(NSString* alternateBinaryID);
|
||||
|
||||
NSException* MakeException(NSString* name, NSString* message);
|
||||
|
||||
void DisplayErrorAlert(NSString* title, NSString* message);
|
||||
|
||||
XRE_GetFileFromPathType XRE_GetFileFromPath;
|
||||
XRE_CreateAppDataType XRE_CreateAppData;
|
||||
XRE_FreeAppDataType XRE_FreeAppData;
|
||||
XRE_mainType XRE_main;
|
||||
|
||||
const nsDynamicFunctionLoad kXULFuncs[] = {
|
||||
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
|
||||
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
|
||||
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
|
||||
{ "XRE_main", (NSFuncPtr*) &XRE_main },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
nsresult
|
||||
AttemptGRELoad(char *greDir)
|
||||
{
|
||||
nsresult rv;
|
||||
char xpcomDLLPath[MAXPATHLEN];
|
||||
snprintf(xpcomDLLPath, MAXPATHLEN, "%s%s", greDir, XPCOM_DLL);
|
||||
|
||||
rv = XPCOMGlueStartup(xpcomDLLPath);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSDictionary *args = [[NSUserDefaults standardUserDefaults]
|
||||
volatileDomainForName:NSArgumentDomain];
|
||||
|
||||
NSString *firefoxPath = nil;
|
||||
NSString *alternateBinaryID = nil;
|
||||
|
||||
//this is our version, to be compared with the version of the binary we are asked to use
|
||||
NSString* myVersion = [NSString stringWithFormat:@"%s", NS_STRINGIFY(GRE_BUILDID)];
|
||||
|
||||
NSLog(@"MY WEBAPPRT BUILDID: %@", myVersion);
|
||||
|
||||
|
||||
//I need to look in our bundle first, before deciding what firefox binary to use
|
||||
NSBundle* myBundle = [NSBundle mainBundle];
|
||||
NSString* myBundlePath = [myBundle bundlePath];
|
||||
alternateBinaryID = [myBundle objectForInfoDictionaryKey:@"FirefoxBinary"];
|
||||
NSLog(@"found override firefox binary: %@", alternateBinaryID);
|
||||
|
||||
@try {
|
||||
//find a webapprt binary to launch with. throws an exception with error dialog if none found.
|
||||
firefoxPath = PathToWebRT(alternateBinaryID);
|
||||
NSLog(@"USING FIREFOX : %@", firefoxPath);
|
||||
|
||||
NSString* myWebRTPath = [myBundle pathForResource:@"webapprt"
|
||||
ofType:nil];
|
||||
if (!myWebRTPath) {
|
||||
myWebRTPath = [myBundlePath stringByAppendingPathComponent:@"Contents"];
|
||||
myWebRTPath = [myWebRTPath stringByAppendingPathComponent:@"MacOS"];
|
||||
myWebRTPath = [myWebRTPath stringByAppendingPathComponent:@"webapprt"];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:myWebRTPath] == NO) {
|
||||
@throw MakeException(@"Missing Web Runtime Files",
|
||||
@"Cannot locate binary for this App");
|
||||
}
|
||||
}
|
||||
|
||||
//GET FIREFOX BUILD ID
|
||||
NSString *firefoxINIFilePath =
|
||||
[NSString stringWithFormat:@"%@%s%s", firefoxPath, APP_RESOURCES_PATH,
|
||||
FXAPPINI_NAME];
|
||||
nsINIParser ffparser;
|
||||
NSLog(@"Looking for firefox ini file here: %@", firefoxINIFilePath);
|
||||
if (NS_FAILED(ffparser.Init([firefoxINIFilePath UTF8String]))) {
|
||||
firefoxINIFilePath = [NSString stringWithFormat:@"%@%s%s", firefoxPath,
|
||||
APP_MACOS_PATH,
|
||||
FXAPPINI_NAME];
|
||||
NSLog(@"Looking for firefox ini file here: %@", firefoxINIFilePath);
|
||||
if (NS_FAILED(ffparser.Init([firefoxINIFilePath UTF8String]))) {
|
||||
NSLog(@"Unable to locate Firefox application.ini");
|
||||
@throw MakeException(@"Error",
|
||||
@"Unable to parse environment files for application startup");
|
||||
}
|
||||
}
|
||||
|
||||
char ffVersChars[MAXPATHLEN];
|
||||
if (NS_FAILED(ffparser.GetString("App", "BuildID", ffVersChars, MAXPATHLEN))) {
|
||||
NSLog(@"Unable to retrieve Firefox BuildID");
|
||||
@throw MakeException(@"Error", @"Unable to determine Firefox version.");
|
||||
}
|
||||
NSString* firefoxVersion = [NSString stringWithFormat:@"%s", ffVersChars];
|
||||
|
||||
NSLog(@"FIREFOX WEBAPPRT BUILDID: %@", firefoxVersion);
|
||||
//GOT FIREFOX BUILD ID
|
||||
|
||||
//COMPARE MY BUILD ID AND FIREFOX BUILD ID
|
||||
if ([myVersion compare: firefoxVersion] != NSOrderedSame) {
|
||||
//we are going to assume that if they are different, we need to re-copy the webapprt, regardless of whether
|
||||
// it is newer or older. If we don't find a webapprt, then the current Firefox must not be new enough to run webapps.
|
||||
NSLog(@"### This Application has an old webrt. Updating it.");
|
||||
NSLog(@"### My webapprt path: %@", myWebRTPath);
|
||||
|
||||
NSFileManager* fileClerk = [[NSFileManager alloc] init];
|
||||
NSError *errorDesc = nil;
|
||||
|
||||
//we know the firefox path, so copy the new webapprt here
|
||||
NSString *newWebRTPath =
|
||||
[NSString stringWithFormat: @"%@%s%s", firefoxPath, APP_RESOURCES_PATH,
|
||||
WEBAPPRT_EXECUTABLE];
|
||||
NSLog(@"### Trying Firefox webapprt path: %@", newWebRTPath);
|
||||
if (![fileClerk fileExistsAtPath:newWebRTPath]) {
|
||||
newWebRTPath =
|
||||
[NSString stringWithFormat: @"%@%s%s", firefoxPath, APP_MACOS_PATH,
|
||||
WEBAPPRT_EXECUTABLE];
|
||||
NSLog(@"### Trying Firefox webapprt path: %@", newWebRTPath);
|
||||
if (![fileClerk fileExistsAtPath:newWebRTPath]) {
|
||||
NSString* msg =
|
||||
[NSString stringWithFormat:
|
||||
@"This version of Firefox (%@) cannot run web applications, because it is not recent enough or damaged", firefoxVersion];
|
||||
@throw MakeException(@"Missing Web Runtime Files", msg);
|
||||
}
|
||||
}
|
||||
|
||||
[fileClerk removeItemAtPath: myWebRTPath error: &errorDesc];
|
||||
if (errorDesc != nil) {
|
||||
NSLog(@"failed to unlink old binary file at path: %@ with error: %@", myWebRTPath, errorDesc);
|
||||
@throw MakeException(@"Unable To Update", @"Failed preparation for Web Runtime update");
|
||||
}
|
||||
|
||||
[fileClerk copyItemAtPath: newWebRTPath toPath: myWebRTPath error: &errorDesc];
|
||||
[fileClerk release];
|
||||
if (errorDesc != nil) {
|
||||
NSLog(@"failed to copy new webrt file: %@", errorDesc);
|
||||
@throw MakeException(@"Unable To Update Web Runtime", @"Failed to update Web Runtime");
|
||||
} else {
|
||||
NSLog(@"### Successfully updated webapprt, relaunching");
|
||||
}
|
||||
|
||||
//execv the new binary, and ride off into the sunset
|
||||
ExecNewBinary(myWebRTPath);
|
||||
|
||||
} else {
|
||||
//we are ready to load XUL and such, and go go go
|
||||
|
||||
NSLog(@"This Application has the newest webrt. Launching!");
|
||||
|
||||
int result = 0;
|
||||
char rtINIPath[MAXPATHLEN];
|
||||
|
||||
// Set up our environment to know where webapp.ini was loaded from.
|
||||
char appEnv[MAXPATHLEN];
|
||||
snprintf(appEnv, MAXPATHLEN, "%s%s%s", [myBundlePath UTF8String],
|
||||
APP_MACOS_PATH, WEBAPPINI_NAME);
|
||||
if (setenv("XUL_APP_FILE", appEnv, 1)) {
|
||||
NSLog(@"Couldn't set XUL_APP_FILE to: %s", appEnv);
|
||||
@throw MakeException(@"Error", @"Unable to set Web Runtime INI file.");
|
||||
}
|
||||
NSLog(@"Set XUL_APP_FILE to: %s", appEnv);
|
||||
|
||||
//CONSTRUCT GREDIR AND CALL XPCOMGLUE WITH IT
|
||||
char greDir[MAXPATHLEN];
|
||||
snprintf(greDir, MAXPATHLEN, "%s%s", [firefoxPath UTF8String],
|
||||
APP_RESOURCES_PATH);
|
||||
if (!NS_SUCCEEDED(AttemptGRELoad(greDir))) {
|
||||
@throw MakeException(@"Error", @"Unable to load XUL files for application startup");
|
||||
}
|
||||
|
||||
// NOTE: The GRE has successfully loaded, so we can use XPCOM now
|
||||
|
||||
NS_LogInit();
|
||||
{ // Scope for any XPCOM stuff we create
|
||||
|
||||
// Get the path to the runtime directory.
|
||||
char rtDir[MAXPATHLEN];
|
||||
snprintf(rtDir, MAXPATHLEN, "%s%s%s", [firefoxPath UTF8String],
|
||||
APP_RESOURCES_PATH,
|
||||
WEBAPPRT_PATH);
|
||||
|
||||
// Get the path to the runtime's INI file. This is in the runtime
|
||||
// directory.
|
||||
snprintf(rtINIPath, MAXPATHLEN, "%s%s%s%s", [firefoxPath UTF8String],
|
||||
APP_RESOURCES_PATH,
|
||||
WEBAPPRT_PATH,
|
||||
WEBRTINI_NAME);
|
||||
NSLog(@"WebappRT application.ini path: %s", rtINIPath);
|
||||
|
||||
// Load the runtime's INI from its path.
|
||||
nsCOMPtr<nsIFile> rtINI;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtINIPath, getter_AddRefs(rtINI)))) {
|
||||
NSLog(@"Runtime INI path not recognized: '%s'\n", rtINIPath);
|
||||
@throw MakeException(@"Error", @"Incorrect path to base INI file.");
|
||||
}
|
||||
|
||||
bool exists;
|
||||
nsresult rv = rtINI->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists) {
|
||||
NSString* msg = [NSString stringWithFormat: @"This copy of Firefox (%@) cannot run Apps, because it is missing the Web Runtime's application.ini file", firefoxVersion];
|
||||
@throw MakeException(@"Missing Web Runtime application.ini", msg);
|
||||
}
|
||||
|
||||
nsXREAppData *webShellAppData;
|
||||
if (NS_FAILED(XRE_CreateAppData(rtINI, &webShellAppData))) {
|
||||
NSLog(@"Couldn't read WebappRT application.ini: %s", rtINIPath);
|
||||
@throw MakeException(@"Error", @"Unable to parse base INI file.");
|
||||
}
|
||||
|
||||
NSString *profile = [args objectForKey:@"profile"];
|
||||
if (profile) {
|
||||
NSLog(@"Profile specified with --profile: %@", profile);
|
||||
}
|
||||
else {
|
||||
nsINIParser parser;
|
||||
if (NS_FAILED(parser.Init(appEnv))) {
|
||||
NSLog(@"%s was not found\n", appEnv);
|
||||
@throw MakeException(@"Error", @"Unable to parse environment files for application startup");
|
||||
}
|
||||
char profile[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
|
||||
NSLog(@"Unable to retrieve profile from App INI file");
|
||||
@throw MakeException(@"Error", @"Unable to retrieve installation profile.");
|
||||
}
|
||||
NSLog(@"setting app profile: %s", profile);
|
||||
SetAllocatedString(webShellAppData->profile, profile);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtDir, getter_AddRefs(directory)))) {
|
||||
NSLog(@"Unable to open app dir");
|
||||
@throw MakeException(@"Error", @"Unable to open App directory.");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> xreDir;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(greDir, getter_AddRefs(xreDir)))) {
|
||||
NSLog(@"Unable to open XRE dir");
|
||||
@throw MakeException(@"Error", @"Unable to open App XRE directory.");
|
||||
}
|
||||
|
||||
xreDir.forget(&webShellAppData->xreDirectory);
|
||||
NS_IF_RELEASE(webShellAppData->directory);
|
||||
directory.forget(&webShellAppData->directory);
|
||||
|
||||
// There is only XUL.
|
||||
result = XRE_main(argc, argv, webShellAppData, 0);
|
||||
|
||||
XRE_FreeAppData(webShellAppData);
|
||||
}
|
||||
NS_LogTerm();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"got exception: %@", e);
|
||||
DisplayErrorAlert([e name], [e reason]);
|
||||
}
|
||||
@finally {
|
||||
[pool drain];
|
||||
}
|
||||
return 0;
|
||||
} //end main
|
||||
|
||||
|
||||
NSException*
|
||||
MakeException(NSString* name, NSString* message)
|
||||
{
|
||||
NSException* myException = [NSException
|
||||
exceptionWithName:name
|
||||
reason:message
|
||||
userInfo:nil];
|
||||
return myException;
|
||||
}
|
||||
|
||||
void
|
||||
DisplayErrorAlert(NSString* title, NSString* message)
|
||||
{
|
||||
CFUserNotificationDisplayNotice(0, kCFUserNotificationNoteAlertLevel,
|
||||
NULL, NULL, NULL,
|
||||
(CFStringRef)title,
|
||||
(CFStringRef)message,
|
||||
CFSTR("Quit")
|
||||
);
|
||||
}
|
||||
|
||||
/* Find the currently installed Firefox, if any, and return
|
||||
* an absolute path to it. may return nil */
|
||||
NSString
|
||||
*PathToWebRT(NSString* alternateBinaryID)
|
||||
{
|
||||
//default is firefox
|
||||
NSString *binaryPath = nil;
|
||||
|
||||
// We're run from the Firefox bundle during WebappRT chrome and content tests.
|
||||
NSString *myBundlePath = [[NSBundle mainBundle] bundlePath];
|
||||
NSString *fxPath =
|
||||
[NSString stringWithFormat:@"%@%sfirefox-bin", myBundlePath,
|
||||
APP_MACOS_PATH];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fxPath]) {
|
||||
return myBundlePath;
|
||||
}
|
||||
|
||||
//we look for these flavors of Firefox, in this order
|
||||
NSArray* launchBinarySearchList = [NSArray arrayWithObjects: @"org.mozilla.nightly",
|
||||
@"org.mozilla.aurora",
|
||||
@"org.mozilla.firefox", nil];
|
||||
|
||||
// If they provided a binary ID, use that.
|
||||
if (alternateBinaryID != nil && ([alternateBinaryID length] > 0)) {
|
||||
binaryPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:alternateBinaryID];
|
||||
if (binaryPath && [binaryPath length] > 0) {
|
||||
return binaryPath;
|
||||
}
|
||||
}
|
||||
|
||||
//No override found, loop through the various flavors of firefox we have
|
||||
for (NSString* signature in launchBinarySearchList) {
|
||||
NSLog(@"SEARCHING for webapprt, trying: %@", signature);
|
||||
binaryPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:signature];
|
||||
if (binaryPath && [binaryPath length] > 0) {
|
||||
return binaryPath;
|
||||
}
|
||||
}
|
||||
|
||||
NSLog(@"unable to find a valid webrt path");
|
||||
@throw MakeException(@"This App requires that Firefox version 16 or above is installed.", @"Firefox 16+ has not been detected.");
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
ExecNewBinary(NSString* launchPath)
|
||||
{
|
||||
NSLog(@" launching webrt at path: %@\n", launchPath);
|
||||
|
||||
const char *const newargv[] = {[launchPath UTF8String], NULL};
|
||||
|
||||
NSLog(@"COMMAND LINE: '%@ %s'", launchPath, newargv[0]);
|
||||
execv([launchPath UTF8String], (char **)newargv);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DIRS += ['win']
|
||||
elif CONFIG['OS_ARCH'] == 'Darwin':
|
||||
DIRS += ['mac']
|
||||
elif CONFIG['MOZ_ENABLE_GTK']:
|
||||
DIRS += ['gtk']
|
||||
|
||||
DIRS += [
|
||||
'locales',
|
||||
'themes',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'CommandLineHandler.js',
|
||||
'components.manifest',
|
||||
'ContentPermission.js',
|
||||
'DirectoryProvider.js',
|
||||
'PaymentUIGlue.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'DownloadView.jsm',
|
||||
'RemoteDebugger.jsm',
|
||||
'Startup.jsm',
|
||||
'WebappManager.jsm',
|
||||
'WebappRT.jsm',
|
||||
'WebRTCHandler.jsm',
|
||||
]
|
||||
|
||||
MOCHITEST_WEBAPPRT_CHROME_MANIFESTS += [
|
||||
'test/chrome/downloads/webapprt.ini',
|
||||
'test/chrome/webapprt.ini',
|
||||
]
|
||||
MOCHITEST_WEBAPPRT_CONTENT_MANIFESTS += ['test/content/webapprt.ini']
|
||||
|
||||
# Place webapprt resources in a separate app dir
|
||||
DIST_SUBDIR = 'webapprt'
|
||||
export('DIST_SUBDIR')
|
||||
|
||||
if CONFIG['MOZ_DEBUG']:
|
||||
DEFINES['MOZ_DEBUG'] = 1
|
||||
|
||||
if CONFIG['MOZILLA_OFFICIAL']:
|
||||
DEFINES['MOZILLA_OFFICIAL'] = True
|
||||
|
||||
DEFINES['GRE_MILESTONE'] = CONFIG['GRE_MILESTONE']
|
||||
DEFINES['MOZ_APP_BASENAME'] = CONFIG['MOZ_APP_BASENAME']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
JS_PREFERENCE_FILES += [
|
||||
'prefs.js',
|
||||
]
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
// Check for updates once a day.
|
||||
pref("webapprt.app_update_interval", 86400);
|
||||
|
||||
pref("browser.chromeURL", "chrome://webapprt/content/webapp.xul");
|
||||
pref("browser.download.folderList", 1);
|
||||
|
||||
// Disable all add-on locations other than the profile (which can't be disabled this way)
|
||||
pref("extensions.enabledScopes", 1);
|
||||
// Auto-disable any add-ons that are "dropped in" to the profile
|
||||
pref("extensions.autoDisableScopes", 1);
|
||||
// Disable add-on installation via the web-exposed APIs
|
||||
pref("xpinstall.enabled", false);
|
||||
// Disable installation of distribution add-ons
|
||||
pref("extensions.installDistroAddons", false);
|
||||
// Disable the add-on compatibility dialog
|
||||
pref("extensions.showMismatchUI", false);
|
||||
|
||||
// Set reportURL for crashes
|
||||
pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
|
||||
|
||||
// Blocklist preferences
|
||||
pref("extensions.blocklist.enabled", true);
|
||||
pref("extensions.blocklist.interval", 86400);
|
||||
// Controls what level the blocklist switches from warning about items to forcibly
|
||||
// blocking them.
|
||||
pref("extensions.blocklist.level", 2);
|
||||
pref("extensions.blocklist.url", "https://blocklist.addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%PING_COUNT%/%TOTAL_PING_COUNT%/%DAYS_SINCE_LAST_PING%/");
|
||||
pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
|
||||
pref("extensions.blocklist.itemURL", "https://blocklist.addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
|
||||
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
||||
// IndexedDB
|
||||
pref("dom.indexedDB.enabled", true);
|
||||
|
||||
// Offline cache prefs
|
||||
pref("browser.offline-apps.notify", false);
|
||||
pref("browser.cache.offline.enable", true);
|
||||
pref("offline-apps.allow_by_default", true);
|
||||
|
||||
// TCPSocket
|
||||
pref("dom.mozTCPSocket.enabled", true);
|
||||
|
||||
// Enable smooth scrolling
|
||||
pref("general.smoothScroll", true);
|
||||
|
||||
// WebPayment
|
||||
pref("dom.mozPay.enabled", true);
|
||||
|
||||
// System messages
|
||||
pref("dom.sysmsg.enabled", true);
|
||||
|
||||
// Alarm API
|
||||
pref("dom.mozAlarms.enabled", true);
|
||||
|
||||
// Disable slow script dialog for apps
|
||||
pref("dom.max_script_run_time", 0);
|
||||
pref("dom.max_chrome_script_run_time", 0);
|
||||
|
||||
// The request URL of the GeoLocation backend
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
// Enable mozPay default provider
|
||||
pref("dom.payment.provider.0.name", "Firefox Marketplace");
|
||||
pref("dom.payment.provider.0.description", "marketplace.firefox.com");
|
||||
pref("dom.payment.provider.0.uri", "https://marketplace.firefox.com/mozpay/?req=");
|
||||
pref("dom.payment.provider.0.type", "mozilla/payments/pay/v1");
|
||||
pref("dom.payment.provider.0.requestMethod", "GET");
|
||||
#endif
|
||||
|
||||
// Enable window resize and move
|
||||
pref("dom.always_allow_move_resize_window", true);
|
||||
|
||||
// Disable all plugins. This has to be a non-empty string to disable plugins;
|
||||
// otherwise, nsPluginHost::IsTypeWhitelisted assumes all plugins are enabled.
|
||||
pref("plugin.allowed_types", " ");
|
||||
|
||||
pref("devtools.debugger.remote-enabled", true);
|
||||
pref("devtools.debugger.force-local", true);
|
||||
|
||||
// The default for this pref reflects whether the build is capable of IPC.
|
||||
// (Turning it on in a no-IPC build will have no effect.)
|
||||
#ifdef XP_MACOSX
|
||||
// i386 ipc preferences
|
||||
pref("dom.ipc.plugins.enabled.i386", false);
|
||||
pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
|
||||
// x86_64 ipc preferences
|
||||
pref("dom.ipc.plugins.enabled.x86_64", true);
|
||||
#else
|
||||
pref("dom.ipc.plugins.enabled", true);
|
||||
#endif
|
||||
|
||||
pref("places.database.growthIncrementKiB", 0);
|
||||
@@ -1,29 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
navigator.mozSetMessageHandler("alarm", function (message) {
|
||||
document.getElementById("msgFired").textContent = "Alarm fired.";
|
||||
});
|
||||
|
||||
var yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
var request = navigator.mozAlarms.add(yesterday, "honorTimezone", {});
|
||||
|
||||
request.onsuccess = function(e) {
|
||||
navigator.mozAlarms.remove(e.target.result);
|
||||
|
||||
document.getElementById("msgSet").textContent = "Success.";
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
document.getElementById("msgSet").textContent = "Failure.";
|
||||
};
|
||||
</script>
|
||||
<p id="msgSet">Webapp waiting to set an alarm...</p>
|
||||
<p id="msgFired">Webapp waiting for an alarm to fire...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "Alarm API Test Webapp",
|
||||
"description": "A webapp for testing the alarm API.",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/alarm.html",
|
||||
"permissions": {
|
||||
"alarms": { "description": "Desc" }
|
||||
},
|
||||
"messages": [
|
||||
{ "alarm": "/alarm.html" }
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,38 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let mutObserverAlarmSet = null;
|
||||
let mutObserverAlarmFired = null;
|
||||
|
||||
let alarmSet = false;
|
||||
|
||||
loadWebapp("alarm.webapp", undefined, function onLoad() {
|
||||
let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal;
|
||||
let permValue = Services.perms.testExactPermissionFromPrincipal(principal, "alarms");
|
||||
is(permValue, Ci.nsIPermissionManager.ALLOW_ACTION, "Alarm permission: allow.");
|
||||
|
||||
let msgSet = gAppBrowser.contentDocument.getElementById("msgSet");
|
||||
mutObserverAlarmSet = new MutationObserver(function(mutations) {
|
||||
is(msgSet.textContent, "Success.", "Alarm added.");
|
||||
alarmSet = true;
|
||||
});
|
||||
mutObserverAlarmSet.observe(msgSet, { childList: true });
|
||||
|
||||
let msgFired = gAppBrowser.contentDocument.getElementById("msgFired");
|
||||
mutObserverAlarmFired = new MutationObserver(function(mutations) {
|
||||
is(msgFired.textContent, "Alarm fired.", "Alarm fired.");
|
||||
|
||||
ok(alarmSet, "Alarm set before firing.");
|
||||
|
||||
finish();
|
||||
});
|
||||
mutObserverAlarmFired.observe(msgFired, { childList: true });
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
mutObserverAlarmSet.disconnect();
|
||||
mutObserverAlarmFired.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
let { RemoteDebugger } = Cu.import("resource://webapprt/modules/RemoteDebugger.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("debugger.webapp", undefined, () => {
|
||||
RemoteDebugger.init(Services.prefs.getIntPref('devtools.debugger.remote-port'));
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(() => {
|
||||
client.listTabs((aResponse) => {
|
||||
is(aResponse.tabs[0].title, "Debugger Test Webapp", "Title correct");
|
||||
is(aResponse.tabs[0].url, "http://test/webapprtChrome/webapprt/test/chrome/debugger.html", "URL correct");
|
||||
ok(aResponse.tabs[0].consoleActor, "consoleActor set");
|
||||
ok(aResponse.tabs[0].gcliActor, "gcliActor set");
|
||||
ok(aResponse.tabs[0].styleEditorActor, "styleEditorActor set");
|
||||
ok(aResponse.tabs[0].inspectorActor, "inspectorActor set");
|
||||
ok(aResponse.tabs[0].traceActor, "traceActor set");
|
||||
ok(aResponse.chromeDebugger, "chromeDebugger set");
|
||||
ok(aResponse.consoleActor, "consoleActor set");
|
||||
ok(aResponse.profilerActor, "profilerActor set");
|
||||
ok(aResponse.deviceActor, "deviceActor set");
|
||||
|
||||
client.close(() => {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
DebuggerServer.destroy();
|
||||
});
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { Downloads } = Cu.import("resource://gre/modules/Downloads.jsm", {});
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
function getFile(aFilename) {
|
||||
// The download database may contain targets stored as file URLs or native
|
||||
// paths. This can still be true for previously stored items, even if new
|
||||
// items are stored using their file URL. See also bug 239948 comment 12.
|
||||
if (aFilename.startsWith("file:")) {
|
||||
// Assume the file URL we obtained from the downloads database or from the
|
||||
// "spec" property of the target has the UTF-8 charset.
|
||||
let fileUrl = NetUtil.newURI(aFilename).QueryInterface(Ci.nsIFileURL);
|
||||
return fileUrl.file.clone();
|
||||
}
|
||||
|
||||
// The downloads database contains a native path. Try to create a local
|
||||
// file, though this may throw an exception if the path is invalid.
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(aFilename);
|
||||
return file;
|
||||
}
|
||||
|
||||
let fileDownloaded = false;
|
||||
|
||||
let download = new DummyDownload("download.test");
|
||||
download.state = 1;
|
||||
download.percentComplete = 100;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.documentURI ==
|
||||
"chrome://mozapps/content/downloads/unknownContentType.xul") {
|
||||
ok(true, "Download dialog shown");
|
||||
|
||||
executeSoon(() => {
|
||||
let button = win.document.documentElement.getButton("accept");
|
||||
button.disabled = false;
|
||||
win.document.documentElement.acceptDialog();
|
||||
});
|
||||
} else if (win.document.documentURI ==
|
||||
"chrome://webapprt/content/downloads/downloads.xul") {
|
||||
ok(true, "Download manager window shown");
|
||||
ok(fileDownloaded, "File downloaded");
|
||||
|
||||
waitDownloadListPopulation(win).then(() => {
|
||||
test_downloadList(win, [download]);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
MockFilePicker.returnFiles = [download.file];
|
||||
MockFilePicker.showCallback = function() {
|
||||
ok(true, "File picker shown");
|
||||
return MockFilePicker.returnOK;
|
||||
}
|
||||
|
||||
let downloadListener = {
|
||||
onDownloadAdded: function(aDownload) {
|
||||
if (aDownload.succeeded) {
|
||||
let downloadedFile = getFile(aDownload.target.path);
|
||||
ok(downloadedFile.exists(), "Download completed");
|
||||
is(downloadedFile.fileSize, 10, "Downloaded file has correct size");
|
||||
fileDownloaded = true;
|
||||
try {
|
||||
downloadedFile.remove(true);
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onDownloadChanged: function(aDownload) {
|
||||
if (aDownload.succeeded) {
|
||||
let downloadedFile = getFile(aDownload.target.path);
|
||||
ok(downloadedFile.exists(), "Download completed");
|
||||
is(downloadedFile.fileSize, 10, "Downloaded file has correct size");
|
||||
fileDownloaded = true;
|
||||
try {
|
||||
downloadedFile.remove(true);
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let downloadList;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.wm.getMostRecentWindow("Download:Manager").close();
|
||||
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
|
||||
MockFilePicker.cleanup();
|
||||
|
||||
if (downloadList) {
|
||||
return downloadList.removeView(downloadListener);
|
||||
}
|
||||
});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("download.webapp", undefined, function onLoad() {
|
||||
Task.spawn(function*() {
|
||||
downloadList = yield Downloads.getList(Downloads.ALL);
|
||||
|
||||
yield downloadList.addView(downloadListener);
|
||||
|
||||
gAppBrowser.contentDocument.getElementById("download").click();
|
||||
}).catch(function(e) {
|
||||
ok(false, "Error during test: " + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let openedWindows = 0;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
openedWindows++;
|
||||
if (openedWindows == 2) {
|
||||
ok(false, "Prompt shown.");
|
||||
win.close();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
let mutObserver = null;
|
||||
|
||||
loadWebapp("geolocation-prompt-noperm.webapp", undefined, function onLoad() {
|
||||
let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal;
|
||||
let permValue = Services.perms.testExactPermissionFromPrincipal(principal, "geolocation");
|
||||
is(permValue, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Geolocation permission: unknown.");
|
||||
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
mutObserver = new MutationObserver(function(mutations) {
|
||||
if (msg.textContent == "Failure.") {
|
||||
ok(true, "Permission not granted.");
|
||||
} else {
|
||||
ok(false, "Permission not granted.");
|
||||
}
|
||||
|
||||
finish();
|
||||
});
|
||||
mutObserver.observe(msg, { childList: true });
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
mutObserver.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let openedWindows = 0;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
openedWindows++;
|
||||
if (openedWindows == 2) {
|
||||
ok(true, "Prompt shown.");
|
||||
win.close();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
let mutObserver = null;
|
||||
|
||||
loadWebapp("geolocation-prompt-perm.webapp", undefined, function onLoad() {
|
||||
let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal;
|
||||
let permValue = Services.perms.testExactPermissionFromPrincipal(principal, "geolocation");
|
||||
is(permValue, Ci.nsIPermissionManager.PROMPT_ACTION, "Geolocation permission: prompt.");
|
||||
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
mutObserver = new MutationObserver(function(mutations) {
|
||||
if (msg.textContent == "Failure.") {
|
||||
ok(true, "Permission not granted.");
|
||||
} else {
|
||||
ok(false, "Permission not granted.");
|
||||
}
|
||||
|
||||
if (openedWindows != 2) {
|
||||
ok(false, "Prompt not shown.");
|
||||
}
|
||||
|
||||
finish();
|
||||
});
|
||||
mutObserver.observe(msg, { childList: true });
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
mutObserver.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("media.navigator.permission.fake", true);
|
||||
|
||||
let getUserMediaDialogOpened = false;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.documentURI == "chrome://webapprt/content/getUserMediaDialog.xul") {
|
||||
getUserMediaDialogOpened = true;
|
||||
win.close();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
let mutObserver = null;
|
||||
|
||||
loadWebapp("getUserMedia.webapp", undefined, function onLoad() {
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
mutObserver = new MutationObserver(function(mutations) {
|
||||
is(msg.textContent, "PermissionDeniedError: The user did not grant permission for the operation.",
|
||||
"getUserMedia permission denied.");
|
||||
ok(getUserMediaDialogOpened, "Prompt shown.");
|
||||
finish();
|
||||
});
|
||||
mutObserver.observe(msg, { childList: true });
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
mutObserver.disconnect();
|
||||
Services.prefs.clearUserPref("media.navigator.permission.fake");
|
||||
});
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { WebappOSUtils } = Cu.import("resource://gre/modules/WebappOSUtils.jsm", {});
|
||||
|
||||
let url = "http://test/webapprtChrome/webapprt/test/chrome/sample.webapp";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("install-app.webapp", undefined, function onLoad() {
|
||||
|
||||
let dialogShown = false;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.documentURI == "chrome://global/content/commonDialog.xul") {
|
||||
dialogShown = true;
|
||||
|
||||
executeSoon(() => {
|
||||
win.document.documentElement.acceptDialog();
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
});
|
||||
|
||||
let request = navigator.mozApps.install(url);
|
||||
request.onsuccess = function() {
|
||||
ok(dialogShown, "Install app dialog shown");
|
||||
ok(request.result, "App installed");
|
||||
|
||||
navigator.mozApps.mgmt.uninstall(request.result).onsuccess = function() {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
request.onerror = function() {
|
||||
ok(false, "Not installed: " + request.error.name);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { PaymentManager } = Cu.import("resource://gre/modules/Payment.jsm", {});
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let curTest = 0;
|
||||
|
||||
let tests = [];
|
||||
tests.push({
|
||||
providerUri: "https://example.com:443/webapprtChrome/webapprt/test/chrome/mozpay-success.html?req=",
|
||||
message: "Success."
|
||||
});
|
||||
tests.push({
|
||||
providerUri: "https://example.com:443/webapprtChrome/webapprt/test/chrome/mozpay-failure.html?req=",
|
||||
message: "Chocolate rejected."
|
||||
});
|
||||
|
||||
let jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhdWQiOiAibW9j" +
|
||||
"a3BheXByb3ZpZGVyLnBocGZvZ2FwcC5jb20iLCAiaXNzIjogIkVudGVyI" +
|
||||
"HlvdSBhcHAga2V5IGhlcmUhIiwgInJlcXVlc3QiOiB7Im5hbWUiOiAiUG" +
|
||||
"llY2Ugb2YgQ2FrZSIsICJwcmljZSI6ICIxMC41MCIsICJwcmljZVRpZXI" +
|
||||
"iOiAxLCAicHJvZHVjdGRhdGEiOiAidHJhbnNhY3Rpb25faWQ9ODYiLCAi" +
|
||||
"Y3VycmVuY3lDb2RlIjogIlVTRCIsICJkZXNjcmlwdGlvbiI6ICJWaXJ0d" +
|
||||
"WFsIGNob2NvbGF0ZSBjYWtlIHRvIGZpbGwgeW91ciB2aXJ0dWFsIHR1bW" +
|
||||
"15In0sICJleHAiOiAxMzUyMjMyNzkyLCAiaWF0IjogMTM1MjIyOTE5Miw" +
|
||||
"gInR5cCI6ICJtb2NrL3BheW1lbnRzL2luYXBwL3YxIn0.QZxc62USCy4U" +
|
||||
"IyKIC1TKelVhNklvk-Ou1l_daKntaFI";
|
||||
|
||||
PaymentManager.registeredProviders = {};
|
||||
PaymentManager.registeredProviders["mock/payments/inapp/v1"] = {
|
||||
name: "mockprovider",
|
||||
description: "Mock Payment Provider",
|
||||
uri: tests[curTest].providerUri,
|
||||
requestMethod: "GET"
|
||||
};
|
||||
|
||||
let providerWindow;
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.getElementById("content").getAttribute("src") ==
|
||||
(tests[curTest].providerUri + jwt)) {
|
||||
ok(true, "Payment provider window shown.");
|
||||
providerWindow = win;
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
let mutObserver = null;
|
||||
|
||||
function onLoad() {
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
mutObserver = new MutationObserver(function(mutations) {
|
||||
is(msg.textContent, tests[curTest].message, "Got: " + tests[curTest].message);
|
||||
|
||||
if (!providerWindow) {
|
||||
ok(false, "Payment provider window shown.");
|
||||
} else {
|
||||
providerWindow.close();
|
||||
providerWindow = null;
|
||||
}
|
||||
|
||||
runNextTest();
|
||||
});
|
||||
mutObserver.observe(msg, { childList: true });
|
||||
}
|
||||
|
||||
loadWebapp("mozpay.webapp", undefined, onLoad);
|
||||
|
||||
function runNextTest() {
|
||||
providerWindow = null;
|
||||
if (mutObserver) {
|
||||
mutObserver.disconnect();
|
||||
}
|
||||
|
||||
curTest++;
|
||||
|
||||
if (curTest < tests.length) {
|
||||
PaymentManager.registeredProviders["mock/payments/inapp/v1"].uri = tests[curTest].providerUri;
|
||||
|
||||
gAppBrowser.addEventListener("load", function onLoadH() {
|
||||
gAppBrowser.removeEventListener("load", onLoadH, true);
|
||||
onLoad();
|
||||
}, true);
|
||||
gAppBrowser.reload();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
mutObserver.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let { AllPossiblePermissions } =
|
||||
Cu.import("resource://gre/modules/PermissionsInstaller.jsm", {});
|
||||
let { AppsUtils } = Cu.import("resource://gre/modules/AppsUtils.jsm", {});
|
||||
let { DOMApplicationRegistry } =
|
||||
Cu.import("resource://gre/modules/Webapps.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("noperm.webapp", undefined, function onLoad() {
|
||||
let app = WebappRT.config.app;
|
||||
|
||||
// Check that the app is non privileged.
|
||||
is(AppsUtils.getAppManifestStatus(app.manifest), Ci.nsIPrincipal.APP_STATUS_INSTALLED, "The app is not privileged");
|
||||
|
||||
// Check that the app principal has the correct appId.
|
||||
let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal;
|
||||
is(DOMApplicationRegistry.getAppLocalIdByManifestURL(app.manifestURL), principal.appId, "Principal app ID correct");
|
||||
|
||||
let alwaysAllowed = ["indexedDB"]
|
||||
|
||||
// Check if all the permissions of the app are unknown.
|
||||
for (let permName of AllPossiblePermissions) {
|
||||
// Get the value for the permission.
|
||||
let permValue = Services.perms.testExactPermissionFromPrincipal(principal, permName);
|
||||
|
||||
if (alwaysAllowed.includes(permName)) {
|
||||
is(permValue, Ci.nsIPermissionManager.ALLOW_ACTION, "Permission " + permName + " allowed.");
|
||||
} else {
|
||||
is(permValue, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Permission " + permName + " unknown.");
|
||||
}
|
||||
}
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// This is a sample WebappRT chrome test. It's just a browser-chrome mochitest.
|
||||
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
ok(true, "true is true!");
|
||||
loadWebapp("sample.webapp", undefined, function onLoad() {
|
||||
is(document.documentElement.getAttribute("title"),
|
||||
WebappRT.config.app.manifest.name,
|
||||
"Window title should be webapp name");
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
var observer = new MutationObserver(function (mutations) {
|
||||
ok(/^Webapp getSelf OK:/.test(msg.textContent),
|
||||
"The webapp should have successfully installed and updated its msg");
|
||||
finish();
|
||||
});
|
||||
observer.observe(msg, { childList: true });
|
||||
});
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let { AppsUtils } = Cu.import("resource://gre/modules/AppsUtils.jsm", {});
|
||||
let { DOMApplicationRegistry } =
|
||||
Cu.import("resource://gre/modules/Webapps.jsm", {});
|
||||
let { PermissionsTable } =
|
||||
Cu.import("resource://gre/modules/PermissionsTable.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("webperm.webapp", undefined, function onLoad() {
|
||||
let app = WebappRT.config.app;
|
||||
|
||||
// Check that the app is non privileged.
|
||||
is(AppsUtils.getAppManifestStatus(app.manifest), Ci.nsIPrincipal.APP_STATUS_INSTALLED, "The app is not privileged");
|
||||
|
||||
// Check that the app principal has the correct appId.
|
||||
let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal;
|
||||
is(DOMApplicationRegistry.getAppLocalIdByManifestURL(app.manifestURL), principal.appId, "Principal app ID correct");
|
||||
|
||||
let perms = [
|
||||
{
|
||||
manifestName: "storage",
|
||||
permName: "indexedDB",
|
||||
},
|
||||
{
|
||||
manifestName: "geolocation",
|
||||
permName: "geolocation",
|
||||
},
|
||||
{
|
||||
manifestName: "camera",
|
||||
permName: "camera",
|
||||
},
|
||||
{
|
||||
manifestName: "alarms",
|
||||
permName: "alarms",
|
||||
},
|
||||
{
|
||||
manifestName: "tcp-socket",
|
||||
permName: "tcp-socket",
|
||||
},
|
||||
{
|
||||
manifestName: "network-events",
|
||||
permName: "network-events",
|
||||
},
|
||||
{
|
||||
manifestName: "webapps-manage",
|
||||
permName: "webapps-manage",
|
||||
},
|
||||
{
|
||||
manifestName: "desktop-notification",
|
||||
permName: "desktop-notification",
|
||||
},
|
||||
];
|
||||
|
||||
for (let perm of perms) {
|
||||
// Get the values for all the permission.
|
||||
let permValue = Services.perms.testExactPermissionFromPrincipal(principal, perm.permName);
|
||||
|
||||
// Check if the app has the permission as specified in the PermissionsTable.jsm file.
|
||||
is(permValue, PermissionsTable[perm.manifestName]["app"], "Permission " + perm.permName + " correctly set.");
|
||||
}
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let HandlerService = {
|
||||
classID: Components.ID("{b4ed9fab-fd39-435a-8e3e-edc3e689e72e}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory,
|
||||
Ci.nsIExternalProtocolService]),
|
||||
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
return this.QueryInterface(aIID);
|
||||
},
|
||||
|
||||
init: function() {
|
||||
Components.manager.nsIComponentRegistrar.registerFactory(this.classID,
|
||||
"Test Protocol Handler Service",
|
||||
"@mozilla.org/uriloader/external-protocol-service;1",
|
||||
this);
|
||||
},
|
||||
|
||||
getProtocolHandlerInfo: function(aProtocolScheme) {
|
||||
let handlerInfoObj = {
|
||||
launchWithURI: function(aURI) {
|
||||
is(aURI.spec,
|
||||
"http://test/webapprtChrome/webapprt/test/chrome/sample.html",
|
||||
"The app tried to open the link in the default browser");
|
||||
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
return handlerInfoObj;
|
||||
}
|
||||
};
|
||||
|
||||
HandlerService.init();
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let progressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
onLocationChange: function(progress, request, location, flags) {
|
||||
ok(false, "Location changed");
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.location == "chrome://webapprt/content/webapp.xul") {
|
||||
ok(false, "New app window opened");
|
||||
finish();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
loadWebapp("window-open-blank.webapp", undefined, function() {
|
||||
gAppBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
gAppBrowser.removeProgressListener(progressListener);
|
||||
});
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let { DOMApplicationRegistry } =
|
||||
Cu.import("resource://gre/modules/Webapps.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let appID = Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
|
||||
let progressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
onLocationChange: function(progress, request, location, flags) {
|
||||
gAppBrowser.addEventListener("load", function onLoad() {
|
||||
gAppBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
is(DOMApplicationRegistry.getAppLocalIdByManifestURL(WebappRT.config.app.manifestURL),
|
||||
appID,
|
||||
"Principal app ID hasn't changed");
|
||||
|
||||
finish();
|
||||
}, true);
|
||||
}
|
||||
};
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.location == "chrome://webapprt/content/webapp.xul") {
|
||||
ok(false, "New app window opened");
|
||||
finish();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
loadWebapp("window-open-self.webapp", undefined, function() {
|
||||
appID = gAppBrowser.contentDocument.defaultView.document.nodePrincipal.appId;
|
||||
|
||||
is(DOMApplicationRegistry.getAppLocalIdByManifestURL(WebappRT.config.app.manifestURL),
|
||||
appID,
|
||||
"Principal app ID correct");
|
||||
|
||||
gAppBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
gAppBrowser.removeProgressListener(progressListener);
|
||||
});
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let { DOMApplicationRegistry } =
|
||||
Cu.import("resource://gre/modules/Webapps.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let appID = Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
|
||||
let progressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
onLocationChange: function(progress, request, location, flags) {
|
||||
ok(false, "Content redirected")
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.location == "chrome://webapprt/content/webapp.xul") {
|
||||
let winAppBrowser = win.document.getElementById("content");
|
||||
winAppBrowser.addEventListener("load", function onLoadBrowser() {
|
||||
winAppBrowser.removeEventListener("load", onLoadBrowser, true);
|
||||
|
||||
is(winAppBrowser.getAttribute("src"),
|
||||
"http://test/webapprtChrome/webapprt/test/chrome/sample.html",
|
||||
"New window browser has correct src");
|
||||
|
||||
is(winAppBrowser.contentDocument.defaultView.document.nodePrincipal.appId,
|
||||
appID,
|
||||
"New window principal app ID correct");
|
||||
|
||||
win.close();
|
||||
|
||||
finish();
|
||||
}, true);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
loadWebapp("window-open.webapp", undefined, function() {
|
||||
appID = gAppBrowser.contentDocument.defaultView.document.nodePrincipal.appId;
|
||||
|
||||
is(DOMApplicationRegistry.getAppLocalIdByManifestURL(WebappRT.config.app.manifestURL),
|
||||
appID,
|
||||
"Principal app ID correct");
|
||||
|
||||
gAppBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
gAppBrowser.removeProgressListener(progressListener);
|
||||
});
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("window-title.webapp", undefined, function onLoad() {
|
||||
is(document.documentElement.getAttribute("title"),
|
||||
WebappRT.config.app.manifest.name,
|
||||
"initial window title should be webapp name");
|
||||
|
||||
// Tests are triples of [URL to load, expected window title, test message].
|
||||
let tests = [
|
||||
["http://example.com/webapprtChrome/webapprt/test/chrome/window-title.html",
|
||||
"http://example.com" + " - " + WebappRT.config.app.manifest.name,
|
||||
"window title should show origin of page at different origin"],
|
||||
["http://test/webapprtChrome/webapprt/test/chrome/window-title.html",
|
||||
WebappRT.config.app.manifest.name,
|
||||
"after returning to app origin, window title should no longer show origin"],
|
||||
];
|
||||
|
||||
let title, message;
|
||||
|
||||
let progressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
onLocationChange: function onLocationChange(progress, request, location,
|
||||
flags) {
|
||||
// Do test in timeout to give runtime time to change title.
|
||||
window.setTimeout(function() {
|
||||
is(document.documentElement.getAttribute("title"), title, message);
|
||||
testNext();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
gAppBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
|
||||
function testNext() {
|
||||
if (!tests.length) {
|
||||
gAppBrowser.removeProgressListener(progressListener);
|
||||
gAppBrowser.stop();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
[gAppBrowser.contentDocument.location, title, message] = tests.shift();
|
||||
}
|
||||
|
||||
testNext();
|
||||
});
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>This is the test webapp.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
{"name": "Debugger Test Webapp", "description": "A debugger test app.", "launch_path": "/webapprtChrome/webapprt/test/chrome/debugger.html" }
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Download Test App</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Download Test App</h1>
|
||||
<a id="download" href="http://mochi.test:8888//webapprtChrome/webapprt/test/chrome/download.test">Download</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
TEST FILE
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Download Test App",
|
||||
"description": "an app for testing downloads",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/download.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,44 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let list = MockDownloadsModule();
|
||||
|
||||
let downloadsInList = [
|
||||
new DummyDownload("test1"),
|
||||
new DummyDownload("test2"),
|
||||
];
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.documentURI ==
|
||||
"chrome://webapprt/content/downloads/downloads.xul") {
|
||||
ok(true, "Download manager window shown");
|
||||
|
||||
waitDownloadListPopulation(win).then(() => {
|
||||
test_downloadList(win, downloadsInList);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
|
||||
Services.wm.getMostRecentWindow("Download:Manager").close();
|
||||
});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("download.webapp", undefined, function onLoad() {
|
||||
for each (let download in downloadsInList) {
|
||||
list.addDownload(download);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let list = MockDownloadsModule();
|
||||
|
||||
let download = new DummyDownload("test");
|
||||
let removedDownload = new DummyDownload("removed");
|
||||
|
||||
let winObserver = function(win, topic) {
|
||||
if (topic == "domwindowopened") {
|
||||
win.addEventListener("load", function onLoadWindow() {
|
||||
win.removeEventListener("load", onLoadWindow, false);
|
||||
|
||||
if (win.document.documentURI ==
|
||||
"chrome://webapprt/content/downloads/downloads.xul") {
|
||||
ok(true, "Download manager window shown");
|
||||
|
||||
waitDownloadListPopulation(win).then(() => {
|
||||
test_downloadList(win, [download, removedDownload]);
|
||||
list.removeDownload(removedDownload);
|
||||
executeSoon(() => {
|
||||
test_downloadList(win, [download]);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(winObserver);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.ww.unregisterNotification(winObserver);
|
||||
|
||||
Services.wm.getMostRecentWindow("Download:Manager").close();
|
||||
});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadWebapp("download.webapp", undefined, function onLoad() {
|
||||
list.addDownload(download);
|
||||
list.addDownload(removedDownload);
|
||||
});
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
../head.js
|
||||
|
||||
[browser_add_download.js]
|
||||
[browser_remove_download.js]
|
||||
@@ -1,22 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
function failureCallback() {
|
||||
document.getElementById("msg").textContent = "Failure.";
|
||||
}
|
||||
|
||||
function successCallback() {
|
||||
document.getElementById("msg").textContent = "Success.";
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(successCallback, failureCallback);
|
||||
};
|
||||
</script>
|
||||
<p id="msg">Webapp waiting for geolocation...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Geolocation Permission Test Webapp",
|
||||
"description": "A webapp for testing geolocation prompt.",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/geolocation-prompt-noperm.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function failureCallback() {
|
||||
document.getElementById("msg").textContent = "Failure.";
|
||||
}
|
||||
function successCallback() {
|
||||
document.getElementById("msg").textContent = "Success.";
|
||||
}
|
||||
navigator.geolocation.getCurrentPosition(successCallback, failureCallback);
|
||||
</script>
|
||||
<p id="msg">Webapp waiting for geolocation...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "Geolocation Permission Test Webapp",
|
||||
"description": "A webapp for testing geolocation prompt.",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/geolocation-prompt-perm.html",
|
||||
"permissions": {
|
||||
"geolocation": { "description": "Desc" }
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>getUserMedia Test App</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<span id="msg"></span>
|
||||
<script>
|
||||
navigator.mozGetUserMedia({ video: true, audio: true, fake: true },
|
||||
function(localMediaStream) {
|
||||
document.getElementById("msg").textContent = window.URL.createObjectURL(localMediaStream);
|
||||
},
|
||||
|
||||
function(err) {
|
||||
document.getElementById("msg").textContent = err;
|
||||
});
|
||||
</script>
|
||||
<h1>getUserMedia Test App</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "getUserMedia Test App",
|
||||
"description": "an app for testing getUserMedia",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/getUserMedia.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,234 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Some of the code we want to provide to chrome mochitests is in another file
|
||||
// so we can share it with the mochitest shim window, thus we need to load it.
|
||||
Services.scriptloader
|
||||
.loadSubScript("chrome://webapprt/content/mochitest-shared.js", this);
|
||||
|
||||
const MANIFEST_URL_BASE = Services.io.newURI(
|
||||
"http://test/webapprtChrome/webapprt/test/chrome/", null, null);
|
||||
|
||||
/**
|
||||
* Load the webapp in the app browser.
|
||||
*
|
||||
* @param {String} manifestURL
|
||||
* @see becomeWebapp
|
||||
* @param {Object} parameters
|
||||
* @see becomeWebapp
|
||||
* @param {Function} onLoad
|
||||
* The callback to call once the webapp is loaded.
|
||||
*/
|
||||
function loadWebapp(manifest, parameters, onLoad) {
|
||||
let url = Services.io.newURI(manifest, null, MANIFEST_URL_BASE);
|
||||
|
||||
becomeWebapp(url.spec, parameters, function onBecome() {
|
||||
function onLoadApp() {
|
||||
gAppBrowser.removeEventListener("load", onLoadApp, true);
|
||||
onLoad();
|
||||
}
|
||||
gAppBrowser.addEventListener("load", onLoadApp, true);
|
||||
gAppBrowser.setAttribute("src", WebappRT.launchURI);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// We load DOMApplicationRegistry into a local scope to avoid appearing
|
||||
// to leak it.
|
||||
let { DOMApplicationRegistry } = Cu.import("resource://gre/modules/Webapps.jsm", {});
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
DOMApplicationRegistry.uninstall(url.spec).then(() => {
|
||||
// Load another page in the browser element, this is needed for tests
|
||||
// that use the same app (that have the same URL).
|
||||
gAppBrowser.setAttribute("src", "about:blank");
|
||||
|
||||
resolve();
|
||||
}, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Utilities for the downloads tests
|
||||
|
||||
let MockDownloadList = function() {
|
||||
};
|
||||
|
||||
MockDownloadList.prototype = {
|
||||
downloads: new Set(),
|
||||
views: new Set(),
|
||||
|
||||
addView: function(aView) {
|
||||
this.views.add(aView);
|
||||
|
||||
for (let download of this.downloads) {
|
||||
for (let view of this.views) {
|
||||
view.onDownloadAdded(download);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeView: function(aView) {
|
||||
this.views.delete(aView);
|
||||
},
|
||||
|
||||
addDownload: function(aDownload) {
|
||||
this.downloads.add(aDownload);
|
||||
|
||||
for (let view of this.views) {
|
||||
view.onDownloadAdded(aDownload);
|
||||
}
|
||||
},
|
||||
|
||||
changeDownload: function(aDownload) {
|
||||
for (let view of this.views) {
|
||||
if (view.onDownloadChanged) {
|
||||
view.onDownloadChanged(aDownload);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeDownload: function(aDownload) {
|
||||
this.downloads.delete(aDownload);
|
||||
|
||||
for (let view of this.views) {
|
||||
if (view.onDownloadRemoved) {
|
||||
view.onDownloadRemoved(aDownload);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function MockDownloadsModule() {
|
||||
let { DownloadView } = Cu.import("resource://webapprt/modules/DownloadView.jsm", {});
|
||||
|
||||
let list = new MockDownloadList();
|
||||
|
||||
let { Downloads } = Cu.import("resource://gre/modules/Downloads.jsm", {});
|
||||
let oldDownloadsGetList = Downloads.getList;
|
||||
|
||||
Downloads.getList = function(aKind) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(list);
|
||||
});
|
||||
};
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
list.removeView(DownloadView);
|
||||
|
||||
Downloads.getList = oldDownloadsGetList;
|
||||
});
|
||||
|
||||
// Reinitialize DownloadView because it's already initialized
|
||||
// when the webapprt test starts.
|
||||
// We need to reinitialize it so that it gets associated to the
|
||||
// MockDownloadList object that we've created.
|
||||
DownloadView.init();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function DummyDownload(aFileName) {
|
||||
this.file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
this.file.append(aFileName);
|
||||
this.file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
|
||||
|
||||
this.startTime = Date.now();
|
||||
this.source = {
|
||||
url: "http://mochi.test:8888//webapprtChrome/webapprt/test/chrome/download.webapp",
|
||||
isPrivate: false,
|
||||
referrer: null,
|
||||
};
|
||||
this.target = {
|
||||
path: this.file.path,
|
||||
partFilePath: this.file.path + ".part",
|
||||
}
|
||||
};
|
||||
|
||||
DummyDownload.prototype = {
|
||||
succeeded: false,
|
||||
canceled: false,
|
||||
stopped: false,
|
||||
hasPartialData: false,
|
||||
hasProgress: false,
|
||||
progress: 0,
|
||||
currentBytes: 0,
|
||||
totalBytes: 0,
|
||||
error: null,
|
||||
|
||||
// Attributes needed to test the download item in the richlistbox
|
||||
state: 0,
|
||||
percentComplete: -1,
|
||||
};
|
||||
|
||||
function waitDownloadListPopulation(aWin) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let disconnected = false;
|
||||
|
||||
var observer = new MutationObserver(function(aMutations) {
|
||||
for each (let mutation in aMutations) {
|
||||
if (mutation.addedNodes) {
|
||||
for each (let node in mutation.addedNodes) {
|
||||
if (node.id == "downloadView") {
|
||||
observer.disconnect();
|
||||
disconnected = true;
|
||||
|
||||
// Wait for the resolution of the Downloads.getList promise.
|
||||
executeSoon(() => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(aWin.document, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: false,
|
||||
characterData: false
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
if (!disconnected) {
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_downloadList(aWin, aDownloadList) {
|
||||
let richlistbox = aWin.document.getElementById("downloadView");
|
||||
|
||||
is(richlistbox.children.length, aDownloadList.length,
|
||||
"There is the correct number of richlistitems");
|
||||
|
||||
for (let i = 0; i < richlistbox.children.length; i++) {
|
||||
let elm = richlistbox.children[i];
|
||||
|
||||
let name = elm.getAttribute("target");
|
||||
|
||||
let download = null;
|
||||
for (let d = 0; d < aDownloadList.length; d++) {
|
||||
if (aDownloadList[d].file.leafName == name) {
|
||||
download = aDownloadList[d];
|
||||
aDownloadList.splice(d, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!download) {
|
||||
ok(false, "Download item unexpected");
|
||||
} else {
|
||||
ok(true, "Download item expected");
|
||||
is(elm.getAttribute("state"), download.state, "Download state correct");
|
||||
is(elm.getAttribute("progress"), download.percentComplete,
|
||||
"Download progress correct");
|
||||
}
|
||||
}
|
||||
|
||||
is(aDownloadList.length, 0,
|
||||
"All the downloads expected to be in the list were in the list");
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Install Test App</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Install Test App</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Install Test App",
|
||||
"description": "an app for testing installing apps",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/install-app.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
mozPaymentProvider.paymentFailed('Chocolate rejected.');
|
||||
</script>
|
||||
<p id="msg">Webapp waiting to pay...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
mozPaymentProvider.paymentSuccess();
|
||||
</script>
|
||||
<p id="msg">Webapp waiting to pay...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,45 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// Payload
|
||||
// {
|
||||
// "aud": "mockpayprovider.phpfogapp.com",
|
||||
// "iss": "Enter you app key here!",
|
||||
// "request": {
|
||||
// "name": "Piece of Cake",
|
||||
// "price": "10.50",
|
||||
// "priceTier": 1,
|
||||
// "productdata": "transaction_id=86",
|
||||
// "currencyCode": "USD",
|
||||
// "description": "Virtual chocolate cake to fill your virtual tummy"
|
||||
// },
|
||||
// "exp": 1352232792,
|
||||
// "iat": 1352229192,
|
||||
// "typ": "mock/payments/inapp/v1"
|
||||
// }
|
||||
var jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhdWQiOiAibW9j" +
|
||||
"a3BheXByb3ZpZGVyLnBocGZvZ2FwcC5jb20iLCAiaXNzIjogIkVudGVyI" +
|
||||
"HlvdSBhcHAga2V5IGhlcmUhIiwgInJlcXVlc3QiOiB7Im5hbWUiOiAiUG" +
|
||||
"llY2Ugb2YgQ2FrZSIsICJwcmljZSI6ICIxMC41MCIsICJwcmljZVRpZXI" +
|
||||
"iOiAxLCAicHJvZHVjdGRhdGEiOiAidHJhbnNhY3Rpb25faWQ9ODYiLCAi" +
|
||||
"Y3VycmVuY3lDb2RlIjogIlVTRCIsICJkZXNjcmlwdGlvbiI6ICJWaXJ0d" +
|
||||
"WFsIGNob2NvbGF0ZSBjYWtlIHRvIGZpbGwgeW91ciB2aXJ0dWFsIHR1bW" +
|
||||
"15In0sICJleHAiOiAxMzUyMjMyNzkyLCAiaWF0IjogMTM1MjIyOTE5Miw" +
|
||||
"gInR5cCI6ICJtb2NrL3BheW1lbnRzL2luYXBwL3YxIn0.QZxc62USCy4U" +
|
||||
"IyKIC1TKelVhNklvk-Ou1l_daKntaFI";
|
||||
|
||||
var request = navigator.mozPay(jwt);
|
||||
request.onsuccess = function onsuccess() {
|
||||
document.getElementById("msg").textContent = "Success.";
|
||||
};
|
||||
request.onerror = function onerror() {
|
||||
document.getElementById("msg").textContent = request.error.name;
|
||||
};
|
||||
</script>
|
||||
<p id="msg">Webapp waiting to be paid...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "mozPay Test Webapp",
|
||||
"description": "A webapp that wants to be paid (and shall be paid).",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/mozpay.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,9 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>This is the test webapp.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "No Permissions Test Webapp",
|
||||
"description": "A webapp for testing permission installation.",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/noperm.html"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<!--
|
||||
This is the webapp. It doesn't need to do anything in particular, just
|
||||
whatever you want to test from your browser_ test file.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
|
||||
function onLoad() {
|
||||
var msg = document.getElementById("msg");
|
||||
var self = navigator.mozApps.getSelf();
|
||||
self.onsuccess = function () {
|
||||
msg.textContent = "Webapp getSelf OK: " + self.result;
|
||||
};
|
||||
self.onerror = function () {
|
||||
msg.textContent = "Webapp getSelf failed: " + self.error.name;
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onLoad();" onunload="">
|
||||
<p>This is the test webapp.</p>
|
||||
<p id="msg">Webapp waiting for page load...</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
{"name": "Sample Test Webapp", "description": "A webapp that demonstrates how to make a WebappRT test.", "launch_path": "/webapprtChrome/webapprt/test/chrome/sample.html" }
|
||||
@@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
||||
@@ -1,67 +0,0 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
sample.webapp
|
||||
sample.webapp^headers^
|
||||
sample.html
|
||||
window-title.webapp
|
||||
window-title.webapp^headers^
|
||||
window-title.html
|
||||
webperm.webapp
|
||||
webperm.webapp^headers^
|
||||
webperm.html
|
||||
noperm.webapp
|
||||
noperm.webapp^headers^
|
||||
noperm.html
|
||||
geolocation-prompt-perm.webapp
|
||||
geolocation-prompt-perm.webapp^headers^
|
||||
geolocation-prompt-noperm.webapp
|
||||
geolocation-prompt-noperm.webapp^headers^
|
||||
geolocation-prompt-perm.html
|
||||
geolocation-prompt-noperm.html
|
||||
debugger.webapp
|
||||
debugger.webapp^headers^
|
||||
debugger.html
|
||||
mozpay.webapp
|
||||
mozpay.webapp^headers^
|
||||
mozpay.html
|
||||
mozpay-success.html
|
||||
mozpay-failure.html
|
||||
getUserMedia.webapp
|
||||
getUserMedia.webapp^headers^
|
||||
getUserMedia.html
|
||||
window-open-self.webapp
|
||||
window-open-self.webapp^headers^
|
||||
window-open-self.html
|
||||
window-open.webapp
|
||||
window-open.webapp^headers^
|
||||
window-open.html
|
||||
window-open-blank.webapp
|
||||
window-open-blank.webapp^headers^
|
||||
window-open-blank.html
|
||||
alarm.html
|
||||
alarm.webapp
|
||||
alarm.webapp^headers^
|
||||
download.html
|
||||
download.webapp
|
||||
download.webapp^headers^
|
||||
download.test
|
||||
install-app.html
|
||||
install-app.webapp
|
||||
install-app.webapp^headers^
|
||||
|
||||
[browser_alarm.js]
|
||||
[browser_debugger.js]
|
||||
[browser_download.js]
|
||||
[browser_geolocation-prompt-noperm.js]
|
||||
[browser_geolocation-prompt-perm.js]
|
||||
[browser_getUserMedia.js]
|
||||
[browser_install-app.js]
|
||||
[browser_mozpay.js]
|
||||
[browser_noperm.js]
|
||||
[browser_sample.js]
|
||||
[browser_webperm.js]
|
||||
[browser_window-open-blank.js]
|
||||
[browser_window-open-self.js]
|
||||
[browser_window-open.js]
|
||||
[browser_window-title.js]
|
||||
@@ -1,9 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>This is the test webapp.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "Hosted Permissions Test Webapp",
|
||||
"description": "A webapp for testing permission installation.",
|
||||
"launch_path": "/webapprtChrome/webapprt/test/chrome/webperm.html",
|
||||
"permissions": {
|
||||
"storage": { "description": "I need to store 1 million dollars in your bank account" },
|
||||
"geolocation": { "description": "Desc" },
|
||||
"camera": { "description": "Desc" },
|
||||
"alarms": { "description": "Desc" },
|
||||
"tcp-socket": { "description": "Desc" },
|
||||
"network-events": { "description": "Desc" },
|
||||
"webapps-manage": { "description": "Desc" },
|
||||
"desktop-notification": { "description": "Desc" }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user