Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/**
* Bug 1641270 - A test case for ensuring the save channel will use the correct
* cookieJarSettings when doing the saving and the cache would
* work as expected.
*/
"use strict";
Services.scriptloader.loadSubScript(
this
);
const TEST_IMAGE_URL = TEST_DOMAIN + TEST_PATH + "file_saveAsImage.sjs";
const TEST_VIDEO_URL = TEST_DOMAIN + TEST_PATH + "file_saveAsVideo.sjs";
const TEST_PAGEINFO_URL = TEST_DOMAIN + TEST_PATH + "file_saveAsPageInfo.html";
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window.browsingContext);
const tempDir = createTemporarySaveDirectory();
MockFilePicker.displayDirectory = tempDir;
function createTemporarySaveDirectory() {
let saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
saveDir.append("testsavedir");
saveDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
return saveDir;
}
function createPromiseForTransferComplete(aDesirableFileName) {
return new Promise(resolve => {
MockFilePicker.showCallback = fp => {
info("MockFilePicker showCallback");
let fileName = fp.defaultString;
let destFile = tempDir.clone();
destFile.append(fileName);
if (aDesirableFileName) {
is(fileName, aDesirableFileName, "The default file name is correct.");
}
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
MockFilePicker.showCallback = null;
mockTransferCallback = function (downloadSuccess) {
ok(downloadSuccess, "File should have been downloaded successfully");
mockTransferCallback = () => {};
resolve();
};
};
});
}
function createPromiseForObservingChannel(aURL, aPartitionKey) {
return new Promise(resolve => {
let observer = (aSubject, aTopic) => {
if (aTopic === "http-on-modify-request") {
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
// Make sure this is the request which we want to check.
if (!httpChannel.URI.spec.endsWith(aURL)) {
return;
}
info(`Checking loadInfo for URI: ${httpChannel.URI.spec}\n`);
is(
reqLoadInfo.cookieJarSettings.partitionKey,
aPartitionKey,
"The loadInfo has the correct partition key"
);
Services.obs.removeObserver(observer, "http-on-modify-request");
resolve();
}
};
Services.obs.addObserver(observer, "http-on-modify-request");
});
}
add_setup(async function () {
info("Setting MockFilePicker.");
mockTransferRegisterer.register();
registerCleanupFunction(function () {
mockTransferRegisterer.unregister();
MockFilePicker.cleanup();
tempDir.remove(true);
});
});
add_task(async function testContextMenuSaveImage() {
let uuidGenerator = Services.uuid;
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
],
});
// We use token to separate the caches.
let token = uuidGenerator.generateUUID().toString();
const testImageURL = `${TEST_IMAGE_URL}?token=${token}`;
info(`Open a new tab for testing "Save image as" in context menu.`);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_TOP_PAGE
);
info(`Insert the testing image into the tab.`);
await SpecialPowers.spawn(
tab.linkedBrowser,
[testImageURL],
async url => {
let img = content.document.createElement("img");
let loaded = new content.Promise(resolve => {
img.onload = resolve;
});
content.document.body.appendChild(img);
img.setAttribute("id", "image1");
img.src = url;
await loaded;
}
);
info("Open the context menu.");
let popupShownPromise = BrowserTestUtils.waitForEvent(
document,
"popupshown"
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#image1",
{
type: "contextmenu",
button: 2,
},
tab.linkedBrowser
);
await popupShownPromise;
let partitionKey = partitionPerSite
? "(http,example.net)"
: "example.net";
let transferCompletePromise = createPromiseForTransferComplete();
let observerPromise = createPromiseForObservingChannel(
testImageURL,
partitionKey
);
let saveElement = document.getElementById("context-saveimage");
info("Triggering the save process.");
saveElement.doCommand();
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
info("Close the context menu.");
let contextMenu = document.getElementById("contentAreaContextMenu");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
contextMenu.hidePopup();
await popupHiddenPromise;
// Check if there will be only one network request. The another one should
// be from cache.
let res = await fetch(`${TEST_IMAGE_URL}?token=${token}&result`);
let res_text = await res.text();
is(res_text, "1", "The image should be loaded only once.");
BrowserTestUtils.removeTab(tab);
}
}
});
add_task(async function testContextMenuSaveVideo() {
let uuidGenerator = Services.uuid;
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
],
});
// We use token to separate the caches.
let token = uuidGenerator.generateUUID().toString();
const testVideoURL = `${TEST_VIDEO_URL}?token=${token}`;
info(`Open a new tab for testing "Save Video as" in context menu.`);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_TOP_PAGE
);
info(`Insert the testing video into the tab.`);
await SpecialPowers.spawn(
tab.linkedBrowser,
[testVideoURL],
async url => {
let video = content.document.createElement("video");
let loaded = new content.Promise(resolve => {
video.onloadeddata = resolve;
});
content.document.body.appendChild(video);
video.setAttribute("id", "video1");
video.src = url;
await loaded;
}
);
info("Open the context menu.");
let popupShownPromise = BrowserTestUtils.waitForEvent(
document,
"popupshown"
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#video1",
{
type: "contextmenu",
button: 2,
},
tab.linkedBrowser
);
await popupShownPromise;
let partitionKey = partitionPerSite
? "(http,example.net)"
: "example.net";
// We also check the default file name, see Bug 1679325.
let transferCompletePromise = createPromiseForTransferComplete(
"file_saveAsVideo.webm"
);
let observerPromise = createPromiseForObservingChannel(
testVideoURL,
partitionKey
);
let saveElement = document.getElementById("context-savevideo");
info("Triggering the save process.");
saveElement.doCommand();
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
info("Close the context menu.");
let contextMenu = document.getElementById("contentAreaContextMenu");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
contextMenu.hidePopup();
await popupHiddenPromise;
// Check if there will be only one network request. The another one should
// be from cache.
let res = await fetch(`${TEST_VIDEO_URL}?token=${token}&result`);
let res_text = await res.text();
is(res_text, "1", "The video should be loaded only once.");
BrowserTestUtils.removeTab(tab);
}
}
});
add_task(async function testSavePageInOfflineMode() {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
],
});
let partitionKey = partitionPerSite
? "(http,example.net)"
: "example.net";
info(`Open a new tab which loads an image`);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_IMAGE_URL
);
info("Toggle on the offline mode");
BrowserOffline.toggleOfflineStatus();
info("Open file menu and trigger 'Save Page As'");
let menubar = document.getElementById("main-menubar");
let filePopup = document.getElementById("menu_FilePopup");
// We only use the shortcut keys to open the file menu in Windows and Linux.
// Mac doesn't have a shortcut to only open the file menu. Instead, we directly
// trigger the save in MAC without any UI interactions.
if (Services.appinfo.OS !== "Darwin") {
let menubarActive = BrowserTestUtils.waitForEvent(
menubar,
"DOMMenuBarActive"
);
EventUtils.synthesizeKey("KEY_F10");
await menubarActive;
let popupShownPromise = BrowserTestUtils.waitForEvent(
filePopup,
"popupshown"
);
// In window, it still needs one extra down key to open the file menu.
if (Services.appinfo.OS === "WINNT") {
EventUtils.synthesizeKey("KEY_ArrowDown");
}
await popupShownPromise;
}
let transferCompletePromise = createPromiseForTransferComplete();
let observerPromise = createPromiseForObservingChannel(
TEST_IMAGE_URL,
partitionKey
);
info("Triggering the save process.");
let fileSavePageAsElement = document.getElementById("menu_savePage");
fileSavePageAsElement.doCommand();
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
// Close the file menu.
if (Services.appinfo.OS !== "Darwin") {
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
filePopup,
"popuphidden"
);
filePopup.hidePopup();
await popupHiddenPromise;
}
info("Toggle off the offline mode");
BrowserOffline.toggleOfflineStatus();
// Clean up
BrowserTestUtils.removeTab(tab);
// Clean up the cache count on the server side.
await fetch(`${TEST_IMAGE_URL}?result`);
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
}
}
});
add_task(async function testPageInfoMediaSaveAs() {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
],
});
let partitionKey = partitionPerSite
? "(http,example.net)"
: "example.net";
info(
`Open a new tab for testing "Save AS" in the media panel of the page info.`
);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_PAGEINFO_URL
);
info("Open the media panel of the pageinfo.");
let pageInfo = BrowserCommands.pageInfo(
gBrowser.selectedBrowser.currentURI.spec,
"mediaTab"
);
await BrowserTestUtils.waitForEvent(pageInfo, "page-info-init");
let imageTree = pageInfo.document.getElementById("imagetree");
let imageRowsNum = imageTree.view.rowCount;
is(imageRowsNum, 2, "There should be two media items here.");
for (let i = 0; i < imageRowsNum; i++) {
imageTree.view.selection.select(i);
imageTree.ensureRowIsVisible(i);
imageTree.focus();
// Wait until the preview is loaded.
let preview = pageInfo.document.getElementById("thepreviewimage");
let mediaType = pageInfo.gImageView.data[i][1]; // COL_IMAGE_TYPE
if (mediaType == "Image") {
await BrowserTestUtils.waitForEvent(preview, "load");
} else if (mediaType == "Video") {
await BrowserTestUtils.waitForEvent(preview, "canplaythrough");
}
let url = pageInfo.gImageView.data[i][0]; // COL_IMAGE_ADDRESS
info(`Start to save the media item with URL: ${url}`);
let transferCompletePromise = createPromiseForTransferComplete();
// Observe the channel and check if it has the correct partitionKey.
let observerPromise = createPromiseForObservingChannel(
url,
partitionKey
);
info("Triggering the save process.");
let saveElement = pageInfo.document.getElementById("imagesaveasbutton");
saveElement.doCommand();
info("Waiting for the channel.");
await observerPromise;
info("Wait until the save is finished.");
await transferCompletePromise;
}
pageInfo.close();
BrowserTestUtils.removeTab(tab);
}
}
});
add_task(async function testPageInfoMediaMultipleSelectedSaveAs() {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
],
});
let partitionKey = partitionPerSite
? "(http,example.net)"
: "example.net";
info(
`Open a new tab for testing "Save AS" in the media panel of the page info.`
);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_PAGEINFO_URL
);
info("Open the media panel of the pageinfo.");
let pageInfo = BrowserCommands.pageInfo(
gBrowser.selectedBrowser.currentURI.spec,
"mediaTab"
);
await BrowserTestUtils.waitForEvent(pageInfo, "page-info-init");
// Make sure the preview image is loaded in order to avoid interfering
// following tests.
let preview = pageInfo.document.getElementById("thepreviewimage");
await BrowserTestUtils.waitForCondition(() => {
return preview.complete;
});
let imageTree = pageInfo.document.getElementById("imagetree");
let imageRowsNum = imageTree.view.rowCount;
is(imageRowsNum, 2, "There should be two media items here.");
imageTree.view.selection.selectAll();
imageTree.focus();
let url = pageInfo.gImageView.data[0][0]; // COL_IMAGE_ADDRESS
info(`Start to save the media item with URL: ${url}`);
let transferCompletePromise = createPromiseForTransferComplete();
let observerPromises = [];
// Observe all channels and check if they have the correct partitionKey.
for (let i = 0; i < imageRowsNum; ++i) {
let observerPromise = createPromiseForObservingChannel(
url,
partitionKey
);
observerPromises.push(observerPromise);
}
info("Triggering the save process.");
let saveElement = pageInfo.document.getElementById("imagesaveasbutton");
saveElement.doCommand();
info("Waiting for the all channels.");
await Promise.all(observerPromises);
info("Wait until the save is finished.");
await transferCompletePromise;
pageInfo.close();
BrowserTestUtils.removeTab(tab);
}
}
});