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 => {
|
this.actor.saveVideoFrameAsImage(this.targetIdentifier).then(dataURL => {
|
||||||
// FIXME can we switch this to a blob URL?
|
// FIXME can we switch this to a blob URL?
|
||||||
saveImageURL(
|
internalSave(
|
||||||
dataURL,
|
dataURL,
|
||||||
name,
|
|
||||||
"SaveImageTitle",
|
|
||||||
true, // bypass cache
|
|
||||||
false, // don't skip prompt for where to save
|
|
||||||
referrerInfo, // referrer info
|
|
||||||
null, // document
|
null, // document
|
||||||
"image/jpeg", // content type - keep in sync with ContextMenuChild!
|
name,
|
||||||
null, // content disposition
|
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,
|
isPrivate,
|
||||||
this.principal
|
this.principal
|
||||||
);
|
);
|
||||||
@@ -1610,32 +1613,38 @@ class nsContextMenu {
|
|||||||
if (this.onCanvas) {
|
if (this.onCanvas) {
|
||||||
// Bypass cache, since it's a data: URL.
|
// Bypass cache, since it's a data: URL.
|
||||||
this._canvasToBlobURL(this.targetIdentifier).then(function(blobURL) {
|
this._canvasToBlobURL(this.targetIdentifier).then(function(blobURL) {
|
||||||
saveImageURL(
|
internalSave(
|
||||||
blobURL,
|
blobURL,
|
||||||
|
null, // document
|
||||||
"canvas.png",
|
"canvas.png",
|
||||||
"SaveImageTitle",
|
null, // content disposition
|
||||||
true,
|
|
||||||
false,
|
|
||||||
referrerInfo,
|
|
||||||
null,
|
|
||||||
"image/png", // _canvasToBlobURL uses image/png by default.
|
"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,
|
isPrivate,
|
||||||
document.nodePrincipal /* system, because blob: */
|
document.nodePrincipal /* system, because blob: */
|
||||||
);
|
);
|
||||||
}, Cu.reportError);
|
}, Cu.reportError);
|
||||||
} else if (this.onImage) {
|
} else if (this.onImage) {
|
||||||
urlSecurityCheck(this.mediaURL, this.principal);
|
urlSecurityCheck(this.mediaURL, this.principal);
|
||||||
saveImageURL(
|
internalSave(
|
||||||
this.mediaURL,
|
this.mediaURL,
|
||||||
null,
|
null, // document
|
||||||
"SaveImageTitle",
|
null, // file name; we'll take it from the URL
|
||||||
false,
|
|
||||||
false,
|
|
||||||
referrerInfo,
|
|
||||||
null,
|
|
||||||
this.contentData.contentType,
|
|
||||||
this.contentData.contentDisposition,
|
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,
|
isPrivate,
|
||||||
this.principal
|
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
|
// This is like saveDocument, but takes any browser/frame-like element
|
||||||
// and saves the current document inside it,
|
// and saves the current document inside it,
|
||||||
// whether in-process or out-of-process.
|
// whether in-process or out-of-process.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
const IMAGE_PAGE =
|
const IMAGE_PAGE =
|
||||||
"https://example.com/browser/toolkit/content/tests/browser/image_page.html";
|
"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;
|
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||||
|
|
||||||
@@ -24,8 +23,7 @@ function waitForFilePicker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that saveImageURL works when we pass in the aIsContentWindowPrivate
|
* Test that internalSave works when saving an image like the context menu does.
|
||||||
* argument instead of a document. This is the preferred API.
|
|
||||||
*/
|
*/
|
||||||
add_task(async function preferred_API() {
|
add_task(async function preferred_API() {
|
||||||
await BrowserTestUtils.withNewTab(
|
await BrowserTestUtils.withNewTab(
|
||||||
@@ -40,17 +38,20 @@ add_task(async function preferred_API() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let filePickerPromise = waitForFilePicker();
|
let filePickerPromise = waitForFilePicker();
|
||||||
saveImageURL(
|
internalSave(
|
||||||
url,
|
url,
|
||||||
|
null, // document
|
||||||
"image.jpg",
|
"image.jpg",
|
||||||
null,
|
null, // content disposition
|
||||||
true,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
null,
|
true, // bypass cache
|
||||||
false,
|
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
|
gBrowser.contentPrincipal
|
||||||
);
|
);
|
||||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
|
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