Bug 1243305 - Only share images whose src length is not too long. r=margaret
If the src is too long, we crash!
To test this, you can use my test page:
https://people.mozilla.org/~mcomella/test/base64.html
An alternative approach would be to prevent users from sharing base64
images altogether because the experience is slightly jarring (since the
base64 string is copied to the application rather than the image).
MozReview-Commit-ID: AQeQ0Ff6ZMB
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -854,17 +854,17 @@ var BrowserApp = {
UITelemetry.addEvent("action.1", "contextmenu", null, "web_copy_image");
let url = aTarget.src;
NativeWindow.contextmenus._copyStringToDefaultClipboard(url);
});
NativeWindow.contextmenus.add({
label: stringGetter("contextmenu.shareImage"),
- selector: NativeWindow.contextmenus._disableRestricted("SHARE", NativeWindow.contextmenus.imageSaveableContext),
+ selector: NativeWindow.contextmenus._disableRestricted("SHARE", NativeWindow.contextmenus.imageShareableContext),
order: NativeWindow.contextmenus.DEFAULT_HTML5_ORDER - 1, // Show above HTML5 menu items
showAsActions: function(aTarget) {
let doc = aTarget.ownerDocument;
let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
.getImgCacheForDocument(doc);
let props = imageCache.findEntryProperties(aTarget.currentURI, doc);
let src = aTarget.src;
return {
@@ -2434,16 +2434,40 @@ var NativeWindow = {
// The image must be loaded to allow saving
let request = aElement.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
return (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE));
}
return false;
}
},
+ imageShareableContext: {
+ matches: function imageShareableContextMatches(aElement) {
+ let imgSrc = '';
+ if (aElement instanceof Ci.nsIDOMHTMLImageElement) {
+ imgSrc = aElement.src;
+ } else if (aElement instanceof Ci.nsIImageLoadingContent &&
+ aElement.currentURI &&
+ aElement.currentURI.spec) {
+ imgSrc = aElement.currentURI.spec;
+ }
+
+ // In order to share an image, we need to pass the image src over IPC via an Intent (in
+ // `ApplicationPackageManager.queryIntentActivities`). However, the transaction has a 1MB limit
+ // (shared by all transactions in progress) - otherwise we crash! (bug 1243305)
+ // https://developer.android.com/reference/android/os/TransactionTooLargeException.html
+ //
+ // The transaction limit is 1MB and we arbitrarily choose to cap this transaction at 1/4 of that = 250,000 bytes.
+ // In Java, a UTF-8 character is 1-4 bytes so, 250,000 bytes / 4 bytes/char = 62,500 char
+ let MAX_IMG_SRC_LEN = 62500;
+ let isTooLong = imgSrc.length >= MAX_IMG_SRC_LEN;
+ return !isTooLong && this.NativeWindow.contextmenus.imageSaveableContext.matches(aElement);
+ }.bind(this)
+ },
+
mediaSaveableContext: {
matches: function mediaSaveableContextMatches(aElement) {
return (aElement instanceof HTMLVideoElement ||
aElement instanceof HTMLAudioElement);
}
},
imageBlockingPolicyContext: {