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:
Paul Zuehlcke 2019-09-05 13:37:55 +00:00
parent 3e8fdbe0ed
commit 99bfbf1328
24 changed files with 168 additions and 444 deletions

View File

@ -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),
});
}
}
}

View File

@ -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);

View File

@ -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);
},
};

View File

@ -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());

View File

@ -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);
});
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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);

View File

@ -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);
},
//

View File

@ -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,

View File

@ -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({

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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); \
} \

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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();

View File

@ -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