Moving remove, add and update code into the web extension background for stability

This commit is contained in:
Jonathan Kingston 2017-05-08 14:32:35 +01:00
parent 337dee2061
commit 1ec86c7fd2
3 changed files with 113 additions and 97 deletions

View file

@ -74,17 +74,6 @@ const assignManager = {
}, },
init() { init() {
browser.runtime.onMessage.addListener((m) => {
switch (m.type) {
case "delete-container":
assignManager.deleteContainer(m.message.userContextId);
break;
case "never-ask":
this._neverAsk(m);
break;
}
});
browser.contextMenus.onClicked.addListener((info, tab) => { browser.contextMenus.onClicked.addListener((info, tab) => {
const userContextId = this.getUserContextIdFromCookieStore(tab); const userContextId = this.getUserContextIdFromCookieStore(tab);
// Mapping ${URL(info.pageUrl).hostname} to ${userContextId} // Mapping ${URL(info.pageUrl).hostname} to ${userContextId}
@ -108,8 +97,7 @@ const assignManager = {
message: `Successfully ${actionName} site to always open in this container`, message: `Successfully ${actionName} site to always open in this container`,
iconUrl: browser.extension.getURL("/img/onboarding-1.png") iconUrl: browser.extension.getURL("/img/onboarding-1.png")
}); });
browser.runtime.sendMessage({ backgroundLogic.sendTelemetryPayload({
method: "sendTelemetryPayload",
event: `${actionName}-container-assignment`, event: `${actionName}-container-assignment`,
userContextId: userContextId, userContextId: userContextId,
}); });
@ -229,14 +217,12 @@ const assignManager = {
// If the user has explicitly checked "Never Ask Again" on the warning page we will send them straight there // If the user has explicitly checked "Never Ask Again" on the warning page we will send them straight there
if (neverAsk) { if (neverAsk) {
browser.tabs.create({url, cookieStoreId: `firefox-container-${userContextId}`, index}); browser.tabs.create({url, cookieStoreId: `firefox-container-${userContextId}`, index});
browser.runtime.sendMessage({ backgroundLogic.sendTelemetryPayload({
method: "sendTelemetryPayload",
event: "auto-reload-page-in-container", event: "auto-reload-page-in-container",
userContextId: userContextId, userContextId: userContextId,
}); });
} else { } else {
browser.runtime.sendMessage({ backgroundLogic.sendTelemetryPayload({
method: "sendTelemetryPayload",
event: "prompt-to-reload-page-in-container", event: "prompt-to-reload-page-in-container",
userContextId: userContextId, userContextId: userContextId,
}); });
@ -251,6 +237,77 @@ const assignManager = {
} }
}; };
const backgroundLogic = {
deleteContainer(userContextId) {
this.sendTelemetryPayload({
event: "delete-container",
userContextId
});
const removeTabsPromise = this._containerTabs(userContextId).then((tabs) => {
const tabIds = tabs.map((tab) => tab.id);
return browser.tabs.remove(tabIds);
});
return new Promise((resolve) => {
removeTabsPromise.then(() => {
const removed = browser.contextualIdentities.remove(this.cookieStoreId(userContextId));
removed.then(() => {
assignManager.deleteContainer(userContextId);
browser.runtime.sendMessage({
method: "forgetIdentityAndRefresh"
}).then(() => {
resolve({done: true, userContextId});
}).catch((e) => {throw e;});
}).catch((e) => {throw e;});
}).catch((e) => {throw e;});
});
},
createOrUpdateContainer(options) {
let donePromise;
if (options.userContextId) {
donePromise = browser.contextualIdentities.update(
this.cookieStoreId(options.userContextId),
options.params
);
this.sendTelemetryPayload({
event: "edit-container",
userContextId: options.userContextId
});
} else {
donePromise = browser.contextualIdentities.create(options.params);
this.sendTelemetryPayload({
event: "add-container"
});
}
return donePromise.then(() => {
browser.runtime.sendMessage({
method: "refreshNeeded"
});
});
},
sendTelemetryPayload(message = {}) {
if (!message.event) {
throw new Error("Missing event name for telemetry");
}
message.method = "sendTelemetryPayload";
browser.runtime.sendMessage(message);
},
cookieStoreId(userContextId) {
return `firefox-container-${userContextId}`;
},
_containerTabs(userContextId) {
return browser.tabs.query({
cookieStoreId: this.cookieStoreId(userContextId)
}).catch((e) => {throw e;});
},
};
const messageHandler = { const messageHandler = {
// After the timer completes we assume it's a tab the user meant to keep open // After the timer completes we assume it's a tab the user meant to keep open
// We use this to catch redirected tabs that have just opened // We use this to catch redirected tabs that have just opened
@ -258,6 +315,23 @@ const messageHandler = {
LAST_CREATED_TAB_TIMER: 2000, LAST_CREATED_TAB_TIMER: 2000,
init() { init() {
browser.runtime.onMessage.addListener((m) => {
let response;
switch (m.method) {
case "deleteContainer":
response = backgroundLogic.deleteContainer(m.message.userContextId);
break;
case "createOrUpdateContainer":
response = backgroundLogic.createOrUpdateContainer(m.message);
break;
case "neverAsk":
assignManager._neverAsk(m);
break;
}
return response;
});
// Handles messages from index.js // Handles messages from index.js
const port = browser.runtime.connect(); const port = browser.runtime.connect();
port.onMessage.addListener(m => { port.onMessage.addListener(m => {
@ -416,8 +490,7 @@ const tabPageCounter = {
return; return;
} }
if (why === "user-closed-tab" && this.counters[tabId].tab) { if (why === "user-closed-tab" && this.counters[tabId].tab) {
browser.runtime.sendMessage({ backgroundLogic.sendTelemetryPayload({
method: "sendTelemetryPayload",
event: "page-requests-completed-per-tab", event: "page-requests-completed-per-tab",
userContextId: this.counters[tabId].tab.cookieStoreId, userContextId: this.counters[tabId].tab.cookieStoreId,
pageRequestCount: this.counters[tabId].tab.pageRequests pageRequestCount: this.counters[tabId].tab.pageRequests
@ -426,8 +499,7 @@ const tabPageCounter = {
// delete both the 'tab' and 'activity' counters // delete both the 'tab' and 'activity' counters
delete this.counters[tabId]; delete this.counters[tabId];
} else if (why === "user-went-idle" && this.counters[tabId].activity) { } else if (why === "user-went-idle" && this.counters[tabId].activity) {
browser.runtime.sendMessage({ backgroundLogic.sendTelemetryPayload({
method: "sendTelemetryPayload",
event: "page-requests-completed-per-activity", event: "page-requests-completed-per-activity",
userContextId: this.counters[tabId].activity.cookieStoreId, userContextId: this.counters[tabId].activity.cookieStoreId,
pageRequestCount: this.counters[tabId].activity.pageRequests pageRequestCount: this.counters[tabId].activity.pageRequests

View file

@ -9,7 +9,7 @@ document.getElementById("redirect-form").addEventListener("submit", (e) => {
// Sending neverAsk message to background to store for next time we see this process // Sending neverAsk message to background to store for next time we see this process
if (neverAsk) { if (neverAsk) {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
type: "never-ask", method: "neverAsk",
neverAsk: true, neverAsk: true,
pageUrl: redirectUrl pageUrl: redirectUrl
}).then(() => { }).then(() => {

View file

@ -141,26 +141,6 @@ const Logic = {
return this._currentIdentity; return this._currentIdentity;
}, },
cookieStoreId(userContextId) {
return `firefox-container-${userContextId}`;
},
_containerTabIterator(userContextId, cb) {
browser.tabs.query({
cookieStoreId: Logic.cookieStoreId(userContextId)
}).then((tabs) => {
tabs.forEach((tab) => {
cb(tab);
});
}).catch((e) => {throw e;});
},
_containerTabs(userContextId) {
return browser.tabs.query({
cookieStoreId: Logic.cookieStoreId(userContextId)
});
},
sendTelemetryPayload(message = {}) { sendTelemetryPayload(message = {}) {
if (!message.event) { if (!message.event) {
throw new Error("Missing event name for telemetry"); throw new Error("Missing event name for telemetry");
@ -170,33 +150,13 @@ const Logic = {
}, },
removeIdentity(userContextId) { removeIdentity(userContextId) {
const eventName = "delete-container";
if (!userContextId) { if (!userContextId) {
return Promise.reject("removeIdentity must be called with userContextId argument."); return Promise.reject("removeIdentity must be called with userContextId argument.");
} }
this.sendTelemetryPayload({ return browser.runtime.sendMessage({
event: eventName, method: "deleteContainer",
userContextId message: {userContextId}
});
const removeTabsPromise = Logic._containerTabs(userContextId).then((tabs) => {
const tabIds = tabs.map((tab) => tab.id);
return browser.tabs.remove(tabIds);
});
return removeTabsPromise.then(() => {
const removed = browser.contextualIdentities.remove(Logic.cookieStoreId(userContextId));
// Send delete event to webextension/background.js
browser.runtime.sendMessage({
type: eventName,
message: {userContextId}
});
browser.runtime.sendMessage({
method: "forgetIdentityAndRefresh"
}).then(() => {
return removed;
}).catch((e) => {throw e;});
}); });
}, },
@ -589,14 +549,17 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
_submitForm() { _submitForm() {
const identity = Logic.currentIdentity(); const identity = Logic.currentIdentity();
const formValues = new FormData(this._editForm); const formValues = new FormData(this._editForm);
this._createOrUpdateIdentity( return browser.runtime.sendMessage({
{ method: "createOrUpdateContainer",
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(), message: {
icon: formValues.get("container-icon") || DEFAULT_ICON, userContextId: identity.userContextId || false,
color: formValues.get("container-color") || DEFAULT_COLOR, params: {
}, name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
identity.userContextId || false icon: formValues.get("container-icon") || DEFAULT_ICON,
).then(() => { color: formValues.get("container-color") || DEFAULT_COLOR,
}
}
}).then(() => {
return Logic.refreshIdentities(); return Logic.refreshIdentities();
}).then(() => { }).then(() => {
Logic.showPreviousPanel(); Logic.showPreviousPanel();
@ -605,30 +568,6 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
}); });
}, },
_createOrUpdateIdentity(params, userContextId) {
let donePromise;
if (userContextId) {
donePromise = browser.contextualIdentities.update(
Logic.cookieStoreId(userContextId),
params
);
Logic.sendTelemetryPayload({
event: "edit-container",
userContextId
});
} else {
donePromise = browser.contextualIdentities.create(params);
Logic.sendTelemetryPayload({
event: "add-container"
});
}
return donePromise.then(() => {
browser.runtime.sendMessage({
method: "refreshNeeded"
});
});
},
initializeRadioButtons() { initializeRadioButtons() {
const colorRadioTemplate = (containerColor) => { const colorRadioTemplate = (containerColor) => {
return escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" /> return escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
@ -686,6 +625,11 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
}); });
document.querySelector("#delete-container-ok-link").addEventListener("click", () => { document.querySelector("#delete-container-ok-link").addEventListener("click", () => {
/* This promise wont resolve if the last tab was removed from the window.
as the message async callback stops listening, this isn't an issue for us however it might be in future
if you want to do anything post delete do it in the background script.
Browser console currently warns about not listening also.
*/
Logic.removeIdentity(Logic.currentIdentity().userContextId).then(() => { Logic.removeIdentity(Logic.currentIdentity().userContextId).then(() => {
return Logic.refreshIdentities(); return Logic.refreshIdentities();
}).then(() => { }).then(() => {