[MM-59552] Remove unsafe-inline from internal CSP, replace with nonce and rework some dynamic styling (#3120)

* Remove unsafe-inline

* Fix dynamic dark mode loading

* Include nonce generator for CSP for styles

* Add nonce provider for react-select

* Fix test
This commit is contained in:
Devin Binnie
2024-08-12 09:38:59 -04:00
committed by GitHub
parent e310fa705f
commit c9f671d82a
17 changed files with 177 additions and 61 deletions

View File

@@ -6,6 +6,9 @@
import 'renderer/css/settings.css';
import createCache from '@emotion/cache';
import {CacheProvider} from '@emotion/react';
import type {EmotionCache} from '@emotion/react';
import React from 'react';
import {FormCheck, Col, FormGroup, FormText, Container, Row, Button, FormControl, Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl';
@@ -39,6 +42,7 @@ type State = DeepPartial<CombinedConfig> & {
availableLanguages: Array<{label: string; value: string}>;
availableSpellcheckerLanguages: Array<{label: string; value: string}>;
canUpgrade?: boolean;
cache?: EmotionCache;
}
type SavingStateItems = {
@@ -127,6 +131,13 @@ class SettingsPage extends React.PureComponent<Props, State> {
availableLanguages.sort((a, b) => a.label.localeCompare(b.label));
this.setState({availableLanguages});
});
window.desktop.getNonce().then((nonce) => {
this.setState({cache: createCache({
key: 'react-select-cache',
nonce,
})});
});
}
getConfig = () => {
@@ -426,6 +437,10 @@ class SettingsPage extends React.PureComponent<Props, State> {
render() {
const {intl} = this.props;
if (!this.state.cache) {
return null;
}
const settingsPage = {
close: {
textDecoration: 'none',
@@ -581,22 +596,24 @@ class SettingsPage extends React.PureComponent<Props, State> {
</FormText>
</FormCheck>
{this.state.useSpellChecker &&
<ReactSelect
inputId='inputSpellCheckerLocalesDropdown'
className='SettingsPage__spellCheckerLocalesDropdown'
classNamePrefix='SettingsPage__spellCheckerLocalesDropdown'
options={this.state.availableSpellcheckerLanguages}
isMulti={true}
isClearable={false}
onChange={this.handleChangeSpellCheckerLocales}
value={this.selectedSpellCheckerLocales}
placeholder={
<FormattedMessage
id='renderer.components.settingsPage.checkSpelling.preferredLanguages'
defaultMessage='Select preferred language(s)'
/>
}
/>
<CacheProvider value={this.state.cache}>
<ReactSelect
inputId='inputSpellCheckerLocalesDropdown'
className='SettingsPage__spellCheckerLocalesDropdown'
classNamePrefix='SettingsPage__spellCheckerLocalesDropdown'
options={this.state.availableSpellcheckerLanguages}
isMulti={true}
isClearable={false}
onChange={this.handleChangeSpellCheckerLocales}
value={this.selectedSpellCheckerLocales}
placeholder={
<FormattedMessage
id='renderer.components.settingsPage.checkSpelling.preferredLanguages'
defaultMessage='Select preferred language(s)'
/>
}
/>
</CacheProvider>
}
</>,
);

View File

@@ -32,6 +32,10 @@ type Props = {
intl: IntlShape;
};
type State = {
nonce?: string;
}
function getStyle(style?: DraggingStyle | NotDraggingStyle) {
if (style?.transform) {
const axisLockX = `${style.transform.slice(0, style.transform.indexOf(','))}, 0px)`;
@@ -43,7 +47,12 @@ function getStyle(style?: DraggingStyle | NotDraggingStyle) {
return style;
}
class TabBar extends React.PureComponent<Props> {
class TabBar extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {};
}
onCloseTab = (id: string) => {
return (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
@@ -51,7 +60,19 @@ class TabBar extends React.PureComponent<Props> {
};
};
componentDidMount(): void {
window.desktop.getNonce().then((nonce) => {
this.setState({
nonce,
});
});
}
render() {
if (!this.state.nonce) {
return null;
}
const tabs = this.props.tabs.map((tab, index) => {
const sessionExpired = this.props.sessionsExpired[tab.id!];
const hasUnreads = this.props.unreadCounts[tab.id!];
@@ -145,7 +166,10 @@ class TabBar extends React.PureComponent<Props> {
});
return (
<DragDropContext onDragEnd={this.props.onDrop}>
<DragDropContext
nonce={this.state.nonce}
onDragEnd={this.props.onDrop}
>
<Droppable
isDropDisabled={this.props.tabsDisabled}
droppableId='tabBar'