Bug 1067721 - [e10s] Make "Save Snapshot As" context menu item work for e10s. r=felipe.
This commit is contained in:
@@ -729,3 +729,16 @@ addEventListener("pageshow", function(event) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addMessageListener("ContextMenu:SaveVideoFrameAsImage", (message) => {
|
||||||
|
let video = message.objects.target;
|
||||||
|
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||||
|
canvas.width = video.videoWidth;
|
||||||
|
canvas.height = video.videoHeight;
|
||||||
|
|
||||||
|
let ctxDraw = canvas.getContext("2d");
|
||||||
|
ctxDraw.drawImage(video, 0, 0);
|
||||||
|
sendAsyncMessage("ContextMenu:SaveVideoFrameAsImage:Result", {
|
||||||
|
dataURL: canvas.toDataURL("image/jpeg", ""),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1037,6 +1037,7 @@ nsContextMenu.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
saveVideoFrameAsImage: function () {
|
saveVideoFrameAsImage: function () {
|
||||||
|
let mm = this.browser.messageManager;
|
||||||
let name = "";
|
let name = "";
|
||||||
if (this.mediaURL) {
|
if (this.mediaURL) {
|
||||||
try {
|
try {
|
||||||
@@ -1048,13 +1049,18 @@ nsContextMenu.prototype = {
|
|||||||
}
|
}
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "snapshot.jpg";
|
name = "snapshot.jpg";
|
||||||
var video = this.target;
|
|
||||||
var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
mm.sendAsyncMessage("ContextMenu:SaveVideoFrameAsImage", {}, {
|
||||||
canvas.width = video.videoWidth;
|
target: this.target,
|
||||||
canvas.height = video.videoHeight;
|
});
|
||||||
var ctxDraw = canvas.getContext("2d");
|
|
||||||
ctxDraw.drawImage(video, 0, 0);
|
let onMessage = (message) => {
|
||||||
saveImageURL(canvas.toDataURL("image/jpeg", ""), name, "SaveImageTitle", true, false, document.documentURIObject, this.target.ownerDocument);
|
mm.removeMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
|
||||||
|
let dataURL = message.data.dataURL;
|
||||||
|
saveImageURL(dataURL, name, "SaveImageTitle", true, false,
|
||||||
|
document.documentURIObject, this.target.ownerDocument);
|
||||||
|
};
|
||||||
|
mm.addMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
|
||||||
},
|
},
|
||||||
|
|
||||||
fullScreenVideo: function () {
|
fullScreenVideo: function () {
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ support-files =
|
|||||||
browser_star_hsts.sjs
|
browser_star_hsts.sjs
|
||||||
browser_tab_dragdrop2_frame1.xul
|
browser_tab_dragdrop2_frame1.xul
|
||||||
browser_web_channel.html
|
browser_web_channel.html
|
||||||
bug564387.html
|
|
||||||
bug564387_video1.ogv
|
|
||||||
bug564387_video1.ogv^headers^
|
|
||||||
bug592338.html
|
bug592338.html
|
||||||
bug792517-2.html
|
bug792517-2.html
|
||||||
bug792517.html
|
bug792517.html
|
||||||
@@ -82,6 +79,9 @@ support-files =
|
|||||||
test_wyciwyg_copying.html
|
test_wyciwyg_copying.html
|
||||||
title_test.svg
|
title_test.svg
|
||||||
video.ogg
|
video.ogg
|
||||||
|
web_video.html
|
||||||
|
web_video1.ogv
|
||||||
|
web_video1.ogv^headers^
|
||||||
zoom_test.html
|
zoom_test.html
|
||||||
test_no_mcb_on_http_site_img.html
|
test_no_mcb_on_http_site_img.html
|
||||||
test_no_mcb_on_http_site_img.css
|
test_no_mcb_on_http_site_img.css
|
||||||
@@ -411,6 +411,7 @@ skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates c
|
|||||||
skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
|
skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
|
||||||
[browser_save_video.js]
|
[browser_save_video.js]
|
||||||
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (event.target)
|
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test directly manipulates content (event.target)
|
||||||
|
[browser_save_video_frame.js]
|
||||||
[browser_scope.js]
|
[browser_scope.js]
|
||||||
[browser_searchSuggestionUI.js]
|
[browser_searchSuggestionUI.js]
|
||||||
skip-if = e10s
|
skip-if = e10s
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ add_task(function*() {
|
|||||||
let actionURL = makeActionURI("switchtab", {url: "about:about"}).spec;
|
let actionURL = makeActionURI("switchtab", {url: "about:about"}).spec;
|
||||||
yield check_a11y_label("% about", "about:about " + actionURL + " Tab");
|
yield check_a11y_label("% about", "about:about " + actionURL + " Tab");
|
||||||
|
|
||||||
|
gURLBar.popup.hidePopup();
|
||||||
yield promisePopupHidden(gURLBar.popup);
|
yield promisePopupHidden(gURLBar.popup);
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ function test() {
|
|||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
var fileName;
|
var fileName;
|
||||||
|
|
||||||
gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/general/bug564387.html");
|
gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/general/web_video.html");
|
||||||
|
|
||||||
gBrowser.addEventListener("pageshow", function pageShown(event) {
|
gBrowser.addEventListener("pageshow", function pageShown(event) {
|
||||||
if (event.target.location == "about:blank")
|
if (event.target.location == "about:blank")
|
||||||
@@ -66,7 +66,7 @@ function test() {
|
|||||||
function onTransferComplete(downloadSuccess) {
|
function onTransferComplete(downloadSuccess) {
|
||||||
ok(downloadSuccess, "Video file should have been downloaded successfully");
|
ok(downloadSuccess, "Video file should have been downloaded successfully");
|
||||||
|
|
||||||
is(fileName, "Bug564387-expectedName.ogv",
|
is(fileName, "web-video1-expectedName.ogv",
|
||||||
"Video file name is correctly retrieved from Content-Disposition http header");
|
"Video file name is correctly retrieved from Content-Disposition http header");
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
126
browser/base/content/test/general/browser_save_video_frame.js
Normal file
126
browser/base/content/test/general/browser_save_video_frame.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const VIDEO_URL = "http://mochi.test:8888/browser/browser/base/content/test/general/web_video.html";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mockTransfer.js provides a utility that lets us mock out
|
||||||
|
* the "Save File" dialog.
|
||||||
|
*/
|
||||||
|
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||||
|
.getService(Ci.mozIJSSubScriptLoader)
|
||||||
|
.loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
|
||||||
|
this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns an nsIFile for a new temporary save
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* @return nsIFile
|
||||||
|
*/
|
||||||
|
function createTemporarySaveDirectory() {
|
||||||
|
let saveDir = Cc["@mozilla.org/file/directory_service;1"]
|
||||||
|
.getService(Ci.nsIProperties)
|
||||||
|
.get("TmpD", Ci.nsIFile);
|
||||||
|
saveDir.append("testsavedir");
|
||||||
|
if (!saveDir.exists())
|
||||||
|
saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||||
|
return saveDir;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* MockTransfer exposes a "mockTransferCallback" global which
|
||||||
|
* allows us to define a callback to be called once the mock file
|
||||||
|
* selector has selected where to save the file.
|
||||||
|
*/
|
||||||
|
function waitForTransferComplete() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
mockTransferCallback = () => {
|
||||||
|
ok(true, "Transfer completed");
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given some browser, loads a framescript that right-clicks
|
||||||
|
* on the video1 element to spawn a contextmenu.
|
||||||
|
*/
|
||||||
|
function rightClickVideo(browser) {
|
||||||
|
let frame_script = () => {
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
|
||||||
|
let document = content.document;
|
||||||
|
let video = document.getElementById("video1");
|
||||||
|
let rect = video.getBoundingClientRect();
|
||||||
|
|
||||||
|
/* Synthesize a click in the center of the video. */
|
||||||
|
let left = rect.left + (rect.width / 2);
|
||||||
|
let top = rect.top + (rect.height / 2);
|
||||||
|
|
||||||
|
utils.sendMouseEvent("contextmenu", left, top,
|
||||||
|
2, /* aButton */
|
||||||
|
1, /* aClickCount */
|
||||||
|
0 /* aModifiers */);
|
||||||
|
};
|
||||||
|
let mm = browser.messageManager;
|
||||||
|
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a page with a <video> element, right-clicks it and chooses
|
||||||
|
* to save a frame screenshot to the disk. Completes once we've
|
||||||
|
* verified that the frame has been saved to disk.
|
||||||
|
*/
|
||||||
|
add_task(function*() {
|
||||||
|
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||||
|
MockFilePicker.init(window);
|
||||||
|
|
||||||
|
// Create the folder the video will be saved into.
|
||||||
|
let destDir = createTemporarySaveDirectory();
|
||||||
|
let destFile = destDir.clone();
|
||||||
|
|
||||||
|
MockFilePicker.displayDirectory = destDir;
|
||||||
|
MockFilePicker.showCallback = function(fp) {
|
||||||
|
destFile.append(fp.defaultString);
|
||||||
|
MockFilePicker.returnFiles = [destFile];
|
||||||
|
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
|
||||||
|
};
|
||||||
|
|
||||||
|
mockTransferRegisterer.register();
|
||||||
|
|
||||||
|
// Make sure that we clean these things up when we're done.
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
mockTransferRegisterer.unregister();
|
||||||
|
MockFilePicker.cleanup();
|
||||||
|
destDir.remove(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
let tab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedTab = tab;
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
info("Loading video tab");
|
||||||
|
yield promiseTabLoadEvent(tab, VIDEO_URL);
|
||||||
|
info("Video tab loaded.");
|
||||||
|
|
||||||
|
let video = browser.contentDocument.getElementById("video1");
|
||||||
|
let context = document.getElementById("contentAreaContextMenu");
|
||||||
|
let popupPromise = promisePopupShown(context);
|
||||||
|
|
||||||
|
info("Synthesizing right-click on video element");
|
||||||
|
rightClickVideo(browser);
|
||||||
|
info("Waiting for popup to fire popupshown.");
|
||||||
|
yield popupPromise;
|
||||||
|
info("Popup fired popupshown");
|
||||||
|
|
||||||
|
let saveSnapshotCommand = document.getElementById("context-video-saveimage");
|
||||||
|
let promiseTransfer = waitForTransferComplete()
|
||||||
|
info("Firing save snapshot command");
|
||||||
|
saveSnapshotCommand.doCommand();
|
||||||
|
context.hidePopup();
|
||||||
|
info("Waiting for transfer completion");
|
||||||
|
yield promiseTransfer;
|
||||||
|
info("Transfer complete");
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
});
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<html>
|
|
||||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=564387 -->
|
|
||||||
<head>
|
|
||||||
<title> Bug 564387 test</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
Testing for Mozilla Bug: 564387
|
|
||||||
<br>
|
|
||||||
<video src="bug564387_video1.ogv" id="video1"> </video>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
Content-Disposition: filename="Bug564387-expectedName.ogv"
|
|
||||||
Content-Type: video/ogg
|
|
||||||
|
|
||||||
@@ -744,7 +744,7 @@ function is_element_hidden(element, msg) {
|
|||||||
function promisePopupEvent(popup, eventSuffix) {
|
function promisePopupEvent(popup, eventSuffix) {
|
||||||
let endState = {shown: "open", hidden: "closed"}[eventSuffix];
|
let endState = {shown: "open", hidden: "closed"}[eventSuffix];
|
||||||
|
|
||||||
if (popup.state = endState)
|
if (popup.state == endState)
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
||||||
let eventType = "popup" + eventSuffix;
|
let eventType = "popup" + eventSuffix;
|
||||||
|
|||||||
10
browser/base/content/test/general/web_video.html
Normal file
10
browser/base/content/test/general/web_video.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Document with Web Video</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
This document has some web video in it.
|
||||||
|
<br>
|
||||||
|
<video src="web_video1.ogv" id="video1"> </video>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Content-Disposition: filename="web-video1-expectedName.ogv"
|
||||||
|
Content-Type: video/ogg
|
||||||
|
|
||||||
Reference in New Issue
Block a user