mirror of
https://github.com/tubearchivist/browser-extension.git
synced 2024-11-22 11:40:13 +00:00
Refactor message passing and surface errors to users (#18)
* refactor message passing between popup/background * surface errors to user in popup.js * move logic into background.js * split youtube message * handle errors from URL constructor
This commit is contained in:
parent
c7069d90cb
commit
9528a347e0
@ -84,44 +84,50 @@ async function getCookieState() {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send ping to server, return response
|
// send ping to server
|
||||||
async function verifyConnection() {
|
async function verifyConnection() {
|
||||||
const path = 'api/ping/';
|
const path = 'api/ping/';
|
||||||
let response = await sendGet(path);
|
let message = await sendGet(path);
|
||||||
console.log('verify connection: ' + JSON.stringify(response));
|
console.log('verify connection: ' + JSON.stringify(message));
|
||||||
|
|
||||||
return response;
|
if (message?.response === 'pong') {
|
||||||
|
return true;
|
||||||
|
} else if (message?.detail) {
|
||||||
|
throw new Error(message.detail);
|
||||||
|
} else {
|
||||||
|
throw new Error(`got unknown message ${JSON.stringify(message)}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send youtube link from injected buttons
|
// send youtube link from injected buttons
|
||||||
async function youtubeLink(youtubeMessage) {
|
async function download(url) {
|
||||||
let path;
|
return await sendData(
|
||||||
let payload;
|
'api/download/',
|
||||||
|
{
|
||||||
if (youtubeMessage.action === 'download') {
|
|
||||||
path = 'api/download/';
|
|
||||||
payload = {
|
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
youtube_id: youtubeMessage.url,
|
youtube_id: url,
|
||||||
status: 'pending',
|
status: 'pending',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
},
|
||||||
} else if (youtubeMessage.action === 'subscribe') {
|
'POST'
|
||||||
path = 'api/channel/';
|
);
|
||||||
payload = {
|
}
|
||||||
|
|
||||||
|
async function subscribe(url) {
|
||||||
|
return await sendData(
|
||||||
|
'api/channel/',
|
||||||
|
{
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
channel_id: youtubeMessage.url,
|
channel_id: url,
|
||||||
channel_subscribed: true,
|
channel_subscribed: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
},
|
||||||
}
|
'POST'
|
||||||
|
);
|
||||||
let response = await sendData(path, payload, 'POST');
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cookieStr(cookieLines) {
|
async function cookieStr(cookieLines) {
|
||||||
@ -172,33 +178,56 @@ async function sendCookies() {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process and return message if needed
|
/*
|
||||||
|
process and return message if needed
|
||||||
|
the following messages are supported:
|
||||||
|
type Message =
|
||||||
|
| { type: 'verify' }
|
||||||
|
| { type: 'cookieState' }
|
||||||
|
| { type: 'sendCookie' }
|
||||||
|
| { type: 'download', url: string }
|
||||||
|
| { type: 'subscribe', url: string }
|
||||||
|
*/
|
||||||
function handleMessage(request, sender, sendResponse) {
|
function handleMessage(request, sender, sendResponse) {
|
||||||
console.log('message background.js listener: ' + JSON.stringify(request));
|
console.log('message background.js listener got message', request);
|
||||||
|
|
||||||
if (request.verify === true) {
|
// this function must return the value `true` in chrome to signal the response will be async;
|
||||||
let response = verifyConnection();
|
// it cannot return a promise
|
||||||
response.then(message => {
|
// so in order to use async/await, we need a wrapper
|
||||||
sendResponse(message);
|
(async () => {
|
||||||
|
switch (request.type) {
|
||||||
|
case 'verify': {
|
||||||
|
return await verifyConnection();
|
||||||
|
}
|
||||||
|
case 'cookieState': {
|
||||||
|
return await getCookieState();
|
||||||
|
}
|
||||||
|
case 'sendCookie': {
|
||||||
|
return await sendCookies();
|
||||||
|
}
|
||||||
|
case 'download': {
|
||||||
|
return await download(request.url);
|
||||||
|
}
|
||||||
|
case 'subscribe': {
|
||||||
|
return await subscribe(request.url);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
let err = new Error(`unknown message type ${JSON.stringify(request.type)}`);
|
||||||
|
console.log(err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
.then(value => sendResponse({ success: true, value }))
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
let message = e?.message ?? e;
|
||||||
|
if (message === 'Failed to fetch') {
|
||||||
|
// chrome's error message for failed `fetch` is not very user-friendly
|
||||||
|
message = 'Could not connect to server';
|
||||||
|
}
|
||||||
|
sendResponse({ success: false, value: message });
|
||||||
});
|
});
|
||||||
} else if (request.youtube) {
|
|
||||||
let response = youtubeLink(request.youtube);
|
|
||||||
response.then(message => {
|
|
||||||
sendResponse(message);
|
|
||||||
});
|
|
||||||
} else if (request.cookieState) {
|
|
||||||
let response = getCookieState();
|
|
||||||
response.then(message => {
|
|
||||||
sendResponse(message);
|
|
||||||
});
|
|
||||||
} else if (request.sendCookie) {
|
|
||||||
console.log('backgound: ' + JSON.stringify(request));
|
|
||||||
let response = sendCookies();
|
|
||||||
response.then(message => {
|
|
||||||
sendResponse(message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<div class="submit">
|
<div class="submit">
|
||||||
<button id="save-login">Save</button><span id="status-icon">☐</span>
|
<button id="save-login">Save</button><span id="status-icon">☐</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="error-out"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Options:</p>
|
<p>Options:</p>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
|
@ -15,29 +15,52 @@ function getBrowser() {
|
|||||||
return chrome;
|
return chrome;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('failed to dedect browser');
|
console.log('failed to detect browser');
|
||||||
throw 'browser detection error';
|
throw 'browser detection error';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendMessage(message) {
|
||||||
|
let { success, value } = await browserType.runtime.sendMessage(message);
|
||||||
|
if (!success) {
|
||||||
|
throw value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let errorOut = document.getElementById('error-out');
|
||||||
|
function setError(message) {
|
||||||
|
errorOut.style.display = 'initial';
|
||||||
|
errorOut.innerText = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearError() {
|
||||||
|
errorOut.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
// store access details
|
// store access details
|
||||||
document.getElementById('save-login').addEventListener('click', function () {
|
document.getElementById('save-login').addEventListener('click', function () {
|
||||||
let url = document.getElementById('full-url').value;
|
let url = document.getElementById('full-url').value;
|
||||||
if (!url.includes('://')) {
|
if (!url.includes('://')) {
|
||||||
url = 'http://' + url;
|
url = 'http://' + url;
|
||||||
}
|
}
|
||||||
let parsed = new URL(url);
|
try {
|
||||||
let toStore = {
|
clearError();
|
||||||
access: {
|
let parsed = new URL(url);
|
||||||
url: `${parsed.protocol}//${parsed.hostname}`,
|
let toStore = {
|
||||||
port: parsed.port || (parsed.protocol === 'https:' ? '443' : '80'),
|
access: {
|
||||||
apiKey: document.getElementById('api-key').value,
|
url: `${parsed.protocol}//${parsed.hostname}`,
|
||||||
},
|
port: parsed.port || (parsed.protocol === 'https:' ? '443' : '80'),
|
||||||
};
|
apiKey: document.getElementById('api-key').value,
|
||||||
browserType.storage.local.set(toStore, function () {
|
},
|
||||||
console.log('Stored connection details: ' + JSON.stringify(toStore));
|
};
|
||||||
pingBackend();
|
browserType.storage.local.set(toStore, function () {
|
||||||
});
|
console.log('Stored connection details: ' + JSON.stringify(toStore));
|
||||||
|
pingBackend();
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setError(e.message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// verify connection status
|
// verify connection status
|
||||||
@ -52,6 +75,7 @@ document.getElementById('sendCookies').addEventListener('click', function () {
|
|||||||
|
|
||||||
function sendCookie() {
|
function sendCookie() {
|
||||||
console.log('popup send cookie');
|
console.log('popup send cookie');
|
||||||
|
clearError();
|
||||||
|
|
||||||
function handleResponse(message) {
|
function handleResponse(message) {
|
||||||
console.log('handle cookie response: ' + JSON.stringify(message));
|
console.log('handle cookie response: ' + JSON.stringify(message));
|
||||||
@ -61,6 +85,7 @@ function sendCookie() {
|
|||||||
|
|
||||||
function handleError(error) {
|
function handleError(error) {
|
||||||
console.log(`Error: ${error}`);
|
console.log(`Error: ${error}`);
|
||||||
|
setError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
let checked = document.getElementById('sendCookies').checked;
|
let checked = document.getElementById('sendCookies').checked;
|
||||||
@ -75,26 +100,26 @@ function sendCookie() {
|
|||||||
if (checked === false) {
|
if (checked === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let sending = browserType.runtime.sendMessage({ sendCookie: true });
|
let sending = sendMessage({ type: 'sendCookie' });
|
||||||
sending.then(handleResponse, handleError);
|
sending.then(handleResponse, handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send ping message to TA backend
|
// send ping message to TA backend
|
||||||
function pingBackend() {
|
function pingBackend() {
|
||||||
function handleResponse(message) {
|
clearError();
|
||||||
if (message.response === 'pong') {
|
function handleResponse() {
|
||||||
setStatusIcon(true);
|
console.log('connection validated');
|
||||||
console.log('connection validated');
|
setStatusIcon(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleError(error) {
|
function handleError(error) {
|
||||||
console.log(`Error: ${error}`);
|
console.log(`Verify got error: ${error}`);
|
||||||
setStatusIcon(false);
|
setStatusIcon(false);
|
||||||
|
setError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('ping TA server');
|
console.log('ping TA server');
|
||||||
let sending = browserType.runtime.sendMessage({ verify: true });
|
let sending = sendMessage({ type: 'verify' });
|
||||||
sending.then(handleResponse, handleError);
|
sending.then(handleResponse, handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +130,7 @@ function addUrl(access) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setCookieState() {
|
function setCookieState() {
|
||||||
|
clearError();
|
||||||
function handleResponse(message) {
|
function handleResponse(message) {
|
||||||
console.log(message);
|
console.log(message);
|
||||||
document.getElementById('sendCookies').checked = message.cookie_enabled;
|
document.getElementById('sendCookies').checked = message.cookie_enabled;
|
||||||
@ -115,10 +141,11 @@ function setCookieState() {
|
|||||||
|
|
||||||
function handleError(error) {
|
function handleError(error) {
|
||||||
console.log(`Error: ${error}`);
|
console.log(`Error: ${error}`);
|
||||||
|
setError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('set cookie state');
|
console.log('set cookie state');
|
||||||
let sending = browserType.runtime.sendMessage({ cookieState: true });
|
let sending = sendMessage({ type: 'cookieState' });
|
||||||
sending.then(handleResponse, handleError);
|
sending.then(handleResponse, handleError);
|
||||||
document.getElementById('sendCookies').checked = true;
|
document.getElementById('sendCookies').checked = true;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ function getBrowser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendMessage(message) {
|
||||||
|
let { success, value } = await browserType.runtime.sendMessage(message);
|
||||||
|
if (!success) {
|
||||||
|
throw value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
const downloadIcon = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
const downloadIcon = `<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
|
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@ -362,18 +370,14 @@ function sendUrl(url, action, button) {
|
|||||||
function handleError(error) {
|
function handleError(error) {
|
||||||
console.log('error');
|
console.log('error');
|
||||||
console.log(JSON.stringify(error));
|
console.log(JSON.stringify(error));
|
||||||
|
buttonError(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = {
|
let message = { type: action, url };
|
||||||
youtube: {
|
|
||||||
url: url,
|
|
||||||
action: action,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('youtube link: ' + JSON.stringify(payload));
|
console.log('youtube link: ' + JSON.stringify(message));
|
||||||
|
|
||||||
let sending = browserType.runtime.sendMessage(payload);
|
let sending = sendMessage(message);
|
||||||
sending.then(handleResponse, handleError);
|
sending.then(handleResponse, handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,4 +76,8 @@ hr {
|
|||||||
}
|
}
|
||||||
.icons img {
|
.icons img {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
}
|
}
|
||||||
|
#error-out {
|
||||||
|
color: red;
|
||||||
|
display: none; /* will be made visible when an error occurs */
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user