mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 08:45:46 +00:00
Bug 1574480 - Updated browser.js and OfflineAppsChild.jsm to use PermissionManager principal methods. r=johannh,smaug
Differential Revision: https://phabricator.services.mozilla.com/D42620 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
3e8fdbe0ed
commit
99bfbf1328
@ -7,10 +7,17 @@
|
||||
var EXPORTED_SYMBOLS = ["OfflineAppsChild"];
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { ActorChild } = ChromeUtils.import(
|
||||
"resource://gre/modules/ActorChild.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
});
|
||||
|
||||
class OfflineAppsChild extends ActorChild {
|
||||
constructor(dispatcher) {
|
||||
super(dispatcher);
|
||||
@ -34,7 +41,7 @@ class OfflineAppsChild extends ActorChild {
|
||||
|
||||
handleEvent(event) {
|
||||
if (event.type == "MozApplicationManifest") {
|
||||
this.offlineAppRequested(event.originalTarget.defaultView);
|
||||
this.registerWindow(event.originalTarget.defaultView);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,37 +66,6 @@ class OfflineAppsChild extends ActorChild {
|
||||
}
|
||||
}
|
||||
|
||||
offlineAppRequested(aContentWindow) {
|
||||
this.registerWindow(aContentWindow);
|
||||
if (!Services.prefs.getBoolPref("browser.offline-apps.notify")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let currentURI = aContentWindow.document.documentURIObject;
|
||||
// don't bother showing UI if the user has already made a decision
|
||||
if (
|
||||
Services.perms.testExactPermission(currentURI, "offline-app") !=
|
||||
Services.perms.UNKNOWN_ACTION
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
|
||||
// all pages can use offline capabilities, no need to ask the user
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// this pref isn't set by default, ignore failures
|
||||
}
|
||||
let docId = ++this._docId;
|
||||
this._docIdMap.set(docId, Cu.getWeakReference(aContentWindow.document));
|
||||
this.mm.sendAsyncMessage("OfflineApps:RequestPermission", {
|
||||
uri: currentURI.spec,
|
||||
docId,
|
||||
});
|
||||
}
|
||||
|
||||
_startFetching(aDocument) {
|
||||
if (!aDocument.documentElement) {
|
||||
return;
|
||||
@ -127,7 +103,10 @@ class OfflineAppsChild extends ActorChild {
|
||||
let cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
|
||||
let uri = cacheUpdate.manifestURI;
|
||||
if (uri && this._docManifestSet.has(uri.spec)) {
|
||||
this.mm.sendAsyncMessage("OfflineApps:CheckUsage", { uri: uri.spec });
|
||||
this.mm.sendAsyncMessage("OfflineApps:CheckUsage", {
|
||||
uri: uri.spec,
|
||||
principal: E10SUtils.serializePrincipal(cacheUpdate.loadingPrincipal),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -951,10 +951,6 @@ pref("places.frecency.unvisitedTypedBonus", 200);
|
||||
// 2 - pre-populate site URL and pre-fetch certificate
|
||||
pref("browser.ssl_override_behavior", 2);
|
||||
|
||||
// True if the user should be prompted when a web application supports
|
||||
// offline apps.
|
||||
pref("browser.offline-apps.notify", true);
|
||||
|
||||
// if true, use full page zoom instead of text zoom
|
||||
pref("browser.zoom.full", true);
|
||||
|
||||
|
@ -1100,7 +1100,10 @@ var gPopupBlockerObserver = {
|
||||
blockedPopupAllowSite.removeAttribute("hidden");
|
||||
let uriHost = uri.asciiHost ? uri.host : uri.spec;
|
||||
var pm = Services.perms;
|
||||
if (pm.testPermission(uri, "popup") == pm.ALLOW_ACTION) {
|
||||
if (
|
||||
pm.testPermissionFromPrincipal(browser.contentPrincipal, "popup") ==
|
||||
pm.ALLOW_ACTION
|
||||
) {
|
||||
// Offer an item to block popups for this site, if a whitelist entry exists
|
||||
// already for it.
|
||||
let blockString = gNavigatorBundle.getFormattedString("popupBlock", [
|
||||
@ -3758,8 +3761,14 @@ var BrowserOnClick = {
|
||||
flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
|
||||
});
|
||||
|
||||
Services.perms.add(
|
||||
// We can't use gBrowser.contentPrincipal which is principal of about:blocked
|
||||
// Create one from uri with current principal origin attributes
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
gBrowser.currentURI,
|
||||
gBrowser.contentPrincipal.originAttributes
|
||||
);
|
||||
Services.perms.addFromPrincipal(
|
||||
principal,
|
||||
"safe-browsing",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION
|
||||
@ -7984,7 +7993,7 @@ var BrowserOffline = {
|
||||
};
|
||||
|
||||
var OfflineApps = {
|
||||
warnUsage(browser, uri) {
|
||||
warnUsage(browser, principal, host) {
|
||||
if (!browser) {
|
||||
return;
|
||||
}
|
||||
@ -7998,7 +8007,7 @@ var OfflineApps = {
|
||||
let warnQuotaKB = Services.prefs.getIntPref("offline-apps.quota.warn");
|
||||
// This message shows the quota in MB, and so we divide the quota (in kb) by 1024.
|
||||
let message = gNavigatorBundle.getFormattedString("offlineApps.usage", [
|
||||
uri.host,
|
||||
host,
|
||||
warnQuotaKB / 1024,
|
||||
]);
|
||||
|
||||
@ -8019,20 +8028,47 @@ var OfflineApps = {
|
||||
|
||||
// Now that we've warned once, prevent the warning from showing up
|
||||
// again.
|
||||
Services.perms.add(
|
||||
uri,
|
||||
Services.perms.addFromPrincipal(
|
||||
principal,
|
||||
"offline-app",
|
||||
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN
|
||||
);
|
||||
},
|
||||
|
||||
_usedMoreThanWarnQuota(uri) {
|
||||
// XXX: duplicated in preferences/advanced.js
|
||||
_getOfflineAppUsage(host, groups) {
|
||||
let cacheService = Cc[
|
||||
"@mozilla.org/network/application-cache-service;1"
|
||||
].getService(Ci.nsIApplicationCacheService);
|
||||
if (!groups) {
|
||||
try {
|
||||
groups = cacheService.getGroups();
|
||||
} catch (ex) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
let usage = 0;
|
||||
for (let group of groups) {
|
||||
let uri = Services.io.newURI(group);
|
||||
if (uri.asciiHost == host) {
|
||||
let cache = cacheService.getActiveCache(group);
|
||||
usage += cache.usage;
|
||||
}
|
||||
}
|
||||
|
||||
return usage;
|
||||
},
|
||||
|
||||
_usedMoreThanWarnQuota(principal, asciiHost) {
|
||||
// if the user has already allowed excessive usage, don't bother checking
|
||||
if (
|
||||
Services.perms.testExactPermission(uri, "offline-app") !=
|
||||
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN
|
||||
Services.perms.testExactPermissionFromPrincipal(
|
||||
principal,
|
||||
"offline-app"
|
||||
) != Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN
|
||||
) {
|
||||
let usageBytes = SiteDataManager.getAppCacheUsageByHost(uri.asciiHost);
|
||||
let usageBytes = this._getOfflineAppUsage(asciiHost);
|
||||
let warnQuotaKB = Services.prefs.getIntPref("offline-apps.quota.warn");
|
||||
// The pref is in kb, the usage we get is in bytes, so multiply the quota
|
||||
// to compare correctly:
|
||||
@ -8044,112 +8080,24 @@ var OfflineApps = {
|
||||
return false;
|
||||
},
|
||||
|
||||
requestPermission(browser, docId, uri) {
|
||||
let host = uri.asciiHost;
|
||||
let notificationID = "offline-app-requested-" + host;
|
||||
let notification = PopupNotifications.getNotification(
|
||||
notificationID,
|
||||
browser
|
||||
);
|
||||
|
||||
if (notification) {
|
||||
notification.options.controlledItems.push([
|
||||
Cu.getWeakReference(browser),
|
||||
docId,
|
||||
uri,
|
||||
]);
|
||||
} else {
|
||||
let mainAction = {
|
||||
label: gNavigatorBundle.getString("offlineApps.allowStoring.label"),
|
||||
accessKey: gNavigatorBundle.getString(
|
||||
"offlineApps.allowStoring.accesskey"
|
||||
),
|
||||
callback() {
|
||||
for (let [ciBrowser, ciDocId, ciUri] of notification.options
|
||||
.controlledItems) {
|
||||
OfflineApps.allowSite(ciBrowser, ciDocId, ciUri);
|
||||
}
|
||||
},
|
||||
};
|
||||
let secondaryActions = [
|
||||
{
|
||||
label: gNavigatorBundle.getString("offlineApps.dontAllow.label"),
|
||||
accessKey: gNavigatorBundle.getString(
|
||||
"offlineApps.dontAllow.accesskey"
|
||||
),
|
||||
callback() {
|
||||
for (let [, , ciUri] of notification.options.controlledItems) {
|
||||
OfflineApps.disallowSite(ciUri);
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
let message = gNavigatorBundle.getFormattedString(
|
||||
"offlineApps.available2",
|
||||
[host]
|
||||
);
|
||||
let anchorID = "indexedDB-notification-icon";
|
||||
let options = {
|
||||
persistent: true,
|
||||
hideClose: true,
|
||||
controlledItems: [[Cu.getWeakReference(browser), docId, uri]],
|
||||
};
|
||||
notification = PopupNotifications.show(
|
||||
browser,
|
||||
notificationID,
|
||||
message,
|
||||
anchorID,
|
||||
mainAction,
|
||||
secondaryActions,
|
||||
options
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
disallowSite(uri) {
|
||||
Services.perms.add(uri, "offline-app", Services.perms.DENY_ACTION);
|
||||
},
|
||||
|
||||
allowSite(browserRef, docId, uri) {
|
||||
Services.perms.add(uri, "offline-app", Services.perms.ALLOW_ACTION);
|
||||
|
||||
// When a site is enabled while loading, manifest resources will
|
||||
// start fetching immediately. This one time we need to do it
|
||||
// ourselves.
|
||||
let browser = browserRef.get();
|
||||
if (browser && browser.messageManager) {
|
||||
browser.messageManager.sendAsyncMessage("OfflineApps:StartFetching", {
|
||||
docId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
manage() {
|
||||
openPreferences("panePrivacy");
|
||||
},
|
||||
|
||||
receiveMessage(msg) {
|
||||
switch (msg.name) {
|
||||
case "OfflineApps:CheckUsage":
|
||||
let uri = makeURI(msg.data.uri);
|
||||
if (this._usedMoreThanWarnQuota(uri)) {
|
||||
this.warnUsage(msg.target, uri);
|
||||
}
|
||||
break;
|
||||
case "OfflineApps:RequestPermission":
|
||||
this.requestPermission(
|
||||
msg.target,
|
||||
msg.data.docId,
|
||||
makeURI(msg.data.uri)
|
||||
);
|
||||
break;
|
||||
if (msg.name !== "OfflineApps:CheckUsage") {
|
||||
return;
|
||||
}
|
||||
let uri = makeURI(msg.data.uri);
|
||||
let principal = E10SUtils.deserializePrincipal(msg.data.principal);
|
||||
if (this._usedMoreThanWarnQuota(principal, uri.asciiHost)) {
|
||||
this.warnUsage(msg.target, principal, uri.host);
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
let mm = window.messageManager;
|
||||
mm.addMessageListener("OfflineApps:CheckUsage", this);
|
||||
mm.addMessageListener("OfflineApps:RequestPermission", this);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,6 @@ registerCleanupFunction(function() {
|
||||
{}
|
||||
);
|
||||
Services.perms.removeFromPrincipal(principal, "offline-app");
|
||||
Services.prefs.clearUserPref("offline-apps.allow_by_default");
|
||||
});
|
||||
|
||||
//
|
||||
@ -83,8 +82,6 @@ function contentTask() {
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("offline-apps.allow_by_default", true);
|
||||
|
||||
// Open a new tab.
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, URL);
|
||||
registerCleanupFunction(() => gBrowser.removeCurrentTab());
|
||||
|
@ -18,7 +18,6 @@ registerCleanupFunction(function() {
|
||||
);
|
||||
Services.perms.removeFromPrincipal(principal, "offline-app");
|
||||
Services.prefs.clearUserPref("offline-apps.quota.warn");
|
||||
Services.prefs.clearUserPref("offline-apps.allow_by_default");
|
||||
let { OfflineAppCacheHelper } = ChromeUtils.import(
|
||||
"resource://gre/modules/offlineAppCache.jsm"
|
||||
);
|
||||
@ -40,67 +39,57 @@ function checkInContentPreferences(win) {
|
||||
finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("offline-apps.allow_by_default", false);
|
||||
let notificationShown = promiseNotification();
|
||||
|
||||
// Open a new tab.
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, URL);
|
||||
registerCleanupFunction(() => gBrowser.removeCurrentTab());
|
||||
|
||||
Promise.all([
|
||||
// Wait for a notification that asks whether to allow offline storage.
|
||||
promiseNotification(),
|
||||
// Wait for the tab to load.
|
||||
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser),
|
||||
]).then(() => {
|
||||
info("Loaded page, adding onCached handler");
|
||||
// Need a promise to keep track of when we've added our handler.
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let onCachedAttached = BrowserTestUtils.waitForMessage(
|
||||
mm,
|
||||
"Test:OnCachedAttached"
|
||||
);
|
||||
let gotCached = ContentTask.spawn(
|
||||
gBrowser.selectedBrowser,
|
||||
null,
|
||||
async function() {
|
||||
return new Promise(resolve => {
|
||||
content.window.applicationCache.oncached = function() {
|
||||
setTimeout(resolve, 0);
|
||||
};
|
||||
sendAsyncMessage("Test:OnCachedAttached");
|
||||
// Wait for the tab to load.
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
info("Loaded page, adding onCached handler");
|
||||
// Need a promise to keep track of when we've added our handler.
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let onCachedAttached = BrowserTestUtils.waitForMessage(
|
||||
mm,
|
||||
"Test:OnCachedAttached"
|
||||
);
|
||||
let gotCached = ContentTask.spawn(
|
||||
gBrowser.selectedBrowser,
|
||||
null,
|
||||
async function() {
|
||||
return new Promise(resolve => {
|
||||
content.window.applicationCache.oncached = function() {
|
||||
setTimeout(resolve, 0);
|
||||
};
|
||||
sendAsyncMessage("Test:OnCachedAttached");
|
||||
});
|
||||
}
|
||||
);
|
||||
gotCached.then(async function() {
|
||||
// We got cached - now we should have provoked the quota warning.
|
||||
await notificationShown;
|
||||
let notification = PopupNotifications.getNotification("offline-app-usage");
|
||||
ok(notification, "have offline-app-usage notification");
|
||||
// select the default action - this should cause the preferences
|
||||
// tab to open - which we track via an "Initialized" event.
|
||||
PopupNotifications.panel.firstElementChild.button.click();
|
||||
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
newTabBrowser.addEventListener(
|
||||
"Initialized",
|
||||
function() {
|
||||
executeSoon(function() {
|
||||
checkInContentPreferences(newTabBrowser.contentWindow);
|
||||
});
|
||||
}
|
||||
},
|
||||
{ capture: true, once: true }
|
||||
);
|
||||
gotCached.then(function() {
|
||||
// We got cached - now we should have provoked the quota warning.
|
||||
let notification = PopupNotifications.getNotification(
|
||||
"offline-app-usage"
|
||||
);
|
||||
ok(notification, "have offline-app-usage notification");
|
||||
// select the default action - this should cause the preferences
|
||||
// tab to open - which we track via an "Initialized" event.
|
||||
PopupNotifications.panel.firstElementChild.button.click();
|
||||
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
newTabBrowser.addEventListener(
|
||||
"Initialized",
|
||||
function() {
|
||||
executeSoon(function() {
|
||||
checkInContentPreferences(newTabBrowser.contentWindow);
|
||||
});
|
||||
},
|
||||
{ capture: true, once: true }
|
||||
);
|
||||
});
|
||||
onCachedAttached.then(function() {
|
||||
Services.prefs.setIntPref("offline-apps.quota.warn", 1);
|
||||
|
||||
// Click the notification panel's "Allow" button. This should kick
|
||||
// off updates which will call our oncached handler above.
|
||||
PopupNotifications.panel.firstElementChild.button.click();
|
||||
});
|
||||
});
|
||||
onCachedAttached.then(function() {
|
||||
Services.prefs.setIntPref("offline-apps.quota.warn", 1);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,6 @@ html|*#webRTC-previewVideo {
|
||||
|
||||
/* OFFLINE APPS */
|
||||
|
||||
.popup-notification-icon[popupid*="offline-app-requested"],
|
||||
.popup-notification-icon[popupid="offline-app-usage"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
@ -1058,13 +1058,16 @@ void nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec) {
|
||||
if (NS_FAILED(rv)) {
|
||||
action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
|
||||
} else {
|
||||
// Only continue if the document has permission to use offline APIs or
|
||||
// when preferences indicate to permit it automatically.
|
||||
if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal()) &&
|
||||
!nsContentUtils::MaybeAllowOfflineAppByDefault(
|
||||
mDocument->NodePrincipal()) &&
|
||||
!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
|
||||
return;
|
||||
if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
|
||||
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
||||
components::OfflineCacheUpdate::Service();
|
||||
if (!updateService) {
|
||||
return;
|
||||
}
|
||||
rv = updateService->AllowOfflineApp(mDocument->NodePrincipal());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool fetchedWithHTTPGetOrEquiv = false;
|
||||
|
@ -1652,8 +1652,7 @@ bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) {
|
||||
}
|
||||
|
||||
bool allowed;
|
||||
nsresult rv = updateService->OfflineAppAllowedForURI(
|
||||
aURI, Preferences::GetRootBranch(), &allowed);
|
||||
nsresult rv = updateService->OfflineAppAllowedForURI(aURI, &allowed);
|
||||
return NS_SUCCEEDED(rv) && allowed;
|
||||
}
|
||||
|
||||
@ -1666,8 +1665,7 @@ bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
|
||||
}
|
||||
|
||||
bool allowed;
|
||||
nsresult rv = updateService->OfflineAppAllowed(
|
||||
aPrincipal, Preferences::GetRootBranch(), &allowed);
|
||||
nsresult rv = updateService->OfflineAppAllowed(aPrincipal, &allowed);
|
||||
return NS_SUCCEEDED(rv) && allowed;
|
||||
}
|
||||
|
||||
@ -1699,28 +1697,6 @@ bool nsContentUtils::PrincipalAllowsL10n(nsIPrincipal* aPrincipal) {
|
||||
return hasFlags;
|
||||
}
|
||||
|
||||
bool nsContentUtils::MaybeAllowOfflineAppByDefault(nsIPrincipal* aPrincipal) {
|
||||
if (!Preferences::GetRootBranch()) return false;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
bool allowedByDefault;
|
||||
rv = Preferences::GetRootBranch()->GetBoolPref(
|
||||
"offline-apps.allow_by_default", &allowedByDefault);
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
if (!allowedByDefault) return false;
|
||||
|
||||
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
||||
components::OfflineCacheUpdate::Service();
|
||||
if (!updateService) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rv = updateService->AllowOfflineApp(aPrincipal);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
// static
|
||||
void nsContentUtils::Shutdown() {
|
||||
sInitialized = false;
|
||||
|
@ -1957,12 +1957,6 @@ class nsContentUtils {
|
||||
*/
|
||||
static bool PrincipalAllowsL10n(nsIPrincipal* aPrincipal);
|
||||
|
||||
/**
|
||||
* If offline-apps.allow_by_default is true, we set offline-app permission
|
||||
* for the principal and return true. Otherwise false.
|
||||
*/
|
||||
static bool MaybeAllowOfflineAppByDefault(nsIPrincipal* aPrincipal);
|
||||
|
||||
/**
|
||||
* Increases the count of blockers preventing scripts from running.
|
||||
* NOTE: You might want to use nsAutoScriptBlocker rather than calling
|
||||
|
@ -4585,8 +4585,14 @@ bool ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent* aActor) {
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvSetOfflinePermission(
|
||||
const Principal& aPrincipal) {
|
||||
nsIPrincipal* principal = aPrincipal;
|
||||
nsContentUtils::MaybeAllowOfflineAppByDefault(principal);
|
||||
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
||||
components::OfflineCacheUpdate::Service();
|
||||
if (!updateService) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
nsresult rv = updateService->AllowOfflineApp(aPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -1087,8 +1087,7 @@ parent:
|
||||
|
||||
/**
|
||||
* Sets "offline-app" permission for the principal. Called when we hit
|
||||
* a web app with the manifest attribute in <html> and
|
||||
* offline-apps.allow_by_default is set to true.
|
||||
* a web app with the manifest attribute in <html>
|
||||
*/
|
||||
async SetOfflinePermission(Principal principal);
|
||||
|
||||
|
@ -59,8 +59,6 @@ fetch: function(callback)
|
||||
|
||||
var OfflineTest = {
|
||||
|
||||
_allowedByDefault: false,
|
||||
|
||||
_hasSlave: false,
|
||||
|
||||
// The window where test results should be sent.
|
||||
@ -74,17 +72,7 @@ _SJSsStated: [],
|
||||
|
||||
setupChild: function()
|
||||
{
|
||||
if (this._allowedByDefault) {
|
||||
this._masterWindow = window;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window.parent.OfflineTest._hasSlave) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._masterWindow = window.top;
|
||||
|
||||
this._masterWindow = window;
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -97,41 +85,8 @@ setupChild: function()
|
||||
*/
|
||||
setup: function()
|
||||
{
|
||||
try {
|
||||
this._allowedByDefault = SpecialPowers.getBoolPref("offline-apps.allow_by_default");
|
||||
} catch (e) {}
|
||||
|
||||
if (this._allowedByDefault) {
|
||||
this._masterWindow = window;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!window.opener || !window.opener.OfflineTest ||
|
||||
!window.opener.OfflineTest._hasSlave) {
|
||||
// Offline applications must be toplevel windows and have the
|
||||
// offline-app permission. Because we were loaded without the
|
||||
// offline-app permission and (probably) in an iframe, we need to
|
||||
// enable the pref and spawn a new window to perform the actual
|
||||
// tests. It will use this window to report successes and
|
||||
// failures.
|
||||
|
||||
if (SpecialPowers.testPermission("offline-app", Ci.nsIPermissionManager.ALLOW_ACTION, document)) {
|
||||
ok(false, "Previous test failed to clear offline-app permission! Expect failures.");
|
||||
}
|
||||
SpecialPowers.addPermission("offline-app", Ci.nsIPermissionManager.ALLOW_ACTION, document);
|
||||
|
||||
// Tests must run as toplevel windows. Open a slave window to run
|
||||
// the test.
|
||||
this._hasSlave = true;
|
||||
window.open(window.location, "offlinetest");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this._masterWindow = window.opener;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
teardownAndFinish: function()
|
||||
@ -160,16 +115,7 @@ teardown: function(callback)
|
||||
|
||||
finish: function()
|
||||
{
|
||||
if (this._allowedByDefault) {
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
} else if (this._masterWindow) {
|
||||
// Slave window: pass control back to master window, close itself.
|
||||
this._masterWindow.SimpleTest.executeSoon(this._masterWindow.OfflineTest.finish);
|
||||
window.close();
|
||||
} else {
|
||||
// Master window: finish test.
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
},
|
||||
|
||||
//
|
||||
|
@ -4,72 +4,6 @@
|
||||
"use strict";
|
||||
|
||||
var OfflineApps = {
|
||||
offlineAppRequested: function(aContentWindow) {
|
||||
if (!Services.prefs.getBoolPref("browser.offline-apps.notify")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = BrowserApp.getTabForWindow(aContentWindow);
|
||||
let principal = aContentWindow.document.nodePrincipal;
|
||||
let currentURI = aContentWindow.document.documentURIObject;
|
||||
|
||||
// Don't bother showing UI if the user has already made a decision
|
||||
if (
|
||||
Services.perms.testExactPermissionFromPrincipal(
|
||||
principal,
|
||||
"offline-app"
|
||||
) != Services.perms.UNKNOWN_ACTION
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
|
||||
// All pages can use offline capabilities, no need to ask the user
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// This pref isn't set by default, ignore failures
|
||||
}
|
||||
|
||||
let host = currentURI.asciiHost;
|
||||
let notificationID = "offline-app-requested-" + host;
|
||||
|
||||
let strings = Strings.browser;
|
||||
let buttons = [
|
||||
{
|
||||
label: strings.GetStringFromName("offlineApps.dontAllow2"),
|
||||
callback: function(aChecked) {
|
||||
if (aChecked) {
|
||||
OfflineApps.disallowSite(aContentWindow.document);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: strings.GetStringFromName("offlineApps.allow"),
|
||||
callback: function() {
|
||||
OfflineApps.allowSite(aContentWindow.document);
|
||||
},
|
||||
positive: true,
|
||||
},
|
||||
];
|
||||
|
||||
let requestor = BrowserApp.manifest
|
||||
? "'" + BrowserApp.manifest.name + "'"
|
||||
: host;
|
||||
let message = strings.formatStringFromName("offlineApps.ask", [requestor]);
|
||||
let options = {
|
||||
checkbox: Strings.browser.GetStringFromName("offlineApps.dontAskAgain"),
|
||||
};
|
||||
NativeWindow.doorhanger.show(
|
||||
message,
|
||||
notificationID,
|
||||
buttons,
|
||||
tab.id,
|
||||
options
|
||||
);
|
||||
},
|
||||
|
||||
allowSite: function(aDocument) {
|
||||
Services.perms.addFromPrincipal(
|
||||
aDocument.nodePrincipal,
|
||||
|
@ -4479,7 +4479,6 @@ Tab.prototype = {
|
||||
this.browser.addEventListener("DOMWillOpenModalDialog", this, true);
|
||||
this.browser.addEventListener("pagehide", this, true);
|
||||
this.browser.addEventListener("pageshow", this, true);
|
||||
this.browser.addEventListener("MozApplicationManifest", this, true);
|
||||
this.browser.addEventListener("TabPreZombify", this, true);
|
||||
this.browser.addEventListener("framefocusrequested", this, true);
|
||||
this.browser.addEventListener("focusin", this, true);
|
||||
@ -4642,7 +4641,6 @@ Tab.prototype = {
|
||||
this.browser.removeEventListener("DOMWillOpenModalDialog", this, true);
|
||||
this.browser.removeEventListener("pagehide", this, true);
|
||||
this.browser.removeEventListener("pageshow", this, true);
|
||||
this.browser.removeEventListener("MozApplicationManifest", this, true);
|
||||
this.browser.removeEventListener("TabPreZombify", this, true);
|
||||
this.browser.removeEventListener("framefocusrequested", this, true);
|
||||
this.browser.removeEventListener("focusin", this, true);
|
||||
@ -5238,11 +5236,6 @@ Tab.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
case "MozApplicationManifest": {
|
||||
OfflineApps.offlineAppRequested(aEvent.originalTarget.defaultView);
|
||||
break;
|
||||
}
|
||||
|
||||
case "framefocusrequested": {
|
||||
if (BrowserApp.selectedTab !== this) {
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
|
@ -62,43 +62,6 @@ public class testDoorHanger extends OldBaseTest {
|
||||
mAsserter.is(mSolo.searchText(GEO_MESSAGE), false, "Geolocation doorhanger notification is hidden when opening a new tab");
|
||||
*/
|
||||
|
||||
// Save offline-allow-by-default preferences first
|
||||
mActions.getPrefs(new String[] { "offline-apps.allow_by_default" },
|
||||
new Actions.PrefHandlerBase() {
|
||||
@Override // Actions.PrefHandlerBase
|
||||
public void prefValue(String pref, boolean value) {
|
||||
mAsserter.is(pref, "offline-apps.allow_by_default", "Expecting correct pref name");
|
||||
offlineAllowedByDefault = value;
|
||||
}
|
||||
}).waitForFinish();
|
||||
|
||||
setPreferenceAndWaitForChange("offline-apps.allow_by_default", false);
|
||||
|
||||
// Load offline storage page
|
||||
loadUrlAndWait(OFFLINE_STORAGE_URL);
|
||||
waitForText(mStringHelper.OFFLINE_MESSAGE);
|
||||
|
||||
// Test doorhanger dismissed when tapping "Don't share"
|
||||
waitForCheckBox();
|
||||
mSolo.clickOnCheckBox(0);
|
||||
mSolo.clickOnButton(mStringHelper.OFFLINE_DENY);
|
||||
waitForTextDismissed(mStringHelper.OFFLINE_MESSAGE);
|
||||
mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger notification is hidden when denying storage");
|
||||
|
||||
// Load offline storage page
|
||||
loadUrlAndWait(OFFLINE_STORAGE_URL);
|
||||
waitForText(mStringHelper.OFFLINE_MESSAGE);
|
||||
|
||||
// Test doorhanger dismissed when tapping "Allow" and is not displayed again
|
||||
mSolo.clickOnButton(mStringHelper.OFFLINE_ALLOW);
|
||||
waitForTextDismissed(mStringHelper.OFFLINE_MESSAGE);
|
||||
mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger notification is hidden when allowing storage");
|
||||
loadUrlAndWait(OFFLINE_STORAGE_URL);
|
||||
mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger is no longer triggered");
|
||||
|
||||
// Revert offline setting
|
||||
setPreferenceAndWaitForChange("offline-apps.allow_by_default", offlineAllowedByDefault);
|
||||
|
||||
// Load new login page
|
||||
loadUrlAndWait(getAbsoluteUrl(mStringHelper.ROBOCOP_LOGIN_01_URL));
|
||||
waitForText(mStringHelper.LOGIN_MESSAGE);
|
||||
|
@ -228,9 +228,6 @@ pref("browser.cache.frecency_half_life_hours", 6);
|
||||
// AppCache over insecure connection is disabled by default
|
||||
pref("browser.cache.offline.insecure.enable", false);
|
||||
|
||||
// enable offline apps by default, disable prompt
|
||||
pref("offline-apps.allow_by_default", true);
|
||||
|
||||
// offline cache capacity in kilobytes
|
||||
pref("browser.cache.offline.capacity", 512000);
|
||||
|
||||
|
@ -2125,7 +2125,7 @@ bool NS_ShouldCheckAppCache(nsIPrincipal* aPrincipal) {
|
||||
}
|
||||
|
||||
bool allowed;
|
||||
rv = offlineService->OfflineAppAllowed(aPrincipal, nullptr, &allowed);
|
||||
rv = offlineService->OfflineAppAllowed(aPrincipal, &allowed);
|
||||
return NS_SUCCEEDED(rv) && allowed;
|
||||
}
|
||||
|
||||
|
@ -251,6 +251,14 @@ OfflineCacheUpdateChild::GetPartial(bool* aPartial) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OfflineCacheUpdateChild::GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) {
|
||||
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_IF_ADDREF(*aLoadingPrincipal = mLoadingPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OfflineCacheUpdateChild::GetManifestURI(nsIURI** aManifestURI) {
|
||||
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
|
||||
|
@ -39,6 +39,10 @@ namespace docshell {
|
||||
NS_IMETHOD GetUpdateDomain(nsACString& aUpdateDomain) override { \
|
||||
return !_to ? NS_ERROR_NULL_POINTER : _to->GetUpdateDomain(aUpdateDomain); \
|
||||
} \
|
||||
NS_IMETHOD GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) override { \
|
||||
return !_to ? NS_ERROR_NULL_POINTER \
|
||||
: _to->GetLoadingPrincipal(aLoadingPrincipal); \
|
||||
} \
|
||||
NS_IMETHOD GetManifestURI(nsIURI** aManifestURI) override { \
|
||||
return !_to ? NS_ERROR_NULL_POINTER : _to->GetManifestURI(aManifestURI); \
|
||||
} \
|
||||
|
@ -90,8 +90,7 @@ nsresult OfflineCacheUpdateParent::Schedule(
|
||||
|
||||
bool offlinePermissionAllowed = false;
|
||||
|
||||
rv = service->OfflineAppAllowed(mLoadingPrincipal, nullptr,
|
||||
&offlinePermissionAllowed);
|
||||
rv = service->OfflineAppAllowed(mLoadingPrincipal, &offlinePermissionAllowed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!offlinePermissionAllowed) return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -88,6 +88,11 @@ interface nsIOfflineCacheUpdate : nsISupports {
|
||||
*/
|
||||
readonly attribute nsIURI manifestURI;
|
||||
|
||||
/**
|
||||
* The principal of the page that is requesting the update.
|
||||
*/
|
||||
readonly attribute nsIPrincipal loadingPrincipal;
|
||||
|
||||
/**
|
||||
* TRUE if the cache update completed successfully.
|
||||
*/
|
||||
@ -261,26 +266,16 @@ interface nsIOfflineCacheUpdateService : nsISupports {
|
||||
* cache.
|
||||
* @param aPrincipal
|
||||
* The principal to check.
|
||||
* @param aPrefBranch
|
||||
* The pref branch to use to check the
|
||||
* offline-apps.allow_by_default pref. If not specified,
|
||||
* the pref service will be used.
|
||||
*/
|
||||
boolean offlineAppAllowed(in nsIPrincipal aPrincipal,
|
||||
in nsIPrefBranch aPrefBranch);
|
||||
boolean offlineAppAllowed(in nsIPrincipal aPrincipal);
|
||||
|
||||
/**
|
||||
* Checks whether a document at the given URI should have access
|
||||
* to the offline cache.
|
||||
* @param aURI
|
||||
* The URI to check
|
||||
* @param aPrefBranch
|
||||
* The pref branch to use to check the
|
||||
* offline-apps.allow_by_default pref. If not specified,
|
||||
* the pref service will be used.
|
||||
*/
|
||||
boolean offlineAppAllowedForURI(in nsIURI aURI,
|
||||
in nsIPrefBranch aPrefBranch);
|
||||
boolean offlineAppAllowedForURI(in nsIURI aURI);
|
||||
|
||||
/**
|
||||
* Sets the "offline-app" permission for the principal.
|
||||
|
@ -1218,7 +1218,7 @@ nsresult nsOfflineCacheUpdate::Init(nsIURI* aManifestURI, nsIURI* aDocumentURI,
|
||||
}
|
||||
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aDocumentURI,
|
||||
nullptr, &mPinned);
|
||||
&mPinned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mState = STATE_INITIALIZED;
|
||||
@ -1265,7 +1265,7 @@ nsresult nsOfflineCacheUpdate::InitForUpdateCheck(
|
||||
mApplicationCache = mPreviousApplicationCache;
|
||||
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aManifestURI,
|
||||
nullptr, &mPinned);
|
||||
&mPinned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mUpdateAvailableObserver = aObserver;
|
||||
@ -1322,7 +1322,7 @@ nsresult nsOfflineCacheUpdate::InitPartial(nsIURI* aManifestURI,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aDocumentURI,
|
||||
nullptr, &mPinned);
|
||||
&mPinned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mState = STATE_INITIALIZED;
|
||||
@ -2033,8 +2033,7 @@ static nsresult EvictOneOfCacheGroups(nsIApplicationCacheService* cacheService,
|
||||
if (NS_FAILED(rv) || !cache) continue;
|
||||
|
||||
bool pinned;
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(uri, nullptr,
|
||||
&pinned);
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(uri, &pinned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!pinned) {
|
||||
@ -2103,6 +2102,14 @@ nsOfflineCacheUpdate::GetManifestURI(nsIURI** aManifestURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdate::GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) {
|
||||
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_IF_ADDREF(*aLoadingPrincipal = mLoadingPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdate::GetSucceeded(bool* aSucceeded) {
|
||||
NS_ENSURE_TRUE(mState == STATE_FINISHED, NS_ERROR_NOT_AVAILABLE);
|
||||
|
@ -341,9 +341,7 @@ class nsOfflineCacheUpdateService final : public nsIOfflineCacheUpdateService,
|
||||
|
||||
static already_AddRefed<nsOfflineCacheUpdateService> GetInstance();
|
||||
|
||||
static nsresult OfflineAppPinnedForURI(nsIURI* aDocumentURI,
|
||||
nsIPrefBranch* aPrefBranch,
|
||||
bool* aPinned);
|
||||
static nsresult OfflineAppPinnedForURI(nsIURI* aDocumentURI, bool* aPinned);
|
||||
|
||||
static nsTHashtable<nsCStringHashKey>* AllowedDomains();
|
||||
|
||||
|
@ -525,7 +525,6 @@ nsOfflineCacheUpdateService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static nsresult OfflineAppPermForPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsIPrefBranch* aPrefBranch,
|
||||
bool pinned, bool* aAllowed) {
|
||||
*aAllowed = false;
|
||||
|
||||
@ -575,35 +574,30 @@ static nsresult OfflineAppPermForPrincipal(nsIPrincipal* aPrincipal,
|
||||
*aAllowed = true;
|
||||
}
|
||||
|
||||
// offline-apps.allow_by_default is now effective at the cache selection
|
||||
// algorithm code (nsContentSink).
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdateService::OfflineAppAllowed(nsIPrincipal* aPrincipal,
|
||||
nsIPrefBranch* aPrefBranch,
|
||||
bool* aAllowed) {
|
||||
return OfflineAppPermForPrincipal(aPrincipal, aPrefBranch, false, aAllowed);
|
||||
return OfflineAppPermForPrincipal(aPrincipal, false, aAllowed);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdateService::OfflineAppAllowedForURI(nsIURI* aURI,
|
||||
nsIPrefBranch* aPrefBranch,
|
||||
bool* aAllowed) {
|
||||
OriginAttributes attrs;
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
BasePrincipal::CreateContentPrincipal(aURI, attrs);
|
||||
return OfflineAppPermForPrincipal(principal, aPrefBranch, false, aAllowed);
|
||||
return OfflineAppPermForPrincipal(principal, false, aAllowed);
|
||||
}
|
||||
|
||||
nsresult nsOfflineCacheUpdateService::OfflineAppPinnedForURI(
|
||||
nsIURI* aDocumentURI, nsIPrefBranch* aPrefBranch, bool* aPinned) {
|
||||
nsIURI* aDocumentURI, bool* aPinned) {
|
||||
OriginAttributes attrs;
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
BasePrincipal::CreateContentPrincipal(aDocumentURI, attrs);
|
||||
return OfflineAppPermForPrincipal(principal, aPrefBranch, true, aPinned);
|
||||
return OfflineAppPermForPrincipal(principal, true, aPinned);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
Loading…
Reference in New Issue
Block a user