Skip to content

Commit

Permalink
Allow individual scripts once
Browse files Browse the repository at this point in the history
  • Loading branch information
spylogsster committed Feb 24, 2023
1 parent b1cb85e commit c7069a4
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 64 deletions.
4 changes: 3 additions & 1 deletion browser/ui/webui/brave_shields/shields_panel_data_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,10 @@ void ShieldsPanelDataHandler::UpdateSiteBlockInfo() {
active_shields_data_controller_->GetTotalBlockedCount();
site_block_info_.ads_list =
active_shields_data_controller_->GetBlockedAdsList();
site_block_info_.js_list =
site_block_info_.blocked_js_list =
active_shields_data_controller_->GetBlockedJsList();
site_block_info_.allowed_js_list =
active_shields_data_controller_->GetAllowedJsList();
site_block_info_.fingerprints_list =
active_shields_data_controller_->GetFingerprintsList();
site_block_info_.http_redirects_list =
Expand Down
4 changes: 3 additions & 1 deletion components/brave_shields/common/brave_shield_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ constexpr webui::LocalizedString kLocalizedStrings[] = {
{"braveShieldsBlockedScriptsLabel",
IDS_BRAVE_SHIELDS_BLOCKED_SCRIPTS_LABEL},
{"braveShieldsManaged", IDS_BRAVE_SHIELDS_MANAGED},
};
{"braveShieldsAllowScriptOnce", IDS_BRAVE_SHIELDS_ALLOW_SCRIPT_ONCE},
{"braveShieldsScriptAllowedOnce", IDS_BRAVE_SHIELDS_SCRIPT_ALLOWED_ONCE},
{"braveShieldsAllowScriptsAll", IDS_BRAVE_SHIELDS_ALLOW_SCRIPTS_ALL}};

const char kCookieListEnabledHistogram[] = "Brave.Shields.CookieListEnabled";
const char kCookieListPromptHistogram[] = "Brave.Shields.CookieListPrompt";
Expand Down
3 changes: 2 additions & 1 deletion components/brave_shields/common/brave_shields_panel.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ struct SiteBlockInfo {
url.mojom.Url favicon_url;
array<url.mojom.Url> ads_list;
array<url.mojom.Url> http_redirects_list;
array<url.mojom.Url> js_list;
array<url.mojom.Url> blocked_js_list;
array<url.mojom.Url> allowed_js_list;
array<url.mojom.Url> fingerprints_list;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function AdvancedControlsContent () {

const adsListCount = siteBlockInfo?.adsList.length ?? 0
const httpRedirectsListCount = siteBlockInfo?.httpRedirectsList.length ?? 0
const jsListCount = siteBlockInfo?.jsList.length ?? 0
const jsListCount = siteBlockInfo?.blockedJsList.length ?? 0
const isHttpsByDefaultEnabled = loadTimeData.getBoolean('isHttpsByDefaultEnabled')
const isTorProfile = loadTimeData.getBoolean('isTorProfile')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,38 @@ import * as S from './style'
import DataContext from '../../state/context'
import { getLocale } from '../../../../../common/locale'
import TreeNode from './tree-node'
import { ViewType } from '../../state/component_types'
import { Url } from 'gen/url/mojom/url.mojom.m.js'
import {
ViewType,
ResourceInfo,
ResourceType,
ResourceState
} from '../../state/component_types'
import Button from '$web-components/button'
import getPanelBrowserAPI from '../../api/panel_browser_api'

interface Props {
data: Url[]
totalBlockedCount: number
blockedCountTitle: string
resourcesList: ResourceInfo[]
type: ResourceType
totalCount: number
totalTitle: string
}

function groupByOrigin (data: Url[]) {
const map: Map<string, string[]> = new Map()
function groupByOrigin (data: ResourceInfo[]) {
const map: Map<string, ResourceInfo[]> = new Map()

const includesDupeOrigin = (searchOrigin: string) => {
const results = data.map(entry => new URL(entry.url).origin)
const results = data.map(entry => new URL(entry.url.url).origin)
.filter(entry => entry.includes(searchOrigin))
return results.length > 1
}

data.forEach(entry => {
const url = new URL(entry.url)
const url = new URL(entry.url.url)
const origin = url.origin
const items = map.get(origin)

if (items) {
items.push(url.pathname + url.search)
items.push(entry)
return // continue
}

Expand All @@ -44,10 +50,31 @@ function groupByOrigin (data: Url[]) {
return map
}

function getScriptsOriginsWithState (data: ResourceInfo[],
state: ResourceState): string[] {
const list: string[] = []

data.forEach(entry => {
const url = new URL(entry.url.url)
if (list.includes(url.origin) || entry.state !== state) {
return // continue
}

list.push(url.origin)
})

return list
}

function TreeList (props: Props) {
const { siteBlockInfo, setViewType } = React.useContext(DataContext)
const mappedData = React.useMemo(() => groupByOrigin(props.data), [props.data])

const mappedBlockedScripts = React.useMemo(() =>
groupByOrigin(props.resourcesList), [props.resourcesList])
const allowAllScripts = () => {
const origins: string[] =
getScriptsOriginsWithState(props.resourcesList, ResourceState.Blocked)
getPanelBrowserAPI().dataHandler.allowScriptsOnce(origins)
}
return (
<S.Box>
<S.HeaderBox>
Expand All @@ -58,17 +85,22 @@ function TreeList (props: Props) {
<S.SiteTitle>{siteBlockInfo?.host}</S.SiteTitle>
</S.SiteTitleBox>
<S.Grid>
<span>{props.totalBlockedCount}</span>
<span>{props.blockedCountTitle}</span>
<span>{props.totalCount}</span>
<span>{props.totalTitle}</span>
<span>{<a href="#" onClick={() => allowAllScripts()}>
{getLocale('braveShieldsAllowScriptsAll')}
</a>
}</span>
</S.Grid>
</S.HeaderBox>
<S.TreeBox>
<div>
{[...mappedData.keys()].map((origin, idx) => {
{[...mappedBlockedScripts.keys()].map((origin, idx) => {
return (<TreeNode
key={idx}
host={origin}
resourceList={mappedData.get(origin) ?? []}
type={props.type}
resourceList={mappedBlockedScripts.get(origin) ?? []}
/>)
})}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export const Box = styled.div`
right: 0;
left: 0;
z-index: 2;
display: flex;
flex-direction: column;
`

export const HeaderBox = styled.section`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
import * as React from 'react'
import styled from 'styled-components'
import UrlElement from './url-element'
import {
ResourceInfo,
ResourceState,
ResourceType
} from '../../state/component_types'
import getPanelBrowserAPI from '../../api/panel_browser_api'
import { getLocale } from '../../../../../common/locale'

const Tree = styled.div`
display: grid;
Expand Down Expand Up @@ -62,9 +69,15 @@ const TreeContents = styled.div`
overflow: hidden; /* to wrap contents */
`

const AllowedOnceText = styled.div`
overflow: hidden; /* to wrap contents */
color: gray
`

interface TreeNodeProps {
host: string
resourceList: string[]
type: ResourceType
resourceList: ResourceInfo[]
}

function rectToQuad (rect: DOMRect) {
Expand All @@ -87,6 +100,21 @@ function getRelativeBoundingRect (from: DOMRect, to: Element) {
)
}

const getResourcesState = (resourceList: ResourceInfo[])
: ResourceState | undefined => {
if (!resourceList.length) { return undefined }
let state: ResourceState | undefined = resourceList[0].state
resourceList.forEach(entry => {
if (state !== entry.state) {
state = undefined
return undefined
}
return entry.state
})

return state
}

function TreeNode (props: TreeNodeProps) {
const treeChildrenBoxRef = React.useRef() as React.MutableRefObject<HTMLDivElement>
const svgBoxRef = React.useRef() as React.MutableRefObject<HTMLElement>
Expand Down Expand Up @@ -184,28 +212,59 @@ function TreeNode (props: TreeNodeProps) {
measure()
}, [props.resourceList, isExpanded])

const handleActionClick = () => {
getPanelBrowserAPI().dataHandler.allowScriptsOnce([props.host])
}
const isAllowedOnce =
getResourcesState(props.resourceList) === ResourceState.AllowedOnce
return (
<Tree>
<TreeControlBox>
{hasResources ? renderTreeExpandToggle() : renderBullet()}
{hasResources && isExpanded ? renderLeftAxis() : null}
</TreeControlBox>
<TreeContents>
<span>
<span>
<UrlElement name={props.host} isHost={true} />
{isAllowedOnce && (
<AllowedOnceText>
{getLocale('braveShieldsScriptAllowedOnce')}
</AllowedOnceText>
)}
</span>
</span>
{hasResources && isExpanded ? (
<div ref={treeChildrenBoxRef}>
{
props.resourceList.map((resourceUrl: string, idx) => {
props.resourceList.map((resource: ResourceInfo, idx) => {
return (
<UrlElement
key={idx}
isHost={false}
name={resourceUrl}
onExpand={() => measure()}
/>
<span>
<UrlElement
key={idx}
isHost={false}
name={resource.url.url}
onExpand={() => measure()}
/>

{props.type === ResourceType.Script &&
resource.state === ResourceState.Blocked && (
<a href='#' onClick={() => handleActionClick()}>
{getLocale('braveShieldsAllowScriptOnce')}
</a>
)}
{props.type === ResourceType.Script &&
resource.state === ResourceState.AllowedOnce && (
<AllowedOnceText>
{getLocale('braveShieldsScriptAllowedOnce')}
</AllowedOnceText>
)}

</span>
)
})
}

</div>
) : null}
</TreeContents>
Expand Down
76 changes: 63 additions & 13 deletions components/brave_shields/resources/panel/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,92 @@ import * as React from 'react'

import MainPanel from './components/main-panel'
import TreeList from './components/tree-list'
import { ViewType } from './state/component_types'
import {
MakeResourceInfoList,
ResourceInfo,
ResourceState,
ResourceType,
ViewType
} from './state/component_types'
import DataContext from './state/context'
import styled from 'styled-components'
import { getLocale } from '../../../common/locale'
import { SiteBlockInfo } from './api/panel_browser_api'

const Box = styled.div`
position: relative;
`

function GetResourceListForView (view: ViewType,
state: ResourceState,
siteBlockInfo: SiteBlockInfo): ResourceInfo[] {
if (view === ViewType.AdsList) {
return MakeResourceInfoList(siteBlockInfo.adsList, ResourceType.Ad, state)
}
if (view === ViewType.HttpsList) {
return MakeResourceInfoList(siteBlockInfo.httpRedirectsList,
ResourceType.Http,
state)
}
if (view === ViewType.ScriptsList && state === ResourceState.Blocked) {
return MakeResourceInfoList(siteBlockInfo.blockedJsList,
ResourceType.Http,
state)
}
if (view === ViewType.ScriptsList && state === ResourceState.AllowedOnce) {
return MakeResourceInfoList(siteBlockInfo.allowedJsList,
ResourceType.Http,
state)
}

return []
}

function Container () {
const { siteBlockInfo, viewType } = React.useContext(DataContext)
const detailView = viewType !== ViewType.Main && siteBlockInfo

const resourceBlockedList = siteBlockInfo ?
GetResourceListForView(viewType, ResourceState.Blocked, siteBlockInfo) : []
const resourceAllowedList = siteBlockInfo ?
GetResourceListForView(viewType,
ResourceState.AllowedOnce,
siteBlockInfo) : []
const renderDetailView = () => {
if (viewType === ViewType.AdsList && detailView) {
return (<TreeList
data={siteBlockInfo?.adsList}
totalBlockedCount={siteBlockInfo?.adsList.length}
blockedCountTitle={getLocale('braveShieldsTrackersAndAds')}
resourcesList={resourceBlockedList}
type={ResourceType.Ad}
totalCount={siteBlockInfo?.adsList.length}
totalTitle={getLocale('braveShieldsTrackersAndAds')}
/>)
}

if (viewType === ViewType.HttpsList && detailView) {
return (<TreeList
data={siteBlockInfo?.httpRedirectsList}
totalBlockedCount={siteBlockInfo?.httpRedirectsList.length}
blockedCountTitle={getLocale('braveShieldsConnectionsUpgraded')}
type={ResourceType.Http}
resourcesList={resourceBlockedList}
totalCount={siteBlockInfo?.httpRedirectsList.length}
totalTitle={getLocale('braveShieldsConnectionsUpgraded')}
/>)
}

if (viewType === ViewType.ScriptsList && detailView) {
return (<TreeList
data={siteBlockInfo?.jsList}
totalBlockedCount={siteBlockInfo?.jsList.length}
blockedCountTitle={getLocale('braveShieldsBlockedScriptsLabel')}
/>)
return (
<Box>
<TreeList
resourcesList={resourceBlockedList}
type={ResourceType.Script}
totalCount={resourceBlockedList.length}
totalTitle={getLocale('braveShieldsBlockedScriptsLabel')}
/>
<TreeList
resourcesList={resourceAllowedList}
type={ResourceType.Script}
totalCount={resourceAllowedList.length}
totalTitle={getLocale('braveShieldsBlockedScriptsLabel')}
/>
</Box>)

}

return null
Expand Down
Loading

0 comments on commit c7069a4

Please sign in to comment.