Improve performance by limiting renders
This commit is contained in:
parent
cf47b79052
commit
7330ebf9f2
29
memory.ts
29
memory.ts
@ -5,7 +5,7 @@ import { RequestCluster } from './request-cluster';
|
||||
|
||||
export default class Memory extends EventEmitter {
|
||||
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
||||
private throttle = makeThrottle(200);
|
||||
private throttle = makeThrottle(100);
|
||||
async register(request: ExtendedRequest) {
|
||||
await request.init();
|
||||
if (!request.isThirdParty()) {
|
||||
@ -20,7 +20,7 @@ export default class Memory extends EventEmitter {
|
||||
this.origin_to_history[request.origin][shorthost] = cluster;
|
||||
}
|
||||
this.origin_to_history[request.origin][shorthost].add(request);
|
||||
this.emit('change');
|
||||
this.emit('change', false, shorthost, 'registered request(shorthost emit)');
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@ -35,9 +35,9 @@ export default class Memory extends EventEmitter {
|
||||
);
|
||||
browser.webRequest.onBeforeSendHeaders.addListener(
|
||||
async (request) => {
|
||||
const extendedRequest = ExtendedRequest.by_id[
|
||||
request.requestId
|
||||
].addHeaders(request.requestHeaders || []);
|
||||
const extendedRequest = ExtendedRequest.by_id[request.requestId].addHeaders(
|
||||
request.requestHeaders || []
|
||||
);
|
||||
this.register(extendedRequest);
|
||||
},
|
||||
{ urls: ['<all_urls>'] },
|
||||
@ -45,13 +45,16 @@ export default class Memory extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
emit(eventName: string, immediate = false) {
|
||||
emit(eventName: string, immediate = false, data = 'any', reason: string) {
|
||||
console.log('emitting!', eventName, data, reason);
|
||||
setTimeout(() => super.emit(eventName, data), 0);
|
||||
return;
|
||||
try {
|
||||
if (immediate) {
|
||||
super.emit(eventName);
|
||||
super.emit(eventName, data);
|
||||
return;
|
||||
} else {
|
||||
this.throttle(() => super.emit(eventName));
|
||||
this.throttle(() => super.emit(eventName, data));
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
@ -68,12 +71,7 @@ export default class Memory extends EventEmitter {
|
||||
if (shorthost) {
|
||||
const cookies = await browser.cookies.getAll({ domain: shorthost });
|
||||
for (const cookie of cookies) {
|
||||
console.log(
|
||||
'removing cookie',
|
||||
cookie.name,
|
||||
'from',
|
||||
cookie.domain
|
||||
);
|
||||
console.log('removing cookie', cookie.name, 'from', cookie.domain);
|
||||
await browser.cookies.remove({
|
||||
name: cookie.name,
|
||||
url: `https://${cookie.domain}`,
|
||||
@ -102,6 +100,5 @@ export function init() {
|
||||
}
|
||||
|
||||
export function getMemory(): Memory {
|
||||
return (browser.extension.getBackgroundPage().window as any)
|
||||
.memory as Memory;
|
||||
return (browser.extension.getBackgroundPage().window as any).memory as Memory;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Options from '../options';
|
||||
import { StolenData } from './stolen-data';
|
||||
import { useEmitter } from '../util';
|
||||
import { getshorthost, useEmitter } from '../util';
|
||||
import { getMemory } from '../memory';
|
||||
|
||||
async function getCurrentTab() {
|
||||
@ -26,7 +26,7 @@ const Sidebar = () => {
|
||||
const [cookiesOnly, setCookiesOnly] = React.useState<boolean>(false);
|
||||
const [stolenDataView, setStolenDataView] = React.useState<boolean>(true);
|
||||
const [cookiesOrOriginOnly, setCookiesOrOriginOnly] = React.useState<boolean>(false);
|
||||
const [counter, setCounter] = useEmitter(getMemory());
|
||||
const [eventCounts, setEventCounts] = useEmitter(getMemory());
|
||||
const [marksOccurrence, setMarksOccurrence] = React.useState<boolean>(false);
|
||||
const [warningDataDialogAck, setWarningDataDialogAck] = React.useState<boolean>(
|
||||
localStorage.getItem('warningDataDialogAck') === null
|
||||
@ -44,7 +44,7 @@ const Sidebar = () => {
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const listener = async (data: any) => {
|
||||
const listener = async () => {
|
||||
console.log('tab change!');
|
||||
const tab = await getCurrentTab();
|
||||
const url = new URL(tab.url);
|
||||
@ -66,7 +66,7 @@ const Sidebar = () => {
|
||||
}
|
||||
}
|
||||
return setMarksOccurrence(false);
|
||||
}, [counter, origin]);
|
||||
}, [eventCounts['*'], origin]);
|
||||
|
||||
return (
|
||||
<div className="sidebar">
|
||||
@ -112,7 +112,7 @@ const Sidebar = () => {
|
||||
<button
|
||||
onClick={() => {
|
||||
getMemory().removeRequestsFor(origin);
|
||||
setCounter((c) => c + 1);
|
||||
getMemory().emit('change', false, origin, 'clicked trash');
|
||||
setMarksOccurrence(false);
|
||||
}}
|
||||
>
|
||||
@ -122,7 +122,7 @@ const Sidebar = () => {
|
||||
<button
|
||||
onClick={() => {
|
||||
getMemory().removeCookiesFor(origin);
|
||||
setCounter((c) => c + 1);
|
||||
getMemory().emit('change', false, origin, 'clicked clear cookies');
|
||||
setMarksOccurrence(false);
|
||||
}}
|
||||
>
|
||||
@ -193,8 +193,7 @@ const Sidebar = () => {
|
||||
) : null}
|
||||
<StolenData
|
||||
origin={origin}
|
||||
refreshToken={counter}
|
||||
refresh={() => setCounter((c) => c + 1)}
|
||||
eventCounts={eventCounts}
|
||||
minValueLength={minValueLength}
|
||||
cookiesOnly={cookiesOnly}
|
||||
cookiesOrOriginOnly={cookiesOrOriginOnly}
|
||||
|
@ -8,23 +8,14 @@ import './stolen-data-cluster.scss';
|
||||
|
||||
const MAX_STRING_VALUE_LENGTH = 100;
|
||||
|
||||
function StolenDataValue({
|
||||
entry,
|
||||
refresh,
|
||||
}: {
|
||||
entry: StolenDataEntry;
|
||||
refresh: Function;
|
||||
prefixKey?: string;
|
||||
}) {
|
||||
function StolenDataValue({ entry }: { entry: StolenDataEntry; prefixKey?: string }) {
|
||||
const [version] = useEmitter(entry);
|
||||
let body = null;
|
||||
if (!entry.value) {
|
||||
body = <></>;
|
||||
} else {
|
||||
body = (
|
||||
<div data-version={version}>
|
||||
{maskString(entry.value, 1, MAX_STRING_VALUE_LENGTH)}
|
||||
</div>
|
||||
<div data-version={version}>{maskString(entry.value, 1, MAX_STRING_VALUE_LENGTH)}</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
@ -32,7 +23,7 @@ function StolenDataValue({
|
||||
className="value"
|
||||
onClick={(e) => {
|
||||
entry.toggleMark();
|
||||
refresh();
|
||||
getMemory().emit('change', false, entry.request.shorthost, 'clicked value');
|
||||
e.stopPropagation();
|
||||
}}
|
||||
title={maskString(entry.value, 1, MAX_STRING_VALUE_LENGTH)}
|
||||
@ -42,13 +33,7 @@ function StolenDataValue({
|
||||
);
|
||||
}
|
||||
|
||||
function StolenDataRow({
|
||||
entry,
|
||||
refresh,
|
||||
}: {
|
||||
entry: StolenDataEntry;
|
||||
refresh: Function;
|
||||
}) {
|
||||
function StolenDataRow({ entry }: { entry: StolenDataEntry }) {
|
||||
const [version] = useEmitter(entry);
|
||||
return (
|
||||
<tr
|
||||
@ -62,7 +47,12 @@ function StolenDataRow({
|
||||
checked={entry.isMarked}
|
||||
onChange={() => {
|
||||
entry.toggleMark();
|
||||
refresh();
|
||||
getMemory().emit(
|
||||
'change',
|
||||
false,
|
||||
entry.request.shorthost,
|
||||
'clicked checkbox'
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
@ -70,7 +60,12 @@ function StolenDataRow({
|
||||
title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}
|
||||
onClick={() => {
|
||||
entry.toggleMark();
|
||||
refresh();
|
||||
getMemory().emit(
|
||||
'change',
|
||||
false,
|
||||
entry.request.shorthost,
|
||||
'Clicked entry name'
|
||||
);
|
||||
}}
|
||||
>
|
||||
{entry.name}
|
||||
@ -86,10 +81,7 @@ function StolenDataRow({
|
||||
/>
|
||||
</span>
|
||||
) : entry.request.hasCookie() ? (
|
||||
<span
|
||||
title="Wysłane w zapytaniu opatrzonym Cookies"
|
||||
style={{ opacity: 0.25 }}
|
||||
>
|
||||
<span title="Wysłane w zapytaniu opatrzonym Cookies" style={{ opacity: 0.25 }}>
|
||||
<img
|
||||
src="/assets/icons/cookie.svg"
|
||||
height={16}
|
||||
@ -121,7 +113,7 @@ function StolenDataRow({
|
||||
</span>
|
||||
) : null}
|
||||
</td>
|
||||
<StolenDataValue refresh={refresh} entry={entry} />
|
||||
<StolenDataValue entry={entry} />
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
@ -130,21 +122,22 @@ export default function StolenDataCluster({
|
||||
origin,
|
||||
shorthost,
|
||||
minValueLength,
|
||||
refresh,
|
||||
cookiesOnly,
|
||||
refreshToken,
|
||||
cookiesOrOriginOnly,
|
||||
}: {
|
||||
origin: string;
|
||||
shorthost: string;
|
||||
refreshToken: number;
|
||||
minValueLength: number;
|
||||
refresh: Function;
|
||||
cookiesOnly: boolean;
|
||||
cookiesOrOriginOnly: boolean;
|
||||
}) {
|
||||
const cluster = getMemory().getClustersForOrigin(origin)[shorthost];
|
||||
const fullHosts = cluster.getFullHosts();
|
||||
|
||||
/* console.log('Stolen data cluster!', shorthost, refreshToken); */
|
||||
|
||||
return (
|
||||
<div className="stolen-data-cluster-container">
|
||||
<header className="domains-container">
|
||||
@ -153,13 +146,8 @@ export default function StolenDataCluster({
|
||||
</a>
|
||||
<div className="subdomains-container">
|
||||
{fullHosts.map((host, index) => (
|
||||
<a
|
||||
className="subdomain"
|
||||
key={host}
|
||||
href={`https://${host}`}
|
||||
>
|
||||
{host}{' '}
|
||||
{`${fullHosts.length - 1 !== index ? '· ' : ''}`}
|
||||
<a className="subdomain" key={host} href={`https://${host}`}>
|
||||
{host} {`${fullHosts.length - 1 !== index ? '· ' : ''}`}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
@ -182,7 +170,6 @@ export default function StolenDataCluster({
|
||||
})
|
||||
.map((entry) => (
|
||||
<StolenDataRow
|
||||
refresh={refresh}
|
||||
{...{
|
||||
entry,
|
||||
key: entry.id,
|
||||
|
@ -1,23 +1,19 @@
|
||||
import React from 'react';
|
||||
import { getMemory } from '../memory';
|
||||
import { RequestCluster } from '../request-cluster';
|
||||
|
||||
import StolenDataCluster from './stolen-data-cluster';
|
||||
import { getshorthost } from '../util';
|
||||
import { getMemory } from '../memory';
|
||||
|
||||
import './stolen-data.scss';
|
||||
|
||||
export function StolenData({
|
||||
origin,
|
||||
minValueLength,
|
||||
refreshToken,
|
||||
refresh,
|
||||
eventCounts,
|
||||
cookiesOnly,
|
||||
cookiesOrOriginOnly,
|
||||
}: {
|
||||
origin: string;
|
||||
refreshToken: number;
|
||||
refresh: () => void;
|
||||
eventCounts: Record<string, number>;
|
||||
minValueLength: number;
|
||||
cookiesOnly: boolean;
|
||||
cookiesOrOriginOnly: boolean;
|
||||
@ -33,10 +29,7 @@ export function StolenData({
|
||||
.sort(RequestCluster.sortCompare)
|
||||
.filter((cluster) => !cookiesOnly || cluster.hasCookies())
|
||||
.filter(
|
||||
(cluster) =>
|
||||
!cookiesOrOriginOnly ||
|
||||
cluster.hasCookies() ||
|
||||
cluster.exposesOrigin()
|
||||
(cluster) => !cookiesOrOriginOnly || cluster.hasCookies() || cluster.exposesOrigin()
|
||||
);
|
||||
return (
|
||||
<div className="stolen-data-container">
|
||||
@ -48,8 +41,7 @@ export function StolenData({
|
||||
origin={origin}
|
||||
shorthost={cluster.id}
|
||||
key={cluster.id + origin}
|
||||
refresh={refresh}
|
||||
refreshToken={refreshToken}
|
||||
refreshToken={eventCounts[cluster.id]}
|
||||
minValueLength={minValueLength}
|
||||
cookiesOnly={cookiesOnly}
|
||||
cookiesOrOriginOnly={cookiesOrOriginOnly}
|
||||
|
@ -12,12 +12,7 @@ import {
|
||||
safeDecodeURIComponent,
|
||||
} from './util';
|
||||
|
||||
export type Sources =
|
||||
| 'cookie'
|
||||
| 'pathname'
|
||||
| 'queryparams'
|
||||
| 'header'
|
||||
| 'request_body';
|
||||
export type Sources = 'cookie' | 'pathname' | 'queryparams' | 'header' | 'request_body';
|
||||
|
||||
export const Classifications = <const>{
|
||||
id: 'Identyfikator internetowy',
|
||||
@ -123,10 +118,7 @@ export class StolenDataEntry extends EventEmitter {
|
||||
}
|
||||
).entries()
|
||||
);
|
||||
if (
|
||||
typeof hash !== 'object' &&
|
||||
Object.keys(searchParams).length === 0
|
||||
) {
|
||||
if (typeof hash !== 'object' && Object.keys(searchParams).length === 0) {
|
||||
return value; // just a string;
|
||||
}
|
||||
const object = {
|
||||
@ -134,11 +126,7 @@ export class StolenDataEntry extends EventEmitter {
|
||||
host: url.host,
|
||||
path: url.pathname,
|
||||
searchParams,
|
||||
...(hash === ''
|
||||
? {}
|
||||
: typeof hash === 'string'
|
||||
? { hash }
|
||||
: hash),
|
||||
...(hash === '' ? {} : typeof hash === 'string' ? { hash } : hash),
|
||||
};
|
||||
return object;
|
||||
} else if (value === null) {
|
||||
@ -148,16 +136,12 @@ export class StolenDataEntry extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
getParsedValue(
|
||||
key_path: string
|
||||
): string | Record<string | symbol, unknown> {
|
||||
getParsedValue(key_path: string): string | Record<string | symbol, unknown> {
|
||||
let object = StolenDataEntry.parseValue(this.value);
|
||||
for (const key of key_path.split('.')) {
|
||||
if (key === '') continue;
|
||||
if (typeof key === 'string') {
|
||||
throw new Error(
|
||||
'something went wrong when parsing ' + key_path
|
||||
);
|
||||
throw new Error('something went wrong when parsing ' + key_path);
|
||||
}
|
||||
object = StolenDataEntry.parseValue(object[key]);
|
||||
}
|
||||
@ -176,7 +160,7 @@ export class StolenDataEntry extends EventEmitter {
|
||||
const had_been_marked_before = this.marked;
|
||||
this.marked = false;
|
||||
if (had_been_marked_before) {
|
||||
this.emit('change');
|
||||
this.emit('change', this.request.origin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,9 +183,7 @@ export class StolenDataEntry extends EventEmitter {
|
||||
}
|
||||
|
||||
isRelatedToID() {
|
||||
return this.request.stolenData.some(
|
||||
(entry) => entry.classification == 'id'
|
||||
);
|
||||
return this.request.stolenData.some((entry) => entry.classification == 'id');
|
||||
}
|
||||
|
||||
matchesHAREntry(har: HAREntry): boolean {
|
||||
@ -216,10 +198,7 @@ export class StolenDataEntry extends EventEmitter {
|
||||
: value.toString();
|
||||
if (typeof value !== 'object' && this.classification == 'id') {
|
||||
return maskString(value, 1 / 3, ID_PREVIEW_MAX_LENGTH);
|
||||
} else if (
|
||||
typeof value === 'object' &&
|
||||
value[Symbol.for('originalString')]
|
||||
) {
|
||||
} else if (typeof value === 'object' && value[Symbol.for('originalString')]) {
|
||||
return value[Symbol.for('originalString')] as string;
|
||||
} else {
|
||||
return str;
|
||||
@ -267,8 +246,8 @@ export class StolenDataEntry extends EventEmitter {
|
||||
}
|
||||
|
||||
exposesHost() {
|
||||
return [this.value, safeDecodeURIComponent(this.value)].some(
|
||||
(haystack) => haystack.includes(getshorthost(this.request.origin))
|
||||
return [this.value, safeDecodeURIComponent(this.value)].some((haystack) =>
|
||||
haystack.includes(getshorthost(this.request.origin))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
26
util.ts
26
util.ts
@ -47,18 +47,34 @@ export function getshorthost(host: string) {
|
||||
|
||||
export function useEmitter(
|
||||
e: EventEmitter
|
||||
): [number, React.Dispatch<React.SetStateAction<number>>] {
|
||||
const [counter, setCounter] = React.useState<number>(0);
|
||||
): [
|
||||
Record<string, number | undefined>,
|
||||
React.Dispatch<React.SetStateAction<Record<string, number | undefined>>>
|
||||
] {
|
||||
const [eventCounts, setEventCounts] = React.useState<Record<string, number | undefined>>({
|
||||
'*': 0,
|
||||
});
|
||||
React.useEffect(() => {
|
||||
const callback = () => {
|
||||
setCounter((counter) => counter + 1);
|
||||
const callback = (eventSubtype: string) => {
|
||||
setEventCounts((eventCounts) => {
|
||||
console.log({
|
||||
...eventCounts,
|
||||
...{ [eventSubtype]: (eventCounts[eventSubtype] || 0) + 1 },
|
||||
...{ '*': (eventCounts['*'] === undefined ? 0 : eventCounts['*']) + 1 },
|
||||
});
|
||||
return {
|
||||
...eventCounts,
|
||||
...{ [eventSubtype]: (eventCounts[eventSubtype] || 0) + 1 },
|
||||
...{ '*': (eventCounts['*'] === undefined ? 0 : eventCounts['*']) + 1 },
|
||||
};
|
||||
});
|
||||
};
|
||||
e.on('change', callback);
|
||||
return () => {
|
||||
e.removeListener('change', callback);
|
||||
};
|
||||
}, []);
|
||||
return [counter, setCounter];
|
||||
return [eventCounts, setEventCounts];
|
||||
}
|
||||
|
||||
export function parseCookie(cookie: string): Record<string, string> {
|
||||
|
Loading…
Reference in New Issue
Block a user