added some tests in the browser html

This commit is contained in:
Kendall Werts 2020-01-08 15:37:08 -06:00
parent b1a4332e0c
commit 38e4c5bde7
4 changed files with 253 additions and 123 deletions

View file

@ -61,9 +61,9 @@ const assignManager = {
if (storageResponse && siteStoreKey in storageResponse) {
resolve(storageResponse[siteStoreKey]);
}
resolve(()=> { throw new Error (siteStoreKey, " does not exist"); });
resolve(null);
}).catch((e) => {
throw e; // reject(e);
reject(e);
});
});
},
@ -101,8 +101,11 @@ const assignManager = {
const siteConfigs = await this.area.get();
for(const urlKey of Object.keys(siteConfigs)) {
if (urlKey.includes("siteContainerMap@@_")) {
// For some reason this is stored as string... lets check them both as that
if (!!userContextId && String(siteConfigs[urlKey].userContextId) !== String(userContextId)) {
// For some reason this is stored as string... lets check
// them both as that
if (!!userContextId &&
String(siteConfigs[urlKey].userContextId)
!== String(userContextId)) {
continue;
}
const site = siteConfigs[urlKey];
@ -119,7 +122,8 @@ const assignManager = {
_neverAsk(m) {
const pageUrl = m.pageUrl;
if (m.neverAsk === true) {
// If we have existing data and for some reason it hasn't been deleted etc lets update it
// If we have existing data and for some reason it hasn't been
// deleted etc lets update it
this.storageArea.get(pageUrl).then((siteSettings) => {
if (siteSettings) {
siteSettings.neverAsk = true;
@ -138,7 +142,8 @@ const assignManager = {
return true;
},
// Before a request is handled by the browser we decide if we should route through a different container
// Before a request is handled by the browser we decide if we should
// route through a different container
async onBeforeRequest(options) {
if (options.frameId !== 0 || options.tabId === -1) {
return {};
@ -150,13 +155,14 @@ const assignManager = {
]);
let container;
try {
container = await browser.contextualIdentities.get(backgroundLogic.cookieStoreId(siteSettings.userContextId));
container = await browser.contextualIdentities
.get(backgroundLogic.cookieStoreId(siteSettings.userContextId));
} catch (e) {
container = false;
}
// The container we have in the assignment map isn't present any more so lets remove it
// then continue the existing load
// The container we have in the assignment map isn't present any
// more so lets remove it then continue the existing load
if (siteSettings && !container) {
this.deleteContainer(siteSettings.userContextId);
return {};
@ -173,7 +179,8 @@ const assignManager = {
const openTabId = removeTab ? tab.openerTabId : tab.id;
if (!this.canceledRequests[tab.id]) {
// we decided to cancel the request at this point, register canceled request
// we decided to cancel the request at this point, register
// canceled request
this.canceledRequests[tab.id] = {
requestIds: {
[options.requestId]: true
@ -183,8 +190,10 @@ const assignManager = {
}
};
// since webRequest onCompleted and onErrorOccurred are not 100% reliable (see #1120)
// we register a timer here to cleanup canceled requests, just to make sure we don't
// since webRequest onCompleted and onErrorOccurred are not 100%
// reliable (see #1120)
// we register a timer here to cleanup canceled requests, just to
// make sure we don't
// end up in a situation where certain urls in a tab.id stay canceled
setTimeout(() => {
if (this.canceledRequests[tab.id]) {
@ -196,10 +205,12 @@ const assignManager = {
if (this.canceledRequests[tab.id].requestIds[options.requestId] ||
this.canceledRequests[tab.id].urls[options.url]) {
// same requestId or url from the same tab
// this is a redirect that we have to cancel early to prevent opening two tabs
// this is a redirect that we have to cancel early to prevent
// opening two tabs
cancelEarly = true;
}
// we decided to cancel the request at this point, register canceled request
// we decided to cancel the request at this point, register canceled
// request
this.canceledRequests[tab.id].requestIds[options.requestId] = true;
this.canceledRequests[tab.id].urls[options.url] = true;
if (cancelEarly) {
@ -221,15 +232,27 @@ const assignManager = {
this.calculateContextMenu(tab);
/* Removal of existing tabs:
We aim to open the new assigned container tab / warning prompt in it's own tab:
- As the history won't span from one container to another it seems most sane to not try and reopen a tab on history.back()
- When users open a new tab themselves we want to make sure we don't end up with three tabs as per: https://github.com/mozilla/testpilot-containers/issues/421
If we are coming from an internal url that are used for the new tab page (NEW_TAB_PAGES), we can safely close as user is unlikely losing history
Detecting redirects on "new tab" opening actions is pretty hard as we don't get tab history:
- Redirects happen from Short URLs and tracking links that act as a gateway
- Extensions don't provide a way to history crawl for tabs, we could inject content scripts to do this
however they don't run on about:blank so this would likely be just as hacky.
We capture the time the tab was created and close if it was within the timeout to try to capture pages which haven't had user interaction or history.
We aim to open the new assigned container tab / warning prompt in
it's own tab:
- As the history won't span from one container to another it
seems most sane to not try and reopen a tab on history.back()
- When users open a new tab themselves we want to make sure we
don't end up with three tabs as per:
https://github.com/mozilla/testpilot-containers/issues/421
If we are coming from an internal url that are used for the new
tab page (NEW_TAB_PAGES), we can safely close as user is unlikely
losing history
Detecting redirects on "new tab" opening actions is pretty hard
as we don't get tab history:
- Redirects happen from Short URLs and tracking links that act as
a gateway
- Extensions don't provide a way to history crawl for tabs, we
could inject content scripts to do this
however they don't run on about:blank so this would likely be
just as hacky.
We capture the time the tab was created and close if it was within
the timeout to try to capture pages which haven't had user
interaction or history.
*/
if (removeTab) {
browser.tabs.remove(tab.id);
@ -241,10 +264,13 @@ const assignManager = {
init() {
browser.contextMenus.onClicked.addListener((info, tab) => {
info.bookmarkId ? this._onClickedBookmark(info) : this._onClickedHandler(info, tab);
info.bookmarkId ?
this._onClickedBookmark(info) :
this._onClickedHandler(info, tab);
});
// Before a request is handled by the browser we decide if we should route through a different container
// Before a request is handled by the browser we decide if we should
// route through a different container
this.canceledRequests = {};
browser.webRequest.onBeforeRequest.addListener((options) => {
return this.onBeforeRequest(options);
@ -266,21 +292,29 @@ const assignManager = {
},
async resetBookmarksMenuItem() {
const hasPermission = await browser.permissions.contains({permissions: ["bookmarks"]});
const hasPermission = await browser.permissions.contains({
permissions: ["bookmarks"]
});
if (this.hadBookmark === hasPermission) {
return;
}
this.hadBookmark = hasPermission;
if (hasPermission) {
this.initBookmarksMenu();
browser.contextualIdentities.onCreated.addListener(this.contextualIdentityCreated);
browser.contextualIdentities.onUpdated.addListener(this.contextualIdentityUpdated);
browser.contextualIdentities.onRemoved.addListener(this.contextualIdentityRemoved);
browser.contextualIdentities.onCreated
.addListener(this.contextualIdentityCreated);
browser.contextualIdentities.onUpdated
.addListener(this.contextualIdentityUpdated);
browser.contextualIdentities.onRemoved
.addListener(this.contextualIdentityRemoved);
} else {
this.removeBookmarksMenu();
browser.contextualIdentities.onCreated.removeListener(this.contextualIdentityCreated);
browser.contextualIdentities.onUpdated.removeListener(this.contextualIdentityUpdated);
browser.contextualIdentities.onRemoved.removeListener(this.contextualIdentityRemoved);
browser.contextualIdentities.onCreated
.removeListener(this.contextualIdentityCreated);
browser.contextualIdentities.onUpdated
.removeListener(this.contextualIdentityUpdated);
browser.contextualIdentities.onRemoved
.removeListener(this.contextualIdentityRemoved);
}
},
@ -289,19 +323,25 @@ const assignManager = {
parentId: assignManager.OPEN_IN_CONTAINER,
id: changeInfo.contextualIdentity.cookieStoreId,
title: changeInfo.contextualIdentity.name,
icons: { "16": `img/usercontext.svg#${changeInfo.contextualIdentity.icon}` }
icons: { "16": `img/usercontext.svg#${
changeInfo.contextualIdentity.icon
}` }
});
},
contextualIdentityUpdated(changeInfo) {
browser.contextMenus.update(changeInfo.contextualIdentity.cookieStoreId, {
title: changeInfo.contextualIdentity.name,
icons: { "16": `img/usercontext.svg#${changeInfo.contextualIdentity.icon}` }
});
browser.contextMenus.update(
changeInfo.contextualIdentity.cookieStoreId, {
title: changeInfo.contextualIdentity.name,
icons: { "16": `img/usercontext.svg#${
changeInfo.contextualIdentity.icon}` }
});
},
contextualIdentityRemoved(changeInfo) {
browser.contextMenus.remove(changeInfo.contextualIdentity.cookieStoreId);
browser.contextMenus.remove(
changeInfo.contextualIdentity.cookieStoreId
);
},
async _onClickedHandler(info, tab) {
@ -317,7 +357,9 @@ const assignManager = {
} else {
remove = true;
}
await this._setOrRemoveAssignment(tab.id, info.pageUrl, userContextId, remove);
await this._setOrRemoveAssignment(
tab.id, info.pageUrl, userContextId, remove
);
break;
case this.MENU_MOVE_ID:
backgroundLogic.moveTabsToWindow({
@ -338,7 +380,8 @@ const assignManager = {
async _onClickedBookmark(info) {
async function _getBookmarksFromInfo(info) {
const [bookmarkTreeNode] = await browser.bookmarks.get(info.bookmarkId);
const [bookmarkTreeNode] =
await browser.bookmarks.get(info.bookmarkId);
if (bookmarkTreeNode.type === "folder") {
return await browser.bookmarks.getChildren(bookmarkTreeNode.id);
}
@ -347,8 +390,10 @@ const assignManager = {
const bookmarks = await _getBookmarksFromInfo(info);
for (const bookmark of bookmarks) {
// Some checks on the urls from https://github.com/Rob--W/bookmark-container-tab/ thanks!
if ( !/^(javascript|place):/i.test(bookmark.url) && bookmark.type !== "folder") {
// Some checks on the urls from
// https://github.com/Rob--W/bookmark-container-tab/ thanks!
if ( !/^(javascript|place):/i.test(bookmark.url) &&
bookmark.type !== "folder") {
const openInReaderMode = bookmark.url.startsWith("about:reader");
if(openInReaderMode) {
try {
@ -376,7 +421,9 @@ const assignManager = {
if (!("cookieStoreId" in tab)) {
return false;
}
return backgroundLogic.getUserContextIdFromCookieStoreId(tab.cookieStoreId);
return backgroundLogic.getUserContextIdFromCookieStoreId(
tab.cookieStoreId
);
},
isTabPermittedAssign(tab) {

View file

@ -1,4 +1,4 @@
const SYNC_DEBUG = true;
const SYNC_DEBUG = false;
const sync = {
storageArea: {
@ -39,28 +39,32 @@ const sync = {
async backup(options) {
if (SYNC_DEBUG) console.log("backup");
// remove listeners to avoid an infinite loop!
browser.storage.onChanged.removeListener(sync.storageArea.onChangedListener);
browser.storage.onChanged.removeListener(
sync.storageArea.onChangedListener);
removeContextualIdentityListeners();
await updateSyncIdentities();
await updateCookieStoreIdMap();
await updateSyncSiteAssignments();
if (options && options.uuid)
await updateDeletedIdentityList(options.uuid);
if (options && options.siteStoreKey)
await addToDeletedSitesList(options.siteStoreKey);
if (options && options.undelete)
await removeFromDeletedSitesList(options.undelete);
try {
await updateSyncIdentities();
await updateCookieStoreIdMap();
await updateSyncSiteAssignments();
if (options && options.uuid)
await updateDeletedIdentityList(options.uuid);
if (options && options.siteStoreKey)
await addToDeletedSitesList(options.siteStoreKey);
if (options && options.undelete)
await removeFromDeletedSitesList(options.undelete);
if (SYNC_DEBUG) {
const storage = await sync.storageArea.get();
console.log("in sync: ", storage);
const localStorage = await browser.storage.local.get();
console.log("inLocal:", localStorage);
if (SYNC_DEBUG) {
const storage = await sync.storageArea.get();
console.log("in sync: ", storage);
const localStorage = await browser.storage.local.get();
console.log("inLocal:", localStorage);
}
} catch (error) {
console.error("Error backing up", error);
}
await browser.storage.onChanged.addListener(sync.storageArea.onChangedListener);
await addContextualIdentityListeners();
browser.storage.onChanged.addListener(
sync.storageArea.onChangedListener);
addContextualIdentityListeners();
async function updateSyncIdentities() {
const identities = await browser.contextualIdentities.query({});
@ -111,7 +115,8 @@ const sync = {
async cleanup() {
console.log("cleanupSync");
browser.storage.onChanged.removeListener(sync.storageArea.onChangedListener);
browser.storage.onChanged.removeListener(
sync.storageArea.onChangedListener);
const identitiesList =
await sync.storageArea.getStoredObject("identities");
const cookieStoreIDmap =
@ -127,7 +132,8 @@ const sync = {
console.log("removed ", cookieStoreId, " from sync list");
}
}
await browser.storage.onChanged.addListener(sync.storageArea.onChangedListener);
await browser.storage.onChanged.addListener(
sync.storageArea.onChangedListener);
},
onChangedListener(changes, areaName) {
@ -212,7 +218,8 @@ async function restoreFirstRun() {
async function reconcileIdentitiesByName(){
console.log("reconcileIdentitiesByName");
const localIdentities = await browser.contextualIdentities.query({});
const syncIdentities = await sync.storageArea.getStoredObject("identities");
const syncIdentities =
await sync.storageArea.getStoredObject("identities");
const cookieStoreIDmap =
await sync.storageArea.getStoredObject("cookieStoreIDmap");
for (const syncIdentity of syncIdentities) {
@ -311,7 +318,8 @@ async function reconcileSiteAssignments() {
assignedSite,
cookieStoreIDmap,
){
const syncCookieStoreId = "firefox-container-" + assignedSite.userContextId;
const syncCookieStoreId =
"firefox-container-" + assignedSite.userContextId;
return cookieStoreIDmap[syncCookieStoreId];
}
}
@ -331,7 +339,8 @@ async function setAssignmentWithUUID (newUUID, assignedSite, urlKey) {
}
async function runSync() {
browser.storage.onChanged.removeListener(sync.storageArea.onChangedListener);
browser.storage.onChanged.removeListener(
sync.storageArea.onChangedListener);
removeContextualIdentityListeners();
console.log("runSync");
await identityState.storageArea.cleanup();
@ -416,7 +425,8 @@ async function reconcileIdentitiesByUUID() {
function findIdentityFromSync(cookieStoreId, identitiesList){
for (const identity of identitiesList) {
const { name, color, icon } = identity;
if (identity.cookieStoreId === cookieStoreId) return { name, color, icon };
if (identity.cookieStoreId === cookieStoreId)
return { name, color, icon };
}
}

View file

@ -1,10 +1,12 @@
browser.tests = {
async runAll() {
await this.test1();
await this.test2();
},
async test1() {
await browser.tests.stopSyncListeners();
console.log("Testing new install with no sync");
// sync state on install: no sync data
await browser.storage.sync.clear();
@ -52,6 +54,123 @@ browser.tests = {
console.log("Finished!");
},
async test2() {
await browser.tests.stopSyncListeners();
console.log("Testing sync differing");
// sync state on install: no sync data
await browser.storage.sync.clear();
const syncData = {
"identities": [
{
"name": "Personal",
"icon": "fingerprint",
"iconUrl": "resource://usercontext-content/fingerprint.svg",
"color": "red",
"colorCode": "#37adff",
"cookieStoreId": "firefox-container-146"
},
{
"name": "Oscar",
"icon": "dollar",
"iconUrl": "resource://usercontext-content/dollar.svg",
"color": "green",
"colorCode": "#51cd00",
"cookieStoreId": "firefox-container-147"
},
{
"name": "Mozilla",
"icon": "pet",
"iconUrl": "resource://usercontext-content/briefcase.svg",
"color": "red",
"colorCode": "#ff613d",
"cookieStoreId": "firefox-container-148"
},
{
"name": "Groceries, obviously",
"icon": "cart",
"iconUrl": "resource://usercontext-content/cart.svg",
"color": "pink",
"colorCode": "#ffcb00",
"cookieStoreId": "firefox-container-149"
},
{
"name": "Facebook",
"icon": "fence",
"iconUrl": "resource://usercontext-content/fence.svg",
"color": "toolbar",
"colorCode": "#7c7c7d",
"cookieStoreId": "firefox-container-150"
}
],
"cookieStoreIDmap": {
"firefox-container-146": "22ded543-5173-44a5-a47a-8813535945ca",
"firefox-container-147": "63e5212f-0858-418e-b5a3-09c2dea61fcd",
"firefox-container-148": "71335417-158e-4d74-a55b-e9e9081601ec",
"firefox-container-149": "59c4e5f7-fe3b-435a-ae60-1340db31a91b",
"firefox-container-150": "3dc916fb-8c0a-4538-9758-73ef819a45f7"
},
"assignedSites": {}
};
await browser.storage.sync.set(syncData);
await browser.storage.local.clear();
const localData = {
"browserActionBadgesClicked": [ "6.1.1" ],
"containerTabsOpened": 7,
"identitiesState@@_firefox-default": { "hiddenTabs": [] },
"onboarding-stage": 5
};
await this.removeAllContainers();
console.log("TEST_CONTAINERS.length", TEST_CONTAINERS.length);
for (let i=0; i < TEST_CONTAINERS.length; i++) {
//build identities
const newIdentity =
await browser.contextualIdentities.create(TEST_CONTAINERS[i]);
// fill identies with site assignments
if (TEST_ASSIGNMENTS[i]) {
localData[TEST_ASSIGNMENTS[i]] = {
"userContextId":
String(
newIdentity.cookieStoreId.replace(/^firefox-container-/, "")
),
"neverAsk": true
};
}
}
await browser.storage.local.set(localData);
console.log("local storage set: ", await browser.storage.local.get());
await sync.initSync();
const getSync = await browser.storage.sync.get();
const getAssignedSites =
await assignManager.storageArea.getAssignedSites();
const identities = await browser.contextualIdentities.query({});
const localCookieStoreIDmap =
await identityState.getCookieStoreIDuuidMap();
console.log(getSync.cookieStoreIDmap);
console.assert(
Object.keys(getSync.cookieStoreIDmap).length === 6,
"cookieStoreIDmap should have 6 entries"
);
console.assert(
Object.keys(localCookieStoreIDmap).length === 7,
"localCookieStoreIDmap should have 7 entries"
);
console.assert(
identities.length === 6,
"There should be 6 identities"
);
console.assert(
Object.keys(getAssignedSites).length === 5,
"There should be 5 site assignments"
);
console.log("Finished!");
},
async removeAllContainers() {
const identities = await browser.contextualIdentities.query({});
for (const identity of identities) {
@ -99,19 +218,13 @@ const TEST_CONTAINERS = [
},
];
browser.resetMAC1 = async function () {
// for debugging and testing: remove all containers except the default 4 and the first one created
browser.tests.stopSyncListeners();
// sync state on install: no sync data
await browser.storage.sync.clear();
// FF1: no sync, Only default containers and 1 extra
browser.storage.local.clear();
const localData = {"browserActionBadgesClicked":["6.1.1"],"containerTabsOpened":6,"identitiesState@@_firefox-container-1":{"hiddenTabs":[]},"identitiesState@@_firefox-container-2":{"hiddenTabs":[]},"identitiesState@@_firefox-container-3":{"hiddenTabs":[]},"identitiesState@@_firefox-container-4":{"hiddenTabs":[]},"identitiesState@@_firefox-container-6":{"hiddenTabs":[]},"identitiesState@@_firefox-default":{"hiddenTabs":[]},"onboarding-stage":5,"siteContainerMap@@_twitter.com":{"userContextId":"1","neverAsk":true},"siteContainerMap@@_www.facebook.com":{"userContextId":"2","neverAsk":true},"siteContainerMap@@_www.linkedin.com":{"userContextId":"4","neverAsk":false}};
browser.storage.local.set(localData);
};
const TEST_ASSIGNMENTS = [
"siteContainerMap@@_developer.mozilla.org",
"siteContainerMap@@_twitter.com",
"siteContainerMap@@_www.facebook.com",
"siteContainerMap@@_www.linkedin.com",
"siteContainerMap@@_reddit.com"
];
browser.resetMAC2 = async function () {
// for debugging and testing: remove all containers except the default 4 and the first one created

View file

@ -65,44 +65,4 @@ describe("Sync", () => {
console.log("!!!b");
});
it("should sync for the first time", async () => {
const mozContainer = await background.browser.contextualIdentities.create({
name:"Test",
color:"green",
icon:"pet"
});
console.log(await background.browser.contextualIdentities.query({}));
await helper.browser.initSyncTest({localStorage:SYNC_TEST_1_LOCAL});
console.log(await background.browser.storage.local.get());
for (const containerName of SYNC_TEST_CONTAINERS) {
const storageKeyString = "identitiesState@@_" + containerName;
const answer = await background.browser.storage.local.get(storageKeyString);
expect(answer[storageKeyString].hasOwnProperty("macAddonUUID")).to.be.true;
}
const storageKeyString = "identitiesState@@_" + mozContainer.cookieStoreId;
const answer = await background.browser.storage.local.get(storageKeyString);
expect(answer[storageKeyString].hasOwnProperty("macAddonUUID")).to.be.true;
});
});
const SYNC_TEST_1_LOCAL = {
"browserActionBadgesClicked":["6.1.1"],
"containerTabsOpened":6,
"identitiesState@@_firefox-container-1":{"hiddenTabs":[]},
"identitiesState@@_firefox-container-2":{"hiddenTabs":[]},
"identitiesState@@_firefox-container-3":{"hiddenTabs":[]},
"identitiesState@@_firefox-container-4":{"hiddenTabs":[]},
"identitiesState@@_firefox-container-6":{"hiddenTabs":[]},
"identitiesState@@_firefox-default":{"hiddenTabs":[]},
"onboarding-stage":5,
"siteContainerMap@@_twitter.com":{"userContextId":"1","neverAsk":true},
"siteContainerMap@@_www.facebook.com":{"userContextId":"2","neverAsk":true},
"siteContainerMap@@_www.linkedin.com":{"userContextId":"4","neverAsk":false}
};
const SYNC_TEST_CONTAINERS = [
"firefox-container-1",
"firefox-container-2",
"firefox-container-3",
"firefox-container-4"
];
});