diff --git a/public/manifest.json b/public/manifest.json index 3e7bf0e3..9ed77517 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -7,9 +7,9 @@ "default_popup": "popup.html" }, "permissions": [ - "webRequest", "tabs", - "storage" + "storage", + "debugger" ], "host_permissions": [ "*://*/*/" diff --git a/src/background/background.ts b/src/background/background.ts index 1838d333..e15dd822 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -1,11 +1,7 @@ import { IBytesRepository } from "../data/bytes/IBytesRepository"; -import { - catchPostRequestBodySize, - catchRequestHeaderSize, - catchResponseSize, -} from "./webRequestListeners"; +import { addBytesTransferred } from "./backgroundHelpers"; -chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { +chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { if (message === "getBytesTransferred") { sendResponse(IBytesRepository.instance.getBytesTransferred()); } @@ -15,33 +11,57 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.command === "startRecordingBytesTransferred") { IBytesRepository.instance.clearBytesTransferred(); - chrome.webRequest.onBeforeRequest.addListener( - catchPostRequestBodySize, - { urls: [""], tabId }, - ["requestBody"] - ); - chrome.webRequest.onBeforeSendHeaders.addListener( - catchRequestHeaderSize, - { urls: [""], tabId }, - ["requestHeaders"] - ); - chrome.webRequest.onCompleted.addListener( - catchResponseSize, - { urls: [""], tabId }, - ["responseHeaders"] - ); + chrome.debugger.attach({ tabId: tabId }, "1.2", () => { + chrome.debugger.sendCommand( + { tabId: tabId }, + "Network.enable", + {}, + () => { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError); + } + } + ); + }); + sendResponse(true); } if (message.command === "stopRecordingBytesTransferred") { - chrome.webRequest.onCompleted.removeListener(catchResponseSize); - chrome.webRequest.onBeforeRequest.removeListener( - catchPostRequestBodySize - ); - chrome.webRequest.onBeforeSendHeaders.removeListener( - catchRequestHeaderSize - ); + try { + await chrome.debugger.detach({ tabId: tabId }); + } catch (e: unknown) { + if ( + (e as Error).message === + `Debugger is not attached to the tab with id: ${tabId}.` + ) { + console.warn( + `Tried to detach debugger from tab (tabId: ${tabId}) when there was none attached. ` + ); + return; + } + throw e; + } sendResponse(true); } return true; }); + +type NetworkParamsType = { + encodedDataLength?: number; +}; + +chrome.debugger.onEvent.addListener( + (source, method: string, params: NetworkParamsType | undefined) => { + switch (method) { + case "Network.loadingFinished": { + if (params?.encodedDataLength && params.encodedDataLength > 0) { + addBytesTransferred(params.encodedDataLength); + } + break; + } + default: + break; + } + } +); diff --git a/src/background/backgroundHelpers.ts b/src/background/backgroundHelpers.ts new file mode 100644 index 00000000..7061dcae --- /dev/null +++ b/src/background/backgroundHelpers.ts @@ -0,0 +1,25 @@ +import { IBytesRepository } from "../data/bytes/IBytesRepository"; + +export const addBytesTransferred = async (bytes: number) => { + IBytesRepository.instance.addBytesTransferred(bytes); + + try { + await chrome.runtime.sendMessage({ + command: { + bytesTransferredChanged: + IBytesRepository.instance.getBytesTransferred(), + }, + }); + } catch (e: unknown) { + if ( + (e as Error).message === + "Could not establish connection. Receiving end does not exist." + ) { + console.warn( + `Error Caught: ${e}\nIf popup is open and this error is seen in the console, debugging is required.` + ); + } else { + throw e; + } + } +}; diff --git a/src/background/getWebRequestSizeHelpers.ts b/src/background/getWebRequestSizeHelpers.ts deleted file mode 100644 index 6aaf15a9..00000000 --- a/src/background/getWebRequestSizeHelpers.ts +++ /dev/null @@ -1,48 +0,0 @@ -export const getRequestHeaderSize = ( - details: chrome.webRequest.WebRequestHeadersDetails -): number => { - return ( - details.requestHeaders?.reduce((acc, header) => { - const encoder = new TextEncoder(); - const headerLength = encoder.encode( - header.name + ": " + (header.value ?? "") - ).length; - return acc + headerLength; - }, 0) ?? 0 - ); -}; - -export const getBodySize = ( - details: chrome.webRequest.WebRequestBodyDetails -): number => { - return details.requestBody?.raw?.[0].bytes?.byteLength ?? 0; -}; - -export const getBodySizeFromContentLengthHeader = ( - details: chrome.webRequest.WebResponseHeadersDetails -): number => { - const contentLengthHeader = details.responseHeaders?.find( - (header) => header.name.toLowerCase() === "content-length" - ); - - const bodySize = - contentLengthHeader?.value !== undefined - ? parseInt(contentLengthHeader.value, 10) - : 0; - - return bodySize; -}; - -export const getResponseHeaderSize = ( - details: chrome.webRequest.WebResponseHeadersDetails -): number => { - return ( - details.responseHeaders?.reduce((acc, header) => { - const encoder = new TextEncoder(); - const headerLength = encoder.encode( - header.name + ": " + (header.value ?? "") - ).length; - return acc + headerLength; - }, 0) ?? 0 - ); -}; diff --git a/src/background/webRequestListeners.ts b/src/background/webRequestListeners.ts deleted file mode 100644 index 70e6750f..00000000 --- a/src/background/webRequestListeners.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { IBytesRepository } from "../data/bytes/IBytesRepository"; -import { - getBodySize, - getBodySizeFromContentLengthHeader, - getRequestHeaderSize, - getResponseHeaderSize, -} from "./getWebRequestSizeHelpers"; - -const addBytesTransferred = async (bytes: number) => { - IBytesRepository.instance.addBytesTransferred(bytes); - - try { - await chrome.runtime.sendMessage({ - command: { - bytesTransferredChanged: - IBytesRepository.instance.getBytesTransferred(), - }, - }); - } catch (e: unknown) { - if (e instanceof Error) { - if ( - e.message === - "Could not establish connection. Receiving end does not exist." - ) { - console.log( - `Error Caught: ${e}\nIf popup is open and this error is seen in the console, debugging is required.` - ); - } - } else { - throw e; - } - } -}; - -export const catchResponseSize = ( - details: chrome.webRequest.WebResponseCacheDetails -) => { - const headerSize = getResponseHeaderSize(details); - - const bodySize = getBodySizeFromContentLengthHeader(details); - - addBytesTransferred(headerSize + bodySize); -}; - -export const catchPostRequestBodySize = ( - details: chrome.webRequest.WebRequestBodyDetails -) => { - if (details.method === "POST") { - const bodySize = getBodySize(details); - - if (bodySize > 0) { - addBytesTransferred(bodySize); - } - } -}; - -export const catchRequestHeaderSize = ( - details: chrome.webRequest.WebRequestHeadersDetails -) => { - const headerSize = getRequestHeaderSize(details); - - if (headerSize > 0) { - addBytesTransferred(headerSize); - } -}; diff --git a/src/view/popup/usePopup.ts b/src/view/popup/usePopup.ts index b65d436c..6817eb63 100644 --- a/src/view/popup/usePopup.ts +++ b/src/view/popup/usePopup.ts @@ -83,7 +83,6 @@ export const usePopup = () => { } try { await calculationsRepository.setOngoingCalculation(true); - backgroundStopRecordingBytes(); } catch (e: unknown) { if (e instanceof Error) { setError(e.message);