Bug 1200524 - Use Blob URLs instead of Data URLs for saving media from the content process. r?felipe
Data URLs were fine for smaller pieces of media, but for large media, we'd quickly
max out the message size limit, and that'd result in a failure to even show the
save dialog.
With Blob URLs, we can refer to large media using a unique identifier that
is easy to pass around, and works from content to parent process.
MozReview-Commit-ID: Gooi1YIqrEM
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -41,16 +41,18 @@ XPCOMUtils.defineLazyModuleGetter(this,
XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
let tmp = {};
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
return new tmp.PageMenuChild();
});
XPCOMUtils.defineLazyModuleGetter(this, "Feeds",
"resource:///modules/Feeds.jsm");
+Cu.importGlobalProperties(["URL"]);
+
// TabChildGlobal
var global = this;
// Load the form validation popup handler
var formSubmitObserver = new FormSubmitObserver(content, this);
addMessageListener("ContextMenu:DoCustomCommand", function(message) {
E10SUtils.wrapHandlingUserInput(
@@ -787,19 +789,21 @@ addMessageListener("ContextMenu:MediaCom
break;
case "fullscreen":
if (content.document.fullscreenEnabled)
media.requestFullscreen();
break;
}
});
-addMessageListener("ContextMenu:Canvas:ToDataURL", (message) => {
- let dataURL = message.objects.target.toDataURL();
- sendAsyncMessage("ContextMenu:Canvas:ToDataURL:Result", { dataURL });
+addMessageListener("ContextMenu:Canvas:ToBlobURL", (message) => {
+ message.objects.target.toBlob((blob) => {
+ let blobURL = URL.createObjectURL(blob);
+ sendAsyncMessage("ContextMenu:Canvas:ToBlobURL:Result", { blobURL });
+ });
});
addMessageListener("ContextMenu:ReloadFrame", (message) => {
message.objects.target.ownerDocument.location.reload();
});
addMessageListener("ContextMenu:ReloadImage", (message) => {
let image = message.objects.target;
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1135,35 +1135,35 @@ nsContextMenu.prototype = {
urlSecurityCheck(this.mediaURL,
this.browser.contentPrincipal,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
this.browser.messageManager.sendAsyncMessage("ContextMenu:ReloadImage",
null, { target: this.target });
},
- _canvasToDataURL: function(target) {
+ _canvasToBlobURL: function(target) {
let mm = this.browser.messageManager;
return new Promise(function(resolve) {
- mm.sendAsyncMessage("ContextMenu:Canvas:ToDataURL", {}, { target });
+ mm.sendAsyncMessage("ContextMenu:Canvas:ToBlobURL", {}, { target });
let onMessage = (message) => {
- mm.removeMessageListener("ContextMenu:Canvas:ToDataURL:Result", onMessage);
- resolve(message.data.dataURL);
+ mm.removeMessageListener("ContextMenu:Canvas:ToBlobURL:Result", onMessage);
+ resolve(message.data.blobURL);
};
- mm.addMessageListener("ContextMenu:Canvas:ToDataURL:Result", onMessage);
+ mm.addMessageListener("ContextMenu:Canvas:ToBlobURL:Result", onMessage);
});
},
// Change current window to the URL of the image, video, or audio.
viewMedia: function(e) {
let referrerURI = gContextMenuContentData.documentURIObject;
if (this.onCanvas) {
- this._canvasToDataURL(this.target).then(function(dataURL) {
- openUILink(dataURL, e, { disallowInheritPrincipal: true,
+ this._canvasToBlobURL(this.target).then(function(blobURL) {
+ openUILink(blobURL, e, { disallowInheritPrincipal: true,
referrerURI: referrerURI });
}, Cu.reportError);
}
else {
urlSecurityCheck(this.mediaURL,
this.browser.contentPrincipal,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
openUILink(this.mediaURL, e, { disallowInheritPrincipal: true,
@@ -1430,18 +1430,18 @@ nsContextMenu.prototype = {
// Save URL of the clicked upon image, video, or audio.
saveMedia: function() {
let doc = this.ownerDoc;
let referrerURI = gContextMenuContentData.documentURIObject;
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
if (this.onCanvas) {
// Bypass cache, since it's a data: URL.
- this._canvasToDataURL(this.target).then(function(dataURL) {
- saveImageURL(dataURL, "canvas.png", "SaveImageTitle",
+ this._canvasToBlobURL(this.target).then(function(blobURL) {
+ saveImageURL(blobURL, "canvas.png", "SaveImageTitle",
true, false, referrerURI, null, null, null,
isPrivate);
}, Cu.reportError);
}
else if (this.onImage) {
urlSecurityCheck(this.mediaURL, this.principal);
saveImageURL(this.mediaURL, null, "SaveImageTitle", false,
false, referrerURI, null, gContextMenuContentData.contentType,