Bug 1554947 - Update saveURL to use referrerInfo class instead of referrer and referrerr policy r=Gijs,snorp

Differential Revision: https://phabricator.services.mozilla.com/D33939

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Thomas Nguyen 2019-07-16 17:59:28 +00:00
parent a951305e06
commit b0fa7cedfe
11 changed files with 131 additions and 101 deletions

View File

@ -647,7 +647,22 @@ class ContextMenuChild extends JSWindowActorChild {
};
if (context.inFrame && !context.inSrcdocFrame) {
data.frameReferrerInfo = doc.referrerInfo;
data.frameReferrerInfo = E10SUtils.serializeReferrerInfo(
doc.referrerInfo
);
}
// In the case "onLink" we may have to send target referrerInfo. This object
// may be used to in saveMedia function.
if (context.onLink) {
let targetReferrerInfo = Cc[
"@mozilla.org/referrer-info;1"
].createInstance(Ci.nsIReferrerInfo);
targetReferrerInfo.initWithNode(aEvent.composedTarget);
data.targetReferrerInfo = E10SUtils.serializeReferrerInfo(
targetReferrerInfo
);
}
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {

View File

@ -7187,6 +7187,14 @@ function handleLinkClick(event, href, linkNode) {
}
var doc = event.target.ownerDocument;
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
if (linkNode) {
referrerInfo.initWithNode(linkNode);
} else {
referrerInfo.initWithDocument(doc);
}
if (where == "save") {
saveURL(
@ -7195,22 +7203,13 @@ function handleLinkClick(event, href, linkNode) {
null,
true,
true,
doc.documentURIObject,
referrerInfo,
doc
);
event.preventDefault();
return true;
}
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
if (linkNode) {
referrerInfo.initWithNode(linkNode);
} else {
referrerInfo.initWithDocument(doc);
}
// if the mixedContentChannel is present and the referring URI passes
// a same origin check with the target URI, we can preserve the users
// decision of disabling MCB on a page for it's child tabs.

View File

@ -43,6 +43,7 @@ function openContextMenu(aMessage, aBrowser, aActor) {
let actor = aActor;
let spellInfo = data.spellInfo;
let frameReferrerInfo = data.frameReferrerInfo;
let targetReferrerInfo = data.targetReferrerInfo;
let principal = data.principal;
let storagePrincipal = data.storagePrincipal;
@ -60,6 +61,10 @@ function openContextMenu(aMessage, aBrowser, aActor) {
frameReferrerInfo = E10SUtils.deserializeReferrerInfo(frameReferrerInfo);
}
if (targetReferrerInfo) {
targetReferrerInfo = E10SUtils.deserializeReferrerInfo(targetReferrerInfo);
}
// For now, JS Window Actors don't deserialize Principals automatically, so we
// have to do it ourselves. See bug 1557852.
if (principal) {
@ -95,6 +100,7 @@ function openContextMenu(aMessage, aBrowser, aActor) {
charSet: data.charSet,
referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo),
frameReferrerInfo,
targetReferrerInfo,
contentType: data.contentType,
contentDisposition: data.contentDisposition,
frameOuterWindowID: data.frameOuterWindowID,
@ -1324,7 +1330,7 @@ nsContextMenu.prototype = {
}
// Cache this because we fetch the data async
let { documentURIObject } = gContextMenuContentData;
let { targetReferrerInfo } = gContextMenuContentData;
this.actor.saveVideoFrameAsImage(this.targetIdentifier).then(dataURL => {
// FIXME can we switch this to a blob URL?
@ -1334,7 +1340,7 @@ nsContextMenu.prototype = {
"SaveImageTitle",
true, // bypass cache
false, // don't skip prompt for where to save
documentURIObject, // referrer
targetReferrerInfo, // referrer info
null, // document
null, // content type
null, // content disposition
@ -1429,7 +1435,7 @@ nsContextMenu.prototype = {
dialogTitle,
bypassCache,
doc,
docURI,
referrerInfo,
windowID,
linkDownload,
isContentWindowPrivate
@ -1497,7 +1503,7 @@ nsContextMenu.prototype = {
dialogTitle,
bypassCache,
false,
docURI,
referrerInfo,
doc,
isContentWindowPrivate,
this._triggeringPrincipal
@ -1579,12 +1585,6 @@ nsContextMenu.prototype = {
channel.loadFlags |= flags;
if (channel instanceof Ci.nsIHttpChannel) {
let referrerInfo = new ReferrerInfo(
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
true,
docURI
);
channel.referrerInfo = referrerInfo;
if (channel instanceof Ci.nsIHttpChannelInternal) {
channel.forceAllowThirdPartyCookie = true;
@ -1615,7 +1615,7 @@ nsContextMenu.prototype = {
null,
true,
this.ownerDoc,
gContextMenuContentData.documentURIObject,
gContextMenuContentData.referrerInfo,
this.frameOuterWindowID,
this.linkDownload,
isContentWindowPrivate
@ -1633,7 +1633,7 @@ nsContextMenu.prototype = {
saveMedia() {
let doc = this.ownerDoc;
let isContentWindowPrivate = this.ownerDoc.isPrivate;
let referrerURI = gContextMenuContentData.documentURIObject;
let referrerInfo = gContextMenuContentData.targetReferrerInfo;
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
if (this.onCanvas) {
// Bypass cache, since it's a data: URL.
@ -1644,7 +1644,7 @@ nsContextMenu.prototype = {
"SaveImageTitle",
true,
false,
referrerURI,
referrerInfo,
null,
null,
null,
@ -1660,7 +1660,7 @@ nsContextMenu.prototype = {
"SaveImageTitle",
false,
false,
referrerURI,
referrerInfo,
null,
gContextMenuContentData.contentType,
gContextMenuContentData.contentDisposition,
@ -1675,7 +1675,7 @@ nsContextMenu.prototype = {
dialogTitle,
false,
doc,
referrerURI,
referrerInfo,
this.frameOuterWindowID,
"",
isContentWindowPrivate

View File

@ -760,6 +760,12 @@ async function selectSaveFolder(aCallback) {
function saveMedia() {
var tree = document.getElementById("imagetree");
var rowArray = getSelectedRows(tree);
let ReferrerInfo = Components.Constructor(
"@mozilla.org/referrer-info;1",
"nsIReferrerInfo",
"init"
);
if (rowArray.length == 1) {
let row = rowArray[0];
let item = gImageView.data[row][COL_IMAGE_NODE];
@ -774,13 +780,19 @@ function saveMedia() {
titleKey = "SaveAudioTitle";
}
// Bug 1565216 to evaluate passing referrer as item.baseURL
let referrerInfo = new ReferrerInfo(
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
true,
Services.io.newURI(item.baseURI)
);
saveURL(
url,
null,
titleKey,
false,
false,
Services.io.newURI(item.baseURI),
referrerInfo,
null,
gDocInfo.isContentWindowPrivate,
gDocInfo.principal
@ -791,6 +803,12 @@ function saveMedia() {
if (aDirectory) {
var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
uniqueFile(aChosenData.file);
let referrerInfo = new ReferrerInfo(
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
true,
aBaseURI
);
internalSave(
aURIString,
null,
@ -800,7 +818,7 @@ function saveMedia() {
false,
"SaveImageTitle",
aChosenData,
aBaseURI,
referrerInfo,
null,
false,
null,

View File

@ -400,7 +400,7 @@ function openLinkIn(url, where, params) {
null,
true,
true,
aReferrerInfo.sendReferrer ? aReferrerInfo.originalReferrer : null,
aReferrerInfo,
null,
params.isContentWindowPrivate,
aPrincipal
@ -413,15 +413,7 @@ function openLinkIn(url, where, params) {
);
return;
}
saveURL(
url,
null,
null,
true,
true,
aReferrerInfo.sendReferrer ? aReferrerInfo.originalReferrer : null,
aInitiatingDoc
);
saveURL(url, null, null, true, true, aReferrerInfo, aInitiatingDoc);
}
return;
}

View File

@ -29,6 +29,8 @@ const TEST_PATH_FRAME = `${TEST_BASE_PATH}file_favicon.png`;
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
const tempDir = createTemporarySaveDirectory();
MockFilePicker.displayDirectory = tempDir;
add_task(async function setup() {
info("Setting the prefs.");
@ -38,22 +40,6 @@ add_task(async function setup() {
});
info("Setting MockFilePicker.");
let tempDir = createTemporarySaveDirectory();
MockFilePicker.displayDirectory = tempDir;
MockFilePicker.showCallback = fp => {
info("MockFilePicker showCallback");
let fileName = fp.defaultString;
let destFile = tempDir.clone();
destFile.append(fileName);
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
info("MockFilePicker showCallback done");
};
mockTransferRegisterer.register();
registerCleanupFunction(function() {
@ -100,14 +86,23 @@ function createPromiseForObservingChannel(aURL, aFirstParty) {
function createPromiseForTransferComplete() {
return new Promise(resolve => {
function onTransferComplete(downloadSuccess) {
ok(downloadSuccess, "File should have been downloaded successfully");
// Clear the callback for now.
mockTransferCallback = () => {};
resolve();
}
MockFilePicker.showCallback = fp => {
info("MockFilePicker showCallback");
mockTransferCallback = onTransferComplete;
let fileName = fp.defaultString;
let destFile = tempDir.clone();
destFile.append(fileName);
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
MockFilePicker.showCallback = null;
mockTransferCallback = function(downloadSuccess) {
ok(downloadSuccess, "File should have been downloaded successfully");
mockTransferCallback = () => {};
resolve();
};
};
});
}
@ -184,6 +179,9 @@ add_task(async function testContextMenuSaveAs() {
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
info("Close the context menu.");
let contextMenu = document.getElementById("contentAreaContextMenu");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
@ -193,9 +191,6 @@ add_task(async function testContextMenuSaveAs() {
contextMenu.hidePopup();
await popupHiddenPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
BrowserTestUtils.removeTab(tab);
}
});
@ -245,6 +240,9 @@ add_task(async function testFileMenuSavePageAs() {
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
// Close the file menu.
if (Services.appinfo.OS !== "Darwin") {
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
@ -255,9 +253,6 @@ add_task(async function testFileMenuSavePageAs() {
await popupHiddenPromise;
}
info("Wait until the save is finished.");
await transferCompletePromise;
BrowserTestUtils.removeTab(tab);
});

View File

@ -47,9 +47,10 @@ function saveToFile(data, filename) {
// append .png extension to filename if it doesn't exist
filename = filename.replace(/\.png$|$/i, ".png");
// In chrome doc, we don't need to pass a referrer, just pass null
chromeWindow.saveURL(data, filename, null,
true, true,
chromeDocument.documentURIObject, chromeDocument);
null, chromeDocument);
}
function simulateCameraEffects(node) {

View File

@ -1330,6 +1330,10 @@ var BrowserApp = {
return;
}
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
referrerInfo.initWithDocument(aTarget.ownerDocument);
let uri = aTarget.currentRequestFinalURI || aTarget.currentURI;
ContentAreaUtils.saveImageURL(
uri.spec,
@ -1337,7 +1341,7 @@ var BrowserApp = {
"SaveImageTitle",
false,
true,
aTarget.ownerDocument.documentURIObject,
referrerInfo,
aTarget.ownerDocument
);
});
@ -1395,6 +1399,10 @@ var BrowserApp = {
}
// Skipped trying to pull MIME type out of cache for now
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
referrerInfo.initWithDocument(aTarget.ownerDocument);
ContentAreaUtils.internalSave(
url,
null,
@ -1404,7 +1412,7 @@ var BrowserApp = {
false,
filePickerTitleKey,
null,
aTarget.ownerDocument.documentURIObject,
referrerInfo,
aTarget.ownerDocument,
true,
null

View File

@ -402,13 +402,21 @@ function promiseStartLegacyDownload(aSourceUrl, aOptions) {
);
persist.progressListener = transfer;
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
referrerInfo.init(
Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
true,
referrer
);
// Start the actual download process.
persist.savePrivacyAwareURI(
sourceURI,
Services.scriptSecurityManager.getSystemPrincipal(),
0,
referrer,
Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
referrerInfo,
null,
null,
targetFile,

View File

@ -244,7 +244,6 @@ var gViewSourceUtils = {
// the default setting is to not decode. we need to decode.
webBrowserPersist.persistFlags = this.mnsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
webBrowserPersist.progressListener = this.viewSourceProgressListener;
let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER;
let ssm = Services.scriptSecurityManager;
let principal = ssm.createContentPrincipal(
data.uri,
@ -255,7 +254,6 @@ var gViewSourceUtils = {
principal,
null,
null,
referrerPolicy,
null,
null,
file,

View File

@ -69,13 +69,13 @@ function saveURL(
aFilePickerTitleKey,
aShouldBypassCache,
aSkipPrompt,
aReferrer,
aReferrerInfo,
aSourceDocument,
aIsContentWindowPrivate,
aPrincipal
) {
forbidCPOW(aURL, "saveURL", "aURL");
forbidCPOW(aReferrer, "saveURL", "aReferrer");
forbidCPOW(aReferrerInfo, "saveURL", "aReferrerInfo");
// Allow aSourceDocument to be a CPOW.
internalSave(
@ -87,7 +87,7 @@ function saveURL(
aShouldBypassCache,
aFilePickerTitleKey,
null,
aReferrer,
aReferrerInfo,
aSourceDocument,
aSkipPrompt,
null,
@ -120,9 +120,8 @@ const nsISupportsCString = Ci.nsISupportsCString;
* If true, we will attempt to save the file with the suggested
* filename to the default downloads folder without showing the
* file picker.
* @param aReferrer (nsIURI, optional)
* The referrer URI object (not a URL string) to use, or null
* if no referrer should be sent.
* @param aReferrerInfo (nsIReferrerInfo, optional)
* the referrerInfo object to use, or null if no referrer should be sent.
* @param aDoc (Document, deprecated, optional)
* The content document that the save is being initiated from. If this
* is omitted, then aIsContentWindowPrivate must be provided.
@ -140,7 +139,7 @@ function saveImageURL(
aFilePickerTitleKey,
aShouldBypassCache,
aSkipPrompt,
aReferrer,
aReferrerInfo,
aDoc,
aContentType,
aContentDisp,
@ -148,7 +147,7 @@ function saveImageURL(
aPrincipal
) {
forbidCPOW(aURL, "saveImageURL", "aURL");
forbidCPOW(aReferrer, "saveImageURL", "aReferrer");
forbidCPOW(aReferrerInfo, "saveImageURL", "aReferrerInfo");
if (aDoc && aIsContentWindowPrivate == undefined) {
if (Cu.isCrossProcessWrapper(aDoc)) {
@ -209,7 +208,7 @@ function saveImageURL(
aShouldBypassCache,
aFilePickerTitleKey,
null,
aReferrer,
aReferrerInfo,
aDoc,
aSkipPrompt,
null,
@ -322,7 +321,7 @@ function saveDocument(aDocument, aSkipPrompt) {
false,
null,
null,
aDocument.referrer ? makeURI(aDocument.referrer) : null,
aDocument.referrerInfo,
aDocument,
aSkipPrompt,
cacheKey
@ -378,9 +377,8 @@ XPCOMUtils.defineConstant(this, "kSaveAsType_Text", kSaveAsType_Text);
* - Determines a local target filename to use
* - Prompts the user to confirm the destination filename and save mode
* (aContentType affects this)
* - [Note] This process involves the parameters aURL, aReferrer (to determine
* how aURL was encoded), aDocument, aDefaultFileName, aFilePickerTitleKey,
* and aSkipPrompt.
* - [Note] This process involves the parameters aURL, aReferrerInfo,
* aDocument, aDefaultFileName, aFilePickerTitleKey, and aSkipPrompt.
*
* If aChosenData is non-null, this method:
* - Uses the provided source URI and save file name
@ -393,8 +391,8 @@ XPCOMUtils.defineConstant(this, "kSaveAsType_Text", kSaveAsType_Text);
* - Creates a 'Persist' object (which will perform the saving in the
* background) and then starts it.
* - [Note] This part of the process only involves the parameters aDocument,
* aShouldBypassCache and aReferrer. The source, the save name and the save
* mode are the ones determined previously.
* aShouldBypassCache and aReferrerInfo. The source, the save name and the
* save mode are the ones determined previously.
*
* @param aURL
* The String representation of the URL of the document being saved
@ -415,9 +413,8 @@ XPCOMUtils.defineConstant(this, "kSaveAsType_Text", kSaveAsType_Text);
* If non-null this contains an instance of object AutoChosen (see below)
* which holds pre-determined data so that the user does not need to be
* prompted for a target filename.
* @param aReferrer
* the referrer URI object (not URL string) to use, or null
* if no referrer should be sent.
* @param aReferrerInfo
* the referrerInfo object to use, or null if no referrer should be sent.
* @param aInitiatingDocument [optional]
* The document from which the save was initiated.
* If this is omitted then aIsContentWindowPrivate has to be provided.
@ -445,7 +442,7 @@ function internalSave(
aShouldBypassCache,
aFilePickerTitleKey,
aChosenData,
aReferrer,
aReferrerInfo,
aInitiatingDocument,
aSkipPrompt,
aCacheKey,
@ -453,7 +450,7 @@ function internalSave(
aPrincipal
) {
forbidCPOW(aURL, "internalSave", "aURL");
forbidCPOW(aReferrer, "internalSave", "aReferrer");
forbidCPOW(aReferrerInfo, "internalSave", "aReferrerInfo");
forbidCPOW(aCacheKey, "internalSave", "aCacheKey");
// Allow aInitiatingDocument to be a CPOW.
@ -503,7 +500,7 @@ function internalSave(
};
// Find a URI to use for determining last-downloaded-to directory
let relatedURI = aReferrer || sourceURI;
let relatedURI = aReferrerInfo ? aReferrerInfo.orginalReferrer : sourceURI;
promiseTargetFile(fpParams, aSkipPrompt, relatedURI)
.then(aDialogAccepted => {
@ -554,7 +551,7 @@ function internalSave(
var persistArgs = {
sourceURI,
sourcePrincipal,
sourceReferrer: aReferrer,
sourceReferrerInfo: aReferrerInfo,
sourceDocument: useSaveDocument ? aDocument : null,
targetContentType: saveAsType == kSaveAsType_Text ? "text/plain" : null,
targetFile: file,
@ -579,10 +576,10 @@ function internalSave(
* If set will be passed to savePrivacyAwareURI
* @param persistArgs.sourceDocument [optional]
* The document to be saved, or null if not saving a complete document
* @param persistArgs.sourceReferrer
* @param persistArgs.sourceReferrerInfo
* Required and used only when persistArgs.sourceDocument is NOT present,
* the nsIURI of the referrer to use, or null if no referrer should be
* sent.
* the nsIReferrerInfo of the referrer info to use, or null if no
* referrer should be sent.
* @param persistArgs.sourcePostData
* Required and used only when persistArgs.sourceDocument is NOT present,
* represents the POST data to be sent along with the HTTP request, and
@ -670,8 +667,7 @@ function internalPersist(persistArgs) {
persistArgs.sourceURI,
persistArgs.sourcePrincipal,
persistArgs.sourceCacheKey,
persistArgs.sourceReferrer,
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
persistArgs.sourceReferrerInfo,
persistArgs.sourcePostData,
null,
targetFileURL,