Skip to content

Commit 55ccd14

Browse files
committed
Better UX for overriding protocol-level permissions.
1 parent ddbd704 commit 55ccd14

3 files changed

Lines changed: 73 additions & 24 deletions

File tree

src/ui/popup.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,17 @@ addEventListener("unload", e => {
175175
typesMap.clear();
176176
let policySites = UI.policy.sites;
177177
let domains = new Map();
178-
178+
let protocols = new Set();
179179
function urlToLabel(url) {
180180
let origin = Sites.origin(url);
181181
let match = policySites.match(url);
182-
if (match) return match;
182+
if (match) {
183+
if (match === url.protocol) {
184+
protocols.add(match);
185+
} else {
186+
return match;
187+
}
188+
}
183189
if (domains.has(origin)) {
184190
if (justDomains) return domains.get(origin);
185191
} else {
@@ -207,6 +213,7 @@ addEventListener("unload", e => {
207213
if (!justDomains) {
208214
for (let domain of domains.values()) sitesSet.add(domain);
209215
}
216+
for (let protocol of protocols) sitesSet.add(protocol);
210217
let sites = [...sitesSet];
211218
for (let parsed of parsedSeen) {
212219
sites.filter(s => parsed.label === s || domains.get(Sites.origin(parsed.url)) === s).forEach(m => {

src/ui/ui.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ label.https-only {
155155
display: none;
156156
}
157157

158+
.preset label.preset.override {
159+
color: #555;
160+
}
161+
158162
[data-preset="UNTRUSTED"] .https-only, [data-preset="DEFAULT"] .https-only {
159163
visibility: hidden;
160164
}

src/ui/ui.js

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ var UI = (() => {
174174

175175
function compareBy(prop, a, b) {
176176
let x = a[prop], y = b[prop];
177+
if (x.endsWith(":")) {
178+
if (!y.endsWith(":")) {
179+
return this.mainDomain ? 1 : -1;
180+
}
181+
} else if (y.endsWith(":")) {
182+
return this.mainDomain ? -1 : 1;
183+
}
177184
return x > y ? 1 : x < y ? -1 : 0;
178185
}
179186

@@ -542,10 +549,10 @@ var UI = (() => {
542549
} else if (y === md) {
543550
return 1;
544551
}
545-
return wrappedCompare(a, b);
552+
return wrappedCompare.call(this, a, b);
546553
}
547554
}
548-
let rows = [...this.allSiteRows()].sort(sorter);
555+
let rows = [...this.allSiteRows()].sort(sorter.bind(this));
549556
if (this.mainSite) {
550557
let mainLabel = "." + this.mainDomain;
551558
let topIdx = rows.findIndex(r => r._label === mainLabel);
@@ -563,7 +570,8 @@ var UI = (() => {
563570
}
564571

565572
sorter(a, b) {
566-
return compareBy("domain", a, b) || compareBy("_label", a, b);
573+
let cb = compareBy.bind(this);
574+
return cb("domain", a, b) || cb("_label", a, b);
567575
}
568576

569577
async tempTrustAll() {
@@ -583,28 +591,36 @@ var UI = (() => {
583591

584592
createSiteRow(site, siteMatch, perms, contextMatch = null, sitesCount = this.sitesCount++) {
585593
debug("Creating row for site: %s, matching %s / %s, %o", site, siteMatch, contextMatch, perms);
586-
594+
let policy = UI.policy;
587595
let row = this.rowTemplate.cloneNode(true);
588596
row.sitesCount = sitesCount;
589597
let url;
590598
try {
591599
url = new URL(site);
600+
if (siteMatch !== site && siteMatch === url.protocol) {
601+
perms = policy.DEFAULT;
602+
}
592603
} catch (e) {
593604
if (/^(\w+:)\/*$/.test(site)) {
594-
url = {protocol: RegExp.$1, hostname: "", origin: site, pathname:""};
595-
let hostname = Sites.toExternal(url.hostname);
596-
debug("Lonely %o", url, Sites.isSecureDomainKey(siteMatch) || !hostname && url.protocol === "https:");
605+
let hostname = "";
606+
url = {protocol: RegExp.$1, hostname, origin: site, pathname:""};
607+
debug("Lonely %o", url);
597608
} else {
609+
debug("Domain %s (%s)", site, siteMatch);
598610
let protocol = Sites.isSecureDomainKey(site) ? "https:" : "http:";
599611
let hostname = Sites.toggleSecureDomainKey(site, false);
600-
url = {protocol, hostname, origin: `${protocol}://${site}`, pathname: "/"};
612+
url = {protocol, hostname, origin: `${protocol}//${site}`, pathname: "/"};
601613
}
602614
}
603615

604616
let hostname = Sites.toExternal(url.hostname);
605-
let domain = tld.getDomain(hostname);
617+
let overrideDefault = url.protocol && site !== url.protocol ?
618+
policy.get(url.protocol, contextMatch) : null;
619+
if (overrideDefault && !overrideDefault.siteMatch) overrideDefault = null;
606620

607-
if (!siteMatch) {
621+
let domain = tld.getDomain(hostname);
622+
let disableDefault = false;
623+
if (!siteMatch || siteMatch === url.protocol && site !== siteMatch) {
608624
siteMatch = site;
609625
}
610626
let secure = Sites.isSecureDomainKey(siteMatch);
@@ -654,23 +670,45 @@ var UI = (() => {
654670
label.setAttribute("for", temp.id);
655671
}
656672
}
657-
let policy = UI.policy;
658673

659-
let presetName = "CUSTOM";
660-
for (let p of ["TRUSTED", "UNTRUSTED", "DEFAULT"]) {
661-
let preset = policy[p];
662-
switch (perms) {
663-
case preset:
664-
presetName = p;
665-
break;
666-
case preset.tempTwin:
667-
presetName = `T_${p}`;
668-
if (!presetName in UI.presets) {
674+
let getPresetName = perms => {
675+
let presetName = "CUSTOM";
676+
for (let p of ["TRUSTED", "UNTRUSTED", "DEFAULT"]) {
677+
let preset = policy[p];
678+
switch (perms) {
679+
case preset:
669680
presetName = p;
681+
break;
682+
case preset.tempTwin:
683+
presetName = `T_${p}`;
684+
if (!presetName in UI.presets) {
685+
presetName = p;
686+
}
687+
break;
688+
}
689+
}
690+
return presetName;
691+
}
692+
693+
let presetName = getPresetName(perms);
694+
if (overrideDefault) {
695+
let overrideName = getPresetName(overrideDefault.perms);
696+
if (overrideName) {
697+
let override = row.querySelector(`.presets input[value="${overrideName}"]`);
698+
if (override) {
699+
let def = row.querySelector(`.presets input[value="DEFAULT"]`);
700+
if (def && def !== override) {
701+
let label = def.nextElementSibling;
702+
label.title = def.title = `${override.title} (${overrideDefault.siteMatch})`;
703+
label.textContent = override.nextElementSibling.textContent + "*";
704+
label.classList.toggle("override", true);
705+
def.dataset.override = overrideName;
706+
def.style.backgroundImage = window.getComputedStyle(override, null).backgroundImage;
670707
}
671-
break;
672708
}
709+
}
673710
}
711+
674712
let tempFirst = true; // TODO: make it a preference
675713
let unsafeMatch = keyStyle !== "secure" && keyStyle !== "full";
676714
if (presetName === "DEFAULT" && (tempFirst || unsafeMatch)) {

0 commit comments

Comments
 (0)