Bug 1616881 - remove saveImageURL which, besides the now-dead CPOW checks, just calls internalSave, r=mconley
Differential Revision: https://phabricator.services.mozilla.com/D70684
This commit is contained in:
@@ -1302,16 +1302,19 @@ class nsContextMenu {
|
||||
|
||||
this.actor.saveVideoFrameAsImage(this.targetIdentifier).then(dataURL => {
|
||||
// FIXME can we switch this to a blob URL?
|
||||
saveImageURL(
|
||||
internalSave(
|
||||
dataURL,
|
||||
name,
|
||||
"SaveImageTitle",
|
||||
true, // bypass cache
|
||||
false, // don't skip prompt for where to save
|
||||
referrerInfo, // referrer info
|
||||
null, // document
|
||||
"image/jpeg", // content type - keep in sync with ContextMenuChild!
|
||||
name,
|
||||
null, // content disposition
|
||||
"image/jpeg", // content type - keep in sync with ContextMenuChild!
|
||||
true, // bypass cache
|
||||
"SaveImageTitle",
|
||||
null, // chosen data
|
||||
referrerInfo,
|
||||
null, // initiating doc
|
||||
false, // don't skip prompt for where to save
|
||||
null, // cache key
|
||||
isPrivate,
|
||||
this.principal
|
||||
);
|
||||
@@ -1610,32 +1613,38 @@ class nsContextMenu {
|
||||
if (this.onCanvas) {
|
||||
// Bypass cache, since it's a data: URL.
|
||||
this._canvasToBlobURL(this.targetIdentifier).then(function(blobURL) {
|
||||
saveImageURL(
|
||||
internalSave(
|
||||
blobURL,
|
||||
null, // document
|
||||
"canvas.png",
|
||||
"SaveImageTitle",
|
||||
true,
|
||||
false,
|
||||
referrerInfo,
|
||||
null,
|
||||
null, // content disposition
|
||||
"image/png", // _canvasToBlobURL uses image/png by default.
|
||||
null,
|
||||
true, // bypass cache
|
||||
"SaveImageTitle",
|
||||
null, // chosen data
|
||||
referrerInfo,
|
||||
null, // initiating doc
|
||||
false, // don't skip prompt for where to save
|
||||
null, // cache key
|
||||
isPrivate,
|
||||
document.nodePrincipal /* system, because blob: */
|
||||
);
|
||||
}, Cu.reportError);
|
||||
} else if (this.onImage) {
|
||||
urlSecurityCheck(this.mediaURL, this.principal);
|
||||
saveImageURL(
|
||||
internalSave(
|
||||
this.mediaURL,
|
||||
null,
|
||||
"SaveImageTitle",
|
||||
false,
|
||||
false,
|
||||
referrerInfo,
|
||||
null,
|
||||
this.contentData.contentType,
|
||||
null, // document
|
||||
null, // file name; we'll take it from the URL
|
||||
this.contentData.contentDisposition,
|
||||
this.contentData.contentType,
|
||||
false, // do not bypass the cache
|
||||
"SaveImageTitle",
|
||||
null, // chosen data
|
||||
referrerInfo,
|
||||
null, // initiating doc
|
||||
false, // don't skip prompt for where to save
|
||||
null, // cache key
|
||||
isPrivate,
|
||||
this.principal
|
||||
);
|
||||
|
||||
@@ -96,129 +96,6 @@ function saveURL(
|
||||
);
|
||||
}
|
||||
|
||||
// Just like saveURL, but will get some info off the image before
|
||||
// calling internalSave
|
||||
// Clientele: (Make sure you don't break any of these)
|
||||
// - Context -> Save Image As...
|
||||
const imgICache = Ci.imgICache;
|
||||
const nsISupportsCString = Ci.nsISupportsCString;
|
||||
|
||||
/**
|
||||
* Offers to save an image URL to the file system.
|
||||
*
|
||||
* @param aURL (string)
|
||||
* The URL of the image to be saved.
|
||||
* @param aFileName (string)
|
||||
* The suggested filename for the saved file.
|
||||
* @param aFilePickerTitleKey (string, optional)
|
||||
* Localized string key for an alternate title for the file
|
||||
* picker. If set to null, this will default to something sensible.
|
||||
* @param aShouldBypassCache (bool)
|
||||
* If true, the image will always be retrieved from the server instead
|
||||
* of the network or image caches.
|
||||
* @param aSkipPrompt (bool)
|
||||
* If true, we will attempt to save the file with the suggested
|
||||
* filename to the default downloads folder without showing the
|
||||
* file picker.
|
||||
* @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.
|
||||
* @param aContentType (string, optional)
|
||||
* The content type of the image.
|
||||
* @param aContentDisp (string, optional)
|
||||
* The content disposition of the image.
|
||||
* @param aIsContentWindowPrivate (bool)
|
||||
* Whether or not the containing window is in private browsing mode.
|
||||
* Does not need to be provided is aDoc is passed.
|
||||
*/
|
||||
function saveImageURL(
|
||||
aURL,
|
||||
aFileName,
|
||||
aFilePickerTitleKey,
|
||||
aShouldBypassCache,
|
||||
aSkipPrompt,
|
||||
aReferrerInfo,
|
||||
aDoc,
|
||||
aContentType,
|
||||
aContentDisp,
|
||||
aIsContentWindowPrivate,
|
||||
aPrincipal
|
||||
) {
|
||||
forbidCPOW(aURL, "saveImageURL", "aURL");
|
||||
forbidCPOW(aReferrerInfo, "saveImageURL", "aReferrerInfo");
|
||||
|
||||
if (aDoc && aIsContentWindowPrivate == undefined) {
|
||||
if (Cu.isCrossProcessWrapper(aDoc)) {
|
||||
Deprecated.warning(
|
||||
"saveImageURL should not be passed document CPOWs. " +
|
||||
"The caller should pass in the content type and " +
|
||||
"disposition themselves",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=1243643"
|
||||
);
|
||||
}
|
||||
// This will definitely not work for in-browser code or multi-process compatible
|
||||
// add-ons due to bug 1233497, which makes unsafe CPOW usage throw by default.
|
||||
Deprecated.warning(
|
||||
"saveImageURL should be passed the private state of " +
|
||||
"the containing window.",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=1243643"
|
||||
);
|
||||
aIsContentWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(
|
||||
aDoc.defaultView
|
||||
);
|
||||
}
|
||||
|
||||
// We'd better have the private state by now.
|
||||
if (aIsContentWindowPrivate == undefined) {
|
||||
throw new Error(
|
||||
"saveImageURL couldn't compute private state of content window"
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!aShouldBypassCache &&
|
||||
aDoc &&
|
||||
!Cu.isCrossProcessWrapper(aDoc) &&
|
||||
!aContentType &&
|
||||
!aContentDisp
|
||||
) {
|
||||
try {
|
||||
var imageCache = Cc["@mozilla.org/image/tools;1"]
|
||||
.getService(Ci.imgITools)
|
||||
.getImgCacheForDocument(aDoc);
|
||||
var props = imageCache.findEntryProperties(
|
||||
makeURI(aURL, getCharsetforSave(null)),
|
||||
aDoc
|
||||
);
|
||||
if (props) {
|
||||
aContentType = props.get("type", nsISupportsCString);
|
||||
aContentDisp = props.get("content-disposition", nsISupportsCString);
|
||||
}
|
||||
} catch (e) {
|
||||
// Failure to get type and content-disposition off the image is non-fatal
|
||||
}
|
||||
}
|
||||
|
||||
internalSave(
|
||||
aURL,
|
||||
null,
|
||||
aFileName,
|
||||
aContentDisp,
|
||||
aContentType,
|
||||
aShouldBypassCache,
|
||||
aFilePickerTitleKey,
|
||||
null,
|
||||
aReferrerInfo,
|
||||
aDoc,
|
||||
aSkipPrompt,
|
||||
null,
|
||||
aIsContentWindowPrivate,
|
||||
aPrincipal
|
||||
);
|
||||
}
|
||||
|
||||
// This is like saveDocument, but takes any browser/frame-like element
|
||||
// and saves the current document inside it,
|
||||
// whether in-process or out-of-process.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
const IMAGE_PAGE =
|
||||
"https://example.com/browser/toolkit/content/tests/browser/image_page.html";
|
||||
const PREF_UNSAFE_FORBIDDEN = "dom.ipc.cpows.forbid-unsafe-from-browser";
|
||||
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
|
||||
@@ -24,8 +23,7 @@ function waitForFilePicker() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that saveImageURL works when we pass in the aIsContentWindowPrivate
|
||||
* argument instead of a document. This is the preferred API.
|
||||
* Test that internalSave works when saving an image like the context menu does.
|
||||
*/
|
||||
add_task(async function preferred_API() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
@@ -40,17 +38,20 @@ add_task(async function preferred_API() {
|
||||
});
|
||||
|
||||
let filePickerPromise = waitForFilePicker();
|
||||
saveImageURL(
|
||||
internalSave(
|
||||
url,
|
||||
null, // document
|
||||
"image.jpg",
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null, // content disposition
|
||||
"image/jpeg",
|
||||
null,
|
||||
false,
|
||||
true, // bypass cache
|
||||
null, // dialog title key
|
||||
null, // chosen data
|
||||
null, // no referrer info
|
||||
null, // no document
|
||||
false, // don't skip the filename prompt
|
||||
null, // cache key
|
||||
false, // not private.
|
||||
gBrowser.contentPrincipal
|
||||
);
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
|
||||
@@ -72,60 +73,3 @@ add_task(async function preferred_API() {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that saveImageURL will still work when passed a document instead
|
||||
* of the aIsContentWindowPrivate argument. This is the deprecated API, and
|
||||
* will not work in apps using remote browsers having PREF_UNSAFE_FORBIDDEN
|
||||
* set to true.
|
||||
*/
|
||||
add_task(async function deprecated_API() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
url: IMAGE_PAGE,
|
||||
},
|
||||
async function(browser) {
|
||||
await pushPrefs([PREF_UNSAFE_FORBIDDEN, false]);
|
||||
|
||||
let url = await SpecialPowers.spawn(browser, [], async function() {
|
||||
let image = content.document.getElementById("image");
|
||||
return image.href;
|
||||
});
|
||||
|
||||
// Now get the document directly from content. If we run this test with
|
||||
// e10s-enabled, this will be a CPOW, which is forbidden. We'll just
|
||||
// pass the XUL document instead to test this interface.
|
||||
let doc = document;
|
||||
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
|
||||
let channel = docShell.currentDocumentChannel;
|
||||
if (channel) {
|
||||
todo(
|
||||
channel.QueryInterface(Ci.nsIHttpChannelInternal)
|
||||
.channelIsForDownload
|
||||
);
|
||||
|
||||
// Throttleable is the only class flag assigned to downloads.
|
||||
todo(
|
||||
channel.QueryInterface(Ci.nsIClassOfService).classFlags ==
|
||||
Ci.nsIClassOfService.Throttleable
|
||||
);
|
||||
}
|
||||
});
|
||||
let filePickerPromise = waitForFilePicker();
|
||||
saveImageURL(
|
||||
url,
|
||||
"image.jpg",
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
doc,
|
||||
"image/jpeg",
|
||||
null
|
||||
);
|
||||
await filePickerPromise;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user