Remove browser tests - Part 1: The Tests (except for experiments)

This commit is contained in:
NTD 2018-02-03 06:00:38 -05:00 • committed by Roy Tam
commit 261374f310
1697 changed files with 0 additions and 144364 deletions

View file

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../testing/mochitest/browser.eslintrc.js"
]
};

View file

@ -1,42 +0,0 @@
[DEFAULT]
support-files =
head.js
[browser_BrowserUITelemetry_buckets.js]
[browser_BrowserUITelemetry_defaults.js]
[browser_BrowserUITelemetry_sidebar.js]
[browser_BrowserUITelemetry_syncedtabs.js]
[browser_ContentSearch.js]
skip-if = true # Bug 1308343
support-files =
contentSearch.js
contentSearchBadImage.xml
contentSearchSuggestions.sjs
contentSearchSuggestions.xml
!/browser/components/search/test/head.js
!/browser/components/search/test/testEngine.xml
[browser_NetworkPrioritizer.js]
[browser_PermissionUI.js]
[browser_ProcessHangNotifications.js]
skip-if = !e10s
[browser_SelfSupportBackend.js]
support-files =
../../components/uitour/test/uitour.html
../../components/uitour/UITour-lib.js
[browser_taskbar_preview.js]
skip-if = os != "win"
[browser_UnsubmittedCrashHandler.js]
run-if = crashreporter
[browser_UsageTelemetry.js]
[browser_UsageTelemetry_private_and_restore.js]
[browser_UsageTelemetry_urlbar.js]
support-files =
usageTelemetrySearchSuggestions.sjs
usageTelemetrySearchSuggestions.xml
[browser_UsageTelemetry_searchbar.js]
support-files =
usageTelemetrySearchSuggestions.sjs
usageTelemetrySearchSuggestions.xml
[browser_UsageTelemetry_content.js]
[browser_UsageTelemetry_content_aboutHome.js]
[browser_urlBar_zoom.js]

View file

@ -1,97 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
WHERE'S MAH BUCKET?!
\
___
.-9 9 `\
=(:(::)= ;
|||| \
|||| `-.
,\|\| `,
/ \
; `'---.,
| `\
; / |
\ | /
) \ __,.--\ /
.-' \,..._\ \` .-' .-'
`-=`` `: | /-/-/`
`.__/
*/
"use strict";
add_task(function* testBUIT() {
let s = {};
Components.utils.import("resource:///modules/BrowserUITelemetry.jsm", s);
let BUIT = s.BrowserUITelemetry;
registerCleanupFunction(function() {
BUIT.setBucket(null);
});
// setBucket
is(BUIT.currentBucket, BUIT.BUCKET_DEFAULT, "Bucket should be default bucket");
BUIT.setBucket("mah-bucket");
is(BUIT.currentBucket, BUIT.BUCKET_PREFIX + "mah-bucket", "Bucket should have correct name");
BUIT.setBucket(null);
is(BUIT.currentBucket, BUIT.BUCKET_DEFAULT, "Bucket should be reset to default");
// _toTimeStr
is(BUIT._toTimeStr(10), "10ms", "Checking time string reprentation, 10ms");
is(BUIT._toTimeStr(1000 + 10), "1s10ms", "Checking time string reprentation, 1s10ms");
is(BUIT._toTimeStr((20 * 1000) + 10), "20s10ms", "Checking time string reprentation, 20s10ms");
is(BUIT._toTimeStr(60 * 1000), "1m", "Checking time string reprentation, 1m");
is(BUIT._toTimeStr(3 * 60 * 1000), "3m", "Checking time string reprentation, 3m");
is(BUIT._toTimeStr((3 * 60 * 1000) + 1), "3m1ms", "Checking time string reprentation, 3m1ms");
is(BUIT._toTimeStr((60 * 60 * 1000) + (10 * 60 * 1000)), "1h10m", "Checking time string reprentation, 1h10m");
is(BUIT._toTimeStr(100 * 60 * 60 * 1000), "100h", "Checking time string reprentation, 100h");
// setExpiringBucket
BUIT.setExpiringBucket("walrus", [1001, 2001, 3001, 10001]);
is(BUIT.currentBucket, BUIT.BUCKET_PREFIX + "walrus" + BUIT.BUCKET_SEPARATOR + "1s1ms",
"Bucket should be expiring and have time step of 1s1ms");
yield waitForConditionPromise(function() {
return BUIT.currentBucket == (BUIT.BUCKET_PREFIX + "walrus" + BUIT.BUCKET_SEPARATOR + "2s1ms");
}, "Bucket should be expiring and have time step of 2s1ms");
yield waitForConditionPromise(function() {
return BUIT.currentBucket == (BUIT.BUCKET_PREFIX + "walrus" + BUIT.BUCKET_SEPARATOR + "3s1ms");
}, "Bucket should be expiring and have time step of 3s1ms");
// Interupt previous expiring bucket
BUIT.setExpiringBucket("walrus2", [1002, 2002]);
is(BUIT.currentBucket, BUIT.BUCKET_PREFIX + "walrus2" + BUIT.BUCKET_SEPARATOR + "1s2ms",
"Should be new expiring bucket, with time step of 1s2ms");
yield waitForConditionPromise(function() {
return BUIT.currentBucket == (BUIT.BUCKET_PREFIX + "walrus2" + BUIT.BUCKET_SEPARATOR + "2s2ms");
}, "Should be new expiring bucket, with time step of 2s2ms");
// Let expiring bucket expire
yield waitForConditionPromise(function() {
return BUIT.currentBucket == BUIT.BUCKET_DEFAULT;
}, "Bucket should have expired, default bucket should now be active");
// Interupt expiring bucket with normal bucket
BUIT.setExpiringBucket("walrus3", [1003, 2003]);
is(BUIT.currentBucket, BUIT.BUCKET_PREFIX + "walrus3" + BUIT.BUCKET_SEPARATOR + "1s3ms",
"Should be new expiring bucket, with time step of 1s3ms");
BUIT.setBucket("mah-bucket");
is(BUIT.currentBucket, BUIT.BUCKET_PREFIX + "mah-bucket", "Bucket should have correct name");
yield waitForConditionPromise(function() {
return BUIT.currentBucket == (BUIT.BUCKET_PREFIX + "mah-bucket");
}, "Next step of old expiring bucket shouldn't have progressed");
});

View file

@ -1,37 +0,0 @@
// The purpose of this test is to ensure that by default, BrowserUITelemetry
// isn't reporting any UI customizations. This is primarily so changes to
// customizableUI (eg, new buttons, button location changes) also have a
// corresponding BrowserUITelemetry change.
function test() {
let s = {};
Cu.import("resource:///modules/CustomizableUI.jsm", s);
Cu.import("resource:///modules/BrowserUITelemetry.jsm", s);
let { CustomizableUI, BrowserUITelemetry } = s;
// Bug 1278176 - DevEdition never has the UI in a default state by default.
if (!AppConstants.MOZ_DEV_EDITION) {
Assert.ok(CustomizableUI.inDefaultState,
"No other test should have left CUI in a dirty state.");
}
let result = BrowserUITelemetry._getWindowMeasurements(window, 0);
// Bug 1278176 - DevEdition always reports the developer-button is moved.
if (!AppConstants.MOZ_DEV_EDITION) {
Assert.deepEqual(result.defaultMoved, []);
}
Assert.deepEqual(result.nondefaultAdded, []);
// This one is a bit weird - the "social-share-button" is dynamically added
// to the toolbar as the feature is first used - but it's listed as being in
// the toolbar by default so it doesn't end up in nondefaultAdded once it
// is created. The end result is that it ends up in defaultRemoved before
// the feature has been activated.
// Bug 1273358 exists to fix this.
Assert.deepEqual(result.defaultRemoved, ["social-share-button"]);
// And mochi insists there's only a single window with a single tab when
// starting a test, so check that for good measure.
Assert.deepEqual(result.visibleTabs, [1]);
}

View file

@ -1,56 +0,0 @@
// Test the sidebar counters in BrowserUITelemetry.
"use strict";
const { BrowserUITelemetry: BUIT } = Cu.import("resource:///modules/BrowserUITelemetry.jsm", {});
add_task(function* testSidebarOpenClose() {
// Reset BrowserUITelemetry's world.
BUIT._countableEvents = {};
yield SidebarUI.show("viewTabsSidebar");
let counts = BUIT._countableEvents[BUIT.currentBucket];
Assert.deepEqual(counts, { sidebar: { viewTabsSidebar: { show: 1 } } });
yield SidebarUI.hide();
Assert.deepEqual(counts, { sidebar: { viewTabsSidebar: { show: 1, hide: 1 } } });
yield SidebarUI.show("viewBookmarksSidebar");
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 1, hide: 1 },
viewBookmarksSidebar: { show: 1 },
}
});
// Re-open the tabs sidebar while bookmarks is open - bookmarks should
// record a close.
yield SidebarUI.show("viewTabsSidebar");
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 2, hide: 1 },
viewBookmarksSidebar: { show: 1, hide: 1 },
}
});
yield SidebarUI.hide();
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 2, hide: 2 },
viewBookmarksSidebar: { show: 1, hide: 1 },
}
});
// Toggle - this will re-open viewTabsSidebar
yield SidebarUI.toggle("viewTabsSidebar");
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 3, hide: 2 },
viewBookmarksSidebar: { show: 1, hide: 1 },
}
});
yield SidebarUI.toggle("viewTabsSidebar");
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 3, hide: 3 },
viewBookmarksSidebar: { show: 1, hide: 1 },
}
});
});

View file

@ -1,114 +0,0 @@
// Test the SyncedTabs counters in BrowserUITelemetry.
"use strict";
const { BrowserUITelemetry: BUIT } = Cu.import("resource:///modules/BrowserUITelemetry.jsm", {});
const {SyncedTabs} = Cu.import("resource://services-sync/SyncedTabs.jsm", {});
function mockSyncedTabs() {
// Mock SyncedTabs.jsm
let mockedInternal = {
get isConfiguredToSyncTabs() { return true; },
getTabClients() {
return Promise.resolve([
{
id: "guid_desktop",
type: "client",
name: "My Desktop",
tabs: [
{
title: "http://example.com/10",
lastUsed: 10, // the most recent
},
],
}
]);
},
syncTabs() {
return Promise.resolve();
},
hasSyncedThisSession: true,
};
let oldInternal = SyncedTabs._internal;
SyncedTabs._internal = mockedInternal;
// configure our broadcasters so we are in the right state.
document.getElementById("sync-reauth-state").hidden = true;
document.getElementById("sync-setup-state").hidden = true;
document.getElementById("sync-syncnow-state").hidden = false;
registerCleanupFunction(() => {
SyncedTabs._internal = oldInternal;
document.getElementById("sync-reauth-state").hidden = true;
document.getElementById("sync-setup-state").hidden = false;
document.getElementById("sync-syncnow-state").hidden = true;
});
}
mockSyncedTabs();
function promiseTabsUpdated() {
return new Promise(resolve => {
Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) {
Services.obs.removeObserver(onNotification, aTopic);
resolve();
}, "synced-tabs-menu:test:tabs-updated", false);
});
}
add_task(function* test_menu() {
// Reset BrowserUITelemetry's world.
BUIT._countableEvents = {};
let tabsUpdated = promiseTabsUpdated();
// check the button's functionality
yield PanelUI.show();
let syncButton = document.getElementById("sync-button");
syncButton.click();
yield tabsUpdated;
// Get our 1 tab and click on it.
let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
let tabEntry = tabList.firstChild.nextSibling;
tabEntry.click();
let counts = BUIT._countableEvents[BUIT.currentBucket];
Assert.deepEqual(counts, {
"click-builtin-item": { "sync-button": { left: 1 } },
"synced-tabs": { open: { "toolbarbutton-subview": 1 } },
});
});
add_task(function* test_sidebar() {
// Reset BrowserUITelemetry's world.
BUIT._countableEvents = {};
yield SidebarUI.show('viewTabsSidebar');
let syncedTabsDeckComponent = SidebarUI.browser.contentWindow.syncedTabsDeckComponent;
syncedTabsDeckComponent._accountStatus = () => Promise.resolve(true);
// Once the tabs container has been selected (which here means "'selected'
// added to the class list") we are ready to test.
let container = SidebarUI.browser.contentDocument.querySelector(".tabs-container");
let promiseUpdated = BrowserTestUtils.waitForAttribute("class", container);
yield syncedTabsDeckComponent.updatePanel();
yield promiseUpdated;
let selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected");
let tab = selectedPanel.querySelector(".tab");
tab.click();
let counts = BUIT._countableEvents[BUIT.currentBucket];
Assert.deepEqual(counts, {
sidebar: {
viewTabsSidebar: { show: 1 },
},
"synced-tabs": { open: { sidebar: 1 } }
});
yield SidebarUI.hide();
});

View file

@ -1,425 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const TEST_MSG = "ContentSearchTest";
const CONTENT_SEARCH_MSG = "ContentSearch";
const TEST_CONTENT_SCRIPT_BASENAME = "contentSearch.js";
// This timeout is absurdly high to avoid random failures like bug 1087120.
// That bug was reported when the timeout was 5 seconds, so let's try 10.
const SUGGESTIONS_TIMEOUT = 10000;
var gMsgMan;
/* eslint no-undef:"error" */
/* import-globals-from ../../components/search/test/head.js */
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/browser/components/search/test/head.js",
this);
let originalEngine = Services.search.currentEngine;
add_task(function* setup() {
yield promiseNewEngine("testEngine.xml", {
setAsCurrent: true,
testPath: "chrome://mochitests/content/browser/browser/components/search/test/",
});
registerCleanupFunction(() => {
Services.search.currentEngine = originalEngine;
});
});
add_task(function* GetState() {
yield addTab();
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "GetState",
});
let msg = yield waitForTestMsg("State");
checkMsg(msg, {
type: "State",
data: yield currentStateObj(),
});
});
add_task(function* SetCurrentEngine() {
yield addTab();
let newCurrentEngine = null;
let oldCurrentEngine = Services.search.currentEngine;
let engines = Services.search.getVisibleEngines();
for (let engine of engines) {
if (engine != oldCurrentEngine) {
newCurrentEngine = engine;
break;
}
}
if (!newCurrentEngine) {
info("Couldn't find a non-selected search engine, " +
"skipping this part of the test");
return;
}
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "SetCurrentEngine",
data: newCurrentEngine.name,
});
let deferred = Promise.defer();
Services.obs.addObserver(function obs(subj, topic, data) {
info("Test observed " + data);
if (data == "engine-current") {
ok(true, "Test observed engine-current");
Services.obs.removeObserver(obs, "browser-search-engine-modified");
deferred.resolve();
}
}, "browser-search-engine-modified", false);
let searchPromise = waitForTestMsg("CurrentEngine");
info("Waiting for test to observe engine-current...");
yield deferred.promise;
let msg = yield searchPromise;
checkMsg(msg, {
type: "CurrentEngine",
data: yield currentEngineObj(newCurrentEngine),
});
Services.search.currentEngine = oldCurrentEngine;
msg = yield waitForTestMsg("CurrentEngine");
checkMsg(msg, {
type: "CurrentEngine",
data: yield currentEngineObj(oldCurrentEngine),
});
});
add_task(function* modifyEngine() {
yield addTab();
let engine = Services.search.currentEngine;
let oldAlias = engine.alias;
engine.alias = "ContentSearchTest";
let msg = yield waitForTestMsg("CurrentState");
checkMsg(msg, {
type: "CurrentState",
data: yield currentStateObj(),
});
engine.alias = oldAlias;
msg = yield waitForTestMsg("CurrentState");
checkMsg(msg, {
type: "CurrentState",
data: yield currentStateObj(),
});
});
add_task(function* search() {
yield addTab();
let engine = Services.search.currentEngine;
let data = {
engineName: engine.name,
searchString: "ContentSearchTest",
healthReportKey: "ContentSearchTest",
searchPurpose: "ContentSearchTest",
};
let submissionURL =
engine.getSubmission(data.searchString, "", data.whence).uri.spec;
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "Search",
data: data,
expectedURL: submissionURL,
});
let msg = yield waitForTestMsg("loadStopped");
Assert.equal(msg.data.url, submissionURL, "Correct search page loaded");
});
add_task(function* searchInBackgroundTab() {
// This test is like search(), but it opens a new tab after starting a search
// in another. In other words, it performs a search in a background tab. The
// search page should be loaded in the same tab that performed the search, in
// the background tab.
yield addTab();
let engine = Services.search.currentEngine;
let data = {
engineName: engine.name,
searchString: "ContentSearchTest",
healthReportKey: "ContentSearchTest",
searchPurpose: "ContentSearchTest",
};
let submissionURL =
engine.getSubmission(data.searchString, "", data.whence).uri.spec;
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "Search",
data: data,
expectedURL: submissionURL,
});
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
registerCleanupFunction(() => gBrowser.removeTab(newTab));
let msg = yield waitForTestMsg("loadStopped");
Assert.equal(msg.data.url, submissionURL, "Correct search page loaded");
});
add_task(function* badImage() {
yield addTab();
// If the bad image URI caused an exception to be thrown within ContentSearch,
// then we'll hang waiting for the CurrentState responses triggered by the new
// engine. That's what we're testing, and obviously it shouldn't happen.
let vals = yield waitForNewEngine("contentSearchBadImage.xml", 1);
let engine = vals[0];
let finalCurrentStateMsg = vals[vals.length - 1];
let expectedCurrentState = yield currentStateObj();
let expectedEngine =
expectedCurrentState.engines.find(e => e.name == engine.name);
ok(!!expectedEngine, "Sanity check: engine should be in expected state");
ok(expectedEngine.iconBuffer === null,
"Sanity check: icon array buffer of engine in expected state " +
"should be null: " + expectedEngine.iconBuffer);
checkMsg(finalCurrentStateMsg, {
type: "CurrentState",
data: expectedCurrentState,
});
// Removing the engine triggers a final CurrentState message. Wait for it so
// it doesn't trip up subsequent tests.
Services.search.removeEngine(engine);
yield waitForTestMsg("CurrentState");
});
add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
yield addTab();
// Add the test engine that provides suggestions.
let vals = yield waitForNewEngine("contentSearchSuggestions.xml", 0);
let engine = vals[0];
let searchStr = "browser_ContentSearch.js-suggestions-";
// Add a form history suggestion and wait for Satchel to notify about it.
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "AddFormHistoryEntry",
data: searchStr + "form",
});
let deferred = Promise.defer();
Services.obs.addObserver(function onAdd(subj, topic, data) {
if (data == "formhistory-add") {
Services.obs.removeObserver(onAdd, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);
yield deferred.promise;
// Send GetSuggestions using the test engine. Its suggestions should appear
// in the remote suggestions in the Suggestions response below.
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "GetSuggestions",
data: {
engineName: engine.name,
searchString: searchStr,
remoteTimeout: SUGGESTIONS_TIMEOUT,
},
});
// Check the Suggestions response.
let msg = yield waitForTestMsg("Suggestions");
checkMsg(msg, {
type: "Suggestions",
data: {
engineName: engine.name,
searchString: searchStr,
formHistory: [searchStr + "form"],
remote: [searchStr + "foo", searchStr + "bar"],
},
});
// Delete the form history suggestion and wait for Satchel to notify about it.
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "RemoveFormHistoryEntry",
data: searchStr + "form",
});
deferred = Promise.defer();
Services.obs.addObserver(function onRemove(subj, topic, data) {
if (data == "formhistory-remove") {
Services.obs.removeObserver(onRemove, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);
yield deferred.promise;
// Send GetSuggestions again.
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "GetSuggestions",
data: {
engineName: engine.name,
searchString: searchStr,
remoteTimeout: SUGGESTIONS_TIMEOUT,
},
});
// The formHistory suggestions in the Suggestions response should be empty.
msg = yield waitForTestMsg("Suggestions");
checkMsg(msg, {
type: "Suggestions",
data: {
engineName: engine.name,
searchString: searchStr,
formHistory: [],
remote: [searchStr + "foo", searchStr + "bar"],
},
});
// Finally, clean up by removing the test engine.
Services.search.removeEngine(engine);
yield waitForTestMsg("CurrentState");
});
function buffersEqual(actualArrayBuffer, expectedArrayBuffer) {
let expectedView = new Int8Array(expectedArrayBuffer);
let actualView = new Int8Array(actualArrayBuffer);
for (let i = 0; i < expectedView.length; i++) {
if (actualView[i] != expectedView[i]) {
return false;
}
}
return true;
}
function arrayBufferEqual(actualArrayBuffer, expectedArrayBuffer) {
ok(actualArrayBuffer instanceof ArrayBuffer, "Actual value is ArrayBuffer.");
ok(expectedArrayBuffer instanceof ArrayBuffer, "Expected value is ArrayBuffer.");
Assert.equal(actualArrayBuffer.byteLength, expectedArrayBuffer.byteLength,
"Array buffers have the same length.");
ok(buffersEqual(actualArrayBuffer, expectedArrayBuffer), "Buffers are equal.");
}
function checkArrayBuffers(actual, expected) {
if (actual instanceof ArrayBuffer) {
arrayBufferEqual(actual, expected);
}
if (typeof actual == "object") {
for (let i in actual) {
checkArrayBuffers(actual[i], expected[i]);
}
}
}
function checkMsg(actualMsg, expectedMsgData) {
let actualMsgData = actualMsg.data;
SimpleTest.isDeeply(actualMsg.data, expectedMsgData, "Checking message");
// Engines contain ArrayBuffers which we have to compare byte by byte and
// not as Objects (like SimpleTest.isDeeply does).
checkArrayBuffers(actualMsgData, expectedMsgData);
}
function waitForMsg(name, type) {
let deferred = Promise.defer();
info("Waiting for " + name + " message " + type + "...");
gMsgMan.addMessageListener(name, function onMsg(msg) {
info("Received " + name + " message " + msg.data.type + "\n");
if (msg.data.type == type) {
gMsgMan.removeMessageListener(name, onMsg);
deferred.resolve(msg);
}
});
return deferred.promise;
}
function waitForTestMsg(type) {
return waitForMsg(TEST_MSG, type);
}
function waitForNewEngine(basename, numImages) {
info("Waiting for engine to be added: " + basename);
// Wait for the search events triggered by adding the new engine.
// engine-added engine-loaded
let expectedSearchEvents = ["CurrentState", "CurrentState"];
// engine-changed for each of the images
for (let i = 0; i < numImages; i++) {
expectedSearchEvents.push("CurrentState");
}
let eventPromises = expectedSearchEvents.map(e => waitForTestMsg(e));
// Wait for addEngine().
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, null, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
addDeferred.resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
addDeferred.reject();
},
});
return Promise.all([addDeferred.promise].concat(eventPromises));
}
function addTab() {
let deferred = Promise.defer();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
tab.linkedBrowser.addEventListener("load", function load() {
tab.linkedBrowser.removeEventListener("load", load, true);
let url = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME;
gMsgMan = tab.linkedBrowser.messageManager;
gMsgMan.sendAsyncMessage(CONTENT_SEARCH_MSG, {
type: "AddToWhitelist",
data: ["about:blank"],
});
waitForMsg(CONTENT_SEARCH_MSG, "AddToWhitelistAck").then(() => {
gMsgMan.loadFrameScript(url, false);
deferred.resolve();
});
}, true);
registerCleanupFunction(() => gBrowser.removeTab(tab));
return deferred.promise;
}
var currentStateObj = Task.async(function* () {
let state = {
engines: [],
currentEngine: yield currentEngineObj(),
};
for (let engine of Services.search.getVisibleEngines()) {
let uri = engine.getIconURLBySize(16, 16);
state.engines.push({
name: engine.name,
iconBuffer: yield arrayBufferFromDataURI(uri),
hidden: false,
});
}
return state;
});
var currentEngineObj = Task.async(function* () {
let engine = Services.search.currentEngine;
let uriFavicon = engine.getIconURLBySize(16, 16);
let bundle = Services.strings.createBundle("chrome://global/locale/autocomplete.properties");
return {
name: engine.name,
placeholder: bundle.formatStringFromName("searchWithEngine", [engine.name], 1),
iconBuffer: yield arrayBufferFromDataURI(uriFavicon),
};
});
function arrayBufferFromDataURI(uri) {
if (!uri) {
return Promise.resolve(null);
}
let deferred = Promise.defer();
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", uri, true);
xhr.responseType = "arraybuffer";
xhr.onerror = () => {
deferred.resolve(null);
};
xhr.onload = () => {
deferred.resolve(xhr.response);
};
try {
xhr.send();
}
catch (err) {
return Promise.resolve(null);
}
return deferred.promise;
}

View file

@ -1,165 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** Tests for NetworkPrioritizer.jsm (Bug 514490) **/
const LOWEST = Ci.nsISupportsPriority.PRIORITY_LOWEST;
const LOW = Ci.nsISupportsPriority.PRIORITY_LOW;
const NORMAL = Ci.nsISupportsPriority.PRIORITY_NORMAL;
const HIGH = Ci.nsISupportsPriority.PRIORITY_HIGH;
const HIGHEST = Ci.nsISupportsPriority.PRIORITY_HIGHEST;
const DELTA = NORMAL - LOW; // lower value means higher priority
// Test helper functions.
// getPriority and setPriority can take a tab or a Browser
function* getPriority(aBrowser) {
if (aBrowser.localName == "tab")
aBrowser = aBrowser.linkedBrowser;
return yield ContentTask.spawn(aBrowser, null, function* () {
return docShell.QueryInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocumentLoader)
.loadGroup
.QueryInterface(Components.interfaces.nsISupportsPriority)
.priority;
});
}
function* setPriority(aBrowser, aPriority) {
if (aBrowser.localName == "tab")
aBrowser = aBrowser.linkedBrowser;
yield ContentTask.spawn(aBrowser, aPriority, function* (aPriority) {
docShell.QueryInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocumentLoader)
.loadGroup
.QueryInterface(Ci.nsISupportsPriority)
.priority = aPriority;
});
}
function* isWindowState(aWindow, aTabPriorities) {
let browsers = aWindow.gBrowser.browsers;
// Make sure we have the right number of tabs & priorities
is(browsers.length, aTabPriorities.length,
"Window has expected number of tabs");
// aState should be in format [ priority, priority, priority ]
for (let i = 0; i < browsers.length; i++) {
is(yield getPriority(browsers[i]), aTabPriorities[i],
"Tab " + i + " had expected priority");
}
}
function promiseWaitForFocus(aWindow) {
return new Promise((resolve) => {
waitForFocus(resolve, aWindow);
});
}
add_task(function*() {
// This is the real test. It creates multiple tabs & windows, changes focus,
// closes windows/tabs to make sure we behave correctly.
// This test assumes that no priorities have been adjusted and the loadgroup
// priority starts at 0.
// Call window "window_A" to make the test easier to follow
let window_A = window;
// Test 1 window, 1 tab case.
yield isWindowState(window_A, [HIGH]);
// Exising tab is tab_A1
let tab_A2 = window_A.gBrowser.addTab("http://example.com");
let tab_A3 = window_A.gBrowser.addTab("about:config");
yield BrowserTestUtils.browserLoaded(tab_A3.linkedBrowser);
// tab_A2 isn't focused yet
yield isWindowState(window_A, [HIGH, NORMAL, NORMAL]);
// focus tab_A2 & make sure priority got updated
window_A.gBrowser.selectedTab = tab_A2;
yield isWindowState(window_A, [NORMAL, HIGH, NORMAL]);
window_A.gBrowser.removeTab(tab_A2);
// Next tab is auto selected synchronously as part of removeTab, and we
// expect the priority to be updated immediately.
yield isWindowState(window_A, [NORMAL, HIGH]);
// Open another window then play with focus
let window_B = yield BrowserTestUtils.openNewBrowserWindow();
yield promiseWaitForFocus(window_B);
yield isWindowState(window_A, [LOW, NORMAL]);
yield isWindowState(window_B, [HIGH]);
yield promiseWaitForFocus(window_A);
yield isWindowState(window_A, [NORMAL, HIGH]);
yield isWindowState(window_B, [NORMAL]);
yield promiseWaitForFocus(window_B);
yield isWindowState(window_A, [LOW, NORMAL]);
yield isWindowState(window_B, [HIGH]);
// Cleanup
window_A.gBrowser.removeTab(tab_A3);
yield BrowserTestUtils.closeWindow(window_B);
});
add_task(function*() {
// This is more a test of nsLoadGroup and how it handles priorities. But since
// we depend on its behavior, it's good to test it. This is testing that there
// are no errors if we adjust beyond nsISupportsPriority's bounds.
yield promiseWaitForFocus();
let tab1 = gBrowser.tabs[0];
let oldPriority = yield getPriority(tab1);
// Set the priority of tab1 to the lowest possible. Selecting the other tab
// will try to lower it
yield setPriority(tab1, LOWEST);
let tab2 = gBrowser.addTab("http://example.com");
yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
gBrowser.selectedTab = tab2;
is(yield getPriority(tab1), LOWEST - DELTA, "Can adjust priority beyond 'lowest'");
// Now set priority to "highest" and make sure that no errors occur.
yield setPriority(tab1, HIGHEST);
gBrowser.selectedTab = tab1;
is(yield getPriority(tab1), HIGHEST + DELTA, "Can adjust priority beyond 'highest'");
// Cleanup
gBrowser.removeTab(tab2);
yield setPriority(tab1, oldPriority);
});
add_task(function*() {
// This tests that the priority doesn't get lost when switching the browser's remoteness
if (!gMultiProcessBrowser) {
return;
}
let browser = gBrowser.selectedBrowser;
browser.loadURI("http://example.com");
yield BrowserTestUtils.browserLoaded(browser);
ok(browser.isRemoteBrowser, "web page should be loaded in remote browser");
is(yield getPriority(browser), HIGH, "priority of selected tab should be 'high'");
browser.loadURI("about:rights");
yield BrowserTestUtils.browserLoaded(browser);
ok(!browser.isRemoteBrowser, "about:rights should switch browser to non-remote");
is(yield getPriority(browser), HIGH,
"priority of selected tab should be 'high' when going from remote to non-remote");
browser.loadURI("http://example.com");
yield BrowserTestUtils.browserLoaded(browser);
ok(browser.isRemoteBrowser, "going from about:rights to web page should switch browser to remote");
is(yield getPriority(browser), HIGH,
"priority of selected tab should be 'high' when going from non-remote to remote");
});

View file

@ -1,445 +0,0 @@
/**
* These tests test the ability for the PermissionUI module to open
* permission prompts to the user. It also tests to ensure that
* add-ons can introduce their own permission prompts.
*/
"use strict";
Cu.import("resource://gre/modules/Integration.jsm", this);
Cu.import("resource:///modules/PermissionUI.jsm", this);
/**
* Given a <xul:browser> at some non-internal web page,
* return something that resembles an nsIContentPermissionRequest,
* using the browsers currently loaded document to get a principal.
*
* @param browser (<xul:browser>)
* The browser that we'll create a nsIContentPermissionRequest
* for.
* @returns A nsIContentPermissionRequest-ish object.
*/
function makeMockPermissionRequest(browser) {
let result = {
types: null,
principal: browser.contentPrincipal,
requester: null,
_cancelled: false,
cancel() {
this._cancelled = true;
},
_allowed: false,
allow() {
this._allowed = true;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
};
// In the e10s-case, nsIContentPermissionRequest will have
// element defined. window is defined otherwise.
if (browser.isRemoteBrowser) {
result.element = browser;
} else {
result.window = browser.contentWindow;
}
return result;
}
/**
* For an opened PopupNotification, clicks on the main action,
* and waits for the panel to fully close.
*
* @return {Promise}
* Resolves once the panel has fired the "popuphidden"
* event.
*/
function clickMainAction() {
let removePromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
let popupNotification = getPopupNotificationNode();
popupNotification.button.click();
return removePromise;
}
/**
* For an opened PopupNotification, clicks on a secondary action,
* and waits for the panel to fully close.
*
* @param {int} index
* The 0-indexed index of the secondary menuitem to choose.
* @return {Promise}
* Resolves once the panel has fired the "popuphidden"
* event.
*/
function clickSecondaryAction(index) {
let removePromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
let popupNotification = getPopupNotificationNode();
let menuitems = popupNotification.children;
menuitems[index].click();
return removePromise;
}
/**
* Makes sure that 1 (and only 1) <xul:popupnotification> is being displayed
* by PopupNotification, and then returns that <xul:popupnotification>.
*
* @return {<xul:popupnotification>}
*/
function getPopupNotificationNode() {
// PopupNotification is a bit overloaded here, so to be
// clear, popupNotifications is a list of <xul:popupnotification>
// nodes.
let popupNotifications = PopupNotifications.panel.childNodes;
Assert.equal(popupNotifications.length, 1,
"Should be showing a <xul:popupnotification>");
return popupNotifications[0];
}
/**
* Tests the PermissionPromptForRequest prototype to ensure that a prompt
* can be displayed. Does not test permission handling.
*/
add_task(function* test_permission_prompt_for_request() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com/",
}, function*(browser) {
const kTestNotificationID = "test-notification";
const kTestMessage = "Test message";
let mainAction = {
label: "Main",
accessKey: "M",
};
let secondaryAction = {
label: "Secondary",
accessKey: "S",
};
let mockRequest = makeMockPermissionRequest(browser);
let TestPrompt = {
__proto__: PermissionUI.PermissionPromptForRequestPrototype,
request: mockRequest,
notificationID: kTestNotificationID,
message: kTestMessage,
promptActions: [mainAction, secondaryAction],
};
let shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
yield shownPromise;
let notification =
PopupNotifications.getNotification(kTestNotificationID, browser);
Assert.ok(notification, "Should have gotten the notification");
Assert.equal(notification.message, kTestMessage,
"Should be showing the right message");
Assert.equal(notification.mainAction.label, mainAction.label,
"The main action should have the right label");
Assert.equal(notification.mainAction.accessKey, mainAction.accessKey,
"The main action should have the right access key");
Assert.equal(notification.secondaryActions.length, 1,
"There should only be 1 secondary action");
Assert.equal(notification.secondaryActions[0].label, secondaryAction.label,
"The secondary action should have the right label");
Assert.equal(notification.secondaryActions[0].accessKey,
secondaryAction.accessKey,
"The secondary action should have the right access key");
Assert.ok(notification.options.displayURI.equals(mockRequest.principal.URI),
"Should be showing the URI of the requesting page");
let removePromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
notification.remove();
yield removePromise;
});
});
/**
* Tests that if the PermissionPrompt sets displayURI to false in popupOptions,
* then there is no URI shown on the popupnotification.
*/
add_task(function* test_permission_prompt_for_popupOptions() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com/",
}, function*(browser) {
const kTestNotificationID = "test-notification";
const kTestMessage = "Test message";
let mainAction = {
label: "Main",
accessKey: "M",
};
let secondaryAction = {
label: "Secondary",
accessKey: "S",
};
let mockRequest = makeMockPermissionRequest(browser);
let TestPrompt = {
__proto__: PermissionUI.PermissionPromptForRequestPrototype,
request: mockRequest,
notificationID: kTestNotificationID,
message: kTestMessage,
promptActions: [mainAction, secondaryAction],
popupOptions: {
displayURI: false,
},
};
let shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
yield shownPromise;
let notification =
PopupNotifications.getNotification(kTestNotificationID, browser);
Assert.ok(!notification.options.displayURI,
"Should not show the URI of the requesting page");
let removePromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
notification.remove();
yield removePromise;
});
});
/**
* Tests that if the PermissionPrompt has the permissionKey
* set that permissions can be set properly by the user. Also
* ensures that callbacks for promptActions are properly fired.
*/
add_task(function* test_with_permission_key() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com",
}, function*(browser) {
const kTestNotificationID = "test-notification";
const kTestMessage = "Test message";
const kTestPermissionKey = "test-permission-key";
let allowed = false;
let mainAction = {
label: "Allow",
accessKey: "M",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expiryType: Ci.nsIPermissionManager.EXPIRE_SESSION,
callback: function() {
allowed = true;
}
};
let denied = false;
let secondaryAction = {
label: "Deny",
accessKey: "D",
action: Ci.nsIPermissionManager.DENY_ACTION,
expiryType: Ci.nsIPermissionManager.EXPIRE_SESSION,
callback: function() {
denied = true;
}
};
let mockRequest = makeMockPermissionRequest(browser);
let principal = mockRequest.principal;
registerCleanupFunction(function() {
Services.perms.removeFromPrincipal(principal, kTestPermissionKey);
});
let TestPrompt = {
__proto__: PermissionUI.PermissionPromptForRequestPrototype,
request: mockRequest,
notificationID: kTestNotificationID,
permissionKey: kTestPermissionKey,
message: kTestMessage,
promptActions: [mainAction, secondaryAction],
};
let shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
yield shownPromise;
let notification =
PopupNotifications.getNotification(kTestNotificationID, browser);
Assert.ok(notification, "Should have gotten the notification");
let curPerm =
Services.perms.testPermissionFromPrincipal(principal,
kTestPermissionKey);
Assert.equal(curPerm, Ci.nsIPermissionManager.UNKNOWN_ACTION,
"Should be no permission set to begin with.");
// First test denying the permission request.
Assert.equal(notification.secondaryActions.length, 1,
"There should only be 1 secondary action");
yield clickSecondaryAction(0);
curPerm = Services.perms.testPermissionFromPrincipal(principal,
kTestPermissionKey);
Assert.equal(curPerm, Ci.nsIPermissionManager.DENY_ACTION,
"Should have denied the action");
Assert.ok(denied, "The secondaryAction callback should have fired");
Assert.ok(!allowed, "The mainAction callback should not have fired");
Assert.ok(mockRequest._cancelled,
"The request should have been cancelled");
Assert.ok(!mockRequest._allowed,
"The request should not have been allowed");
// Clear the permission and pretend we never denied
Services.perms.removeFromPrincipal(principal, kTestPermissionKey);
denied = false;
mockRequest._cancelled = false;
// Bring the PopupNotification back up now...
shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
yield shownPromise;
// Next test allowing the permission request.
yield clickMainAction();
curPerm = Services.perms.testPermissionFromPrincipal(principal,
kTestPermissionKey);
Assert.equal(curPerm, Ci.nsIPermissionManager.ALLOW_ACTION,
"Should have allowed the action");
Assert.ok(!denied, "The secondaryAction callback should not have fired");
Assert.ok(allowed, "The mainAction callback should have fired");
Assert.ok(!mockRequest._cancelled,
"The request should not have been cancelled");
Assert.ok(mockRequest._allowed,
"The request should have been allowed");
});
});
/**
* Tests that the onBeforeShow method will be called before
* the popup appears.
*/
add_task(function* test_on_before_show() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com",
}, function*(browser) {
const kTestNotificationID = "test-notification";
const kTestMessage = "Test message";
let mainAction = {
label: "Test action",
accessKey: "T",
};
let mockRequest = makeMockPermissionRequest(browser);
let beforeShown = false;
let TestPrompt = {
__proto__: PermissionUI.PermissionPromptForRequestPrototype,
request: mockRequest,
notificationID: kTestNotificationID,
message: kTestMessage,
promptActions: [mainAction],
onBeforeShow() {
beforeShown = true;
}
};
let shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
Assert.ok(beforeShown, "Should have called onBeforeShown");
yield shownPromise;
let notification =
PopupNotifications.getNotification(kTestNotificationID, browser);
let removePromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
notification.remove();
yield removePromise;
});
});
/**
* Tests that we can open a PermissionPrompt without wrapping a
* nsIContentPermissionRequest.
*/
add_task(function* test_no_request() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com",
}, function*(browser) {
const kTestNotificationID = "test-notification";
let allowed = false;
let mainAction = {
label: "Allow",
accessKey: "M",
callback: function() {
allowed = true;
}
};
let denied = false;
let secondaryAction = {
label: "Deny",
accessKey: "D",
callback: function() {
denied = true;
}
};
const kTestMessage = "Test message with no request";
let principal = browser.contentPrincipal;
let beforeShown = false;
let TestPrompt = {
__proto__: PermissionUI.PermissionPromptPrototype,
notificationID: kTestNotificationID,
principal,
browser,
message: kTestMessage,
promptActions: [mainAction, secondaryAction],
onBeforeShow() {
beforeShown = true;
}
};
let shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
Assert.ok(beforeShown, "Should have called onBeforeShown");
yield shownPromise;
let notification =
PopupNotifications.getNotification(kTestNotificationID, browser);
Assert.equal(notification.message, kTestMessage,
"Should be showing the right message");
Assert.equal(notification.mainAction.label, mainAction.label,
"The main action should have the right label");
Assert.equal(notification.mainAction.accessKey, mainAction.accessKey,
"The main action should have the right access key");
Assert.equal(notification.secondaryActions.length, 1,
"There should only be 1 secondary action");
Assert.equal(notification.secondaryActions[0].label, secondaryAction.label,
"The secondary action should have the right label");
Assert.equal(notification.secondaryActions[0].accessKey,
secondaryAction.accessKey,
"The secondary action should have the right access key");
Assert.ok(notification.options.displayURI.equals(principal.URI),
"Should be showing the URI of the requesting page");
// First test denying the permission request.
Assert.equal(notification.secondaryActions.length, 1,
"There should only be 1 secondary action");
yield clickSecondaryAction(0);
Assert.ok(denied, "The secondaryAction callback should have fired");
Assert.ok(!allowed, "The mainAction callback should not have fired");
shownPromise =
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
TestPrompt.prompt();
yield shownPromise;
// Next test allowing the permission request.
yield clickMainAction();
Assert.ok(allowed, "The mainAction callback should have fired");
});
});

View file

@ -1,189 +0,0 @@
Cu.import("resource://gre/modules/UpdateUtils.jsm");
function getNotificationBox(aWindow) {
return aWindow.document.getElementById("high-priority-global-notificationbox");
}
function promiseNotificationShown(aWindow, aName) {
return new Promise((resolve) => {
let notification = getNotificationBox(aWindow);
notification.addEventListener("AlertActive", function active() {
notification.removeEventListener("AlertActive", active, true);
is(notification.allNotifications.length, 1, "Notification Displayed.");
resolve(notification);
});
});
}
function promiseReportCallMade(aValue) {
return new Promise((resolve) => {
let old = gTestHangReport.testCallback;
gTestHangReport.testCallback = function (val) {
gTestHangReport.testCallback = old;
is(aValue, val, "was the correct method call made on the hang report object?");
resolve();
};
});
}
function pushPrefs(...aPrefs) {
return new Promise((resolve) => {
SpecialPowers.pushPrefEnv({"set": aPrefs}, resolve);
resolve();
});
}
function popPrefs() {
return new Promise((resolve) => {
SpecialPowers.popPrefEnv(resolve);
resolve();
});
}
let gTestHangReport = {
SLOW_SCRIPT: 1,
PLUGIN_HANG: 2,
TEST_CALLBACK_CANCELED: 1,
TEST_CALLBACK_TERMSCRIPT: 2,
TEST_CALLBACK_TERMPLUGIN: 3,
_hangType: 1,
_tcb: function (aCallbackType) {},
get hangType() {
return this._hangType;
},
set hangType(aValue) {
this._hangType = aValue;
},
set testCallback(aValue) {
this._tcb = aValue;
},
QueryInterface: function (aIID) {
if (aIID.equals(Components.interfaces.nsIHangReport) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
userCanceled: function () {
this._tcb(this.TEST_CALLBACK_CANCELED);
},
terminateScript: function () {
this._tcb(this.TEST_CALLBACK_TERMSCRIPT);
},
terminatePlugin: function () {
this._tcb(this.TEST_CALLBACK_TERMPLUGIN);
},
isReportForBrowser: function(aFrameLoader) {
return true;
}
};
// on dev edition we add a button for js debugging of hung scripts.
let buttonCount = (UpdateUtils.UpdateChannel == "aurora" ? 3 : 2);
/**
* Test if hang reports receive a terminate script callback when the user selects
* stop in response to a script hang.
*/
add_task(function* terminateScriptTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
// Fails on aurora on-push builds, bug 1232204
// is(buttons.length, buttonCount, "proper number of buttons");
// Click the "Stop It" button, we should get a terminate script callback
gTestHangReport.hangType = gTestHangReport.SLOW_SCRIPT;
promise = promiseReportCallMade(gTestHangReport.TEST_CALLBACK_TERMSCRIPT);
buttons[0].click();
yield promise;
});
/**
* Test if hang reports receive user canceled callbacks after a user selects wait
* and the browser frees up from a script hang on its own.
*/
add_task(function* waitForScriptTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
// Fails on aurora on-push builds, bug 1232204
// is(buttons.length, buttonCount, "proper number of buttons");
yield pushPrefs(["browser.hangNotification.waitPeriod", 1000]);
function nocbcheck() {
ok(false, "received a callback?");
}
let oldcb = gTestHangReport.testCallback;
gTestHangReport.testCallback = nocbcheck;
// Click the "Wait" button this time, we shouldn't get a callback at all.
buttons[1].click();
gTestHangReport.testCallback = oldcb;
// send another hang pulse, we should not get a notification here
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
is(notification.currentNotification, null, "no notification should be visible");
gTestHangReport.testCallback = function() {};
Services.obs.notifyObservers(gTestHangReport, "clear-hang-report", null);
gTestHangReport.testCallback = oldcb;
yield popPrefs();
});
/**
* Test if hang reports receive user canceled callbacks after the content
* process stops sending hang notifications.
*/
add_task(function* hangGoesAwayTest() {
yield pushPrefs(["browser.hangNotification.expiration", 1000]);
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
yield promise;
promise = promiseReportCallMade(gTestHangReport.TEST_CALLBACK_CANCELED);
Services.obs.notifyObservers(gTestHangReport, "clear-hang-report", null);
yield promise;
yield popPrefs();
});
/**
* Tests if hang reports receive a terminate plugin callback when the user selects
* stop in response to a plugin hang.
*/
add_task(function* terminatePluginTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
// Fails on aurora on-push builds, bug 1232204
// is(buttons.length, buttonCount, "proper number of buttons");
// Click the "Stop It" button, we should get a terminate script callback
gTestHangReport.hangType = gTestHangReport.PLUGIN_HANG;
promise = promiseReportCallMade(gTestHangReport.TEST_CALLBACK_TERMPLUGIN);
buttons[0].click();
yield promise;
});

View file

@ -1,214 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Pass an empty scope object to the import to prevent "leaked window property"
// errors in tests.
var Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
var PromiseUtils = Cu.import("resource://gre/modules/PromiseUtils.jsm", {}).PromiseUtils;
var SelfSupportBackend =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackend;
const PREF_SELFSUPPORT_ENABLED = "browser.selfsupport.enabled";
const PREF_SELFSUPPORT_URL = "browser.selfsupport.url";
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";
const TEST_WAIT_RETRIES = 60;
const TEST_PAGE_URL = getRootDirectory(gTestPath) + "uitour.html";
const TEST_PAGE_URL_HTTPS = TEST_PAGE_URL.replace("chrome://mochitests/content/", "https://example.com/");
function sendSessionRestoredNotification() {
let selfSupportBackendImpl =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
selfSupportBackendImpl.observe(null, "sessionstore-windows-restored", null);
}
/**
* Find a browser, with an IFRAME as parent, who has aURL as the source attribute.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Object} The browser element or null on failure.
*/
function findSelfSupportBrowser(aURL) {
let frames = Services.appShell.hiddenDOMWindow.document.querySelectorAll('iframe');
for (let frame of frames) {
try {
let browser = frame.contentDocument.getElementById("win").querySelectorAll('browser')[0];
let url = browser.getAttribute("src");
if (url == aURL) {
return browser;
}
} catch (e) {
continue;
}
}
return null;
}
/**
* Wait for self support page to load.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Promise} Return a promise which is resolved when SelfSupport page is fully
* loaded.
*/
function promiseSelfSupportLoad(aURL) {
return new Promise((resolve, reject) => {
// Find the SelfSupport browser.
let browserPromise = waitForConditionPromise(() => !!findSelfSupportBrowser(aURL),
"SelfSupport browser not found.",
TEST_WAIT_RETRIES);
// Once found, append a "load" listener to catch page loads.
browserPromise.then(() => {
let browser = findSelfSupportBrowser(aURL);
if (browser.contentDocument.readyState === "complete") {
resolve(browser);
} else {
let handler = () => {
browser.removeEventListener("load", handler, true);
resolve(browser);
};
browser.addEventListener("load", handler, true);
}
}, reject);
});
}
/**
* Wait for self support to close.
*
* @param aURL The URL to look for to identify the browser.
*
* @returns {Promise} Return a promise which is resolved when SelfSupport browser cannot
* be found anymore.
*/
function promiseSelfSupportClose(aURL) {
return waitForConditionPromise(() => !findSelfSupportBrowser(aURL),
"SelfSupport browser is still open.", TEST_WAIT_RETRIES);
}
/**
* Prepare the test environment.
*/
add_task(function* setupEnvironment() {
// We always run the SelfSupportBackend in tests to check for weird behaviours.
// Disable it to test its start-up.
SelfSupportBackend.uninit();
// Testing prefs are set via |user_pref|, so we need to get their value in order
// to restore them.
let selfSupportEnabled = Preferences.get(PREF_SELFSUPPORT_ENABLED, true);
let uitourEnabled = Preferences.get(PREF_UITOUR_ENABLED, false);
let selfSupportURL = Preferences.get(PREF_SELFSUPPORT_URL, "");
// Enable the SelfSupport backend and set the page URL. We also make sure UITour
// is enabled.
Preferences.set(PREF_SELFSUPPORT_ENABLED, true);
Preferences.set(PREF_UITOUR_ENABLED, true);
Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL_HTTPS);
// Whitelist the HTTPS page to use UITour.
let pageURI = Services.io.newURI(TEST_PAGE_URL_HTTPS, null, null);
Services.perms.add(pageURI, "uitour", Services.perms.ALLOW_ACTION);
registerCleanupFunction(() => {
Services.perms.remove(pageURI, "uitour");
Preferences.set(PREF_SELFSUPPORT_ENABLED, selfSupportEnabled);
Preferences.set(PREF_UITOUR_ENABLED, uitourEnabled);
Preferences.set(PREF_SELFSUPPORT_URL, selfSupportURL);
});
});
/**
* Test that the self support page can use the UITour API and close itself.
*/
add_task(function* test_selfSupport() {
// Initialise the SelfSupport backend and trigger the load.
SelfSupportBackend.init();
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
sendSessionRestoredNotification();
// Wait for the SelfSupport page to load.
info("Waiting for the SelfSupport local page to load.");
let selfSupportBrowser = yield promiseSelfSupportLoad(TEST_PAGE_URL_HTTPS);
Assert.ok(!!selfSupportBrowser, "SelfSupport browser must exist.");
// Get a reference to the UITour API.
info("Testing access to the UITour API.");
let contentWindow =
Cu.waiveXrays(selfSupportBrowser.contentDocument.defaultView);
let uitourAPI = contentWindow.Mozilla.UITour;
// Test the UITour API with a ping.
let pingPromise = new Promise((resolve) => {
uitourAPI.ping(resolve);
});
yield pingPromise;
info("Ping succeeded");
let observePromise = ContentTask.spawn(selfSupportBrowser, null, function* checkObserve() {
yield new Promise(resolve => {
let win = Cu.waiveXrays(content);
win.Mozilla.UITour.observe((event, data) => {
if (event != "Heartbeat:Engaged") {
return;
}
Assert.equal(data.flowId, "myFlowID", "Check flowId");
Assert.ok(!!data.timestamp, "Check timestamp");
resolve(data);
}, () => {});
});
});
info("Notifying Heartbeat:Engaged");
UITour.notify("Heartbeat:Engaged", {
flowId: "myFlowID",
timestamp: Date.now(),
});
yield observePromise;
info("Observed in the hidden frame");
// Close SelfSupport from content.
contentWindow.close();
// Wait until SelfSupport closes.
info("Waiting for the SelfSupport to close.");
yield promiseSelfSupportClose(TEST_PAGE_URL_HTTPS);
// Find the SelfSupport browser, again. We don't expect to find it.
selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL_HTTPS);
Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
// doesn't create any problem.
SelfSupportBackend.uninit();
});
/**
* Test that SelfSupportBackend only allows HTTPS.
*/
add_task(function* test_selfSupport_noHTTPS() {
Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL);
SelfSupportBackend.init();
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
sendSessionRestoredNotification();
// Find the SelfSupport browser. We don't expect to find it since we are not using https.
let selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL);
Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
// doesn't create any problem.
SelfSupportBackend.uninit();
})

View file

@ -1,680 +0,0 @@
"use strict";
/**
* This suite tests the "unsubmitted crash report" notification
* that is seen when we detect pending crash reports on startup.
*/
const { UnsubmittedCrashHandler } =
Cu.import("resource:///modules/ContentCrashHandlers.jsm", this);
const { FileUtils } =
Cu.import("resource://gre/modules/FileUtils.jsm", this);
const { makeFakeAppDir } =
Cu.import("resource://testing-common/AppData.jsm", this);
const { OS } =
Cu.import("resource://gre/modules/osfile.jsm", this);
const DAY = 24 * 60 * 60 * 1000; // milliseconds
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
/**
* Returns the directly where the browsing is storing the
* pending crash reports.
*
* @returns nsIFile
*/
function getPendingCrashReportDir() {
// The fake UAppData directory that makeFakeAppDir provides
// is just UAppData under the profile directory.
return FileUtils.getDir("ProfD", [
"UAppData",
"Crash Reports",
"pending",
], false);
}
/**
* Synchronously deletes all entries inside the pending
* crash report directory.
*/
function clearPendingCrashReports() {
let dir = getPendingCrashReportDir();
let entries = dir.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
if (entry.isFile()) {
entry.remove(false);
}
}
}
/**
* Randomly generates howMany crash report .dmp and .extra files
* to put into the pending crash report directory. We're not
* actually creating real crash reports here, just stubbing
* out enough of the files to satisfy our notification and
* submission code.
*
* @param howMany (int)
* How many pending crash reports to put in the pending
* crash report directory.
* @param accessDate (Date, optional)
* What date to set as the last accessed time on the created
* crash reports. This defaults to the current date and time.
* @returns Promise
*/
function* createPendingCrashReports(howMany, accessDate) {
let dir = getPendingCrashReportDir();
if (!accessDate) {
accessDate = new Date();
}
/**
* Helper function for creating a file in the pending crash report
* directory.
*
* @param fileName (string)
* The filename for the crash report, not including the
* extension. This is usually a UUID.
* @param extension (string)
* The file extension for the created file.
* @param accessDate (Date)
* The date to set lastAccessed to.
* @param contents (string, optional)
* Set this to whatever the file needs to contain, if anything.
* @returns Promise
*/
let createFile = (fileName, extension, accessDate, contents) => {
let file = dir.clone();
file.append(fileName + "." + extension);
file.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
let promises = [OS.File.setDates(file.path, accessDate)];
if (contents) {
let encoder = new TextEncoder();
let array = encoder.encode(contents);
promises.push(OS.File.writeAtomic(file.path, array, {
tmpPath: file.path + ".tmp",
}));
}
return Promise.all(promises);
}
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
// CrashSubmit expects there to be a ServerURL key-value
// pair in the .extra file, so we'll satisfy it.
let extraFileContents = "ServerURL=" + SERVER_URL;
return Task.spawn(function*() {
let uuids = [];
for (let i = 0; i < howMany; ++i) {
let uuid = uuidGenerator.generateUUID().toString();
// Strip the {}...
uuid = uuid.substring(1, uuid.length - 1);
yield createFile(uuid, "dmp", accessDate);
yield createFile(uuid, "extra", accessDate, extraFileContents);
uuids.push(uuid);
}
return uuids;
});
}
/**
* Returns a Promise that resolves once CrashSubmit starts sending
* success notifications for crash submission matching the reportIDs
* being passed in.
*
* @param reportIDs (Array<string>)
* The IDs for the reports that we expect CrashSubmit to have sent.
* @returns Promise
*/
function waitForSubmittedReports(reportIDs) {
let promises = [];
for (let reportID of reportIDs) {
let promise = TestUtils.topicObserved("crash-report-status", (subject, data) => {
if (data == "success") {
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
let dumpID = propBag.getPropertyAsAString("minidumpID");
if (dumpID == reportID) {
return true;
}
}
return false;
});
promises.push(promise);
}
return Promise.all(promises);
}
/**
* Returns a Promise that resolves once a .dmp.ignore file is created for
* the crashes in the pending directory matching the reportIDs being
* passed in.
*
* @param reportIDs (Array<string>)
* The IDs for the reports that we expect CrashSubmit to have been
* marked for ignoring.
* @returns Promise
*/
function waitForIgnoredReports(reportIDs) {
let dir = getPendingCrashReportDir();
let promises = [];
for (let reportID of reportIDs) {
let file = dir.clone();
file.append(reportID + ".dmp.ignore");
promises.push(OS.File.exists(file.path));
}
return Promise.all(promises);
}
let gNotificationBox;
add_task(function* setup() {
// Pending crash reports are stored in the UAppData folder,
// which exists outside of the profile folder. In order to
// not overwrite / clear pending crash reports for the poor
// soul who runs this test, we use AppData.jsm to point to
// a special made-up directory inside the profile
// directory.
yield makeFakeAppDir();
// We'll assume that the notifications will be shown in the current
// browser window's global notification box.
gNotificationBox = document.getElementById("global-notificationbox");
// If we happen to already be seeing the unsent crash report
// notification, it's because the developer running this test
// happened to have some unsent reports in their UAppDir.
// We'll remove the notification without touching those reports.
let notification =
gNotificationBox.getNotificationWithValue("pending-crash-reports");
if (notification) {
notification.close();
}
let env = Cc["@mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment);
let oldServerURL = env.get("MOZ_CRASHREPORTER_URL");
env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
// nsBrowserGlue starts up UnsubmittedCrashHandler automatically
// so at this point, it is initialized. It's possible that it
// was initialized, but is preffed off, so it's inert, so we
// shut it down, make sure it's preffed on, and then restart it.
// Note that making the component initialize even when it's
// disabled is an intentional choice, as this allows for easier
// simulation of startup and shutdown.
UnsubmittedCrashHandler.uninit();
yield SpecialPowers.pushPrefEnv({
set: [
["browser.crashReports.unsubmittedCheck.enabled", true],
],
});
UnsubmittedCrashHandler.init();
registerCleanupFunction(function() {
gNotificationBox = null;
clearPendingCrashReports();
env.set("MOZ_CRASHREPORTER_URL", oldServerURL);
});
});
/**
* Tests that if there are no pending crash reports, then the
* notification will not show up.
*/
add_task(function* test_no_pending_no_notification() {
// Make absolutely sure there are no pending crash reports first...
clearPendingCrashReports();
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null,
"There should not be a notification if there are no " +
"pending crash reports");
});
/**
* Tests that there is a notification if there is one pending
* crash report.
*/
add_task(function* test_one_pending() {
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that there is a notification if there is more than one
* pending crash report.
*/
add_task(function* test_several_pending() {
yield createPendingCrashReports(3);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that there is no notification if the only pending crash
* reports are over 28 days old. Also checks that if we put a newer
* crash with that older set, that we can still get a notification.
*/
add_task(function* test_several_pending() {
// Let's create some crash reports from 30 days ago.
let oldDate = new Date(Date.now() - (30 * DAY));
yield createPendingCrashReports(3, oldDate);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null,
"There should not be a notification if there are only " +
"old pending crash reports");
// Now let's create a new one and check again
yield createPendingCrashReports(1);
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that the notification can submit a report.
*/
add_task(function* test_can_submit() {
let reportIDs = yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Attempt to submit the notification by clicking on the submit
// button
let buttons = notification.querySelectorAll(".notification-button");
// ...which should be the first button.
let submit = buttons[0];
let promiseReports = waitForSubmittedReports(reportIDs);
info("Sending crash report");
submit.click();
info("Sent!");
// We'll not wait for the notification to finish its transition -
// we'll just remove it right away.
gNotificationBox.removeNotification(notification, true);
info("Waiting on reports to be received.");
yield promiseReports;
info("Received!");
clearPendingCrashReports();
});
/**
* Tests that the notification can submit multiple reports.
*/
add_task(function* test_can_submit_several() {
let reportIDs = yield createPendingCrashReports(3);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Attempt to submit the notification by clicking on the submit
// button
let buttons = notification.querySelectorAll(".notification-button");
// ...which should be the first button.
let submit = buttons[0];
let promiseReports = waitForSubmittedReports(reportIDs);
info("Sending crash reports");
submit.click();
info("Sent!");
// We'll not wait for the notification to finish its transition -
// we'll just remove it right away.
gNotificationBox.removeNotification(notification, true);
info("Waiting on reports to be received.");
yield promiseReports;
info("Received!");
clearPendingCrashReports();
});
/**
* Tests that choosing "Send Always" flips the autoSubmit pref
* and sends the pending crash reports.
*/
add_task(function* test_can_submit_always() {
let pref = "browser.crashReports.unsubmittedCheck.autoSubmit2";
Assert.equal(Services.prefs.getBoolPref(pref), false,
"We should not be auto-submitting by default");
let reportIDs = yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Attempt to submit the notification by clicking on the send all
// button
let buttons = notification.querySelectorAll(".notification-button");
// ...which should be the second button.
let sendAll = buttons[1];
let promiseReports = waitForSubmittedReports(reportIDs);
info("Sending crash reports");
sendAll.click();
info("Sent!");
// We'll not wait for the notification to finish its transition -
// we'll just remove it right away.
gNotificationBox.removeNotification(notification, true);
info("Waiting on reports to be received.");
yield promiseReports;
info("Received!");
// Make sure the pref was set
Assert.equal(Services.prefs.getBoolPref(pref), true,
"The autoSubmit pref should have been set");
// And revert back to default now.
Services.prefs.clearUserPref(pref);
clearPendingCrashReports();
});
/**
* Tests that if the user has chosen to automatically send
* crash reports that no notification is displayed to the
* user.
*/
add_task(function* test_can_auto_submit() {
yield SpecialPowers.pushPrefEnv({ set: [
["browser.crashReports.unsubmittedCheck.autoSubmit2", true],
]});
let reportIDs = yield createPendingCrashReports(3);
let promiseReports = waitForSubmittedReports(reportIDs);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null, "There should be no notification");
info("Waiting on reports to be received.");
yield promiseReports;
info("Received!");
clearPendingCrashReports();
yield SpecialPowers.popPrefEnv();
});
/**
* Tests that if the user chooses to dismiss the notification,
* then the current pending requests won't cause the notification
* to appear again in the future.
*/
add_task(function* test_can_ignore() {
let reportIDs = yield createPendingCrashReports(3);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Dismiss the notification by clicking on the "X" button.
let anonyNodes = document.getAnonymousNodes(notification)[0];
let closeButton = anonyNodes.querySelector(".close-icon");
closeButton.click();
// We'll not wait for the notification to finish its transition -
// we'll just remove it right away.
gNotificationBox.removeNotification(notification, true);
yield waitForIgnoredReports(reportIDs);
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null, "There should be no notification");
clearPendingCrashReports();
});
/**
* Tests that if the notification is shown, then the
* lastShownDate is set for today.
*/
add_task(function* test_last_shown_date() {
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
let today = UnsubmittedCrashHandler.dateString(new Date());
let lastShownDate =
UnsubmittedCrashHandler.prefs.getCharPref("lastShownDate");
Assert.equal(today, lastShownDate,
"Last shown date should be today.");
UnsubmittedCrashHandler.prefs.clearUserPref("lastShownDate");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if UnsubmittedCrashHandler is uninit with a
* notification still being shown, that
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set to true.
*/
add_task(function* test_shutdown_while_showing() {
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
UnsubmittedCrashHandler.prefs.clearUserPref("shutdownWhileShowing");
UnsubmittedCrashHandler.init();
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if UnsubmittedCrashHandler is uninit after
* the notification has been closed, that
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* not set in prefs.
*/
add_task(function* test_shutdown_while_not_showing() {
let reportIDs = yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Dismiss the notification by clicking on the "X" button.
let anonyNodes = document.getAnonymousNodes(notification)[0];
let closeButton = anonyNodes.querySelector(".close-icon");
closeButton.click();
// We'll not wait for the notification to finish its transition -
// we'll just remove it right away.
gNotificationBox.removeNotification(notification, true);
yield waitForIgnoredReports(reportIDs);
UnsubmittedCrashHandler.uninit();
Assert.throws(() => {
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
}, "We should have noticed that the notification had closed before " +
"uninitting.");
UnsubmittedCrashHandler.init();
clearPendingCrashReports();
});
/**
* Tests that if
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set and the lastShownDate is today, then we don't decrement
* browser.crashReports.unsubmittedCheck.chancesUntilSuppress.
*/
add_task(function* test_dont_decrement_chances_on_same_day() {
let initChances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.ok(initChances > 1, "We should start with at least 1 chance.");
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
gNotificationBox.removeNotification(notification, true);
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
let today = UnsubmittedCrashHandler.dateString(new Date());
let lastShownDate =
UnsubmittedCrashHandler.prefs.getCharPref("lastShownDate");
Assert.equal(today, lastShownDate,
"Last shown date should be today.");
UnsubmittedCrashHandler.init();
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should still be a notification");
let chances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.equal(initChances, chances,
"We should not have decremented chances.");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set and the lastShownDate is before today, then we decrement
* browser.crashReports.unsubmittedCheck.chancesUntilSuppress.
*/
add_task(function* test_decrement_chances_on_other_day() {
let initChances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.ok(initChances > 1, "We should start with at least 1 chance.");
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
gNotificationBox.removeNotification(notification, true);
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
// Now pretend that the notification was shown yesterday.
let yesterday = UnsubmittedCrashHandler.dateString(new Date(Date.now() - DAY));
UnsubmittedCrashHandler.prefs.setCharPref("lastShownDate", yesterday);
UnsubmittedCrashHandler.init();
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should still be a notification");
let chances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.equal(initChances - 1, chances,
"We should have decremented our chances.");
UnsubmittedCrashHandler.prefs.clearUserPref("chancesUntilSuppress");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if we've shutdown too many times showing the
* notification, and we've run out of chances, then
* browser.crashReports.unsubmittedCheck.suppressUntilDate is
* set for some days into the future.
*/
add_task(function* test_can_suppress_after_chances() {
// Pretend that a notification was shown yesterday.
let yesterday = UnsubmittedCrashHandler.dateString(new Date(Date.now() - DAY));
UnsubmittedCrashHandler.prefs.setCharPref("lastShownDate", yesterday);
UnsubmittedCrashHandler.prefs.setBoolPref("shutdownWhileShowing", true);
UnsubmittedCrashHandler.prefs.setIntPref("chancesUntilSuppress", 0);
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null,
"There should be no notification if we've run out of chances");
// We should have set suppressUntilDate into the future
let suppressUntilDate =
UnsubmittedCrashHandler.prefs.getCharPref("suppressUntilDate");
let today = UnsubmittedCrashHandler.dateString(new Date());
Assert.ok(suppressUntilDate > today,
"We should be suppressing until some days into the future.");
UnsubmittedCrashHandler.prefs.clearUserPref("chancesUntilSuppress");
UnsubmittedCrashHandler.prefs.clearUserPref("suppressUntilDate");
UnsubmittedCrashHandler.prefs.clearUserPref("lastShownDate");
clearPendingCrashReports();
});
/**
* Tests that if there's a suppression date set, then no notification
* will be shown even if there are pending crash reports.
*/
add_task(function* test_suppression() {
let future = UnsubmittedCrashHandler.dateString(new Date(Date.now() + (DAY * 5)));
UnsubmittedCrashHandler.prefs.setCharPref("suppressUntilDate", future);
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
Assert.ok(UnsubmittedCrashHandler.suppressed,
"The UnsubmittedCrashHandler should be suppressed.");
UnsubmittedCrashHandler.prefs.clearUserPref("suppressUntilDate");
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
});
/**
* Tests that if there's a suppression date set, but we've exceeded
* it, then we can show the notification again.
*/
add_task(function* test_end_suppression() {
let yesterday = UnsubmittedCrashHandler.dateString(new Date(Date.now() - DAY));
UnsubmittedCrashHandler.prefs.setCharPref("suppressUntilDate", yesterday);
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
Assert.ok(!UnsubmittedCrashHandler.suppressed,
"The UnsubmittedCrashHandler should not be suppressed.");
Assert.ok(!UnsubmittedCrashHandler.prefs.prefHasUserValue("suppressUntilDate"),
"The suppression date should been cleared from preferences.");
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
});

View file

@ -1,268 +0,0 @@
"use strict";
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";
const MAX_CONCURRENT_WINDOWS = "browser.engagement.max_concurrent_window_count";
const WINDOW_OPEN_COUNT = "browser.engagement.window_open_event_count";
const TOTAL_URI_COUNT = "browser.engagement.total_uri_count";
const UNIQUE_DOMAINS_COUNT = "browser.engagement.unique_domains_count";
const UNFILTERED_URI_COUNT = "browser.engagement.unfiltered_uri_count";
const TELEMETRY_SUBSESSION_TOPIC = "internal-telemetry-after-subsession-split";
/**
* Waits for the web progress listener associated with this tab to fire an
* onLocationChange for a non-error page.
*
* @param {xul:browser} browser
* A xul:browser.
*
* @return {Promise}
* @resolves When navigating to a non-error page.
*/
function browserLocationChanged(browser) {
return new Promise(resolve => {
let wpl = {
onStateChange() {},
onSecurityChange() {},
onStatusChange() {},
onLocationChange(aWebProgress, aRequest, aURI, aFlags) {
if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) {
browser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(wpl);
resolve();
}
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsIWebProgressListener2,
]),
};
const filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
filter.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL);
browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
});
}
/**
* An helper that checks the value of a scalar if it's expected to be > 0,
* otherwise makes sure that the scalar it's not reported.
*/
let checkScalar = (scalars, scalarName, value, msg) => {
if (value > 0) {
is(scalars[scalarName], value, msg);
return;
}
ok(!(scalarName in scalars), scalarName + " must not be reported.");
};
/**
* Get a snapshot of the scalars and check them against the provided values.
*/
let checkScalars = (countsObject) => {
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
// Check the expected values. Scalars that are never set must not be reported.
checkScalar(scalars, MAX_CONCURRENT_TABS, countsObject.maxTabs,
"The maximum tab count must match the expected value.");
checkScalar(scalars, TAB_EVENT_COUNT, countsObject.tabOpenCount,
"The number of open tab event count must match the expected value.");
checkScalar(scalars, MAX_CONCURRENT_WINDOWS, countsObject.maxWindows,
"The maximum window count must match the expected value.");
checkScalar(scalars, WINDOW_OPEN_COUNT, countsObject.windowsOpenCount,
"The number of window open event count must match the expected value.");
checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
"The total URI count must match the expected value.");
checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
"The unique domains count must match the expected value.");
checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
"The unfiltered URI count must match the expected value.");
};
add_task(function* test_tabsAndWindows() {
// Let's reset the counts.
Services.telemetry.clearScalars();
let openedTabs = [];
let expectedTabOpenCount = 0;
let expectedWinOpenCount = 0;
let expectedMaxTabs = 0;
let expectedMaxWins = 0;
// Add a new tab and check that the count is right.
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
expectedTabOpenCount = 1;
expectedMaxTabs = 2;
// This, and all the checks below, also check that initial pages (about:newtab, about:blank, ..)
// are not counted by the total_uri_count and the unfiltered_uri_count probes.
checkScalars({maxTabs: expectedMaxTabs, tabOpenCount: expectedTabOpenCount, maxWindows: expectedMaxWins,
windowsOpenCount: expectedWinOpenCount, totalURIs: 0, domainCount: 0,
totalUnfilteredURIs: 0});
// Add two new tabs in the same window.
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
expectedTabOpenCount += 2;
expectedMaxTabs += 2;
checkScalars({maxTabs: expectedMaxTabs, tabOpenCount: expectedTabOpenCount, maxWindows: expectedMaxWins,
windowsOpenCount: expectedWinOpenCount, totalURIs: 0, domainCount: 0,
totalUnfilteredURIs: 0});
// Add a new window and then some tabs in it. An empty new windows counts as a tab.
let win = yield BrowserTestUtils.openNewBrowserWindow();
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
// The new window started with a new tab, so account for it.
expectedTabOpenCount += 4;
expectedWinOpenCount += 1;
expectedMaxWins = 2;
expectedMaxTabs += 4;
// Remove a tab from the first window, the max shouldn't change.
yield BrowserTestUtils.removeTab(openedTabs.pop());
checkScalars({maxTabs: expectedMaxTabs, tabOpenCount: expectedTabOpenCount, maxWindows: expectedMaxWins,
windowsOpenCount: expectedWinOpenCount, totalURIs: 0, domainCount: 0,
totalUnfilteredURIs: 0});
// Remove all the extra windows and tabs.
for (let tab of openedTabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(win);
// Make sure all the scalars still have the expected values.
checkScalars({maxTabs: expectedMaxTabs, tabOpenCount: expectedTabOpenCount, maxWindows: expectedMaxWins,
windowsOpenCount: expectedWinOpenCount, totalURIs: 0, domainCount: 0,
totalUnfilteredURIs: 0});
});
add_task(function* test_subsessionSplit() {
// Let's reset the counts.
Services.telemetry.clearScalars();
// Add a new window (that will have 4 tabs).
let win = yield BrowserTestUtils.openNewBrowserWindow();
let openedTabs = [];
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:mozilla"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "http://www.example.com"));
// Check that the scalars have the right values. We expect 2 unfiltered URI loads
// (about:mozilla and www.example.com, but no about:blank) and 1 URI totalURIs
// (only www.example.com).
checkScalars({maxTabs: 5, tabOpenCount: 4, maxWindows: 2, windowsOpenCount: 1,
totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 2});
// Remove a tab.
yield BrowserTestUtils.removeTab(openedTabs.pop());
// Simulate a subsession split by clearing the scalars (via |snapshotScalars|) and
// notifying the subsession split topic.
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* clearScalars */);
Services.obs.notifyObservers(null, TELEMETRY_SUBSESSION_TOPIC, "");
// After a subsession split, only the MAX_CONCURRENT_* scalars must be available
// and have the correct value. No tabs, windows or URIs were opened so other scalars
// must not be reported.
checkScalars({maxTabs: 4, tabOpenCount: 0, maxWindows: 2, windowsOpenCount: 0,
totalURIs: 0, domainCount: 0, totalUnfilteredURIs: 0});
// Remove all the extra windows and tabs.
for (let tab of openedTabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* test_URIAndDomainCounts() {
// Let's reset the counts.
Services.telemetry.clearScalars();
let checkCounts = (countsObject) => {
// Get a snapshot of the scalars and then clear them.
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
"The URI scalar must contain the expected value.");
checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
"The unique domains scalar must contain the expected value.");
checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
"The unfiltered URI scalar must contain the expected value.");
};
// Check that about:blank doesn't get counted in the URI total.
let firstTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
checkCounts({totalURIs: 0, domainCount: 0, totalUnfilteredURIs: 0});
// Open a different page and check the counts.
yield BrowserTestUtils.loadURI(firstTab.linkedBrowser, "http://example.com/");
yield BrowserTestUtils.browserLoaded(firstTab.linkedBrowser);
checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1});
// Activating a different tab must not increase the URI count.
let secondTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
yield BrowserTestUtils.switchTab(gBrowser, firstTab);
checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1});
yield BrowserTestUtils.removeTab(secondTab);
// Open a new window and set the tab to a new address.
let newWin = yield BrowserTestUtils.openNewBrowserWindow();
yield BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/");
yield BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser);
checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2});
// We should not count AJAX requests.
const XHR_URL = "http://example.com/r";
yield ContentTask.spawn(newWin.gBrowser.selectedBrowser, XHR_URL, function(url) {
return new Promise(resolve => {
var xhr = new content.window.XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve();
xhr.send();
});
});
checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2});
// Check that we're counting page fragments.
let loadingStopped = browserLocationChanged(newWin.gBrowser.selectedBrowser);
yield BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/#2");
yield loadingStopped;
checkCounts({totalURIs: 3, domainCount: 1, totalUnfilteredURIs: 3});
// Check that a different URI from the example.com domain doesn't increment the unique count.
yield BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://test1.example.com/");
yield BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser);
checkCounts({totalURIs: 4, domainCount: 1, totalUnfilteredURIs: 4});
// Make sure that the unique domains counter is incrementing for a different domain.
yield BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "https://example.org/");
yield BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser);
checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5});
// Check that we only account for top level loads (e.g. we don't count URIs from
// embedded iframes).
yield ContentTask.spawn(newWin.gBrowser.selectedBrowser, null, function* () {
let doc = content.document;
let iframe = doc.createElement("iframe");
let promiseIframeLoaded = ContentTaskUtils.waitForEvent(iframe, "load", false);
iframe.src = "https://example.org/test";
doc.body.insertBefore(iframe, doc.body.firstChild);
yield promiseIframeLoaded;
});
checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5});
// Check that uncommon protocols get counted in the unfiltered URI probe.
const TEST_PAGE =
"data:text/html,<a id='target' href='%23par1'>Click me</a><a name='par1'>The paragraph.</a>";
yield BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, TEST_PAGE);
yield BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser);
checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 6});
// Clean up.
yield BrowserTestUtils.removeTab(firstTab);
yield BrowserTestUtils.closeWindow(newWin);
});

View file

@ -1,121 +0,0 @@
"use strict";
const BASE_PROBE_NAME = "browser.engagement.navigation.";
const SCALAR_CONTEXT_MENU = BASE_PROBE_NAME + "contextmenu";
const SCALAR_ABOUT_NEWTAB = BASE_PROBE_NAME + "about_newtab";
add_task(function* setup() {
// Create two new search engines. Mark one as the default engine, so
// the test don't crash. We need to engines for this test as the searchbar
// in content doesn't display the default search engine among the one-off engines.
Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
"http://example.com/?q={searchTerms}");
Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
"http://example.com/?q={searchTerms}");
// Make the first engine the default search engine.
let engineDefault = Services.search.getEngineByName("MozSearch");
let originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engineDefault;
// Move the second engine at the beginning of the one-off list.
let engineOneOff = Services.search.getEngineByName("MozSearch2");
Services.search.moveEngine(engineOneOff, 0);
yield SpecialPowers.pushPrefEnv({"set": [
["dom.select_events.enabled", true], // We want select events to be fired.
["toolkit.telemetry.enabled", true] // And Extended Telemetry to be enabled.
]});
// Make sure to restore the engine once we're done.
registerCleanupFunction(function* () {
Services.search.currentEngine = originalEngine;
Services.search.removeEngine(engineDefault);
Services.search.removeEngine(engineOneOff);
});
});
add_task(function* test_context_menu() {
// Let's reset the Telemetry data.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Open a new tab with a page containing some text.
let tab =
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/plain;charset=utf8,test%20search");
info("Select all the text in the page.");
yield ContentTask.spawn(tab.linkedBrowser, "", function*() {
return new Promise(resolve => {
content.document.addEventListener("selectionchange", () => resolve(), { once: true });
content.document.getSelection().selectAllChildren(content.document.body);
});
});
info("Open the context menu.");
let contextMenu = document.getElementById("contentAreaContextMenu");
let popupPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
BrowserTestUtils.synthesizeMouseAtCenter("body", { type: "contextmenu", button: 2 },
gBrowser.selectedBrowser);
yield popupPromise;
info("Click on search.");
let searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
searchItem.click();
info("Validate the search metrics.");
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_CONTEXT_MENU, "search", 1);
Assert.equal(Object.keys(scalars[SCALAR_CONTEXT_MENU]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.contextmenu', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "contextmenu", null, {engine: "other-MozSearch"}]]);
contextMenu.hidePopup();
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_about_newtab() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
yield ContentTask.spawn(tab.linkedBrowser, null, function* () {
yield ContentTaskUtils.waitForCondition(() => !content.document.hidden);
});
info("Trigger a simple serch, just text + enter.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield typeInSearchField(tab.linkedBrowser, "test query", "newtab-search-text");
yield BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_ABOUT_NEWTAB, "search_enter", 1);
Assert.equal(Object.keys(scalars[SCALAR_ABOUT_NEWTAB]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.newtab', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_newtab", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -1,84 +0,0 @@
"use strict";
const SCALAR_ABOUT_HOME = "browser.engagement.navigation.about_home";
add_task(function* setup() {
// about:home uses IndexedDB. However, the test finishes too quickly and doesn't
// allow it enougth time to save. So it throws. This disables all the uncaught
// exception in this file and that's the reason why we split about:home tests
// out of the other UsageTelemetry files.
ignoreAllUncaughtExceptions();
// Create two new search engines. Mark one as the default engine, so
// the test don't crash. We need to engines for this test as the searchbar
// in content doesn't display the default search engine among the one-off engines.
Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
"http://example.com/?q={searchTerms}");
Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
"http://example.com/?q={searchTerms}");
// Make the first engine the default search engine.
let engineDefault = Services.search.getEngineByName("MozSearch");
let originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engineDefault;
// Move the second engine at the beginning of the one-off list.
let engineOneOff = Services.search.getEngineByName("MozSearch2");
Services.search.moveEngine(engineOneOff, 0);
// Enable Extended Telemetry.
yield SpecialPowers.pushPrefEnv({"set": [["toolkit.telemetry.enabled", true]]});
// Make sure to restore the engine once we're done.
registerCleanupFunction(function* () {
Services.search.currentEngine = originalEngine;
Services.search.removeEngine(engineDefault);
Services.search.removeEngine(engineOneOff);
});
});
add_task(function* test_abouthome_simpleQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
info("Setup waiting for AboutHomeLoadSnippetsCompleted.");
let promiseAboutHomeLoaded = new Promise(resolve => {
tab.linkedBrowser.addEventListener("AboutHomeLoadSnippetsCompleted", function loadListener(event) {
tab.linkedBrowser.removeEventListener("AboutHomeLoadSnippetsCompleted", loadListener, true);
resolve();
}, true, true);
});
info("Load about:home.");
tab.linkedBrowser.loadURI("about:home");
info("Wait for AboutHomeLoadSnippetsCompleted.");
yield promiseAboutHomeLoaded;
info("Trigger a simple serch, just test + enter.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield typeInSearchField(tab.linkedBrowser, "test query", "searchText");
yield BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_ABOUT_HOME, "search_enter", 1);
Assert.equal(Object.keys(scalars[SCALAR_ABOUT_HOME]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.abouthome', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_home", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -1,90 +0,0 @@
"use strict";
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";
const MAX_CONCURRENT_WINDOWS = "browser.engagement.max_concurrent_window_count";
const WINDOW_OPEN_COUNT = "browser.engagement.window_open_event_count";
const TOTAL_URI_COUNT = "browser.engagement.total_uri_count";
const UNFILTERED_URI_COUNT = "browser.engagement.unfiltered_uri_count";
const UNIQUE_DOMAINS_COUNT = "browser.engagement.unique_domains_count";
function promiseBrowserStateRestored() {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic) {
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
resolve();
}, "sessionstore-browser-state-restored", false);
});
}
add_task(function* test_privateMode() {
// Let's reset the counts.
Services.telemetry.clearScalars();
// Open a private window and load a website in it.
let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
yield BrowserTestUtils.loadURI(privateWin.gBrowser.selectedBrowser, "http://example.com/");
yield BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
// Check that tab and window count is recorded.
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs in private mode.");
ok(!(UNFILTERED_URI_COUNT in scalars), "We should not track URIs in private mode.");
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains in private mode.");
is(scalars[TAB_EVENT_COUNT], 1, "The number of open tab event count must match the expected value.");
is(scalars[MAX_CONCURRENT_TABS], 2, "The maximum tab count must match the expected value.");
is(scalars[WINDOW_OPEN_COUNT], 1, "The number of window open event count must match the expected value.");
is(scalars[MAX_CONCURRENT_WINDOWS], 2, "The maximum window count must match the expected value.");
// Clean up.
yield BrowserTestUtils.closeWindow(privateWin);
});
add_task(function* test_sessionRestore() {
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// Let's reset the counts.
Services.telemetry.clearScalars();
// The first window will be put into the already open window and the second
// window will be opened with _openWindowWithState, which is the source of the problem.
const state = {
windows: [
{
tabs: [
{ entries: [{ url: "http://example.org" }], extData: { "uniq": 3785 } }
],
selected: 1
}
]
};
// Save the current session.
let SessionStore =
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}).SessionStore;
// Load the custom state and wait for SSTabRestored, as we want to make sure
// that the URI counting code was hit.
let tabRestored = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "SSTabRestored");
SessionStore.setBrowserState(JSON.stringify(state));
yield tabRestored;
// Check that the URI is not recorded.
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
ok(!(UNFILTERED_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains from restored sessions.");
// Restore the original session and cleanup.
let sessionRestored = promiseBrowserStateRestored();
SessionStore.setBrowserState(JSON.stringify(state));
yield sessionRestored;
});

View file

@ -1,195 +0,0 @@
"use strict";
const SCALAR_SEARCHBAR = "browser.engagement.navigation.searchbar";
let searchInSearchbar = Task.async(function* (inputText) {
let win = window;
yield new Promise(r => waitForFocus(r, win));
let sb = BrowserSearch.searchBar;
// Write the search query in the searchbar.
sb.focus();
sb.value = inputText;
sb.textbox.controller.startSearch(inputText);
// Wait for the popup to show.
yield BrowserTestUtils.waitForEvent(sb.textbox.popup, "popupshown");
// And then for the search to complete.
yield BrowserTestUtils.waitForCondition(() => sb.textbox.controller.searchStatus >=
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH,
"The search in the searchbar must complete.");
});
/**
* Click one of the entries in the search suggestion popup.
*
* @param {String} entryName
* The name of the elemet to click on.
*/
function clickSearchbarSuggestion(entryName) {
let popup = BrowserSearch.searchBar.textbox.popup;
let column = popup.tree.columns[0];
for (let rowID = 0; rowID < popup.tree.view.rowCount; rowID++) {
const suggestion = popup.tree.view.getValueAt(rowID, column);
if (suggestion !== entryName) {
continue;
}
// Make sure the suggestion is visible, just in case.
let tbo = popup.tree.treeBoxObject;
tbo.ensureRowIsVisible(rowID);
// Calculate the click coordinates.
let rect = tbo.getCoordsForCellItem(rowID, column, "text");
let x = rect.x + rect.width / 2;
let y = rect.y + rect.height / 2;
// Simulate the click.
EventUtils.synthesizeMouse(popup.tree.body, x, y, {},
popup.tree.ownerGlobal);
break;
}
}
add_task(function* setup() {
// Create two new search engines. Mark one as the default engine, so
// the test don't crash. We need to engines for this test as the searchbar
// doesn't display the default search engine among the one-off engines.
Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
"http://example.com/?q={searchTerms}");
Services.search.addEngineWithDetails("MozSearch2", "", "mozalias2", "", "GET",
"http://example.com/?q={searchTerms}");
// Make the first engine the default search engine.
let engineDefault = Services.search.getEngineByName("MozSearch");
let originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engineDefault;
// Move the second engine at the beginning of the one-off list.
let engineOneOff = Services.search.getEngineByName("MozSearch2");
Services.search.moveEngine(engineOneOff, 0);
// Enable Extended Telemetry.
yield SpecialPowers.pushPrefEnv({"set": [["toolkit.telemetry.enabled", true]]});
// Make sure to restore the engine once we're done.
registerCleanupFunction(function* () {
Services.search.currentEngine = originalEngine;
Services.search.removeEngine(engineDefault);
Services.search.removeEngine(engineOneOff);
});
});
add_task(function* test_plainQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Simulate entering a simple search.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInSearchbar("simple query");
EventUtils.sendKey("return");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_enter", 1);
Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_oneOff() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Perform a one-off search using the first engine.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInSearchbar("query");
info("Pressing Alt+Down to highlight the first one off engine.");
EventUtils.synthesizeKey("VK_DOWN", { altKey: true });
EventUtils.sendKey("return");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_oneoff", 1);
Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch2.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "oneoff", {engine: "other-MozSearch2"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_suggestion() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Create an engine to generate search suggestions and add it as default
// for this test.
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = yield new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
onSuccess(engine) { resolve(engine) },
onError() { reject() }
});
});
let previousEngine = Services.search.currentEngine;
Services.search.currentEngine = suggestionEngine;
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Perform a one-off search using the first engine.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInSearchbar("query");
info("Clicking the searchbar suggestion.");
clickSearchbarSuggestion("queryfoo");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_suggestion", 1);
Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
let searchEngineId = 'other-' + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + '.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}]]);
Services.search.currentEngine = previousEngine;
Services.search.removeEngine(suggestionEngine);
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -1,220 +0,0 @@
"use strict";
const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
// The preference to enable suggestions in the urlbar.
const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
// The name of the search engine used to generate suggestions.
const SUGGESTION_ENGINE_NAME = "browser_UsageTelemetry usageTelemetrySearchSuggestions.xml";
const ONEOFF_URLBAR_PREF = "browser.urlbar.oneOffSearches";
let searchInAwesomebar = Task.async(function* (inputText, win=window) {
yield new Promise(r => waitForFocus(r, win));
// Write the search query in the urlbar.
win.gURLBar.focus();
win.gURLBar.value = inputText;
win.gURLBar.controller.startSearch(inputText);
// Wait for the popup to show.
yield BrowserTestUtils.waitForEvent(win.gURLBar.popup, "popupshown");
// And then for the search to complete.
yield BrowserTestUtils.waitForCondition(() => win.gURLBar.controller.searchStatus >=
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH);
});
/**
* Click one of the entries in the urlbar suggestion popup.
*
* @param {String} entryName
* The name of the elemet to click on.
*/
function clickURLBarSuggestion(entryName) {
// The entry in the suggestion list should follow the format:
// "<search term> <engine name> Search"
const expectedSuggestionName = entryName + " " + SUGGESTION_ENGINE_NAME + " Search";
for (let child of gURLBar.popup.richlistbox.children) {
if (child.label === expectedSuggestionName) {
// This entry is the search suggestion we're looking for.
child.click();
return;
}
}
}
add_task(function* setup() {
// Create a new search engine.
Services.search.addEngineWithDetails("MozSearch", "", "mozalias", "", "GET",
"http://example.com/?q={searchTerms}");
// Make it the default search engine.
let engine = Services.search.getEngineByName("MozSearch");
let originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engine;
// And the first one-off engine.
Services.search.moveEngine(engine, 0);
// Enable search suggestions in the urlbar.
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
// Enable the urlbar one-off buttons.
Services.prefs.setBoolPref(ONEOFF_URLBAR_PREF, true);
// Enable Extended Telemetry.
yield SpecialPowers.pushPrefEnv({"set": [["toolkit.telemetry.enabled", true]]});
// Make sure to restore the engine once we're done.
registerCleanupFunction(function* () {
Services.search.currentEngine = originalEngine;
Services.search.removeEngine(engine);
Services.prefs.clearUserPref(SUGGEST_URLBAR_PREF, true);
Services.prefs.clearUserPref(ONEOFF_URLBAR_PREF);
});
});
add_task(function* test_simpleQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Simulate entering a simple search.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInAwesomebar("simple query");
EventUtils.sendKey("return");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_URLBAR, "search_enter", 1);
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_searchAlias() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Search using a search alias.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInAwesomebar("mozalias query");
EventUtils.sendKey("return");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_URLBAR, "search_alias", 1);
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "alias", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_oneOff() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Perform a one-off search using the first engine.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInAwesomebar("query");
info("Pressing Alt+Down to take us to the first one-off engine.");
EventUtils.synthesizeKey("VK_DOWN", { altKey: true });
EventUtils.sendKey("return");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_URLBAR, "search_oneoff", 1);
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "oneoff", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_suggestion() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Create an engine to generate search suggestions and add it as default
// for this test.
const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
let suggestionEngine = yield new Promise((resolve, reject) => {
Services.search.addEngine(url, null, "", false, {
onSuccess(engine) { resolve(engine) },
onError() { reject() }
});
});
let previousEngine = Services.search.currentEngine;
Services.search.currentEngine = suggestionEngine;
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
info("Perform a one-off search using the first engine.");
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield searchInAwesomebar("query");
info("Clicking the urlbar suggestion.");
clickURLBarSuggestion("queryfoo");
yield p;
// Check if the scalars contain the expected values.
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_URLBAR, "search_suggestion", 1);
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
let searchEngineId = 'other-' + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + '.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "suggestion", {engine: searchEngineId}]]);
Services.search.currentEngine = previousEngine;
Services.search.removeEngine(suggestionEngine);
yield BrowserTestUtils.removeTab(tab);
});

View file

@ -1,100 +0,0 @@
function test() {
var isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
is(!!Win7Features, isWin7OrHigher, "Win7Features available when it should be");
if (!isWin7OrHigher)
return;
const ENABLE_PREF_NAME = "browser.taskbar.previews.enable";
let temp = {};
Cu.import("resource:///modules/WindowsPreviewPerTab.jsm", temp);
let AeroPeek = temp.AeroPeek;
waitForExplicitFinish();
gPrefService.setBoolPref(ENABLE_PREF_NAME, true);
is(1, AeroPeek.windows.length, "Got the expected number of windows");
checkPreviews(1, "Browser starts with one preview");
gBrowser.addTab();
gBrowser.addTab();
gBrowser.addTab();
checkPreviews(4, "Correct number of previews after adding");
for (let preview of AeroPeek.previews)
ok(preview.visible, "Preview is shown as expected");
gPrefService.setBoolPref(ENABLE_PREF_NAME, false);
is(0, AeroPeek.previews.length, "Should have 0 previews when disabled");
gPrefService.setBoolPref(ENABLE_PREF_NAME, true);
checkPreviews(4, "Previews are back when re-enabling");
for (let preview of AeroPeek.previews)
ok(preview.visible, "Preview is shown as expected after re-enabling");
[1, 2, 3, 4].forEach(function (idx) {
gBrowser.selectedTab = gBrowser.tabs[idx];
ok(checkSelectedTab(), "Current tab is correctly selected");
});
// Close #4
getPreviewForTab(gBrowser.selectedTab).controller.onClose();
checkPreviews(3, "Expected number of previews after closing selected tab via controller");
ok(gBrowser.tabs.length == 3, "Successfully closed a tab");
// Select #1
ok(getPreviewForTab(gBrowser.tabs[0]).controller.onActivate(), "Activation was accepted");
ok(gBrowser.tabs[0].selected, "Correct tab was selected");
checkSelectedTab();
// Remove #3 (non active)
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
checkPreviews(2, "Expected number of previews after closing unselected via browser");
// Remove #1 (active)
gBrowser.removeTab(gBrowser.tabContainer.firstChild);
checkPreviews(1, "Expected number of previews after closing selected tab via browser");
// Add a new tab
gBrowser.addTab();
checkPreviews(2);
// Check default selection
checkSelectedTab();
// Change selection
gBrowser.selectedTab = gBrowser.tabs[0];
checkSelectedTab();
// Close nonselected tab via controller
getPreviewForTab(gBrowser.tabs[1]).controller.onClose();
checkPreviews(1);
if (gPrefService.prefHasUserValue(ENABLE_PREF_NAME))
gPrefService.setBoolPref(ENABLE_PREF_NAME, !gPrefService.getBoolPref(ENABLE_PREF_NAME));
finish();
function checkPreviews(aPreviews, msg) {
let nPreviews = AeroPeek.previews.length;
is(aPreviews, gBrowser.tabs.length, "Browser has expected number of tabs - " + msg);
is(nPreviews, gBrowser.tabs.length, "Browser has one preview per tab - " + msg);
is(nPreviews, aPreviews, msg || "Got expected number of previews");
}
function getPreviewForTab(tab) {
return window.gTaskbarTabGroup.previewFromTab(tab);
}
function checkSelectedTab() {
return getPreviewForTab(gBrowser.selectedTab).active;
}
}

View file

@ -1,73 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var initialPageZoom = ZoomManager.zoom;
const kTimeoutInMS = 20000;
add_task(function* () {
info("Confirm whether the browser zoom is set to the default level");
is(initialPageZoom, 1, "Page zoom is set to default (100%)");
let zoomResetButton = document.getElementById("urlbar-zoom-button");
is(zoomResetButton.hidden, true, "Zoom reset button is currently hidden");
info("Change zoom and confirm zoom button appears");
let labelUpdatePromise = BrowserTestUtils.waitForAttribute("label", zoomResetButton);
FullZoom.enlarge();
yield labelUpdatePromise;
info("Zoom increased to " + Math.floor(ZoomManager.zoom * 100) + "%");
is(zoomResetButton.hidden, false, "Zoom reset button is now visible");
let pageZoomLevel = Math.floor(ZoomManager.zoom * 100);
let expectedZoomLevel = 110;
let buttonZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
is(buttonZoomLevel, expectedZoomLevel, ("Button label updated successfully to " + Math.floor(ZoomManager.zoom * 100) + "%"));
let zoomResetPromise = promiseObserverNotification("browser-fullZoom:zoomReset");
zoomResetButton.click();
yield zoomResetPromise;
pageZoomLevel = Math.floor(ZoomManager.zoom * 100);
expectedZoomLevel = 100;
is(pageZoomLevel, expectedZoomLevel, "Clicking zoom button successfully resets browser zoom to 100%");
is(zoomResetButton.hidden, true, "Zoom reset button returns to being hidden");
});
add_task(function* () {
info("Confirm that URL bar zoom button doesn't appear when customizable zoom widget is added to toolbar");
CustomizableUI.addWidgetToArea("zoom-controls", CustomizableUI.AREA_NAVBAR);
let zoomCustomizableWidget = document.getElementById("zoom-reset-button");
let zoomResetButton = document.getElementById("urlbar-zoom-button");
let zoomChangePromise = promiseObserverNotification("browser-fullZoom:zoomChange");
FullZoom.enlarge();
yield zoomChangePromise;
is(zoomResetButton.hidden, true, "URL zoom button remains hidden despite zoom increase");
is(parseInt(zoomCustomizableWidget.label, 10), 110, "Customizable zoom widget's label has updated to " + zoomCustomizableWidget.label);
});
add_task(function* asyncCleanup() {
// reset zoom level and customizable widget
ZoomManager.zoom = initialPageZoom;
is(ZoomManager.zoom, 1, "Zoom level was restored");
if (document.getElementById("zoom-controls")) {
CustomizableUI.removeWidgetFromArea("zoom-controls", CustomizableUI.AREA_NAVBAR);
ok(!document.getElementById("zoom-controls"), "Customizable zoom widget removed from toolbar");
}
});
function promiseObserverNotification(aObserver) {
let deferred = Promise.defer();
function notificationCallback(e) {
Services.obs.removeObserver(notificationCallback, aObserver, false);
clearTimeout(timeoutId);
deferred.resolve();
}
let timeoutId = setTimeout(() => {
Services.obs.removeObserver(notificationCallback, aObserver, false);
deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
}, kTimeoutInMS);
Services.obs.addObserver(notificationCallback, aObserver, false);
return deferred.promise;
}

View file

@ -1,64 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const TEST_MSG = "ContentSearchTest";
const SERVICE_EVENT_TYPE = "ContentSearchService";
const CLIENT_EVENT_TYPE = "ContentSearchClient";
// Forward events from the in-content service to the test.
content.addEventListener(SERVICE_EVENT_TYPE, event => {
// The event dispatch code in content.js clones the event detail into the
// content scope. That's generally the right thing, but causes us to end
// up with an XrayWrapper to it here, which will screw us up when trying to
// serialize the object in sendAsyncMessage. Waive Xrays for the benefit of
// the test machinery.
sendAsyncMessage(TEST_MSG, Components.utils.waiveXrays(event.detail));
});
// Forward messages from the test to the in-content service.
addMessageListener(TEST_MSG, msg => {
// If the message is a search, stop the page from loading and then tell the
// test that it loaded.
if (msg.data.type == "Search") {
waitForLoadAndStopIt(msg.data.expectedURL, url => {
sendAsyncMessage(TEST_MSG, {
type: "loadStopped",
url: url,
});
});
}
content.dispatchEvent(
new content.CustomEvent(CLIENT_EVENT_TYPE, {
detail: msg.data,
})
);
});
function waitForLoadAndStopIt(expectedURL, callback) {
let Ci = Components.interfaces;
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
let listener = {
onStateChange: function (webProg, req, flags, status) {
if (req instanceof Ci.nsIChannel) {
let url = req.originalURI.spec;
dump("waitForLoadAndStopIt: onStateChange " + url + "\n");
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
Ci.nsIWebProgressListener.STATE_START;
if ((flags & docStart) && webProg.isTopLevel && url == expectedURL) {
webProgress.removeProgressListener(listener);
req.cancel(Components.results.NS_ERROR_FAILURE);
callback(url);
}
}
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
]),
};
webProgress.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
dump("waitForLoadAndStopIt: Waiting for URL to load: " + expectedURL + "\n");
}

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>browser_ContentSearch contentSearchBadImage.xml</ShortName>
<Url type="text/html" method="GET" template="http://browser-ContentSearch.com/contentSearchBadImage" rel="searchform"/>
<Image width="16" height="16">data:image/x-icon;base64,notbase64</Image>
</SearchPlugin>

View file

@ -1,9 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(req, resp) {
let suffixes = ["foo", "bar"];
let data = [req.queryString, suffixes.map(s => req.queryString + s)];
resp.setHeader("Content-Type", "application/json", false);
resp.write(JSON.stringify(data));
}

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>browser_ContentSearch contentSearchSuggestions.xml</ShortName>
<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/modules/test/contentSearchSuggestions.sjs?{searchTerms}"/>
<Url type="text/html" method="GET" template="http://browser-ContentSearch.com/contentSearchSuggestions" rel="searchform"/>
</SearchPlugin>

View file

@ -1,113 +0,0 @@
Cu.import("resource://gre/modules/Promise.jsm");
const SINGLE_TRY_TIMEOUT = 100;
const NUMBER_OF_TRIES = 30;
function waitForConditionPromise(condition, timeoutMsg, tryCount=NUMBER_OF_TRIES) {
let defer = Promise.defer();
let tries = 0;
function checkCondition() {
if (tries >= tryCount) {
defer.reject(timeoutMsg);
}
var conditionPassed;
try {
conditionPassed = condition();
} catch (e) {
return defer.reject(e);
}
if (conditionPassed) {
return defer.resolve();
}
tries++;
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return undefined;
}
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return defer.promise;
}
function waitForCondition(condition, nextTest, errorMsg) {
waitForConditionPromise(condition, errorMsg).then(nextTest, (reason) => {
ok(false, reason + (reason.stack ? "\n" + reason.stack : ""));
});
}
/**
* Checks if the snapshotted keyed scalars contain the expected
* data.
*
* @param {Object} scalars
* The snapshot of the keyed scalars.
* @param {String} scalarName
* The name of the keyed scalar to check.
* @param {String} key
* The key that must be within the keyed scalar.
* @param {String|Boolean|Number} expectedValue
* The expected value for the provided key in the scalar.
*/
function checkKeyedScalar(scalars, scalarName, key, expectedValue) {
Assert.ok(scalarName in scalars,
scalarName + " must be recorded.");
Assert.ok(key in scalars[scalarName],
scalarName + " must contain the '" + key + "' key.");
Assert.ok(scalars[scalarName][key], expectedValue,
scalarName + "['" + key + "'] must contain the expected value");
}
/**
* An utility function to write some text in the search input box
* in a content page.
* @param {Object} browser
* The browser that contains the content.
* @param {String} text
* The string to write in the search field.
* @param {String} fieldName
* The name of the field to write to.
*/
let typeInSearchField = Task.async(function* (browser, text, fieldName) {
yield ContentTask.spawn(browser, { fieldName, text }, function* ({fieldName, text}) {
// Avoid intermittent failures.
if (fieldName === "searchText") {
content.wrappedJSObject.gContentSearchController.remoteTimeout = 5000;
}
// Put the focus on the search box.
let searchInput = content.document.getElementById(fieldName);
searchInput.focus();
searchInput.value = text;
});
});
/**
* Clear and get the SEARCH_COUNTS histogram.
*/
function getSearchCountsHistogram() {
let search_hist = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
search_hist.clear();
return search_hist;
}
/**
* Check that the keyed histogram contains the right value.
*/
function checkKeyedHistogram(h, key, expectedValue) {
const snapshot = h.snapshot();
Assert.ok(key in snapshot, `The histogram must contain ${key}.`);
Assert.equal(snapshot[key].sum, expectedValue, `The key ${key} must contain ${expectedValue}.`);
}
function checkEvents(events, expectedEvents) {
if (!Services.telemetry.canRecordExtended) {
// Currently we only collect the tested events when extended Telemetry is enabled.
return;
}
Assert.equal(events.length, expectedEvents.length, "Should have matching amount of events.");
// Strip timestamps from the events for easier comparison.
events = events.map(e => e.slice(1));
for (let i = 0; i < events.length; ++i) {
Assert.deepEqual(events[i], expectedEvents[i], "Events should match.");
}
}

View file

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

View file

@ -1,6 +0,0 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="s1" id="bad.com@services.mozilla.org"></emItem>
</emItems>
</blocklist>

View file

@ -1,210 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var Social, SocialService;
var manifests = [
{
name: "provider 1",
origin: "https://example1.com",
sidebarURL: "https://example1.com/sidebar/",
},
{
name: "provider 2",
origin: "https://example2.com",
sidebarURL: "https://example1.com/sidebar/",
}
];
const MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
// SocialProvider class relies on blocklisting being enabled. To enable
// blocklisting, we have to setup an app and initialize the blocklist (see
// initApp below).
const gProfD = do_get_profile();
function createAppInfo(ID, name, version, platformVersion="1.0") {
let tmp = {};
Cu.import("resource://testing-common/AppInfo.jsm", tmp);
tmp.updateAppInfo({
ID, name, version, platformVersion,
crashReporter: true,
});
gAppInfo = tmp.getAppInfo();
}
function initApp() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
// prepare a blocklist file for the blocklist service
var blocklistFile = gProfD.clone();
blocklistFile.append("blocklist.xml");
if (blocklistFile.exists())
blocklistFile.remove(false);
var source = do_get_file("blocklist.xml");
source.copyTo(gProfD, "blocklist.xml");
blocklistFile.lastModifiedTime = Date.now();
let internalManager = Cc["@mozilla.org/addons/integration;1"].
getService(Ci.nsIObserver).
QueryInterface(Ci.nsITimerCallback);
internalManager.observe(null, "addons-startup", null);
}
function setManifestPref(manifest) {
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue("social.manifest." + manifest.origin, Ci.nsISupportsString, string);
}
function do_wait_observer(obsTopic, cb) {
function observer(subject, topic, data) {
Services.obs.removeObserver(observer, topic);
cb();
}
Services.obs.addObserver(observer, obsTopic, false);
}
function do_add_providers(cb) {
// run only after social is already initialized
SocialService.addProvider(manifests[0], function() {
do_wait_observer("social:providers-changed", function() {
do_check_eq(Social.providers.length, 2, "2 providers installed");
do_execute_soon(cb);
});
SocialService.addProvider(manifests[1]);
});
}
function do_initialize_social(enabledOnStartup, cb) {
initApp();
if (enabledOnStartup) {
// set prefs before initializing social
manifests.forEach(function (manifest) {
setManifestPref(manifest);
});
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
for (let m of manifests)
active[m.origin] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
do_register_cleanup(function() {
manifests.forEach(function (manifest) {
Services.prefs.clearUserPref("social.manifest." + manifest.origin);
});
Services.prefs.clearUserPref("social.activeProviders");
});
// expecting 2 providers installed
do_wait_observer("social:providers-changed", function() {
do_check_eq(Social.providers.length, 2, "2 providers installed");
do_execute_soon(cb);
});
}
// import and initialize everything
SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
do_check_eq(enabledOnStartup, SocialService.hasEnabledProviders, "Service has enabled providers");
Social = Cu.import("resource:///modules/Social.jsm", {}).Social;
do_check_false(Social.initialized, "Social is not initialized");
Social.init();
do_check_true(Social.initialized, "Social is initialized");
if (!enabledOnStartup)
do_execute_soon(cb);
}
function AsyncRunner() {
do_test_pending();
do_register_cleanup(() => this.destroy());
this._callbacks = {
done: do_test_finished,
error: function (err) {
// xpcshell test functions like do_check_eq throw NS_ERROR_ABORT on
// failure. Ignore those so they aren't rethrown here.
if (err !== Cr.NS_ERROR_ABORT) {
if (err.stack) {
err = err + " - See following stack:\n" + err.stack +
"\nUseless do_throw stack";
}
do_throw(err);
}
},
consoleError: function (scriptErr) {
// Try to ensure the error is related to the test.
let filename = scriptErr.sourceName || scriptErr.toString() || "";
if (filename.indexOf("/toolkit/components/social/") >= 0)
do_throw(scriptErr);
},
};
this._iteratorQueue = [];
// This catches errors reported to the console, e.g., via Cu.reportError, but
// not on the runner's stack.
Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService).
registerListener(this);
}
AsyncRunner.prototype = {
appendIterator: function appendIterator(iter) {
this._iteratorQueue.push(iter);
},
next: function next(arg) {
if (!this._iteratorQueue.length) {
this.destroy();
this._callbacks.done();
return;
}
try {
var { done, value: val } = this._iteratorQueue[0].next(arg);
if (done) {
this._iteratorQueue.shift();
this.next();
return;
}
}
catch (err) {
this._callbacks.error(err);
}
// val is an iterator => prepend it to the queue and start on it
// val is otherwise truthy => call next
if (val) {
if (typeof(val) != "boolean")
this._iteratorQueue.unshift(val);
this.next();
}
},
destroy: function destroy() {
Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService).
unregisterListener(this);
this.destroy = function alreadyDestroyed() {};
},
observe: function observe(msg) {
if (msg instanceof Ci.nsIScriptError &&
!(msg.flags & Ci.nsIScriptError.warningFlag))
{
this._callbacks.consoleError(msg);
}
},
};

View file

@ -1,166 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
function run_test() {
initApp();
// NOTE: none of the manifests here can have a workerURL set, or we attempt
// to create a FrameWorker and that fails under xpcshell...
let manifests = [
{ // normal provider
name: "provider 1",
origin: "https://example1.com",
shareURL: "https://example1.com/share/",
},
{ // provider without workerURL
name: "provider 2",
origin: "https://example2.com",
shareURL: "https://example2.com/share/",
}
];
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);
runner.appendIterator(testAddProviders(manifests, next));
runner.appendIterator(testGetProvider(manifests, next));
runner.appendIterator(testGetProviderList(manifests, next));
runner.appendIterator(testAddRemoveProvider(manifests, next));
runner.appendIterator(testIsSameOrigin(manifests, next));
runner.appendIterator(testResolveUri (manifests, next));
runner.appendIterator(testOrderedProviders(manifests, next));
runner.appendIterator(testRemoveProviders(manifests, next));
runner.next();
}
function* testAddProviders(manifests, next) {
do_check_false(SocialService.enabled);
let provider = yield SocialService.addProvider(manifests[0], next);
do_check_true(SocialService.enabled);
do_check_false(provider.enabled);
provider = yield SocialService.addProvider(manifests[1], next);
do_check_false(provider.enabled);
}
function* testRemoveProviders(manifests, next) {
do_check_true(SocialService.enabled);
yield SocialService.disableProvider(manifests[0].origin, next);
yield SocialService.disableProvider(manifests[1].origin, next);
do_check_false(SocialService.enabled);
}
function* testGetProvider(manifests, next) {
for (let i = 0; i < manifests.length; i++) {
let manifest = manifests[i];
let provider = yield SocialService.getProvider(manifest.origin, next);
do_check_neq(provider, null);
do_check_eq(provider.name, manifest.name);
do_check_eq(provider.workerURL, manifest.workerURL);
do_check_eq(provider.origin, manifest.origin);
}
do_check_eq((yield SocialService.getProvider("bogus", next)), null);
}
function* testGetProviderList(manifests, next) {
let providers = yield SocialService.getProviderList(next);
do_check_true(providers.length >= manifests.length);
for (let i = 0; i < manifests.length; i++) {
let providerIdx = providers.map(p => p.origin).indexOf(manifests[i].origin);
let provider = providers[providerIdx];
do_check_true(!!provider);
do_check_false(provider.enabled);
do_check_eq(provider.workerURL, manifests[i].workerURL);
do_check_eq(provider.name, manifests[i].name);
}
}
function* testAddRemoveProvider(manifests, next) {
var threw;
try {
// Adding a provider whose origin already exists should fail
SocialService.addProvider(manifests[0]);
} catch (ex) {
threw = ex;
}
do_check_neq(threw.toString().indexOf("SocialService.addProvider: provider with this origin already exists"), -1);
let originalProviders = yield SocialService.getProviderList(next);
// Check that provider installation succeeds
let newProvider = yield SocialService.addProvider({
name: "foo",
origin: "http://example3.com"
}, next);
let retrievedNewProvider = yield SocialService.getProvider(newProvider.origin, next);
do_check_eq(newProvider, retrievedNewProvider);
let providersAfter = yield SocialService.getProviderList(next);
do_check_eq(providersAfter.length, originalProviders.length + 1);
do_check_neq(providersAfter.indexOf(newProvider), -1);
// Now remove the provider
yield SocialService.disableProvider(newProvider.origin, next);
providersAfter = yield SocialService.getProviderList(next);
do_check_eq(providersAfter.length, originalProviders.length);
do_check_eq(providersAfter.indexOf(newProvider), -1);
newProvider = yield SocialService.getProvider(newProvider.origin, next);
do_check_true(!newProvider);
}
function* testIsSameOrigin(manifests, next) {
let providers = yield SocialService.getProviderList(next);
let provider = providers[0];
// provider.origin is a string.
do_check_true(provider.isSameOrigin(provider.origin));
do_check_true(provider.isSameOrigin(Services.io.newURI(provider.origin, null, null)));
do_check_true(provider.isSameOrigin(provider.origin + "/some-sub-page"));
do_check_true(provider.isSameOrigin(Services.io.newURI(provider.origin + "/some-sub-page", null, null)));
do_check_false(provider.isSameOrigin("http://something.com"));
do_check_false(provider.isSameOrigin(Services.io.newURI("http://something.com", null, null)));
do_check_false(provider.isSameOrigin("data:text/html,<p>hi"));
do_check_true(provider.isSameOrigin("data:text/html,<p>hi", true));
do_check_false(provider.isSameOrigin(Services.io.newURI("data:text/html,<p>hi", null, null)));
do_check_true(provider.isSameOrigin(Services.io.newURI("data:text/html,<p>hi", null, null), true));
// we explicitly handle null and return false
do_check_false(provider.isSameOrigin(null));
}
function* testResolveUri(manifests, next) {
let providers = yield SocialService.getProviderList(next);
let provider = providers[0];
do_check_eq(provider.resolveUri(provider.origin).spec, provider.origin + "/");
do_check_eq(provider.resolveUri("foo.html").spec, provider.origin + "/foo.html");
do_check_eq(provider.resolveUri("/foo.html").spec, provider.origin + "/foo.html");
do_check_eq(provider.resolveUri("http://somewhereelse.com/foo.html").spec, "http://somewhereelse.com/foo.html");
do_check_eq(provider.resolveUri("data:text/html,<p>hi").spec, "data:text/html,<p>hi");
}
function* testOrderedProviders(manifests, next) {
let providers = yield SocialService.getProviderList(next);
// add visits for only one of the providers
let visits = [];
let startDate = Date.now() * 1000;
for (let i = 0; i < 10; i++) {
visits.push({
uri: Services.io.newURI(providers[1].shareURL + i, null, null),
visitDate: startDate + i
});
}
PlacesTestUtils.addVisits(visits).then(next);
yield;
let orderedProviders = yield SocialService.getOrderedProviderList(next);
do_check_eq(orderedProviders[0], providers[1]);
do_check_eq(orderedProviders[1], providers[0]);
do_check_true(orderedProviders[0].frecency > orderedProviders[1].frecency);
PlacesTestUtils.clearHistory().then(next);
yield;
}

View file

@ -1,54 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://gre/modules/Services.jsm");
const DEFAULT_PREFS = Services.prefs.getDefaultBranch("social.manifest.");
function run_test() {
// Test must run at startup for migration to occur, so we can only test
// one migration per test file
initApp();
// NOTE: none of the manifests here can have a workerURL set, or we attempt
// to create a FrameWorker and that fails under xpcshell...
let manifest = { // normal provider
name: "provider 1",
origin: "https://example1.com",
builtin: true // as of fx22 this should be true for default prefs
};
DEFAULT_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
Services.prefs.setBoolPref("social.active", true);
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);
runner.appendIterator(testMigration(manifest, next));
runner.next();
}
function* testMigration(manifest, next) {
// look at social.activeProviders, we should have migrated into that, and
// we should be set as a user level pref after migration
do_check_false(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
// we need to access the providers for everything to initialize
yield SocialService.getProviderList(next);
do_check_true(SocialService.enabled);
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString);
activeProviders = JSON.parse(pref);
do_check_true(activeProviders[manifest.origin]);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
do_check_true(JSON.parse(DEFAULT_PREFS.getCharPref(manifest.origin)).builtin);
let userPref = JSON.parse(MANIFEST_PREFS.getCharPref(manifest.origin));
do_check_true(parseInt(userPref.updateDate) > 0);
// migrated providers wont have an installDate
do_check_true(userPref.installDate === 0);
}

View file

@ -1,67 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://gre/modules/Services.jsm");
const DEFAULT_PREFS = Services.prefs.getDefaultBranch("social.manifest.");
function run_test() {
// Test must run at startup for migration to occur, so we can only test
// one migration per test file
initApp();
// NOTE: none of the manifests here can have a workerURL set, or we attempt
// to create a FrameWorker and that fails under xpcshell...
let manifest = { // normal provider
name: "provider 1",
origin: "https://example1.com",
builtin: true // as of fx22 this should be true for default prefs
};
DEFAULT_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
active[manifest.origin] = 1;
// bad.origin tests that a missing manifest does not break migration, bug 859715
active["bad.origin"] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);
runner.appendIterator(testMigration(manifest, next));
runner.next();
}
function* testMigration(manifest, next) {
// look at social.activeProviders, we should have migrated into that, and
// we should be set as a user level pref after migration
do_check_false(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
// we need to access the providers for everything to initialize
yield SocialService.getProviderList(next);
do_check_true(SocialService.enabled);
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString);
activeProviders = JSON.parse(pref);
do_check_true(activeProviders[manifest.origin]);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
do_check_true(JSON.parse(DEFAULT_PREFS.getCharPref(manifest.origin)).builtin);
let userPref = JSON.parse(MANIFEST_PREFS.getCharPref(manifest.origin));
do_check_true(parseInt(userPref.updateDate) > 0);
// migrated providers wont have an installDate
do_check_true(userPref.installDate === 0);
// bug 859715, this should have been removed during migration
do_check_false(!!activeProviders["bad.origin"]);
}

View file

@ -1,61 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://gre/modules/Services.jsm");
function run_test() {
// Test must run at startup for migration to occur, so we can only test
// one migration per test file
initApp();
// NOTE: none of the manifests here can have a workerURL set, or we attempt
// to create a FrameWorker and that fails under xpcshell...
let manifest = { // normal provider
name: "provider 1",
origin: "https://example1.com",
};
MANIFEST_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
active[manifest.origin] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
// social.enabled pref is the key focus of this test. We set the user pref,
// and then migration should a) remove the provider from activeProviders and
// b) unset social.enabled
Services.prefs.setBoolPref("social.enabled", false);
Cu.import("resource:///modules/SocialService.jsm");
let runner = new AsyncRunner();
let next = runner.next.bind(runner);
runner.appendIterator(testMigration(manifest, next));
runner.next();
}
function* testMigration(manifest, next) {
// look at social.activeProviders, we should have migrated into that, and
// we should be set as a user level pref after migration
do_check_true(Services.prefs.prefHasUserValue("social.enabled"));
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
// we need to access the providers for everything to initialize
yield SocialService.getProviderList(next);
do_check_false(SocialService.enabled);
do_check_false(Services.prefs.prefHasUserValue("social.enabled"));
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString).data;
activeProviders = JSON.parse(pref);
do_check_true(activeProviders[manifest.origin] == undefined);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
}

View file

@ -1,32 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
function run_test() {
// we are testing worker startup specifically
do_test_pending();
add_test(testStartupEnabled);
add_test(testDisableAfterStartup);
do_initialize_social(true, run_next_test);
}
function testStartupEnabled() {
// wait on startup before continuing
do_check_eq(Social.providers.length, 2, "two social providers enabled");
do_check_true(Social.providers[0].enabled, "provider 0 is enabled");
do_check_true(Social.providers[1].enabled, "provider 1 is enabled");
run_next_test();
}
function testDisableAfterStartup() {
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
SocialService.disableProvider(Social.providers[0].origin, function() {
do_wait_observer("social:providers-changed", function() {
do_check_eq(Social.enabled, false, "Social is disabled");
do_check_eq(Social.providers.length, 0, "no social providers available");
do_test_finished();
run_next_test();
});
SocialService.disableProvider(Social.providers[0].origin)
});
}

View file

@ -1,29 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
function run_test() {
// we are testing worker startup specifically
do_test_pending();
add_test(testStartupDisabled);
add_test(testEnableAfterStartup);
do_initialize_social(false, run_next_test);
}
function testStartupDisabled() {
// wait on startup before continuing
do_check_false(Social.enabled, "Social is disabled");
do_check_eq(Social.providers.length, 0, "zero social providers available");
run_next_test();
}
function testEnableAfterStartup() {
do_add_providers(function () {
do_check_true(Social.enabled, "Social is enabled");
do_check_eq(Social.providers.length, 2, "two social providers available");
do_check_true(Social.providers[0].enabled, "provider 0 is enabled");
do_check_true(Social.providers[1].enabled, "provider 1 is enabled");
do_test_finished();
run_next_test();
});
}

View file

@ -1,13 +0,0 @@
[DEFAULT]
head = head.js
tail =
firefox-appdir = browser
skip-if = toolkit == 'android'
support-files = blocklist.xml
[test_social.js]
[test_socialDisabledStartup.js]
[test_SocialService.js]
[test_SocialServiceMigration21.js]
[test_SocialServiceMigration22.js]
[test_SocialServiceMigration29.js]

View file

@ -1,9 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(req, resp) {
let suffixes = ["foo", "bar"];
let data = [req.queryString, suffixes.map(s => req.queryString + s)];
resp.setHeader("Content-Type", "application/json", false);
resp.write(JSON.stringify(data));
}

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>browser_UsageTelemetry usageTelemetrySearchSuggestions.xml</ShortName>
<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/modules/test/usageTelemetrySearchSuggestions.sjs?{searchTerms}"/>
<Url type="text/html" method="GET" template="http://example.com" rel="searchform"/>
</SearchPlugin>

View file

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

View file

@ -1,110 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource:///modules/AttributionCode.jsm");
Cu.import('resource://gre/modules/osfile.jsm');
Cu.import("resource://gre/modules/Services.jsm");
let validAttrCodes = [
{code: "source%3Dgoogle.com%26medium%3Dorganic%26campaign%3D(not%20set)%26content%3D(not%20set)",
parsed: {"source": "google.com", "medium": "organic",
"campaign": "(not%20set)", "content": "(not%20set)"}},
{code: "source%3Dgoogle.com%26medium%3Dorganic%26campaign%3D%26content%3D",
parsed: {"source": "google.com", "medium": "organic"}},
{code: "source%3Dgoogle.com%26medium%3Dorganic%26campaign%3D(not%20set)",
parsed: {"source": "google.com", "medium": "organic", "campaign": "(not%20set)"}},
{code: "source%3Dgoogle.com%26medium%3Dorganic",
parsed: {"source": "google.com", "medium": "organic"}},
{code: "source%3Dgoogle.com",
parsed: {"source": "google.com"}},
{code: "medium%3Dgoogle.com",
parsed: {"medium": "google.com"}},
{code: "campaign%3Dgoogle.com",
parsed: {"campaign": "google.com"}},
{code: "content%3Dgoogle.com",
parsed: {"content": "google.com"}}
];
let invalidAttrCodes = [
// Empty string
"",
// Not escaped
"source=google.com&medium=organic&campaign=(not set)&content=(not set)",
// Too long
"source%3Dreallyreallyreallyreallyreallyreallyreallyreallyreallylongdomain.com%26medium%3Dorganic%26campaign%3D(not%20set)%26content%3Dalmostexactlyenoughcontenttomakethisstringlongerthanthe200characterlimit",
// Unknown key name
"source%3Dgoogle.com%26medium%3Dorganic%26large%3Dgeneticallymodified",
// Empty key name
"source%3Dgoogle.com%26medium%3Dorganic%26%3Dgeneticallymodified"
];
function* writeAttributionFile(data) {
let appDir = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
let file = appDir.clone();
file.append(Services.appinfo.vendor || "mozilla");
file.append(AppConstants.MOZ_APP_NAME);
yield OS.File.makeDir(file.path,
{from: appDir.path, ignoreExisting: true});
file.append("postSigningData");
yield OS.File.writeAtomic(file.path, data);
}
/**
* Test validation of attribution codes,
* to make sure we reject bad ones and accept good ones.
*/
add_task(function* testValidAttrCodes() {
for (let entry of validAttrCodes) {
AttributionCode._clearCache();
yield writeAttributionFile(entry.code);
let result = yield AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, entry.parsed,
"Parsed code should match expected value, code was: " + entry.code);
}
AttributionCode._clearCache();
});
/**
* Make sure codes with various formatting errors are not seen as valid.
*/
add_task(function* testInvalidAttrCodes() {
for (let code of invalidAttrCodes) {
AttributionCode._clearCache();
yield writeAttributionFile(code);
let result = yield AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, {},
"Code should have failed to parse: " + code);
}
AttributionCode._clearCache();
});
/**
* Test the cache by deleting the attribution data file
* and making sure we still get the expected code.
*/
add_task(function* testDeletedFile() {
// Set up the test by clearing the cache and writing a valid file.
yield writeAttributionFile(validAttrCodes[0].code);
let result = yield AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, validAttrCodes[0].parsed,
"The code should be readable directly from the file");
// Delete the file and make sure we can still read the value back from cache.
yield AttributionCode.deleteFileAsync();
result = yield AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, validAttrCodes[0].parsed,
"The code should be readable from the cache");
// Clear the cache and check we can't read anything.
AttributionCode._clearCache();
result = yield AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, {},
"Shouldn't be able to get a code after file is deleted and cache is cleared");
});

File diff suppressed because it is too large Load diff

View file

@ -1,138 +0,0 @@
"use strict";
const kEnabledPref = "browser.laterrun.enabled";
const kPagePrefRoot = "browser.laterrun.pages.";
const kSessionCountPref = "browser.laterrun.bookkeeping.sessionCount";
const kProfileCreationTime = "browser.laterrun.bookkeeping.profileCreationTime";
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource:///modules/LaterRun.jsm");
Services.prefs.setBoolPref(kEnabledPref, true);
Components.utils.import("resource://testing-common/AppInfo.jsm");
updateAppInfo();
add_task(function* test_page_applies() {
Services.prefs.setCharPref(kPagePrefRoot + "test_LaterRun_unittest.url", "https://www.mozilla.org/%VENDOR%/%NAME%/%ID%/%VERSION%/");
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumHoursSinceInstall", 10);
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumSessionCount", 3);
let pages = LaterRun.readPages();
// We have to filter the pages because it's possible Firefox ships with other URLs
// that get included in this test.
pages = pages.filter(page => page.pref == kPagePrefRoot + "test_LaterRun_unittest.");
Assert.equal(pages.length, 1, "Got 1 page");
let page = pages[0];
Assert.equal(page.pref, kPagePrefRoot + "test_LaterRun_unittest.", "Should know its own pref");
Assert.equal(page.minimumHoursSinceInstall, 10, "Needs to have 10 hours since install");
Assert.equal(page.minimumSessionCount, 3, "Needs to have 3 sessions");
Assert.equal(page.requireBoth, false, "Either requirement is enough");
let expectedURL = "https://www.mozilla.org/" +
Services.appinfo.vendor + "/" +
Services.appinfo.name + "/" +
Services.appinfo.ID + "/" +
Services.appinfo.version + "/";
Assert.equal(page.url, expectedURL, "URL is stored correctly");
Assert.ok(page.applies({hoursSinceInstall: 1, sessionCount: 3}),
"Applies when session count has been met.");
Assert.ok(page.applies({hoursSinceInstall: 1, sessionCount: 4}),
"Applies when session count has been exceeded.");
Assert.ok(page.applies({hoursSinceInstall: 10, sessionCount: 2}),
"Applies when total session time has been met.");
Assert.ok(page.applies({hoursSinceInstall: 20, sessionCount: 2}),
"Applies when total session time has been exceeded.");
Assert.ok(page.applies({hoursSinceInstall: 10, sessionCount: 3}),
"Applies when both time and session count have been met.");
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 1}),
"Does not apply when neither time and session count have been met.");
page.requireBoth = true;
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 3}),
"Does not apply when only session count has been met.");
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 4}),
"Does not apply when only session count has been exceeded.");
Assert.ok(!page.applies({hoursSinceInstall: 10, sessionCount: 2}),
"Does not apply when only total session time has been met.");
Assert.ok(!page.applies({hoursSinceInstall: 20, sessionCount: 2}),
"Does not apply when only total session time has been exceeded.");
Assert.ok(page.applies({hoursSinceInstall: 10, sessionCount: 3}),
"Applies when both time and session count have been met.");
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 1}),
"Does not apply when neither time and session count have been met.");
// Check that pages that have run never apply:
Services.prefs.setBoolPref(kPagePrefRoot + "test_LaterRun_unittest.hasRun", true);
page.requireBoth = false;
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 3}),
"Does not apply when page has already run (sessionCount equal).");
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 4}),
"Does not apply when page has already run (sessionCount exceeding).");
Assert.ok(!page.applies({hoursSinceInstall: 10, sessionCount: 2}),
"Does not apply when page has already run (hoursSinceInstall equal).");
Assert.ok(!page.applies({hoursSinceInstall: 20, sessionCount: 2}),
"Does not apply when page has already run (hoursSinceInstall exceeding).");
Assert.ok(!page.applies({hoursSinceInstall: 10, sessionCount: 3}),
"Does not apply when page has already run (both criteria equal).");
Assert.ok(!page.applies({hoursSinceInstall: 1, sessionCount: 1}),
"Does not apply when page has already run (both criteria insufficient anyway).");
clearAllPagePrefs();
});
add_task(function* test_get_URL() {
Services.prefs.setIntPref(kProfileCreationTime, Math.floor((Date.now() - 11 * 60 * 60 * 1000) / 1000));
Services.prefs.setCharPref(kPagePrefRoot + "test_LaterRun_unittest.url", "https://www.mozilla.org/");
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumHoursSinceInstall", 10);
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumSessionCount", 3);
let pages = LaterRun.readPages();
// We have to filter the pages because it's possible Firefox ships with other URLs
// that get included in this test.
pages = pages.filter(page => page.pref == kPagePrefRoot + "test_LaterRun_unittest.");
Assert.equal(pages.length, 1, "Should only be 1 matching page");
let page = pages[0];
let url;
do {
url = LaterRun.getURL();
// We have to loop because it's possible Firefox ships with other URLs that get triggered by
// this test.
} while (url && url != "https://www.mozilla.org/");
Assert.equal(url, "https://www.mozilla.org/", "URL should be as expected when prefs are set.");
Assert.ok(Services.prefs.prefHasUserValue(kPagePrefRoot + "test_LaterRun_unittest.hasRun"), "Should have set pref");
Assert.ok(Services.prefs.getBoolPref(kPagePrefRoot + "test_LaterRun_unittest.hasRun"), "Should have set pref to true");
Assert.ok(page.hasRun, "Other page objects should know it has run, too.");
clearAllPagePrefs();
});
add_task(function* test_insecure_urls() {
Services.prefs.setCharPref(kPagePrefRoot + "test_LaterRun_unittest.url", "http://www.mozilla.org/");
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumHoursSinceInstall", 10);
Services.prefs.setIntPref(kPagePrefRoot + "test_LaterRun_unittest.minimumSessionCount", 3);
let pages = LaterRun.readPages();
// We have to filter the pages because it's possible Firefox ships with other URLs
// that get triggered in this test.
pages = pages.filter(page => page.pref == kPagePrefRoot + "test_LaterRun_unittest.");
Assert.equal(pages.length, 0, "URL with non-https scheme should get ignored");
clearAllPagePrefs();
});
add_task(function* test_dynamic_pref_getter_setter() {
delete LaterRun._sessionCount;
Services.prefs.setIntPref(kSessionCountPref, 0);
Assert.equal(LaterRun.sessionCount, 0, "Should start at 0");
LaterRun.sessionCount++;
Assert.equal(LaterRun.sessionCount, 1, "Should increment.");
Assert.equal(Services.prefs.getIntPref(kSessionCountPref), 1, "Should update pref");
});
function clearAllPagePrefs() {
let allChangedPrefs = Services.prefs.getChildList(kPagePrefRoot);
for (let pref of allChangedPrefs) {
Services.prefs.clearUserPref(pref);
}
}

View file

@ -1,115 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
Components.utils.import("resource:///modules/SitePermissions.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
add_task(function* testPermissionsListing() {
Assert.deepEqual(SitePermissions.listPermissions().sort(),
["camera", "cookie", "desktop-notification", "geo", "image",
"indexedDB", "install", "microphone", "popup", "screen"],
"Correct list of all permissions");
});
add_task(function* testGetAllByURI() {
// check that it returns an empty array on an invalid URI
// like a file URI, which doesn't support site permissions
let wrongURI = Services.io.newURI("file:///example.js", null, null)
Assert.deepEqual(SitePermissions.getAllByURI(wrongURI), []);
let uri = Services.io.newURI("https://example.com", null, null)
Assert.deepEqual(SitePermissions.getAllByURI(uri), []);
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
Assert.deepEqual(SitePermissions.getAllByURI(uri), [
{ id: "camera", state: SitePermissions.ALLOW }
]);
SitePermissions.set(uri, "microphone", SitePermissions.SESSION);
SitePermissions.set(uri, "desktop-notification", SitePermissions.BLOCK);
Assert.deepEqual(SitePermissions.getAllByURI(uri), [
{ id: "camera", state: SitePermissions.ALLOW },
{ id: "microphone", state: SitePermissions.SESSION },
{ id: "desktop-notification", state: SitePermissions.BLOCK }
]);
SitePermissions.remove(uri, "microphone");
Assert.deepEqual(SitePermissions.getAllByURI(uri), [
{ id: "camera", state: SitePermissions.ALLOW },
{ id: "desktop-notification", state: SitePermissions.BLOCK }
]);
SitePermissions.remove(uri, "camera");
SitePermissions.remove(uri, "desktop-notification");
Assert.deepEqual(SitePermissions.getAllByURI(uri), []);
// XXX Bug 1303108 - Control Center should only show non-default permissions
SitePermissions.set(uri, "addon", SitePermissions.BLOCK);
Assert.deepEqual(SitePermissions.getAllByURI(uri), []);
SitePermissions.remove(uri, "addon");
});
add_task(function* testGetPermissionDetailsByURI() {
// check that it returns an empty array on an invalid URI
// like a file URI, which doesn't support site permissions
let wrongURI = Services.io.newURI("file:///example.js", null, null)
Assert.deepEqual(SitePermissions.getPermissionDetailsByURI(wrongURI), []);
let uri = Services.io.newURI("https://example.com", null, null)
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
SitePermissions.set(uri, "cookie", SitePermissions.SESSION);
SitePermissions.set(uri, "popup", SitePermissions.BLOCK);
let permissions = SitePermissions.getPermissionDetailsByURI(uri);
let camera = permissions.find(({id}) => id === "camera");
Assert.deepEqual(camera, {
id: "camera",
label: "Use the Camera",
state: SitePermissions.ALLOW,
availableStates: [
{ id: SitePermissions.UNKNOWN, label: "Always Ask" },
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
// check that removed permissions (State.UNKNOWN) are skipped
SitePermissions.remove(uri, "camera");
permissions = SitePermissions.getPermissionDetailsByURI(uri);
camera = permissions.find(({id}) => id === "camera");
Assert.equal(camera, undefined);
// check that different available state values are represented
let cookie = permissions.find(({id}) => id === "cookie");
Assert.deepEqual(cookie, {
id: "cookie",
label: "Set Cookies",
state: SitePermissions.SESSION,
availableStates: [
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.SESSION, label: "Allow for Session" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
let popup = permissions.find(({id}) => id === "popup");
Assert.deepEqual(popup, {
id: "popup",
label: "Open Pop-up Windows",
state: SitePermissions.BLOCK,
availableStates: [
{ id: SitePermissions.ALLOW, label: "Allow" },
{ id: SitePermissions.BLOCK, label: "Block" },
]
});
SitePermissions.remove(uri, "cookie");
SitePermissions.remove(uri, "popup");
});

View file

@ -1,11 +0,0 @@
[DEFAULT]
head =
tail =
firefox-appdir = browser
skip-if = toolkit == 'android'
[test_AttributionCode.js]
skip-if = os != 'win'
[test_DirectoryLinksProvider.js]
[test_SitePermissions.js]
[test_LaterRun.js]