зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c on a CLOSED TREE.
This commit is contained in:
Коммит
31a2144ac4
|
@ -4445,7 +4445,8 @@ nsBrowserAccess.prototype = {
|
|||
break;
|
||||
case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB :
|
||||
let browser = this._openURIInNewTab(aURI, aOpener, isExternal);
|
||||
newWindow = browser.contentWindow;
|
||||
if (browser)
|
||||
newWindow = browser.contentWindow;
|
||||
break;
|
||||
default : // OPEN_CURRENTWINDOW or an illegal value
|
||||
newWindow = content;
|
||||
|
@ -4470,7 +4471,10 @@ nsBrowserAccess.prototype = {
|
|||
|
||||
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
|
||||
let browser = this._openURIInNewTab(aURI, aOpener, isExternal);
|
||||
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
|
||||
if (browser)
|
||||
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
isTabContentWindow: function (aWindow) {
|
||||
|
|
|
@ -368,7 +368,7 @@ function test18a() {
|
|||
if (event.type == "TabOpen") {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
|
||||
this.tab = event.originalTarget;
|
||||
ok(event.target.label == this.url, "Test 18a, Update link should open up the plugin check page");
|
||||
is(event.target.label, this.url, "Test 18a, Update link should open up the plugin check page");
|
||||
gBrowser.removeTab(this.tab);
|
||||
test18b();
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
<div class="banner-content" template='{"type":"attribute","path":"adb.available","name":"adb-available"}'>
|
||||
<span>&connection.notConnected2;</span>
|
||||
<div id="connection-manual">
|
||||
<button class="action-primary left" onclick="UI.connect()" id="connect-button" template='{"type":"localizedContent","property":"connection.connectTo","paths":["connection.host","connection.port"]}'></button>
|
||||
<button class="right" onclick="UI.editConnectionParameters()">&connection.changeHostAndPort;</button>
|
||||
<button class="action-primary left" onclick="UI.connect()" id="connect-button" template='{"type":"localizedContent","property":"connection.connectTo","paths":["connection.host","connection.port"]}' title="&connection.connectTooltip;"></button>
|
||||
<button class="right" onclick="UI.editConnectionParameters()" title="&connection.changeHostAndPortTooltip;">&connection.changeHostAndPort;</button>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"content": "",
|
||||
"docshell": "",
|
||||
"dom": "",
|
||||
"layout": ""
|
||||
"layout": "",
|
||||
"toolkit/devtools/apps": ""
|
||||
},
|
||||
"excludetests": {
|
||||
"content/xul":"tests that use xul",
|
||||
|
|
|
@ -1089,10 +1089,7 @@ function openURL(aURL)
|
|||
else {
|
||||
var recentWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (recentWindow) {
|
||||
var win = recentWindow.browserDOMWindow.openURI(uri, null,
|
||||
recentWindow.browserDOMWindow.OPEN_DEFAULTWINDOW,
|
||||
recentWindow.browserDOMWindow.OPEN_NEW);
|
||||
win.focus();
|
||||
recentWindow.openUILinkIn(uri.spec, "tab");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,12 +170,10 @@ function installPackaged(client, webappsActor, packagePath, appId) {
|
|||
if (res.error) {
|
||||
deferred.reject(res);
|
||||
}
|
||||
});
|
||||
client.addOneTimeListener("webappsEvent", function (aState, aType, aPacket) {
|
||||
if ("error" in aType)
|
||||
deferred.reject({error: aType.error, message: aType.message});
|
||||
if ("error" in res)
|
||||
deferred.reject({error: res.error, message: res.message});
|
||||
else
|
||||
deferred.resolve({appId: aType.appId});
|
||||
deferred.resolve({appId: res.appId});
|
||||
});
|
||||
// Ensure deleting the temporary package file, but only if that a temporary
|
||||
// package created when we pass a directory as `packagePath`
|
||||
|
@ -203,12 +201,10 @@ function installHosted(client, webappsActor, appId, metadata, manifest) {
|
|||
if (res.error) {
|
||||
deferred.reject(res);
|
||||
}
|
||||
});
|
||||
client.addOneTimeListener("webappsEvent", function (aState, aType, aPacket) {
|
||||
if ("error" in aType)
|
||||
deferred.reject({error: aType.error, message: aType.message});
|
||||
if ("error" in res)
|
||||
deferred.reject({error: res.error, message: res.message});
|
||||
else
|
||||
deferred.resolve({appId: aType.appId});
|
||||
deferred.resolve({appId: res.appId});
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
# The mochitest doesn't work on fennec yet
|
||||
ifneq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_FILES = \
|
||||
test_webapps_actor.html \
|
||||
debugger-protocol-helper.js \
|
||||
data/ \
|
||||
redirect.sjs \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,86 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
const { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
const { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let gClient, gActor;
|
||||
|
||||
function connect(onDone) {
|
||||
// Initialize a loopback remote protocol connection
|
||||
DebuggerServer.init(function () { return true; });
|
||||
// We need to register browser actors to have `listTabs` working
|
||||
// and also have a root actor
|
||||
|
||||
if (Services.appinfo.name == "B2G") {
|
||||
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webbrowser.js");
|
||||
DebuggerServer.addActors('chrome://browser/content/dbg-browser-actors.js');
|
||||
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webapps.js");
|
||||
} else {
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
// Setup client and actor used in all tests
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function onConnect() {
|
||||
gClient.listTabs(function onListTabs(aResponse) {
|
||||
gActor = aResponse.webappsActor;
|
||||
if (gActor)
|
||||
onDone();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function webappActorRequest(request, onResponse) {
|
||||
if (!gActor) {
|
||||
connect(webappActorRequest.bind(null, request, onResponse));
|
||||
return;
|
||||
}
|
||||
|
||||
request.to = gActor;
|
||||
gClient.request(request, onResponse);
|
||||
}
|
||||
|
||||
|
||||
function downloadURL(url, file) {
|
||||
let channel = Services.io.newChannel(url, null, null);
|
||||
let istream = channel.open();
|
||||
let bstream = Cc["@mozilla.org/binaryinputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
bstream.setInputStream(istream);
|
||||
let data = bstream.readBytes(bstream.available());
|
||||
|
||||
let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(file, 0x04 | 0x08 | 0x20, 0600, 0);
|
||||
ostream.write(data, data.length);
|
||||
ostream.QueryInterface(Ci.nsISafeOutputStream).finish();
|
||||
}
|
||||
|
||||
// Install a test packaged webapp from data folder
|
||||
addMessageListener("install", function (aMessage) {
|
||||
let url = aMessage.url;
|
||||
let appId = aMessage.appId;
|
||||
|
||||
try {
|
||||
// Download its content from mochitest http server
|
||||
// Copy our package to tmp folder, where the actor retrieves it
|
||||
let zip = FileUtils.getDir("TmpD", ["b2g", appId], true, true);
|
||||
zip.append("application.zip");
|
||||
downloadURL(url, zip);
|
||||
|
||||
let request = {type: "install", appId: appId};
|
||||
webappActorRequest(request, function (aResponse) {
|
||||
sendAsyncMessage("installed", aResponse);
|
||||
});
|
||||
} catch(e) {
|
||||
dump("installTestApp exception: " + e + "\n");
|
||||
}
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
const REDIRECTION_URL = "http://example.com/redirection-target.html";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
|
||||
response.setHeader("Location", REDIRECTION_URL, false);
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={821589}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {821589} Packaged apps installation and update</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={821589}">Mozilla Bug {821589}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
||||
"use strict";
|
||||
|
||||
var launchableValue = undefined;
|
||||
|
||||
var index = -1;
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("== Tests debug == " + aMsg + "\n");
|
||||
}
|
||||
|
||||
function next() {
|
||||
index += 1;
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
steps[index]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
next();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.setAllAppsLaunchable(launchableValue);
|
||||
SpecialPowers.removePermission("webapps-manage", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbError(aError) {
|
||||
ok(false, "Error callback invoked " + aError);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var installTestApp;
|
||||
|
||||
var steps = [
|
||||
function() {
|
||||
ok(true, "Start setting up");
|
||||
// Set up
|
||||
launchableValue = SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.addPermission("webapps-manage", true, document);
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.addPermission("embed-apps", true, document);
|
||||
|
||||
// Required on firefox as these prefs are only set on b2g:
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.mozBrowserFramesEnabled", true],
|
||||
["security.apps.privileged.CSP.default",
|
||||
"default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"]
|
||||
]
|
||||
}, next);
|
||||
},
|
||||
function () {
|
||||
// Load a chrome script in order to dispatch devtool debugger requests.
|
||||
// Because of wrapping issues, we can't use SpecialPowers.Cu.import to load
|
||||
// devtools jsm into mochitest scope. We end up not receiving
|
||||
// DebuggerClient.addListener callback arguments...
|
||||
let scriptUrl = SimpleTest.getTestFileURL("debugger-protocol-helper.js");
|
||||
let mm = SpecialPowers.loadChromeScript(scriptUrl);
|
||||
installTestApp = function (url, appId, callback) {
|
||||
let installResponse, appObject;
|
||||
mm.sendAsyncMessage("install", {url: url, appId: appId});
|
||||
mm.addMessageListener("installed", function onInstalled(aResponse) {
|
||||
mm.removeMessageListener("installed", onInstalled);
|
||||
installResponse = aResponse;
|
||||
if (appObject)
|
||||
callback(aResponse, appObject);
|
||||
});
|
||||
navigator.mozApps.mgmt.oninstall = function(evt) {
|
||||
appObject = evt.application;
|
||||
if (installResponse)
|
||||
callback(installResponse, appObject);
|
||||
};
|
||||
};
|
||||
SpecialPowers.autoConfirmAppInstall(next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Install packaged app");
|
||||
let appId = "test-app-id";
|
||||
let url = SimpleTest.getTestFileURL("data/app.zip");
|
||||
installTestApp(url, appId,
|
||||
function (aResponse, aApp) {
|
||||
ok(true, "Installed");
|
||||
is(aResponse.appId, appId, "Got same app id");
|
||||
if ("error" in aResponse) {
|
||||
ok(false, "Error: " + aResponse.error);
|
||||
}
|
||||
if ("message" in aResponse) {
|
||||
ok(false, "Error message: " + aResponse.message);
|
||||
}
|
||||
ok(!("error" in aResponse), "app installed without any error");
|
||||
is(aApp.manifest.name, "Test app", "app name is correct");
|
||||
next();
|
||||
}
|
||||
);
|
||||
},
|
||||
function () {
|
||||
ok(true, "== TEST == Reinstall packaged app");
|
||||
let appId = "test-app-id";
|
||||
let url = SimpleTest.getTestFileURL("data/app-updated.zip");
|
||||
installTestApp(url, appId,
|
||||
function (aResponse, aApp) {
|
||||
ok(true, "Reinstalled");
|
||||
is(aResponse.appId, appId, "Got same app id");
|
||||
if ("error" in aResponse) {
|
||||
ok(false, "Error: " + aResponse.error);
|
||||
}
|
||||
if ("message" in aResponse) {
|
||||
ok(false, "Error message: " + aResponse.message);
|
||||
}
|
||||
ok(!("error" in aResponse), "app installed without any error");
|
||||
is(aApp.manifest.name, "updated-name", "app name on update is correct");
|
||||
next();
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
ok(true, "all done!\n");
|
||||
SpecialPowers.popPrefEnv(finish);
|
||||
}
|
||||
];
|
||||
|
||||
addLoadEvent(start);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Двоичные данные
toolkit/devtools/apps/tests/unit/data/app-redirect.zip
Двоичные данные
toolkit/devtools/apps/tests/unit/data/app-redirect.zip
Двоичный файл не отображается.
|
@ -54,19 +54,13 @@ function installTestApp(zipName, appId, onDone) {
|
|||
let request = {type: "install", appId: appId};
|
||||
webappActorRequest(request, function (aResponse) {
|
||||
do_check_eq(aResponse.appId, appId);
|
||||
});
|
||||
|
||||
// The install request is asynchronous and send back an event to tell
|
||||
// if the installation succeed or failed
|
||||
gClient.addListener("webappsEvent", function (aState, aType, aPacket) {
|
||||
do_check_eq(aType.appId, appId);
|
||||
if ("error" in aType) {
|
||||
do_throw("Error: " + aType.error);
|
||||
if ("error" in aResponse) {
|
||||
do_throw("Error: " + aResponse.error);
|
||||
}
|
||||
if ("message" in aType) {
|
||||
do_throw("Error message: " + aType.message);
|
||||
if ("message" in aResponse) {
|
||||
do_throw("Error message: " + aResponse.message);
|
||||
}
|
||||
do_check_false("error" in aType);
|
||||
do_check_false("error" in aResponse);
|
||||
|
||||
onDone();
|
||||
});
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
// We need to lazily instanciate apps service,
|
||||
// as we have to wait for head setup before being
|
||||
// able to instanciate it without exception
|
||||
XPCOMUtils.defineLazyGetter(this, "appsService", function() {
|
||||
return Cc["@mozilla.org/AppsService;1"]
|
||||
.getService(Ci.nsIAppsService);
|
||||
});
|
||||
|
||||
const SERVER_PORT = 4444;
|
||||
const HTTP_BASE = "http://localhost:" + SERVER_PORT + "/";
|
||||
|
||||
const APP_ID = "actor-test";
|
||||
const APP_BASE = "app://" + APP_ID + "/";
|
||||
|
||||
const APP_MANIFEST = APP_BASE + "manifest.webapp";
|
||||
// The remote url being redirect to...
|
||||
const REDIRECTED_URL = HTTP_BASE + "redirection-source.html";
|
||||
// ...redirected to this another remote url.
|
||||
const REMOTE_REDIRECTION_URL = HTTP_BASE + "redirection-target.html";
|
||||
// The app local file URL that overide REMOTE_REDIRECTION_URL
|
||||
const LOCAL_REDIRECTION_URL = APP_BASE + "redirected.html";
|
||||
|
||||
add_test(function testInstallApp() {
|
||||
installTestApp("app-redirect.zip", APP_ID, run_next_test);
|
||||
});
|
||||
|
||||
add_test(function testLaunchApp() {
|
||||
let server = new HttpServer();
|
||||
|
||||
// First register the URL that redirect
|
||||
// from /redirection-source.html
|
||||
// to /redirection-target.html
|
||||
server.registerPathHandler("/redirection-source.html", function handle(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
|
||||
response.setHeader("Location", REMOTE_REDIRECTION_URL, false);
|
||||
|
||||
// We have to wait for one even loop cycle before checking the new document location
|
||||
do_timeout(0, function () {
|
||||
do_check_eq(d.document.documentURIObject.spec, LOCAL_REDIRECTION_URL);
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
||||
server.registerPathHandler("/redirection-target.html", function handle(request, response) {
|
||||
do_throw("We shouldn't receive any request to the remote redirection");
|
||||
});
|
||||
server.start(SERVER_PORT)
|
||||
|
||||
// Load the remote URL in a docshell configured as an app
|
||||
let d = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
|
||||
d.QueryInterface(Ci.nsIWebNavigation);
|
||||
d.QueryInterface(Ci.nsIWebProgress);
|
||||
|
||||
let localAppId = appsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
||||
d.setIsApp(localAppId);
|
||||
do_check_true(d.isApp);
|
||||
do_check_eq(d.appId, localAppId);
|
||||
|
||||
d.loadURI(REDIRECTED_URL, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
setup();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -28,33 +28,11 @@ add_test(function testCloseInexistantApp() {
|
|||
|
||||
// Install a test app
|
||||
add_test(function testInstallPackaged() {
|
||||
// Copy our test webapp to tmp folder, where the actor retrieves it
|
||||
let zip = do_get_file("data/app.zip");
|
||||
let appDir = FileUtils.getDir("TmpD", ["b2g", gAppId], true, true);
|
||||
zip.copyTo(appDir, "application.zip");
|
||||
|
||||
let request = {type: "install", appId: gAppId};
|
||||
webappActorRequest(request, function (aResponse) {
|
||||
do_check_eq(aResponse.appId, gAppId);
|
||||
});
|
||||
|
||||
// The install request is asynchronous and send back an event to tell
|
||||
// if the installation succeed or failed
|
||||
gClient.addOneTimeListener("webappsEvent", function listener(aState, aType, aPacket) {
|
||||
do_check_eq(aType.appId, gAppId);
|
||||
if ("error" in aType) {
|
||||
do_print("Error: " + aType.error);
|
||||
}
|
||||
if ("message" in aType) {
|
||||
do_print("Error message: " + aType.message);
|
||||
}
|
||||
do_check_eq("error" in aType, false);
|
||||
|
||||
installTestApp("app.zip", gAppId, function () {
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Now check that the app appear in getAll
|
||||
add_test(function testGetAll() {
|
||||
let request = {type: "getAll"};
|
||||
|
@ -68,7 +46,7 @@ add_test(function testGetAll() {
|
|||
do_check_eq(app.name, "Test app");
|
||||
do_check_eq(app.manifest.description, "Testing webapps actor");
|
||||
do_check_eq(app.manifest.launch_path, "/index.html");
|
||||
do_check_eq(app.origin, "app://" + gAppId);
|
||||
do_check_eq(app.origin, APP_ORIGIN);
|
||||
do_check_eq(app.installOrigin, app.origin);
|
||||
do_check_eq(app.manifestURL, app.origin + "/manifest.webapp");
|
||||
run_next_test();
|
||||
|
@ -80,7 +58,7 @@ add_test(function testGetAll() {
|
|||
});
|
||||
|
||||
add_test(function testLaunchApp() {
|
||||
let manifestURL = "app://" + gAppId + "/manifest.webapp";
|
||||
let manifestURL = APP_ORIGIN + "/manifest.webapp";
|
||||
let startPoint = "/index.html";
|
||||
let request = {
|
||||
type: "launch",
|
||||
|
@ -101,7 +79,7 @@ add_test(function testLaunchApp() {
|
|||
});
|
||||
|
||||
add_test(function testCloseApp() {
|
||||
let manifestURL = "app://" + gAppId + "/manifest.webapp";
|
||||
let manifestURL = APP_ORIGIN + "/manifest.webapp";
|
||||
let request = {
|
||||
type: "close",
|
||||
manifestURL: manifestURL
|
||||
|
@ -158,8 +136,7 @@ add_test(function testGetIconWithCustomSize() {
|
|||
});
|
||||
|
||||
add_test(function testUninstall() {
|
||||
let origin = "app://" + gAppId;
|
||||
let manifestURL = origin + "/manifest.webapp";
|
||||
let manifestURL = APP_ORIGIN + "/manifest.webapp";
|
||||
let request = {
|
||||
type: "uninstall",
|
||||
manifestURL: manifestURL
|
||||
|
@ -169,7 +146,7 @@ add_test(function testUninstall() {
|
|||
Services.obs.removeObserver(observer, topic);
|
||||
let json = JSON.parse(data);
|
||||
do_check_eq(json.manifestURL, manifestURL);
|
||||
do_check_eq(json.origin, origin);
|
||||
do_check_eq(json.origin, APP_ORIGIN);
|
||||
do_check_eq(json.id, gAppId);
|
||||
run_next_test();
|
||||
}, "webapps-uninstall", false);
|
||||
|
|
|
@ -4,6 +4,3 @@ tail = tail_apps.js
|
|||
|
||||
[test_webappsActor.js]
|
||||
skip-if = (os == "win" || "linux" || "mac")
|
||||
[test_appInstall.js]
|
||||
# Persistent failures.
|
||||
skip-if = true
|
||||
|
|
|
@ -197,7 +197,6 @@ const UnsolicitedNotifications = {
|
|||
"addonListChanged": "addonListChanged",
|
||||
"tabNavigated": "tabNavigated",
|
||||
"pageError": "pageError",
|
||||
"webappsEvent": "webappsEvent",
|
||||
"documentLoad": "documentLoad",
|
||||
"enteredFrame": "enteredFrame",
|
||||
"exitedFrame": "exitedFrame"
|
||||
|
|
|
@ -57,8 +57,10 @@ let DeviceActor = protocol.ActorClass({
|
|||
|
||||
_getSetting: function(name) {
|
||||
let deferred = promise.defer();
|
||||
if (Services.settings) {
|
||||
let req = Services.settings.createLock().get(name, {
|
||||
|
||||
if ("@mozilla.org/settingsService;1" in Cc) {
|
||||
let settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
|
||||
let req = settingsService.createLock().get(name, {
|
||||
handle: (name, value) => deferred.resolve(value),
|
||||
handleError: (error) => deferred.reject(error),
|
||||
});
|
||||
|
|
|
@ -144,7 +144,7 @@ WebappsActor.prototype = {
|
|||
this.conn = null;
|
||||
},
|
||||
|
||||
_registerApp: function wa_actorRegisterApp(aApp, aId, aDir) {
|
||||
_registerApp: function wa_actorRegisterApp(aDeferred, aApp, aId, aDir) {
|
||||
debug("registerApp");
|
||||
let reg = DOMApplicationRegistry;
|
||||
let self = this;
|
||||
|
@ -191,10 +191,7 @@ WebappsActor.prototype = {
|
|||
});
|
||||
|
||||
delete aApp.manifest;
|
||||
self.conn.send({ from: self.actorID,
|
||||
type: "webappsEvent",
|
||||
appId: aId
|
||||
});
|
||||
aDeferred.resolve({ appId: aId, path: aDir.path });
|
||||
|
||||
// We can't have appcache for packaged apps.
|
||||
if (!aApp.origin.startsWith("app://")) {
|
||||
|
@ -207,15 +204,13 @@ WebappsActor.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_sendError: function wa_actorSendError(aMsg, aId) {
|
||||
_sendError: function wa_actorSendError(aDeferred, aMsg, aId) {
|
||||
debug("Sending error: " + aMsg);
|
||||
this.conn.send(
|
||||
{ from: this.actorID,
|
||||
type: "webappsEvent",
|
||||
appId: aId,
|
||||
error: "installationFailed",
|
||||
message: aMsg
|
||||
});
|
||||
aDeferred.resolve({
|
||||
error: "installationFailed",
|
||||
message: aMsg,
|
||||
appId: aId
|
||||
});
|
||||
},
|
||||
|
||||
_getAppType: function wa_actorGetAppType(aType) {
|
||||
|
@ -258,6 +253,7 @@ WebappsActor.prototype = {
|
|||
aManifest, aMetadata) {
|
||||
debug("installHostedApp");
|
||||
let self = this;
|
||||
let deferred = promise.defer();
|
||||
|
||||
function readManifest() {
|
||||
if (aManifest) {
|
||||
|
@ -339,72 +335,112 @@ WebappsActor.prototype = {
|
|||
receipts: aReceipts,
|
||||
};
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
self._registerApp(deferred, app, aId, aDir);
|
||||
}, function (error) {
|
||||
self._sendError(error, aId);
|
||||
self._sendError(deferred, error, aId);
|
||||
});
|
||||
} catch(e) {
|
||||
// If anything goes wrong, just send it back.
|
||||
self._sendError(e.toString(), aId);
|
||||
self._sendError(deferred, e.toString(), aId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Services.tm.currentThread.dispatch(runnable,
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
installPackagedApp: function wa_actorInstallPackaged(aDir, aId, aReceipts) {
|
||||
debug("installPackagedApp");
|
||||
let self = this;
|
||||
let deferred = promise.defer();
|
||||
|
||||
let runnable = {
|
||||
run: function run() {
|
||||
try {
|
||||
// The destination directory for this app.
|
||||
let installDir = DOMApplicationRegistry._getAppDir(aId);
|
||||
|
||||
// Move application.zip to the destination directory, and
|
||||
// extract manifest.webapp there.
|
||||
// Open the app zip package
|
||||
let zipFile = aDir.clone();
|
||||
zipFile.append("application.zip");
|
||||
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
|
||||
.createInstance(Ci.nsIZipReader);
|
||||
zipReader.open(zipFile);
|
||||
|
||||
// Read app manifest `manifest.webapp` from `application.zip`
|
||||
let istream = zipReader.getInputStream("manifest.webapp");
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let jsonString = converter.ConvertToUnicode(
|
||||
NetUtil.readInputStreamToString(istream, istream.available())
|
||||
);
|
||||
|
||||
let manifest;
|
||||
try {
|
||||
manifest = JSON.parse(jsonString);
|
||||
} catch(e) {
|
||||
self._sendError(deferred, "Error Parsing manifest.webapp: " + e, aId);
|
||||
}
|
||||
|
||||
let appType = self._getAppType(manifest.type);
|
||||
|
||||
// In production builds, don't allow installation of certified apps.
|
||||
if (!DOMApplicationRegistry.allowSideloadingCertified &&
|
||||
appType == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
self._sendError(deferred, "Installing certified apps is not allowed.", aId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Privileged and certified packaged apps can setup a custom origin
|
||||
// via `origin` manifest property
|
||||
let id = aId;
|
||||
if (appType >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED &&
|
||||
manifest.origin !== undefined) {
|
||||
let uri;
|
||||
try {
|
||||
uri = Services.io.newURI(manifest.origin, null, null);
|
||||
} catch(e) {
|
||||
self._sendError(deferred, "Invalid origin in webapp's manifest", aId);
|
||||
}
|
||||
|
||||
if (uri.scheme != "app") {
|
||||
self._sendError(deferred, "Invalid origin in webapp's manifest", aId);
|
||||
}
|
||||
id = uri.prePath.substring(6);
|
||||
}
|
||||
|
||||
// Only after security checks are made and after final app id is computed
|
||||
// we can move application.zip to the destination directory, and
|
||||
// extract manifest.webapp there.
|
||||
let installDir = DOMApplicationRegistry._getAppDir(id);
|
||||
let manFile = installDir.clone();
|
||||
manFile.append("manifest.webapp");
|
||||
zipReader.extract("manifest.webapp", manFile);
|
||||
zipReader.close();
|
||||
zipFile.moveTo(installDir, "application.zip");
|
||||
|
||||
DOMApplicationRegistry._loadJSONAsync(manFile, function(aManifest) {
|
||||
if (!aManifest) {
|
||||
self._sendError("Error Parsing manifest.webapp", aId);
|
||||
}
|
||||
let origin = "app://" + id;
|
||||
|
||||
let appType = self._getAppType(aManifest.type);
|
||||
let origin = "app://" + aId;
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: origin,
|
||||
manifestURL: origin + "/manifest.webapp",
|
||||
appStatus: appType,
|
||||
receipts: aReceipts,
|
||||
}
|
||||
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: origin,
|
||||
manifestURL: origin + "/manifest.webapp",
|
||||
appStatus: appType,
|
||||
receipts: aReceipts,
|
||||
}
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
});
|
||||
self._registerApp(deferred, app, id, aDir);
|
||||
} catch(e) {
|
||||
// If anything goes wrong, just send it back.
|
||||
self._sendError(e.toString(), aId);
|
||||
self._sendError(deferred, e.toString(), aId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Services.tm.currentThread.dispatch(runnable,
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -417,13 +453,12 @@ WebappsActor.prototype = {
|
|||
debug("install");
|
||||
|
||||
let appId = aRequest.appId;
|
||||
let reg = DOMApplicationRegistry;
|
||||
if (!appId) {
|
||||
return { error: "missingParameter",
|
||||
message: "missing parameter appId" }
|
||||
appId = reg.makeAppId();
|
||||
}
|
||||
|
||||
// Check that we are not overriding a preinstalled application.
|
||||
let reg = DOMApplicationRegistry;
|
||||
if (appId in reg.webapps && reg.webapps[appId].removable === false) {
|
||||
return { error: "badParameterType",
|
||||
message: "The application " + appId + " can't be overriden."
|
||||
|
@ -462,49 +497,48 @@ WebappsActor.prototype = {
|
|||
let receipts = (aRequest.receipts && Array.isArray(aRequest.receipts))
|
||||
? aRequest.receipts
|
||||
: [];
|
||||
let manifest, metadata;
|
||||
|
||||
if (testFile.exists()) {
|
||||
this.installPackagedApp(appDir, appId, receipts);
|
||||
} else {
|
||||
let missing =
|
||||
["manifest.webapp", "metadata.json"]
|
||||
.some(function(aName) {
|
||||
testFile = appDir.clone();
|
||||
testFile.append(aName);
|
||||
return !testFile.exists();
|
||||
});
|
||||
|
||||
if (missing) {
|
||||
if (aRequest.manifest && aRequest.metadata &&
|
||||
aRequest.metadata.origin) {
|
||||
manifest = aRequest.manifest;
|
||||
metadata = aRequest.metadata;
|
||||
} else {
|
||||
try {
|
||||
appDir.remove(true);
|
||||
} catch(e) {}
|
||||
return { error: "badParameterType",
|
||||
message: "hosted app file and manifest/metadata fields are missing" };
|
||||
}
|
||||
}
|
||||
|
||||
this.installHostedApp(appDir, appId, receipts, manifest, metadata);
|
||||
return this.installPackagedApp(appDir, appId, receipts);
|
||||
}
|
||||
|
||||
return { appId: appId, path: appDir.path }
|
||||
let manifest, metadata;
|
||||
let missing =
|
||||
["manifest.webapp", "metadata.json"]
|
||||
.some(function(aName) {
|
||||
testFile = appDir.clone();
|
||||
testFile.append(aName);
|
||||
return !testFile.exists();
|
||||
});
|
||||
if (missing) {
|
||||
if (aRequest.manifest && aRequest.metadata &&
|
||||
aRequest.metadata.origin) {
|
||||
manifest = aRequest.manifest;
|
||||
metadata = aRequest.metadata;
|
||||
} else {
|
||||
try {
|
||||
appDir.remove(true);
|
||||
} catch(e) {}
|
||||
return { error: "badParameterType",
|
||||
message: "hosted app file and manifest/metadata fields " +
|
||||
"are missing"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return this.installHostedApp(appDir, appId, receipts, manifest, metadata);
|
||||
},
|
||||
|
||||
getAll: function wa_actorGetAll(aRequest) {
|
||||
debug("getAll");
|
||||
|
||||
let defer = promise.defer();
|
||||
let deferred = promise.defer();
|
||||
let reg = DOMApplicationRegistry;
|
||||
reg.getAll(apps => {
|
||||
defer.resolve({ apps: this._filterAllowedApps(apps) });
|
||||
deferred.resolve({ apps: this._filterAllowedApps(apps) });
|
||||
});
|
||||
|
||||
return defer.promise;
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_areCertifiedAppsAllowed: function wa__areCertifiedAppsAllowed() {
|
||||
|
@ -539,19 +573,19 @@ WebappsActor.prototype = {
|
|||
message: "missing parameter manifestURL" };
|
||||
}
|
||||
|
||||
let defer = promise.defer();
|
||||
let deferred = promise.defer();
|
||||
let reg = DOMApplicationRegistry;
|
||||
reg.uninstall(
|
||||
manifestURL,
|
||||
function onsuccess() {
|
||||
defer.resolve({});
|
||||
deferred.resolve({});
|
||||
},
|
||||
function onfailure(reason) {
|
||||
defer.resolve({ error: reason });
|
||||
deferred.resolve({ error: reason });
|
||||
}
|
||||
);
|
||||
|
||||
return defer.promise;
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_findManifestByURL: function wa__findManifestByURL(aManifestURL) {
|
||||
|
@ -643,20 +677,20 @@ WebappsActor.prototype = {
|
|||
message: "missing parameter manifestURL" };
|
||||
}
|
||||
|
||||
let defer = promise.defer();
|
||||
let deferred = promise.defer();
|
||||
|
||||
DOMApplicationRegistry.launch(
|
||||
aRequest.manifestURL,
|
||||
aRequest.startPoint || "",
|
||||
Date.now(),
|
||||
function onsuccess() {
|
||||
defer.resolve({});
|
||||
deferred.resolve({});
|
||||
},
|
||||
function onfailure(reason) {
|
||||
defer.resolve({ error: reason });
|
||||
deferred.resolve({ error: reason });
|
||||
});
|
||||
|
||||
return defer.promise;
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
close: function wa_actorLaunch(aRequest) {
|
||||
|
@ -718,7 +752,7 @@ WebappsActor.prototype = {
|
|||
},
|
||||
|
||||
_connectToApp: function (aFrame) {
|
||||
let defer = Promise.defer();
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let mm = aFrame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||
mm.loadFrameScript("resource://gre/modules/devtools/server/child.js", false);
|
||||
|
@ -746,7 +780,7 @@ WebappsActor.prototype = {
|
|||
|
||||
this._appActorsMap.set(mm, actor);
|
||||
|
||||
defer.resolve(actor);
|
||||
deferred.resolve(actor);
|
||||
}).bind(this);
|
||||
mm.addMessageListener("debug:actor", onActorCreated);
|
||||
|
||||
|
@ -762,7 +796,7 @@ WebappsActor.prototype = {
|
|||
// Otherwise, the app has been closed before the actor
|
||||
// had a chance to be created, so we are not able to create
|
||||
// the actor.
|
||||
defer.resolve(null);
|
||||
deferred.resolve(null);
|
||||
}
|
||||
this._appActorsMap.delete(mm);
|
||||
}
|
||||
|
@ -773,7 +807,7 @@ WebappsActor.prototype = {
|
|||
let prefixStart = this.conn.prefix + "child";
|
||||
mm.sendAsyncMessage("debug:connect", { prefix: prefixStart });
|
||||
|
||||
return defer.promise;
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
getAppActor: function ({ manifestURL }) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче