Bug 1178533 - Add nsIInstallPackagedWebapp for registering permissions when navigating to signed packages r=bholley,fabrice,valentin

This commit is contained in:
Stephanie Ouillon 2015-08-26 13:12:13 +02:00
parent 110dd2935a
commit 08bc7dd59d
28 changed files with 401 additions and 65 deletions

View File

@ -185,6 +185,7 @@
@RESPATH@/components/dom.xpt
@RESPATH@/components/dom_activities.xpt
@RESPATH@/components/dom_apps.xpt
@RESPATH@/components/dom_newapps.xpt
@RESPATH@/components/dom_audiochannel.xpt
@RESPATH@/components/dom_base.xpt
@RESPATH@/components/dom_system.xpt
@ -729,6 +730,10 @@
@RESPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@
#endif
; Signed Packaged Content
@RESPATH@/components/InstallPackagedWebapp.manifest
@RESPATH@/components/InstallPackagedWebapp.js
; ANGLE on Win32
#ifdef XP_WIN32
#ifndef HAVE_64BIT_BUILD

View File

@ -6,7 +6,6 @@
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
var gAdvancedPane = {
_inited: false,
@ -572,7 +571,7 @@ var gAdvancedPane = {
var list = document.getElementById("offlineAppsList");
var item = list.selectedItem;
var origin = item.getAttribute("origin");
var principal = BrowserUtils.principalFromOrigin(origin);
var principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);

View File

@ -9,7 +9,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/BrowserUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "gLangBundle", () =>
Services.strings.createBundle("chrome://global/locale/languageNames.properties"));
@ -214,7 +213,7 @@ var gTranslationExceptions = {
onSiteDeleted: function() {
let removedSites = this._siteTree.getSelectedItems();
for (let origin of removedSites) {
let principal = BrowserUtils.principalFromOrigin(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
Services.perms.removeFromPrincipal(principal, kPermissionType);
}
},
@ -227,7 +226,7 @@ var gTranslationExceptions = {
this._siteTree.boxObject.rowCountChanged(0, -removedSites.length);
for (let origin of removedSites) {
let principal = BrowserUtils.principalFromOrigin(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
Services.perms.removeFromPrincipal(principal, kPermissionType);
}

View File

@ -9,7 +9,6 @@ this.EXPORTED_SYMBOLS = ["SessionStorage"];
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/BrowserUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -105,7 +104,7 @@ var SessionStorageInternal = {
restore: function (aDocShell, aStorageData) {
for (let origin of Object.keys(aStorageData)) {
let data = aStorageData[origin];
let principal = BrowserUtils.principalFromOrigin(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
let window = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);

View File

@ -193,6 +193,7 @@
@RESPATH@/components/dom_messages.xpt
#endif
@RESPATH@/components/dom_apps.xpt
@RESPATH@/components/dom_newapps.xpt
@RESPATH@/components/dom_base.xpt
@RESPATH@/components/dom_system.xpt
#ifdef MOZ_B2G_BT
@ -638,6 +639,10 @@
@RESPATH@/components/PrivateBrowsing.manifest
@RESPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js
; Signed Packaged Content
@RESPATH@/components/InstallPackagedWebapp.manifest
@RESPATH@/components/InstallPackagedWebapp.js
; ANGLE GLES-on-D3D rendering library
#ifdef MOZ_ANGLE_RENDERER
@BINPATH@/libEGL.dll

View File

@ -426,6 +426,28 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs)
return codebase.forget();
}
already_AddRefed<BasePrincipal>
BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
{
MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
"CreateCodebasePrincipal does not support System and Expanded principals");
MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
"CreateCodebasePrincipal does not support nsNullPrincipal");
nsAutoCString originNoSuffix;
mozilla::OriginAttributes attrs;
if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
return nullptr;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
NS_ENSURE_SUCCESS(rv, nullptr);
return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
}
bool
BasePrincipal::AddonAllowsLoad(nsIURI* aURI)
{

View File

@ -160,6 +160,7 @@ public:
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs);
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin);
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
uint32_t AppId() const { return mOriginAttributes.mAppId; }

View File

@ -26,7 +26,7 @@ class DomainPolicyClone;
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
[scriptable, uuid(6e8a4d1e-d9c6-4d86-bf53-d73f58f36148)]
[scriptable, uuid(b7ae2310-576e-11e5-a837-0800200c9a66)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@ -197,6 +197,13 @@ interface nsIScriptSecurityManager : nsISupports
[implicit_jscontext]
nsIPrincipal createCodebasePrincipal(in nsIURI uri, in jsval originAttributes);
/**
* Returns a principal whose origin is the one we pass in.
* See nsIPrincipal.idl for a description of origin attributes, and
* ChromeUtils.webidl for a list of origin attributes and their defaults.
*/
nsIPrincipal createCodebasePrincipalFromOrigin(in ACString origin);
/**
* Returns a unique nonce principal with |originAttributes|.
* See nsIPrincipal.idl for a description of origin attributes, and

View File

@ -67,6 +67,7 @@
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsILoadInfo.h"
#include "nsXPCOMStrings.h"
// This should be probably defined on some other place... but I couldn't find it
#define WEBAPPS_PERM_NAME "webapps-manage"
@ -1043,6 +1044,23 @@ nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle<JS::Va
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateCodebasePrincipalFromOrigin(const nsACString& aOrigin,
nsIPrincipal** aPrincipal)
{
if (StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("["))) {
return NS_ERROR_INVALID_ARG;
}
if (StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":"))) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aOrigin);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)

View File

@ -3,7 +3,6 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/BrowserUtils.jsm");
var ssm = Services.scriptSecurityManager;
function makeURI(uri) { return Services.io.newURI(uri, null, null); }
@ -28,9 +27,9 @@ function checkOriginAttributes(prin, attrs, suffix) {
do_check_eq(prin.originAttributes.inBrowser, attrs.inBrowser || false);
do_check_eq(prin.originSuffix, suffix || '');
if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) {
do_check_true(BrowserUtils.principalFromOrigin(prin.origin).equals(prin));
do_check_true(ssm.createCodebasePrincipalFromOrigin(prin.origin).equals(prin));
} else {
checkThrows(() => BrowserUtils.principalFromOrigin(prin.origin));
checkThrows(() => ssm.createCodebasePrincipalFromOrigin(prin.origin));
}
}

View File

@ -164,7 +164,8 @@ this.PermissionsInstaller = {
PermissionSettingsModule.getPermission(expandedPermNames[idx],
aApp.manifestURL,
aApp.origin,
false);
false,
aApp.isCachedPackage);
if (permValue === "unknown") {
permValue = PERM_TO_STRING[permission];
}
@ -192,7 +193,7 @@ this.PermissionsInstaller = {
* The permission value.
* @param object aApp
* The just-installed app configuration.
* The properties used are manifestURL and origin.
* The properties used are manifestURL, origin, appId, isCachedPackage.
* @returns void
**/
_setPermission: function setPermission(aPermName, aPermValue, aApp) {
@ -201,7 +202,9 @@ this.PermissionsInstaller = {
origin: aApp.origin,
manifestURL: aApp.manifestURL,
value: aPermValue,
browserFlag: false
browserFlag: false,
localId: aApp.localId,
isCachedPackage: aApp.isCachedPackage,
});
}
};

View File

@ -113,6 +113,7 @@ DIRS += [
'resourcestats',
'manifest',
'vr',
'newapps',
]
if CONFIG['OS_ARCH'] == 'WINNT':

View File

@ -0,0 +1,63 @@
/* 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 { classes: Cc, interfaces: Ci, utils: Cu, results: Cr, Constructor: CC } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsInstaller",
"resource://gre/modules/PermissionsInstaller.jsm");
function debug(aMsg) {
dump("-*-*- InstallPackagedWebapps.js : " + aMsg + "\n");
}
function InstallPackagedWebapp() {
}
InstallPackagedWebapp.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIInstallPackagedWebapp]),
classID: Components.ID("{5cc6554a-5421-4a5e-b8c2-c62e8b7f4f3f}"),
/**
* Install permissions for signed packaged web content
* @param string manifestContent
* The manifest content of the cached package.
* @param string aOrigin
* The package origin.
* @param string aManifestURL
* The manifest URL of the package.
* @returns boolean
**/
installPackagedWebapp: function(aManifestContent, aOrigin, aManifestURL) {
try {
let isSuccess = true;
let manifest = JSON.parse(aManifestContent);
PermissionsInstaller.installPermissions({
manifest: manifest,
manifestURL: aManifestURL,
origin: aOrigin,
isPreinstalled: false,
isCachedPackage: true
}, false, function() {
Cu.reportError(ex);
});
// TODO Bug 1206058 - Register app handlers (system msg) on navigation
// to signed packages.
return isSuccess;
}
catch(ex) {
Cu.reportError(ex);
return false;
}
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([InstallPackagedWebapp]);

View File

@ -0,0 +1,2 @@
component {5cc6554a-5421-4a5e-b8c2-c62e8b7f4f3f} InstallPackagedWebapp.js
contract @mozilla.org/newapps/installpackagedwebapp;1 {5cc6554a-5421-4a5e-b8c2-c62e8b7f4f3f}

View File

@ -0,0 +1,11 @@
# -*- 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/.
XPIDL_SOURCES += [
'nsIInstallPackagedWebapp.idl'
]
XPIDL_MODULE = 'dom_newapps'

View File

@ -0,0 +1,13 @@
/* 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 "nsISupports.idl"
[scriptable, uuid(3b4b69a0-56dc-11e5-a837-0800200c9a66)]
interface nsIInstallPackagedWebapp : nsISupports
{
boolean installPackagedWebapp(in string aManifestContent,
in string aOrigin,
in string aManifestURL);
};

14
dom/newapps/moz.build Normal file
View File

@ -0,0 +1,14 @@
# -*- 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/.
DIRS += ['interfaces']
EXTRA_COMPONENTS += [
'InstallPackagedWebapp.js',
'InstallPackagedWebapp.manifest',
]
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']

View File

@ -0,0 +1,123 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
'use strict';
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import("resource://gre/modules/PermissionSettings.jsm");
Cu.import("resource://gre/modules/PermissionsTable.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
const mod = Cc['@mozilla.org/newapps/installpackagedwebapp;1']
.getService(Ci.nsIInstallPackagedWebapp);
XPCOMUtils.defineLazyServiceGetter(this,
"appsService",
"@mozilla.org/AppsService;1",
"nsIAppsService");
function run_test() {
do_get_profile();
let manifestWithPerms = {
name: "Test App",
launch_path: "/index.html",
type: "privileged",
permissions: {
"alarms": { },
"wifi-manage": { },
"tcp-socket": { },
"desktop-notification": { },
"geolocation": { },
},
};
let manifestNoPerms = {
name: "Test App",
launch_path: "/index.html",
type: "privileged",
};
let appStatus = "privileged";
// Triggering error due to bad manifest
let origin = "";
let manifestURL = "";
let manifestString = "boum";
let res = mod.installPackagedWebapp(manifestString, origin, manifestURL);
equal(res, false);
// Install a package with permissions
origin = "http://test.com^appId=1019&inBrowser=1";
manifestURL = "http://test.com/manifest.json";
manifestString = JSON.stringify(manifestWithPerms);
let manifestHelper = new ManifestHelper(manifestWithPerms, origin, manifestURL);
cleanDB(manifestHelper, origin, manifestURL);
res = mod.installPackagedWebapp(manifestString, origin, manifestURL);
equal(res, true);
checkPermissions(manifestHelper, origin, manifestURL, appStatus);
// Install a package with permissions
origin = "http://test.com";
manifestHelper = new ManifestHelper(manifestWithPerms, origin, manifestURL);
cleanDB(manifestHelper, origin, manifestURL);
res = mod.installPackagedWebapp(manifestString, origin, manifestURL);
equal(res, true);
checkPermissions(manifestHelper, origin, manifestURL, appStatus);
// Install a package with no permission
origin = "http://bar.com^appId=1337&inBrowser=1";
manifestURL = "http://bar.com/manifest.json";
manifestString = JSON.stringify(manifestNoPerms);
manifestHelper = new ManifestHelper(manifestNoPerms, origin, manifestURL);
cleanDB(manifestHelper, origin, manifestURL);
res = mod.installPackagedWebapp(manifestString, origin, manifestURL);
equal(res, true);
checkPermissions(manifestHelper, origin, manifestURL, appStatus);
}
// Cleaning permissions database before running a test
function cleanDB(manifestHelper, origin, manifestURL) {
for (let permName in manifestHelper.permissions) {
PermissionSettingsModule.removePermission(permName, manifestURL, origin, "", true);
}
}
// Check permissions are correctly set in the database
function checkPermissions(manifestHelper, origin, manifestURL, appStatus) {
let perm;
for (let permName in manifestHelper.permissions) {
let permValue = PermissionSettingsModule.getPermission(
permName, manifestURL, origin, "", true);
switch (PermissionsTable[permName][appStatus]) {
case Ci.nsIPermissionManager.UNKNOWN_ACTION:
perm = "unknown";
break;
case Ci.nsIPermissionManager.ALLOW_ACTION:
perm = "allow";
break;
case Ci.nsIPermissionManager.DENY_ACTION:
perm = "deny";
break;
case Ci.nsIPermissionManager.PROMPT_ACTION:
perm = "prompt";
break;
default:
break;
}
equal(permValue, perm);
}
}

View File

@ -0,0 +1,5 @@
[DEFAULT]
head =
tail =
[test_install.js]

View File

@ -67,13 +67,23 @@ this.PermissionSettingsModule = {
_internalAddPermission: function _internalAddPermission(aData, aAllowAllChanges, aCallbacks) {
// TODO: Bug 1196644 - Add signPKg parameter into PermissionSettings.jsm
let uri = Services.io.newURI(aData.origin, null, null);
let app = appsService.getAppByManifestURL(aData.manifestURL);
let principal =
Services.scriptSecurityManager.createCodebasePrincipal(uri,
{appId: app.localId,
inBrowser: aData.browserFlag});
// TODO: Bug 1196644 - Add signPKg parameter into PermissionSettings.jsm.
let app;
let principal;
// Test if app is cached (signed streamable package) or installed via DOMApplicationRegistry
if (aData.isCachedPackage) {
// If the app is from packaged web app, the origin includes origin attributes already.
principal =
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(aData.origin);
app = {localId: principal.appId};
} else {
app = appsService.getAppByManifestURL(aData.manifestURL);
let uri = Services.io.newURI(aData.origin, null, null);
principal =
Services.scriptSecurityManager.createCodebasePrincipal(uri,
{appId: app.localId,
inBrowser: aData.browserFlag});
}
let action;
switch (aData.value)
@ -106,17 +116,24 @@ this.PermissionSettingsModule = {
}
},
getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag, aIsCachedPackage) {
// TODO: Bug 1196644 - Add signPKg parameter into PermissionSettings.jsm
debug("getPermission: " + aPermName + ", " + aManifestURL + ", " + aOrigin);
let uri = Services.io.newURI(aOrigin, null, null);
let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
let principal =
Services.scriptSecurityManager.createCodebasePrincipal(uri,
{appId: appID,
inBrowser: aBrowserFlag});
let principal;
// Test if app is cached (signed streamable package) or installed via DOMApplicationRegistry
if (aIsCachedPackage) {
// If the app is from packaged web app, the origin includes origin attributes already.
principal =
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(aOrigin);
} else {
let uri = Services.io.newURI(aOrigin, null, null);
let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
principal =
Services.scriptSecurityManager.createCodebasePrincipal(uri,
{appId: appID,
inBrowser: aBrowserFlag});
}
let result = Services.perms.testExactPermissionFromPrincipal(principal, aPermName);
switch (result)
{
case Ci.nsIPermissionManager.UNKNOWN_ACTION:
@ -133,13 +150,14 @@ this.PermissionSettingsModule = {
}
},
removePermission: function removePermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
removePermission: function removePermission(aPermName, aManifestURL, aOrigin, aBrowserFlag, aIsCachedPackage) {
let data = {
type: aPermName,
origin: aOrigin,
manifestURL: aManifestURL,
value: "unknown",
browserFlag: aBrowserFlag
browserFlag: aBrowserFlag,
isCachedPackage: aIsCachedPackage
};
this._internalAddPermission(data, true);
},

View File

@ -19,8 +19,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
this.EXPORTED_SYMBOLS = ["PushRecord"];
@ -218,7 +216,7 @@ Object.defineProperties(PushRecord.prototype, {
// Allow tests to omit origin attributes.
url += this.originAttributes;
}
principal = BrowserUtils.principalFromOrigin(url);
principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(url);
principals.set(this, principal);
}
return principal;

View File

@ -20,7 +20,6 @@ const RSYNC_STATE_ENABLED = "enabled";
const RSYNC_STATE_DISABLED = "disabled";
const RSYNC_STATE_WIFIONLY = "wifiOnly";
Cu.import("resource://gre/modules/BrowserUtils.jsm");
Cu.import('resource://gre/modules/IndexedDBHelper.jsm');
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -175,7 +174,7 @@ this.RequestSyncService = {
let dbKeys = [];
for (let key in this._registrations) {
let prin = BrowserUtils.principalFromOrigin(key);
let prin = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(key);
if (!ChromeUtils.originAttributesMatchPattern(prin.originAttributes, pattern)) {
continue;
}

View File

@ -138,6 +138,7 @@
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_activities.xpt
@BINPATH@/components/dom_apps.xpt
@BINPATH@/components/dom_newapps.xpt
@BINPATH@/components/dom_base.xpt
@BINPATH@/components/dom_canvas.xpt
@BINPATH@/components/dom_core.xpt
@ -677,6 +678,9 @@ bin/libfreebl_32int64_3.so
@BINPATH@/components/SystemMessageCache.js
@BINPATH@/components/SystemMessageManager.manifest
@BINPATH@/components/InstallPackagedWebapp.manifest
@BINPATH@/components/InstallPackagedWebapp.js
@BINPATH@/components/B2GComponents.manifest
@BINPATH@/components/AlertsService.js
@BINPATH@/components/ContentPermissionPrompt.js

View File

@ -138,6 +138,7 @@
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_activities.xpt
@BINPATH@/components/dom_apps.xpt
@BINPATH@/components/dom_newapps.xpt
@BINPATH@/components/dom_base.xpt
@BINPATH@/components/dom_canvas.xpt
@BINPATH@/components/dom_core.xpt
@ -427,6 +428,9 @@
@BINPATH@/components/SystemMessageCache.js
@BINPATH@/components/SystemMessageManager.manifest
@BINPATH@/components/InstallPackagedWebapp.manifest
@BINPATH@/components/InstallPackagedWebapp.js
#ifdef MOZ_WEBRTC
@BINPATH@/components/PeerConnection.js
@BINPATH@/components/PeerConnection.manifest

View File

@ -17,6 +17,7 @@
#include "mozilla/DebugOnly.h"
#include "nsIHttpHeaderVisitor.h"
#include "mozilla/LoadContext.h"
#include "nsIInstallPackagedWebapp.h"
namespace mozilla {
namespace net {
@ -427,6 +428,7 @@ PackagedAppService::PackagedAppDownloader::Init(nsILoadContextInfo* aInfo,
mPackageKey = aKey;
mPackageOrigin = aPackageOrigin;
mProcessingFirstRequest = true;
return NS_OK;
}
@ -620,6 +622,8 @@ PackagedAppService::PackagedAppDownloader::OnStopRequest(nsIRequest *aRequest,
LOG(("[%p] PackagedAppDownloader::OnStopRequest > status:%X multiChannel:%p\n",
this, aStatusCode, multiChannel.get()));
mProcessingFirstRequest = false;
// lastPart will be true if this is the last part in the package,
// or if aRequest isn't a multipart channel
bool lastPart = true;
@ -700,6 +704,11 @@ PackagedAppService::PackagedAppDownloader::ConsumeData(nsIInputStream *aStream,
self->mWriter->ConsumeData(aFromRawSegment, aCount, aWriteCount);
if (self->mProcessingFirstRequest) {
// mProcessingFirstRequest will be set to false on the first OnStopRequest.
self->mManifestContent.Append(aFromRawSegment, aCount);
}
nsCOMPtr<nsIInputStream> stream = CreateSharedStringStream(aFromRawSegment, aCount);
return self->mVerifier->OnDataAvailable(nullptr, nullptr, stream, 0, aCount);
}
@ -855,11 +864,39 @@ PackagedAppService::PackagedAppDownloader::NotifyOnStartSignedPackageRequest(con
LOG(("Notifying the signed package is ready to load."));
}
void PackagedAppService::PackagedAppDownloader::InstallSignedPackagedApp()
void PackagedAppService::PackagedAppDownloader::InstallSignedPackagedApp(const ResourceCacheInfo* aInfo)
{
// TODO: Bug 1178533 to register permissions, system messages etc on navigation to
// signed packages.
LOG(("Install this packaged app."));
bool isSuccess = false;
nsCOMPtr<nsIInstallPackagedWebapp> installer =
do_GetService("@mozilla.org/newapps/installpackagedwebapp;1");
if (!installer) {
LOG(("InstallSignedPackagedApp: fail to get InstallPackagedWebapp service"));
return OnError(ERROR_GET_INSTALLER_FAILED);
}
nsCString manifestURL;
aInfo->mURI->GetAsciiSpec(manifestURL);
// Use the origin stored in the verifier since the signed packaged app would
// have a specifi package identifer defined in the manifest file.
nsCString packageOrigin;
mVerifier->GetPackageOrigin(packageOrigin);
installer->InstallPackagedWebapp(mManifestContent.get(),
packageOrigin.get(),
manifestURL.get(),
&isSuccess);
if (!isSuccess) {
LOG(("InstallSignedPackagedApp: failed to install permissions"));
return OnError(ERROR_INSTALL_RESOURCE_FAILED);
}
LOG(("InstallSignedPackagedApp: success."));
}
//------------------------------------------------------------------
@ -917,7 +954,7 @@ PackagedAppService::PackagedAppDownloader::OnManifestVerified(const ResourceCach
nsCString packageOrigin;
mVerifier->GetPackageOrigin(packageOrigin);
NotifyOnStartSignedPackageRequest(packageOrigin);
InstallSignedPackagedApp();
InstallSignedPackagedApp(aInfo);
}
void
@ -1084,7 +1121,7 @@ PackagedAppService::GetResource(nsIChannel *aChannel,
downloader = new PackagedAppDownloader();
nsCString packageOrigin;
principal->GetOriginNoSuffix(packageOrigin);
principal->GetOrigin(packageOrigin);
rv = downloader->Init(loadContextInfo, key, packageOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -106,6 +106,8 @@ private:
enum EErrorType {
ERROR_MANIFEST_VERIFIED_FAILED,
ERROR_RESOURCE_VERIFIED_FAILED,
ERROR_GET_INSTALLER_FAILED,
ERROR_INSTALL_RESOURCE_FAILED,
};
public:
@ -172,7 +174,7 @@ private:
// Handle all tasks about app installation like permission and system message
// registration.
void InstallSignedPackagedApp();
void InstallSignedPackagedApp(const ResourceCacheInfo* aInfo);
// Calls all the callbacks registered for the given URI.
// aURI is the full URI of a subresource, composed of packageURI + !// + subresourcePath
@ -211,6 +213,15 @@ private:
// If you need the origin with the signity taken into account, use
// PackagedAppVerifier::GetPackageOrigin().
nsCString mPackageOrigin;
//The app id of the package loaded from the LoadContextInfo
uint32_t mAppId;
// A flag to indicate if we are processing the first request.
bool mProcessingFirstRequest;
// A in-memory copy of the manifest content.
nsCString mManifestContent;
};
// Intercepts OnStartRequest, OnDataAvailable*, OnStopRequest method calls

View File

@ -100,30 +100,6 @@ this.BrowserUtils = {
return Services.io.newURI(aCPOWURI.spec, aCPOWURI.originCharset, null);
},
// Creates a codebase principal from a canonical origin string. This is
// the inverse operation of .origin on a codebase principal.
principalFromOrigin: function(aOriginString) {
if (aOriginString.startsWith('[')) {
throw new Error("principalFromOrigin does not support System and Expanded principals");
}
if (aOriginString.startsWith("moz-nullprincipal:")) {
throw new Error("principalFromOrigin does not support nsNullPrincipal");
}
var parts = aOriginString.split('^');
if (parts.length > 2) {
throw new Error("bad origin string: " + aOriginString);
}
var uri = Services.io.newURI(parts[0], null, null);
var attrs = {};
// Parse the parameters string into a dictionary.
(parts[1] || "").split("&").map((x) => x.split('=')).forEach((x) => attrs[x[0]] = x[1]);
return Services.scriptSecurityManager.createCodebasePrincipal(uri, attrs);
},
/**
* For a given DOM element, returns its position in "screen"
* coordinates. In a content process, the coordinates returned will

View File

@ -29,7 +29,7 @@ function importPrefBranch(aPrefBranch, aPermission, aAction) {
for (let origin of origins) {
let principals = [];
try {
principals = [ BrowserUtils.principalFromOrigin(origin) ];
principals = [ Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin) ];
} catch (e) {
// This preference used to contain a list of hosts. For back-compat
// reasons, we convert these hosts into http:// and https:// permissions