Skip to content

Commit

Permalink
Merge pull request #145 from duckduckgo/03-29-support_invalid_certs
Browse files Browse the repository at this point in the history
support invalid certs
  • Loading branch information
shakyShane committed Apr 8, 2024
2 parents 620921f + b5dee92 commit 14b13d0
Show file tree
Hide file tree
Showing 84 changed files with 1,065 additions and 431 deletions.
1 change: 1 addition & 0 deletions build/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<h2>Links</h2>
<ul>
<li><a href="docs">Documentation</a></li>
<li><a href="./html/iframe.html">iframe debugging</a></li>
<li><a href="https://github.com/duckduckgo/privacy-dashboard">Repo (Github)</a></li>
</ul>
</body>
Expand Down
3 changes: 2 additions & 1 deletion build/app/public/css/popup.css
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,8 @@ body.environment--windows {

.hero-icon--insecure-connection,
.hero-icon--trackers-blocked,
.hero-icon--connection-none {
.hero-icon--connection-none,
.hero-icon--connection-invalid {
background-image: url("../../img/refresh-assets/Unlocked-128.svg");
}

Expand Down
151 changes: 92 additions & 59 deletions build/app/public/js/base.js

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions debugger/debugger.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { h, render } from 'preact'
import styles from './debugger.module.css'
import { createDataStates } from '../shared/js/ui/views/tests/generate-data.mjs'

import google from '../schema/__fixtures__/request-data-google.json'
import cnn from '../schema/__fixtures__/request-data-cnn.json'

const states = createDataStates(google, cnn)
const keys = Object.keys(states)

const items = [
{
platform: 'android',
height: 780,
},
{
platform: 'ios',
height: 780,
},
{
platform: 'macos',
height: 600,
},
{
platform: 'windows',
height: 780,
},
{
platform: 'browser',
},
]

let initialState = new URL(window.location).searchParams.get('state')
if (!keys.includes(initialState)) {
initialState = 'protectionsOn_blocked'
}

let platforms = (() => {
let subject = new URL(window.location).searchParams.get('platforms')
const known = items.map((x) => x.platform)
if (subject) {
const selected = subject
.split(',')
.map((x) => x.trim())
.filter((x) => known.includes(x))
if (selected.length > 0) {
return selected
}
}
return known.slice(0, 3)
})()

function update(value) {
const url = new URL(window.location.href)
url.searchParams.set('state', value)
window.location = url
}

function updatePlatforms(value) {
const url = new URL(window.location.href)
url.searchParams.set('platforms', value.join(','))
window.location = url
}

function App() {
return (
<div class={styles.grid}>
<div class={styles.header}>
<Selector selected={initialState} onChange={update} />
<Toggles selected={platforms} onChange={updatePlatforms} />
</div>
<div class={styles.content}>
<Frames platforms={platforms} initialState={initialState} />
</div>
</div>
)
}

function Selector({ selected, onChange }) {
return (
<select onChange={(e) => onChange(e.target.value)}>
{Object.entries(states).map(([key, value]) => {
return (
<option value={key} selected={selected === key}>
{key}
</option>
)
})}
</select>
)
}

function Toggles({ selected, onChange }) {
function onChanged(e) {
const d = new FormData(e.target.form)
onChange(d.getAll('platform'))
}
return (
<form onChange={onChanged}>
{items.map((item) => {
return (
<label class={styles.label}>
<input type="checkbox" name="platform" value={item.platform} checked={selected.includes(item.platform)}></input>{' '}
{item.platform}
</label>
)
})}
</form>
)
}

function Frames({ platforms, initialState }) {
const previewJSON = states[initialState]
const { certificate, ...rest } = previewJSON
rest.certificate = certificate
return (
<div class={styles.frames}>
<div class={styles.code} data-state="ready">
<pre>
<code>{JSON.stringify(rest, null, 2)}</code>
</pre>
</div>
{items.map((item) => {
const { platform, ...rest } = item
const params = new URLSearchParams({ ...rest, state: initialState }).toString()
const src = item.platform + '.html?' + params.toString()
const height = item.height ?? 600
return (
<div class={styles.frame} data-state={platforms.includes(platform) ? 'ready' : 'hidden'}>
<p>
<a href={src} target="_blank">
Open in new tab
</a>
</p>
<p>
<code>{item.platform}</code> <small>{initialState}</small>
</p>
<iframe
src={src}
frameBorder="0"
style={{
width: '360px',
height: height + 'px',
}}
></iframe>
</div>
)
})}
</div>
)
}

render(<App />, document.querySelector('#app'))
52 changes: 52 additions & 0 deletions debugger/debugger.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import url('./reset.css');
body {
max-height: 100vh;
max-width: 100vw;
overflow: hidden;
}
.grid {
display: grid;
height: 100vh;
overflow: hidden;
grid-template-rows: auto 1fr;
grid-template-areas:
'header'
'content';
}
.header {
border: 1px dashed black;
grid-area: header;
padding: 1em;
}
.content {
padding: 1em;
border: 1px dashed green;
grid-area: content;
overflow-y: scroll;
height: 100%;
}
.frames {
display: grid;
grid-template-columns: repeat(auto-fill, 360px);
grid-gap: 10px;
}
.frame {
display: none;
font-family: monospace;
}
.frame[data-state='ready'] {
display: block;
}
.code {
overflow: scroll;
max-height: 80vh;
font-size: 10px;
}
form {
display: flex;
gap: 1em;
}
.label {
display: flex;
gap: 0.5em;
}
13 changes: 13 additions & 0 deletions debugger/iframe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Debug</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="../debugger/debugger.css" />
</head>
<body>
<div id="app"></div>
<script src="../debugger/debugger.js"></script>
</body>
</html>
62 changes: 62 additions & 0 deletions debugger/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
1. Use a more-intuitive box-sizing model.
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
2. Remove default margin
*/
* {
margin: 0;
}
/*
Typographic tweaks!
3. Add accessible line-height
4. Improve text rendering
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
5. Improve media defaults
*/
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
/*
6. Remove built-in form typography styles
*/
input,
button,
textarea,
select {
font: inherit;
}
/*
7. Avoid text overflows
*/
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
/*
8. Create a root stacking context
*/
#root,
#__next {
isolation: isolate;
}
14 changes: 14 additions & 0 deletions integration-tests/DashboardPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ export class DashboardPage {
await this.page.locator('[data-page="connection"]').waitFor({ timeout: 2000 })
}

async hasInvalidCertText() {
const { page } = this
await expect(page.locator('#popup-container')).toContainText(
'The certificate for this site is invalid. You might be connecting to a server that is pretending to be example.com which could put your confidential information at risk.'
)
}

async showsInvalidCertDetail() {
const { page } = this
await expect(page.locator('#key-insight')).toContainText(
'The certificate for this site is invalid. You might be connecting to a server that is pretending to be example.com which could put your confidential information at risk.'
)
}

async showsTrackersScreen() {
await this.page.locator('[data-page="trackers"]').waitFor({ timeout: 2000 })
}
Expand Down
11 changes: 11 additions & 0 deletions integration-tests/macos.spec-int.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ test.describe('permissions', () => {
settingPermissions((page) => DashboardPage.webkit(page, { platform: 'macos' }))
})

test('invalid/missing certificate', async ({ page }) => {
/** @type {DashboardPage} */
const dash = await DashboardPage.webkit(page, { platform: 'macos' })
await dash.addState([testDataStates['without-certificate']])
await dash.screenshot('invalid-cert.png')
await dash.hasInvalidCertText()
await dash.viewConnection()
await dash.screenshot('invalid-detail.png')
await dash.showsInvalidCertDetail()
})

test.describe('opening breakage form', () => {
test('shows breakage form only', async ({ page }) => {
/** @type {DashboardPage} */
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 14b13d0

Please sign in to comment.