Skip to content

Commit

Permalink
Remove non-locale uses of innerHTML
Browse files Browse the repository at this point in the history
and add npm script to check for Trusted Type violations. locale strings
will be fixed in a separate PR.

fix brave/brave-browser#11686
  • Loading branch information
diracdeltas committed Sep 14, 2020
1 parent ffb15a5 commit 52edf9e
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 92 deletions.
9 changes: 8 additions & 1 deletion browser/resources/settings/brave_overrides/about_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ RegisterPolymerTemplateModifications({
if (!version) {
console.error('[Brave Settings Overrides] Could not find version div')
}
version.innerHTML = '<a id="release-notes" target="_blank" href="https://brave.com/latest/">' + version.innerHTML + '</a>'
const parent = version.parentNode
const wrapper = document.createElement('a')
wrapper.setAttribute('id', 'release-notes')
wrapper.setAttribute('target', '_blank')
wrapper.setAttribute('rel', 'noopener noreferrer')
wrapper.setAttribute('href', 'https://brave.com/latest/')
parent.replaceChild(wrapper, version)
wrapper.appendChild(version)
}
}
})
113 changes: 76 additions & 37 deletions browser/resources/settings/brave_overrides/basic_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ export function getSectionElement (templateContent, sectionName) {
return sectionEl
}

/**
* Creates a settings-section element with a single child and returns it.
* @param {string} sectionName - value of the section attribute
* @param {string} titleName - loadTimeData key for page-title
* @param {string} childName - name of child element
* @param {Object} childAttributes - key-value pairs of child element attributes
* @returns {Element}
*/
function createSectionElement (sectionName, titleName, childName, childAttributes) {
const el = document.createElement('settings-section')
el.setAttribute('page-title', loadTimeData.getString(titleName))
el.setAttribute('section', sectionName)
const child = document.createElement(childName)
for (const attribute in childAttributes) {
child.setAttribute(attribute, childAttributes[attribute])
}
el.appendChild(child)
return el
}

RegisterStyleOverride(
'settings-basic-page',
html`
Expand Down Expand Up @@ -94,67 +114,86 @@ RegisterPolymerTemplateModifications({
sectionGetStarted.setAttribute('is', 'dom-if')
sectionGetStarted.setAttribute('restamp', true)
sectionGetStarted.setAttribute('if', '[[showPage_(pageVisibility.getStarted)]]')
sectionGetStarted.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveGetStartedTitle')}" section="getStarted">
<brave-settings-getting-started prefs={{prefs}} page-visibility=[[pageVisibility]]></brave-settings-getting-started>
</settings-section>
`
sectionGetStarted.content.appendChild(createSectionElement(
'getStarted',
'braveGetStartedTitle',
'brave-settings-getting-started',
{
prefs: '{{prefs}}',
'page-visibility': '[[pageVisibility]]'
}
))
const sectionExtensions = document.createElement('template')
sectionExtensions.setAttribute('is', 'dom-if')
sectionExtensions.setAttribute('restamp', true)
sectionExtensions.setAttribute('if', '[[showPage_(pageVisibility.extensions)]]')
sectionExtensions.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveDefaultExtensions')}" section="extensions">
<settings-brave-default-extensions-page prefs="{{prefs}}"></settings-brave-default-extensions-page>
</settings-section>
`
sectionExtensions.content.appendChild(createSectionElement(
'extensions',
'braveDefaultExtensions',
'settings-brave-default-extensions-page',
{
prefs: '{{prefs}}'
}
))
const sectionSync = document.createElement('template')
sectionSync.setAttribute('is', 'dom-if')
sectionSync.setAttribute('restamp', true)
sectionSync.setAttribute('if', '[[showPage_(pageVisibility.braveSync)]]')
sectionSync.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveSync')}" section="braveSync">
<settings-brave-sync-page></settings-brave-sync-page>
</settings-section>
`
sectionSync.content.appendChild(createSectionElement(
'braveSync',
'braveSync',
'settings-brave-sync-page',
{}
))

const sectionShields = document.createElement('template')
sectionShields.setAttribute('is', 'dom-if')
sectionShields.setAttribute('restamp', true)
sectionShields.setAttribute('if', '[[showPage_(pageVisibility.shields)]]')
sectionShields.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveShieldsTitle')}"
section="shields">
<settings-default-brave-shields-page prefs="{{prefs}}"></settings-default-brave-shields-page>
</settings-section>
`
sectionShields.content.appendChild(createSectionElement(
'shields',
'braveShieldsTitle',
'settings-default-brave-shields-page',
{
prefs: '{{prefs}}'
}
))
const sectionSocialBlocking = document.createElement('template')
sectionSocialBlocking.setAttribute('is', 'dom-if')
sectionSocialBlocking.setAttribute('restamp', true)
sectionSocialBlocking.setAttribute('if', '[[showPage_(pageVisibility.socialBlocking)]]')
sectionSocialBlocking.innerHTML = `
<settings-section page-title="${loadTimeData.getString('socialBlocking')}"
section="socialBlocking">
<settings-social-blocking-page prefs="{{prefs}}"></settings-social-blocking-page>
</settings-section>
`
sectionSocialBlocking.content.appendChild(createSectionElement(
'socialBlocking',
'socialBlocking',
'settings-social-blocking-page',
{
prefs: '{{prefs}}'
}
))
const sectionHelpTips = document.createElement('template')
sectionHelpTips.setAttribute('is', 'dom-if')
sectionHelpTips.setAttribute('restamp', true)
sectionHelpTips.setAttribute('if', '[[showPage_(pageVisibility.braveHelpTips)]]')
sectionHelpTips.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveHelpTips')}" section="braveHelpTips">
<settings-brave-help-tips-page prefs="{{prefs}}"></settings-brave-help-tips-page>
</settings-section>
`
sectionHelpTips.content.appendChild(createSectionElement(
'braveHelpTips',
'braveHelpTips',
'settings-brave-help-tips-page',
{
prefs: '{{prefs}}'
}
))
const sectionNewTab = document.createElement('template')
sectionNewTab.setAttribute('is', 'dom-if')
sectionNewTab.setAttribute('restamp', true)
sectionNewTab.setAttribute('if', '[[showPage_(pageVisibility.newTab)]]')
sectionNewTab.innerHTML = `
<settings-section page-title="${loadTimeData.getString('braveNewTab')}" section="newTab">
<settings-brave-new-tab-page prefs="{{prefs}}"></settings-brave-new-tab-page>
</settings-section>
`
sectionNewTab.content.appendChild(createSectionElement(
'newTab',
'braveNewTab',
'settings-brave-new-tab-page',
{
prefs: '{{prefs}}'
}
))
// Get Started at top
basicPageEl.insertAdjacentElement('afterbegin', sectionGetStarted)
// Move Appearance item
Expand Down
25 changes: 10 additions & 15 deletions browser/resources/settings/brave_overrides/import_data_dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@ import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'

RegisterPolymerTemplateModifications({
'settings-import-data-dialog': (templateContent) => {
let checkBoxesParent = templateContent.querySelector('#browserSelect').parentElement
let innerHTML = checkBoxesParent.innerHTML
innerHTML += `
<settings-checkbox
hidden="[[!selected_.extensions]]"
pref="{{prefs.import_dialog_extensions}}"
label="${I18nBehavior.i18n('importExtensions')}" no-set-pref>
</settings-checkbox>
<settings-checkbox
hidden="[[!selected_.payments]]"
pref="{{prefs.import_dialog_payments}}"
label="${I18nBehavior.i18n('importPayments')}" no-set-pref>
</settings-checkbox>
`
checkBoxesParent.innerHTML = innerHTML
let checkBoxesParent = templateContent.querySelector('#browserSelect').parentElement;
['extensions', 'payments'].forEach((item) => {
const checkbox = document.createElement('settings-checkbox')
checkbox.setAttribute('hidden', `[[!selected_.${item}]]`)
checkbox.setAttribute('pref', `{{prefs.import_dialog_${item}}}`)
checkbox.setAttribute('label',
I18nBehavior.i18n(`import${item[0].toUpperCase()}${item.slice(1)}`))
checkbox.setAttribute('no-set-pref', '')
checkBoxesParent.appendChild(checkbox)
})
}
})

Expand Down
2 changes: 1 addition & 1 deletion browser/resources/settings/brave_overrides/people_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ RegisterPolymerTemplateModifications({
// remove the google account button
const manageGoogleAccount = signinTemplate.content.querySelector('#manage-google-account')
if (!manageGoogleAccount) {
console.error('[Brave Settings Overrides] Could not find the google account settings item', templateContent, templateContent.innerHTML)
console.error('[Brave Settings Overrides] Could not find the google account settings item', templateContent, templateContent.textContent)
return
}
manageGoogleAccount.remove()
Expand Down
54 changes: 38 additions & 16 deletions browser/resources/settings/brave_overrides/settings_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ function createMenuElement (title, href, iconName, pageVisibilitySection) {
menuEl.setAttribute('hidden', `[[!pageVisibility.${pageVisibilitySection}]]`)
}
menuEl.href = href
menuEl.innerHTML = `
<iron-icon icon="${iconName}"></iron-icon>
${title}
`
const child = document.createElement('iron-icon')
child.setAttribute('icon', iconName)
menuEl.appendChild(child)
const text = document.createTextNode(title)
menuEl.appendChild(text)
return menuEl
}

Expand Down Expand Up @@ -140,7 +141,7 @@ RegisterPolymerTemplateModifications({
// Add title
const titleEl = document.createElement('h1')
titleEl.id = 'settingsHeader'
titleEl.innerHTML = loadTimeData.getString('settings')
titleEl.textContent = loadTimeData.getString('settings')
const topMenuEl = templateContent.querySelector('#topMenu')
if (!topMenuEl) {
console.error('[Brave Settings Overrides] Could not find topMenu element to add title after')
Expand All @@ -152,7 +153,7 @@ RegisterPolymerTemplateModifications({
if (!advancedToggle) {
console.error('[Brave Settings Overrides] Could not find advancedButton to modify text')
}
advancedToggle.innerText = loadTimeData.getString('braveAdditionalSettingsTitle')
advancedToggle.textContent = loadTimeData.getString('braveAdditionalSettingsTitle')
// Add 'Get Started' item
const peopleEl = getMenuElement(templateContent, '/people')
const getStartedEl = createMenuElement(
Expand Down Expand Up @@ -238,16 +239,37 @@ RegisterPolymerTemplateModifications({
const aboutEl = templateContent.querySelector('#about-menu')
if (!aboutEl) {
console.error('[Brave Settings Overrides] Could not find about-menu element')
return
}
const aboutTitleContent = aboutEl.innerHTML
aboutEl.innerHTML = `
<div class="brave-about-graphic">
<iron-icon icon="brave_settings:full-color-brave-lion"><iron-icon>
</div>
<div class="brave-about-meta">
<span class="brave-about-item brave-about-menu-link-text">${aboutTitleContent}</span>
<span class="brave-about-item brave-about-menu-version">v ${loadTimeData.getString('braveProductVersion')}</span>
</div>
`
const parent = aboutEl.parentNode
parent.removeChild(aboutEl)

const newAboutEl = document.createElement('a')
newAboutEl.setAttribute('href', '/help')
newAboutEl.setAttribute('id', aboutEl.id)

const graphicsEl = document.createElement('div')
graphicsEl.setAttribute('class', 'brave-about-graphic')

const icon = document.createElement('iron-icon')
icon.setAttribute('icon', 'brave_settings:full-color-brave-lion')

const metaEl = document.createElement('div')
metaEl.setAttribute('class', 'brave-about-meta')

const menuLink = document.createElement('span')
menuLink.setAttribute('class', 'brave-about-item brave-about-menu-link-text')
menuLink.textContent = aboutEl.textContent

const versionEl = document.createElement('span')
versionEl.setAttribute('class', 'brave-about-item brave-about-menu-version')
versionEl.textContent = `v ${loadTimeData.getString('braveProductVersion')}`

parent.appendChild(newAboutEl)
newAboutEl.appendChild(graphicsEl)
graphicsEl.appendChild(icon)
newAboutEl.appendChild(metaEl)
metaEl.appendChild(menuLink)
metaEl.appendChild(versionEl)
}
})
29 changes: 29 additions & 0 deletions build/commands/scripts/checkSecurity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2020 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.

const execSync = require('child_process').execSync

// Grep for any usage of innerHTML. TODO: add dangerouslySetInnerHTML.
// Ping @security-team before changing this.
const cmd = "git grep --extended-regexp '(innerHTML|document.write)' ':(exclude)*test.cc' ':(exclude)test/*' ':(exclude)*.json' ':(exclude)build/*' ':(exclude)*browsertest*.cc'"

try {
const stdout = execSync(cmd)
if (stdout.length) {
console.log(stdout.toString())
// grep returned results, so the test fails.
console.log('checkSecurity failed! Found uses of innerHTML/document.write.')
process.exit(1)
}
} catch (e) {
if (!e.stderr.length && !e.stdout.length && e.status === 1) {
// no grep results, so test passes
console.log('checkSecurity passed.')
process.exit(0)
} else {
console.log('checkSecurity failed. See above for error.')
process.exit(e.status)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const callback = (mutationsList: MutationRecord[], observer: MutationObserver) =
const buttons: NodeListOf<Element> = document.querySelectorAll('div.webstore-test-button-label')

buttons.forEach((button: Element) => {
const text: string = button.innerHTML
const text: string = button.textContent || ''
if (textToMatch.includes(text)) {
button.innerHTML = text.replace('Chrome', 'Brave')
button.textContent = text.replace('Chrome', 'Brave')
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ const createBraveTipAction = (elem: Element, getMetaData: (elem: Element) => Rew

// Create style element for hover color
const style = document.createElement('style')
style.innerHTML = '.GitHubTip-actionButton :hover { color: #FB542B }'
style.appendChild(
document.createTextNode('.GitHubTip-actionButton :hover { color: #FB542B }')
)
shadowRoot.appendChild(style)

return braveTipAction
Expand All @@ -123,7 +125,7 @@ const getCommentMetaData = (elem: Element): RewardsTip.MediaMetaData | null => {
const authorCollection = ancestor.getElementsByClassName('author')
if (authorCollection.length) {
const author = authorCollection[0] as HTMLElement
const userName = author.innerHTML
const userName = author.textContent
return {
mediaType: 'github',
userName: userName || ''
Expand Down Expand Up @@ -155,7 +157,7 @@ const getReviewItemMetaData = (elem: Element): RewardsTip.MediaMetaData | null =
const authorCollection = ancestor.getElementsByClassName('author')
if (authorCollection.length) {
const author = authorCollection[0] as HTMLElement
const userName = author.innerHTML
const userName = author.textContent
return {
mediaType: 'github',
userName: userName || ''
Expand Down Expand Up @@ -254,7 +256,7 @@ const getPageHeadMetaData = (elem: Element): RewardsTip.MediaMetaData | null =>
const aTags = author.getElementsByTagName('A')
if (aTags.length) {
const aTag = aTags[0] as HTMLAnchorElement
const userName = aTag.innerHTML
const userName = aTag.textContent
return {
mediaType: 'github',
userName: userName || ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ const createRedditTipButton = () => {
braveTipButton.type = 'button'

const style = document.createElement('style')
style.innerHTML = '.reddit-actionButton :hover { color: #FB542B }'
const css = '.reddit-actionButton :hover { color: #FB542B }'
style.appendChild(document.createTextNode(css))
braveTipButton.appendChild(style)

return braveTipButton
Expand Down Expand Up @@ -232,13 +233,15 @@ const createRedditTipActionCountPresentation = () => {
const createHoverStyleElement = (isPost: boolean) => {
// Create style element for hover
const style = document.createElement('style')
style.innerHTML = isPost ? ':host { outline: none } :host(:hover) { background-color: var(--newRedditTheme-navIconFaded10) }' : '.reddit-actionButton { text-decoration: none; color: var(--newCommunityTheme-actionIcon); font-weight: bold; padding: 0px 1px; } .reddit-actionButton:hover { color: var(--newCommunityTheme-bodyText); text-decoration: underline }'
const css = isPost ? ':host { outline: none } :host(:hover) { background-color: var(--newRedditTheme-navIconFaded10) }' : '.reddit-actionButton { text-decoration: none; color: var(--newCommunityTheme-actionIcon); font-weight: bold; padding: 0px 1px; } .reddit-actionButton:hover { color: var(--newCommunityTheme-bodyText); text-decoration: underline }'
style.appendChild(document.createTextNode(css))
return style
}

const createHoverStyleElementForOld = () => {
const style = document.createElement('style')
style.innerHTML = '.reddit-actionButton { color: #888; font-weight: bold; paddings: 0 1px; text-decoration: none } .reddit-actionButton:hover { text-decoration: underline }'
const css = '.reddit-actionButton { color: #888; font-weight: bold; paddings: 0 1px; text-decoration: none } .reddit-actionButton:hover { text-decoration: underline }'
style.appendChild(document.createTextNode(css))
return style
}

Expand Down
Loading

0 comments on commit 52edf9e

Please sign in to comment.