Bug 852848 - Add support for app-specific redirections r=bz,ferjm
This commit is contained in:
@@ -202,6 +202,8 @@
|
|||||||
#include "nsIAppShellService.h"
|
#include "nsIAppShellService.h"
|
||||||
#include "nsAppShellCID.h"
|
#include "nsAppShellCID.h"
|
||||||
|
|
||||||
|
#include "nsIAppsService.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||||
@@ -6436,6 +6438,30 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||||||
if (!oldURI || !newURI) {
|
if (!oldURI || !newURI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if we have a redirect registered for this url.
|
||||||
|
uint32_t appId;
|
||||||
|
nsresult rv = GetAppId(&appId);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appId != nsIScriptSecurityManager::NO_APP_ID &&
|
||||||
|
appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||||
|
nsCOMPtr<nsIAppsService> appsService =
|
||||||
|
do_GetService(APPS_SERVICE_CONTRACTID);
|
||||||
|
NS_ASSERTION(appsService, "No AppsService available");
|
||||||
|
nsCOMPtr<nsIURI> redirect;
|
||||||
|
rv = appsService->GetRedirect(appId, newURI, getter_AddRefs(redirect));
|
||||||
|
if (NS_SUCCEEDED(rv) && redirect) {
|
||||||
|
aNewChannel->Cancel(NS_BINDING_ABORTED);
|
||||||
|
rv = LoadURI(redirect, nullptr, 0, false);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// On session restore we get a redirect from page to itself. Don't count it.
|
// On session restore we get a redirect from page to itself. Don't count it.
|
||||||
bool equals = false;
|
bool equals = false;
|
||||||
if (mTiming &&
|
if (mTiming &&
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const Ci = Components.interfaces;
|
|||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
|
const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
|
||||||
|
|
||||||
@@ -78,6 +79,42 @@ AppsService.prototype = {
|
|||||||
return DOMApplicationRegistry.getAppInfo(aAppId);
|
return DOMApplicationRegistry.getAppInfo(aAppId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getRedirect: function getRedirect(aLocalId, aURI) {
|
||||||
|
debug("getRedirect for " + aLocalId + " " + aURI.spec);
|
||||||
|
if (aLocalId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||||
|
aLocalId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = DOMApplicationRegistry.getAppByLocalId(aLocalId);
|
||||||
|
if (app && app.redirects) {
|
||||||
|
let spec = aURI.spec;
|
||||||
|
for (let i = 0; i < app.redirects.length; i++) {
|
||||||
|
let redirect = app.redirects[i];
|
||||||
|
if (spec.startsWith(redirect.from)) {
|
||||||
|
// Prepend the app origin to the redirection. We need that since
|
||||||
|
// the origin of packaged apps is a uuid created at install time.
|
||||||
|
let to = app.origin + redirect.to;
|
||||||
|
// If we have a ? or a # in the current URL, add this part to the
|
||||||
|
// redirection.
|
||||||
|
let index = -1;
|
||||||
|
index = spec.indexOf('?');
|
||||||
|
if (index == -1) {
|
||||||
|
index = spec.indexOf('#');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
to += spec.substring(index);
|
||||||
|
}
|
||||||
|
debug('App specific redirection from ' + spec + ' to ' + to);
|
||||||
|
return Services.io.newURI(to, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
classID : APPS_SERVICE_CID,
|
classID : APPS_SERVICE_CID,
|
||||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
|||||||
|
|
||||||
// Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js
|
// Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["AppsUtils", "ManifestHelper"];
|
this.EXPORTED_SYMBOLS = ["AppsUtils", "ManifestHelper", "isAbsoluteURI"];
|
||||||
|
|
||||||
function debug(s) {
|
function debug(s) {
|
||||||
//dump("-*- AppsUtils.jsm: " + s + "\n");
|
//dump("-*- AppsUtils.jsm: " + s + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAbsoluteURI(aURI) {
|
this.isAbsoluteURI = function(aURI) {
|
||||||
let foo = Services.io.newURI("http://foo", null, null);
|
let foo = Services.io.newURI("http://foo", null, null);
|
||||||
let bar = Services.io.newURI("http://bar", null, null);
|
let bar = Services.io.newURI("http://bar", null, null);
|
||||||
return Services.io.newURI(aURI, null, foo).prePath != foo.prePath ||
|
return Services.io.newURI(aURI, null, foo).prePath != foo.prePath ||
|
||||||
@@ -92,7 +92,8 @@ this.AppsUtils = {
|
|||||||
installerAppId: aApp.installerAppId || Ci.nsIScriptSecurityManager.NO_APP_ID,
|
installerAppId: aApp.installerAppId || Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||||
installerIsBrowser: !!aApp.installerIsBrowser,
|
installerIsBrowser: !!aApp.installerIsBrowser,
|
||||||
storeId: aApp.storeId || "",
|
storeId: aApp.storeId || "",
|
||||||
storeVersion: aApp.storeVersion || 0
|
storeVersion: aApp.storeVersion || 0,
|
||||||
|
redirects: aApp.redirects
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -196,6 +196,24 @@ this.DOMApplicationRegistry = {
|
|||||||
this._saveApps();
|
this._saveApps();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Ensure that the .to property in redirects is a relative URL.
|
||||||
|
sanitizeRedirects: function sanitizeRedirects(aSource) {
|
||||||
|
if (!aSource) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = [];
|
||||||
|
for (let i = 0; i < aSource.length; i++) {
|
||||||
|
let redirect = aSource[i];
|
||||||
|
if (redirect.from && redirect.to &&
|
||||||
|
isAbsoluteURI(redirect.from) &&
|
||||||
|
!isAbsoluteURI(redirect.to)) {
|
||||||
|
res.push(redirect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.length > 0 ? res : null;
|
||||||
|
},
|
||||||
|
|
||||||
// Registers all the activities and system messages.
|
// Registers all the activities and system messages.
|
||||||
registerAppsHandlers: function registerAppsHandlers(aRunUpdate) {
|
registerAppsHandlers: function registerAppsHandlers(aRunUpdate) {
|
||||||
this.notifyAppsRegistryStart();
|
this.notifyAppsRegistryStart();
|
||||||
@@ -211,7 +229,11 @@ this.DOMApplicationRegistry = {
|
|||||||
// twice
|
// twice
|
||||||
this._readManifests(ids, (function readCSPs(aResults) {
|
this._readManifests(ids, (function readCSPs(aResults) {
|
||||||
aResults.forEach(function registerManifest(aResult) {
|
aResults.forEach(function registerManifest(aResult) {
|
||||||
this.webapps[aResult.id].csp = aResult.manifest.csp || "";
|
let app = this.webapps[aResult.id];
|
||||||
|
app.csp = aResult.manifest.csp || "";
|
||||||
|
if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
|
||||||
|
app.redirects = this.sanitizeRedirects(aResult.redirects);
|
||||||
|
}
|
||||||
}, this);
|
}, this);
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
@@ -673,6 +695,9 @@ this.DOMApplicationRegistry = {
|
|||||||
let manifest = aResult.manifest;
|
let manifest = aResult.manifest;
|
||||||
app.name = manifest.name;
|
app.name = manifest.name;
|
||||||
app.csp = manifest.csp || "";
|
app.csp = manifest.csp || "";
|
||||||
|
if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
|
||||||
|
app.redirects = this.sanitizeRedirects(manifest.redirects);
|
||||||
|
}
|
||||||
this._registerSystemMessages(manifest, app);
|
this._registerSystemMessages(manifest, app);
|
||||||
appsToRegister.push({ manifest: manifest, app: app });
|
appsToRegister.push({ manifest: manifest, app: app });
|
||||||
}, this);
|
}, this);
|
||||||
@@ -1327,11 +1352,14 @@ this.DOMApplicationRegistry = {
|
|||||||
return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
|
return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Updates the activities and system message handlers.
|
// Updates the redirect mapping, activities and system message handlers.
|
||||||
// aOldManifest can be null if we don't have any handler to unregister.
|
// aOldManifest can be null if we don't have any handler to unregister.
|
||||||
updateAppHandlers: function(aOldManifest, aNewManifest, aApp) {
|
updateAppHandlers: function(aOldManifest, aNewManifest, aApp) {
|
||||||
debug("updateAppHandlers: old=" + aOldManifest + " new=" + aNewManifest);
|
debug("updateAppHandlers: old=" + aOldManifest + " new=" + aNewManifest);
|
||||||
this.notifyAppsRegistryStart();
|
this.notifyAppsRegistryStart();
|
||||||
|
if (aApp.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
|
||||||
|
aApp.redirects = this.sanitizeRedirects(aNewManifest.redirects);
|
||||||
|
}
|
||||||
|
|
||||||
if (supportSystemMessages()) {
|
if (supportSystemMessages()) {
|
||||||
if (aOldManifest) {
|
if (aOldManifest) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
interface mozIDOMApplication;
|
interface mozIDOMApplication;
|
||||||
interface mozIApplication;
|
interface mozIApplication;
|
||||||
|
interface nsIURI;
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
#define APPS_SERVICE_CID { 0x05072afa, 0x92fe, 0x45bf, { 0xae, 0x22, 0x39, 0xb6, 0x9c, 0x11, 0x70, 0x58 } }
|
#define APPS_SERVICE_CID { 0x05072afa, 0x92fe, 0x45bf, { 0xae, 0x22, 0x39, 0xb6, 0x9c, 0x11, 0x70, 0x58 } }
|
||||||
@@ -16,7 +17,7 @@ interface mozIApplication;
|
|||||||
* This service allows accessing some DOMApplicationRegistry methods from
|
* This service allows accessing some DOMApplicationRegistry methods from
|
||||||
* non-javascript code.
|
* non-javascript code.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(1113c6e3-28a2-4315-be10-8b3230eecc0f)]
|
[scriptable, uuid(27b995cf-bec8-47de-aa48-6117c950fce3)]
|
||||||
interface nsIAppsService : nsISupports
|
interface nsIAppsService : nsISupports
|
||||||
{
|
{
|
||||||
mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
|
mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
|
||||||
@@ -63,6 +64,12 @@ interface nsIAppsService : nsISupports
|
|||||||
|
|
||||||
jsval getAppInfo(in DOMString appId);
|
jsval getAppInfo(in DOMString appId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a URI to redirect to when we get a redirection to 'uri'.
|
||||||
|
* Returns null if no redirection is declared for this uri.
|
||||||
|
*/
|
||||||
|
nsIURI getRedirect(in unsigned long localId, in nsIURI uri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the localId if the app was installed from a store
|
* Returns the localId if the app was installed from a store
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user