diff --git a/app/extensions/brave/locales/en-US/app.properties b/app/extensions/brave/locales/en-US/app.properties index 3d0c3ab20e..5c11eeac33 100644 --- a/app/extensions/brave/locales/en-US/app.properties +++ b/app/extensions/brave/locales/en-US/app.properties @@ -94,7 +94,8 @@ applyAndRestart=Apply and restart fullscreenNotice={{origin}} is now fullscreen. Press ESC to exit. secureConnection=Secure connection secureConnectionInfo=This page was loaded securely over HTTPS. -mixedConnection=Partially insecure connection +partiallySecureConnection=Partially insecure connection +partiallySecureConnectionInfo=This page was loaded over HTTPS, but some elements were not loaded securely. insecureConnection=Using an insecure connection insecureConnectionInfo=Your connection to this site is not private. An eavesdropper may be able to tamper with this page and read your data. blockedTrackingElements={{blockedTrackingElementsSize}} Blocked tracking elements diff --git a/app/renderer/components/urlBarIcon.js b/app/renderer/components/urlBarIcon.js index eb0d220f75..9132dcea0f 100644 --- a/app/renderer/components/urlBarIcon.js +++ b/app/renderer/components/urlBarIcon.js @@ -11,40 +11,28 @@ const dndData = require('../../../js/dndData') const {isSourceAboutUrl} = require('../../../js/lib/appUrlUtil') const searchIconSize = 16 -const getIconCssClass = (ctx) => { - if (ctx.isSearch) { - return 'fa-search' - } else if (ctx.isAboutPage && !ctx.props.titleMode) { - return 'fa-list' - } else if (ctx.isSecure) { - // NOTE: EV style not approved yet; see discussion at https://github.com/brave/browser-laptop/issues/791 - return 'fa-lock' - } else if (ctx.isInsecure) { - return 'fa-unlock' - } -} - class UrlBarIcon extends ImmutableComponent { constructor () { super() this.onClick = this.onClick.bind(this) this.onDragStart = this.onDragStart.bind(this) } - get isSecure () { - return this.props.isHTTPPage && - this.props.isSecure && - !this.props.active - } - /** - * insecure icon does not show when: - * - loading - * - in title mode - * - urlbar is active (ex: you can type) - */ - get isInsecure () { - return this.props.isHTTPPage && - this.props.isSecure === false && - !this.props.active + get iconCssClasses () { + if (this.isSearch) { + return ['fa-search'] + } else if (this.isAboutPage && !this.props.titleMode) { + return ['fa-list'] + } else if (this.props.isHTTPPage && !this.props.active) { + // NOTE: EV style not approved yet; see discussion at https://github.com/brave/browser-laptop/issues/791 + if (this.props.isSecure === true) { + return ['fa-lock'] + } else if (this.props.isSecure === false) { + return ['fa-unlock', 'insecure-color'] + } else if (this.props.isSecure === 1) { + return ['fa-unlock'] + } + } + return [] } /** * search icon: @@ -55,7 +43,7 @@ class UrlBarIcon extends ImmutableComponent { get isSearch () { const showSearch = this.props.isSearching && !this.props.titleMode - const defaultToSearch = (!this.isSecure && !this.isInsecure && !showSearch) && + const defaultToSearch = (!this.props.isHTTPPage || this.props.active) && !this.props.titleMode && !this.isAboutPage @@ -69,12 +57,14 @@ class UrlBarIcon extends ImmutableComponent { if (this.props.activateSearchEngine) { return cx({urlbarIcon: true}) } - - return cx({ + const iconClasses = { urlbarIcon: true, - 'fa': true, - [ getIconCssClass(this) ]: true + fa: true + } + this.iconCssClasses.forEach((iconClass) => { + iconClasses[iconClass] = true }) + return cx(iconClasses) } get iconStyles () { if (!this.props.activateSearchEngine) { diff --git a/docs/state.md b/docs/state.md index b03629611c..4d113669c3 100644 --- a/docs/state.md +++ b/docs/state.md @@ -456,8 +456,8 @@ WindowStore showFullScreenWarning: boolean, // true if a warning should be shown about full screen security: { blockedRunInsecureContent: Array, // sources of blocked active mixed content - isSecure: boolean, // is using https - isExtendedValidation: boolean, // is using https ev + isSecure: (boolean|number), // true = fully secure, false = fully insecure, 1 = partially secure + isExtendedValidation: boolean, // is using https ev. not currently used. loginRequiredDetail: { isProxy: boolean, host: string, diff --git a/js/components/frame.js b/js/components/frame.js index 79320fee80..7aac451b5d 100644 --- a/js/components/frame.js +++ b/js/components/frame.js @@ -892,19 +892,19 @@ class Frame extends ImmutableComponent { } let isSecure = null let runInsecureContent = this.runInsecureContent() - // 'warning' and 'passive mixed content' should never upgrade the - // security state from insecure to secure - if (e.securityState === 'secure' || - (this.props.isSecure !== false && - runInsecureContent !== true && - ['warning', 'passive-mixed-content'].includes(e.securityState))) { + if (e.securityState === 'secure') { isSecure = true } else if (['broken', 'insecure'].includes(e.securityState)) { isSecure = false + } else if (this.props.isSecure !== false && + ['warning', 'passive-mixed-content'].includes(e.securityState)) { + // Passive mixed content should not upgrade an insecure connection to a + // partially-secure connection. It can only downgrade a secure + // connection. + isSecure = 1 } - // TODO: show intermediate UI for 'warning' and 'passive-mixed-content' windowActions.setSecurityState(this.frame, { - secure: isSecure, + secure: runInsecureContent ? false : isSecure, runInsecureContent }) if (isSecure) { diff --git a/js/components/main.js b/js/components/main.js index f0f8b5eeb1..597bd787c4 100644 --- a/js/components/main.js +++ b/js/components/main.js @@ -998,8 +998,7 @@ class Main extends ImmutableComponent { partitionNumber={activeFrame && activeFrame.get('partitionNumber') || 0} history={activeFrame && activeFrame.get('history') || emptyList} suggestionIndex={activeFrame && activeFrame.getIn(['navbar', 'urlbar', 'suggestions', 'selectedIndex']) || 0} - isSecure={activeFrame && activeFrame.getIn(['security', 'isSecure']) && - !activeFrame.getIn(['security', 'runInsecureContent'])} + isSecure={activeFrame ? activeFrame.getIn(['security', 'isSecure']) : null} hasLocationValueSuffix={activeFrame && activeFrame.getIn(['navbar', 'urlbar', 'suggestions', 'urlSuffix'])} startLoadTime={activeFrame && activeFrame.get('startLoadTime') || undefined} endLoadTime={activeFrame && activeFrame.get('endLoadTime') || undefined} diff --git a/js/components/siteInfo.js b/js/components/siteInfo.js index d7e3f3ce26..16fe6b5cdb 100644 --- a/js/components/siteInfo.js +++ b/js/components/siteInfo.js @@ -57,17 +57,20 @@ class SiteInfo extends ImmutableComponent { partitionNumber: this.partitionNumber } let secureIcon - if (this.isSecure && !this.runInsecureContent) { + if (this.isSecure === true && !this.runInsecureContent) { + // fully secure secureIcon =
  • - } else if (this.isSecure && this.runInsecureContent) { - secureIcon =
  • + } else if (this.isSecure === 1 && !this.runInsecureContent) { + // passive mixed content loaded + secureIcon =
  • } else { - secureIcon =
  • + // insecure + secureIcon =
  • } let partitionInfo @@ -99,9 +102,12 @@ class SiteInfo extends ImmutableComponent { - } else if (this.isSecure) { + } else if (this.isSecure === true) { connectionInfo =
    + } else if (this.isSecure === 1) { + connectionInfo = +
    } else { connectionInfo =
    diff --git a/less/navigationBar.less b/less/navigationBar.less index ac8527633f..9c98effafd 100644 --- a/less/navigationBar.less +++ b/less/navigationBar.less @@ -807,7 +807,7 @@ left: 2px; min-width: 0; - &.fa-unlock { + &.insecure-color { color: @siteInsecureColor; opacity: 1.0; } @@ -911,7 +911,7 @@ font-size: 16px; } - &.fa-unlock { + &.insecure-color { color: @siteInsecureColor; } diff --git a/test/components/navigationBarTest.js b/test/components/navigationBarTest.js index b97b156078..10ef433f89 100644 --- a/test/components/navigationBarTest.js +++ b/test/components/navigationBarTest.js @@ -406,7 +406,7 @@ describe('navigationBar tests', function () { .activateURLMode() .waitForExist(urlbarIcon) .getAttribute(urlbarIcon, 'class').then((classes) => - classes.includes('fa-unlock') + classes.includes('fa-unlock') && classes.includes('insecure-color') )) .windowByUrl(Brave.browserWindowUrl) .click(urlbarIcon) @@ -426,7 +426,7 @@ describe('navigationBar tests', function () { .waitForExist(titleBar) .isExisting(urlbarIcon).then((isExisting) => assert(isExisting)) .getAttribute(urlbarIcon, 'class').then((classes) => - classes.includes('fa-unlock') + classes.includes('fa-unlock') && classes.includes('insecure-color') ) }) it('Shows secure URL icon', function * () { @@ -470,7 +470,7 @@ describe('navigationBar tests', function () { assert(!classes.includes('fa-lock')) ) }) - it('shows secure icon on a site with passive mixed content', function * () { + it('shows partially-secure icon on a site with passive mixed content', function * () { const page1Url = 'https://mixed.badssl.com/' yield this.app.client.tabByUrl(Brave.newTabUrl).url(page1Url).waitForUrl(page1Url).windowParentByUrl(page1Url) yield this.app.client @@ -478,9 +478,11 @@ describe('navigationBar tests', function () { .waitForExist(urlbarIcon) .waitUntil(() => this.app.client.getAttribute(urlbarIcon, 'class').then((classes) => - classes.includes('fa-lock') + classes.includes('fa-unlock') && !classes.includes('insecure-color') ) ) + .click(urlbarIcon) + .waitForVisible('[data-l10n-id="partiallySecureConnection"]') }) it('shows insecure icon on a site with a sha-1 cert', function * () { const page1Url = 'https://sha1-2017.badssl.com/' @@ -490,7 +492,7 @@ describe('navigationBar tests', function () { .waitForExist(urlbarIcon) .waitUntil(() => this.app.client.getAttribute(urlbarIcon, 'class').then((classes) => - classes.includes('fa-unlock') + classes.includes('fa-unlock') && classes.includes('insecure-color') ) ) }) @@ -514,7 +516,7 @@ describe('navigationBar tests', function () { .waitForExist(urlbarIcon) .waitUntil(() => this.app.client.getAttribute(urlbarIcon, 'class').then((classes) => - classes.includes('fa-unlock') + classes.includes('fa-unlock') && classes.includes('insecure-color') ) ) }) @@ -598,7 +600,7 @@ describe('navigationBar tests', function () { .windowByUrl(Brave.browserWindowUrl) .waitForExist(urlbarIcon) .click(urlbarIcon) - .waitForVisible('[data-l10n-id="mixedConnection"]') + .waitForVisible('[data-l10n-id="insecureConnection"]') .waitForVisible('.denyRunInsecureContentWarning') .waitForVisible(dismissDenyRunInsecureContentButton) .waitForVisible(denyRunInsecureContentButton)