Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add option to process single or multiple tab for better performance #136

Merged
merged 15 commits into from
Sep 8, 2023
2 changes: 1 addition & 1 deletion packages/extension/src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Privacy Analysis Tool",
"name": "Privacy Sandbox Analysis Tool",
"description": "Tooling for understanding cookie usage and guidance on new privacy-preserving Chrome APIs.",
"version": "0.1.0",
"manifest_version": 3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export { default as MatrixComponentHorizontal } from './matrix/matrixComponent/m
export { default as Matrix } from './matrix';
export { default as MessageBox } from './messageBox';
export { default as Button } from './button';
export { default as ProgressBar } from './progressBar';

export type { MatrixComponentProps } from './matrix/matrixComponent';

This file was deleted.

18 changes: 17 additions & 1 deletion packages/extension/src/view/devtools/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import './app.css';
import TABS from './tabs';
import { Sidebar } from './components';
import { useCookieStore } from './stateProviders/syncCookieStore';
import { Button } from '../design-system/components';
import { Button, ProgressBar } from '../design-system/components';

const App: React.FC = () => {
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
Expand All @@ -35,14 +35,30 @@ const App: React.FC = () => {
returningToSingleTab,
changeListeningToThisTab,
allowedNumberOfTabs,
loading,
} = useCookieStore(({ state, actions }) => ({
isCurrentTabBeingListenedTo: state.isCurrentTabBeingListenedTo,
returningToSingleTab: state.returningToSingleTab,
changeListeningToThisTab: actions.changeListeningToThisTab,
allowedNumberOfTabs: state.allowedNumberOfTabs,
loading: state.loading,
}));
const TabContent = TABS[selectedTabIndex].component;

if (
loading ||
(loading &&
isCurrentTabBeingListenedTo &&
allowedNumberOfTabs &&
allowedNumberOfTabs === 'single')
) {
return (
<div className="w-full h-screen flex items-center justify-center overflow-hidden bg-white dark:bg-raisin-black">
<ProgressBar additionalStyles="w-full" />
</div>
);
}

if (
(isCurrentTabBeingListenedTo &&
allowedNumberOfTabs &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,6 @@ const Sidebar: React.FC<SidebarProps> = ({ selectedIndex, setIndex }) => {
accordionState && accordionState[id]
)}
index={index}
isCookiesTabOpen={Boolean(
accordionState && accordionState['cookies']
)}
isAccordionHeaderSelected={
selectedIndex === index && !selectedFrame
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import React, {
useEffect,
useState,
useCallback,
useRef,
} from 'react';

/**
Expand All @@ -37,6 +38,7 @@ export interface CookieStoreContext {
state: {
tabCookies: TabCookies | null;
tabUrl: string | null;
loading: boolean;
tabFrames: TabFrames | null;
selectedFrame: string | null;
returningToSingleTab: boolean;
Expand All @@ -55,6 +57,7 @@ const initialState: CookieStoreContext = {
tabUrl: null,
tabFrames: null,
selectedFrame: null,
loading: true,
isCurrentTabBeingListenedTo: false,
returningToSingleTab: false,
allowedNumberOfTabs: null,
Expand All @@ -69,6 +72,8 @@ export const Context = createContext<CookieStoreContext>(initialState);

export const Provider = ({ children }: PropsWithChildren) => {
const [tabId, setTabId] = useState<number | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const loadingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
const [isCurrentTabBeingListenedTo, setIsCurrentTabBeingListenedTo] =
useState<boolean>(false);

Expand Down Expand Up @@ -137,11 +142,18 @@ export const Provider = ({ children }: PropsWithChildren) => {
setTabId(_tabId);

const extensionStorage = await chrome.storage.sync.get();
const _allowedNumberOfTabs =
extensionStorage?.allowedNumberOfTabs || 'single';

if (extensionStorage?.allowedNumberOfTabs) {
setAllowedNumberOfTabs(extensionStorage?.allowedNumberOfTabs);
if (!extensionStorage?.allowedNumberOfTabs) {
await chrome.storage.sync.clear();
await chrome.storage.sync.set({
allowedNumberOfTabs: 'single',
});
}

setAllowedNumberOfTabs(_allowedNumberOfTabs);

if (_tabId) {
if (extensionStorage?.allowedNumberOfTabs === 'single') {
const getTabBeingListenedTo = await chrome.storage.local.get();
Expand All @@ -161,6 +173,7 @@ export const Provider = ({ children }: PropsWithChildren) => {
_tabId.toString() !== getTabBeingListenedTo?.tabToRead
) {
setIsCurrentTabBeingListenedTo(false);
setLoading(false);
return;
} else {
setIsCurrentTabBeingListenedTo(true);
Expand Down Expand Up @@ -192,6 +205,7 @@ export const Provider = ({ children }: PropsWithChildren) => {

setTabCookies(_cookies);
}
setLoading(false);

chrome.devtools.inspectedWindow.eval(
'window.location.href',
Expand Down Expand Up @@ -255,17 +269,22 @@ export const Provider = ({ children }: PropsWithChildren) => {
tabId.toString() !== getTabBeingListenedTo?.tabToRead
) {
setIsCurrentTabBeingListenedTo(false);
setLoading(false);
return;
} else {
setIsCurrentTabBeingListenedTo(true);
chrome.tabs.query({ active: true }, (tab) => {
if (tab[0]?.url) {
setTabUrl(tab[0]?.url);
chrome.devtools.inspectedWindow.eval(
'window.location.href',
(result, isException) => {
if (!isException && typeof result === 'string') {
setTabUrl(result);
}
}
});
);
}
}
}
setLoading(false);
},
[tabId, getAllFramesForCurrentTab]
);
Expand Down Expand Up @@ -296,14 +315,18 @@ export const Provider = ({ children }: PropsWithChildren) => {
return Promise.resolve();
});

chrome.tabs.query({ active: true }, (tab) => {
if (tab[0]?.url) {
setTabUrl(tab[0]?.url);
chrome.devtools.inspectedWindow.eval(
'window.location.href',
(result, isException) => {
if (!isException && typeof result === 'string') {
setTabUrl(result);
}
}
});
);

await chrome.tabs.reload(Number(changedTabId));
setIsCurrentTabBeingListenedTo(true);
setLoading(false);
}, []);

const tabUpdateListener = useCallback(
Expand Down Expand Up @@ -361,13 +384,26 @@ export const Provider = ({ children }: PropsWithChildren) => {
changeSyncStorageListener,
]);

useEffect(() => {
loadingTimeout.current = setTimeout(() => {
setLoading(false);
}, 6500);

return () => {
if (loadingTimeout.current) {
clearTimeout(loadingTimeout.current);
}
};
}, []);

return (
<Context.Provider
value={{
state: {
tabCookies,
tabUrl,
tabFrames,
loading,
selectedFrame,
isCurrentTabBeingListenedTo,
returningToSingleTab,
Expand Down
56 changes: 56 additions & 0 deletions packages/extension/src/view/devtools/tests/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,62 @@ describe('App', () => {
expect(await screen.findByTestId('cookies-content')).toBeInTheDocument();
});

it('should open bounce tracking panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('antiCovertTracking-accordion-opener'));
fireEvent.click(screen.getByTestId('Bounce Tracking'));
expect(
await screen.findByTestId('bounce-tracking-content')
).toBeInTheDocument();
});

it('should open fingerprinting panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('antiCovertTracking-accordion-opener'));
fireEvent.click(screen.getByTestId('Fingerprinting'));
expect(
await screen.findByTestId('fingerprinting-content')
).toBeInTheDocument();
});

it('should open attribution panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('privateAdvertising-accordion-opener'));
fireEvent.click(screen.getByTestId('Attribution'));
expect(
await screen.findByTestId('attribution-content')
).toBeInTheDocument();
});

it('should open topics panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('privateAdvertising-accordion-opener'));
fireEvent.click(screen.getByTestId('Topics'));
expect(await screen.findByTestId('topics-content')).toBeInTheDocument();
});

it('should open CHIPS panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('siteBoundaries-accordion-opener'));
fireEvent.click(screen.getByTestId('CHIPS'));
expect(await screen.findByTestId('chips-content')).toBeInTheDocument();
});

it('should open Related Website Sets panel when selected from accordion.', async () => {
await act(() => render(<App />));
// Move to another tab
fireEvent.click(screen.getByTestId('siteBoundaries-accordion-opener'));
fireEvent.click(screen.getByTestId('Related Website Sets'));
expect(
await screen.findByTestId('related-website-sets-content')
).toBeInTheDocument();
});

it('should switch to AntiCovert Tracking Panel when clicked', async () => {
await act(() => render(<App />));
// Click on Bounce Tracking tab
Expand Down
Loading