Firefox add-on for highlighting insecure links

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite












My first Firefox add-on puts a red border around insecure links, including plain HTTP links and links with a JavaScript event handler. The code is linted and appears to have good unit and acceptance test coverage. I'm mostly worried about breaking WebExtensions or JavaScript rules or conventions.



manifest.json:




"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.19",
"author": "Victor Engmark",
"homepage_url": "https://github.com/l0b0/insecure-links-highlighter",
"content_scripts": [

"matches": [
"<all_urls>"
],
"js": [
"defaultOptions.js",
"dom.js",
"url.js",
"highlight.js"
],
"all_frames": true

],
"options_ui":
"browser_style": true,
"page": "options.html"
,
"permissions": [
"storage"
],
"icons":
"48": "icons/48.png",
"96": "icons/96.png"
,
"default_locale": "en",
"applications":
"gecko":
"id": "da90161a-9c5c-4315-adae-2eedbe24810a"





defaultOptions.js:



(function (exports) 
exports.defaultOptions =
borderColor: 'red',
elementsWithEventHandlersAreInsecure: true,
class: 'insecure-links-highlighter-highlighted',
;
(this));


dom.js (trimmed most of eventHandlerAttributes for brevity):



(function (exports) 
'use strict';

const eventHandlerAttributes = [
'onabort',
'onwheel',
];

function commonAncestor(elements)
const ancestorLists = elements.map(ancestors);
let commonAncestorIndex = 0,
commonAncestor;

function hasNextAncestor(ancestors)
return ancestors[commonAncestorIndex + 1] === commonAncestor;


do
commonAncestor = ancestorLists[0][commonAncestorIndex];
commonAncestorIndex++;
while (ancestorLists.every(hasNextAncestor));

return commonAncestor;


function ancestors(element)
let ancestors = [element];
while (element.parentElement !== null)
let parent = element.parentElement;
ancestors.unshift(parent);
element = parent;

return ancestors;


function hasInsecureHrefAttribute(element, protocol)
return element.hasAttribute('href') && !isSecureURL(element.getAttribute('href'), protocol);


function hasNonDefaultEventHandler(element)
function hasEventHandler(handlerAttribute)
const attribute = element[handlerAttribute];
return attribute !== undefined && attribute !== null;


return eventHandlerAttributes.some(hasEventHandler);


function highlight(element, configuration)
if (element.style.cssText !== '')
element.style.cssText += '; ';


element.classList.add(configuration.class);
element.style.cssText += `border-color: $configuration.borderColor !important; border-style: solid !important; border-width: medium !important;`;


function getLinks(node)
return Array.from(node.getElementsByTagName('a'));


function isElement(node)
return node.nodeType === Node.ELEMENT_NODE;


exports.ancestors = ancestors;
exports.commonAncestor = commonAncestor;
exports.getLinks = getLinks;
exports.hasInsecureHrefAttribute = hasInsecureHrefAttribute;
exports.hasNonDefaultEventHandler = hasNonDefaultEventHandler;
exports.highlight = highlight;
exports.isElement = isElement;
(this));


highlight.js:



(function () 
'use strict';
let configuration;

function onConfigurationRetrieved(items)
configuration = items;
processAndObserveDocument();


function processAndObserveDocument()
const attributeObserver = new MutationObserver(onAttributeMutation),
elementObserver = new MutationObserver(onElementMutation);

processNode(document);

attributeObserver.observe(document.body, 'attributes': true, 'subtree': true);
elementObserver.observe(document.body, 'childList': true, 'subtree': true);


function onAttributeMutation(mutationRecords)
mutationRecords.forEach(processAttributeMutationRecord);


function processAttributeMutationRecord(mutationRecord)
if (mutationRecord.attributeName === 'href')
highlightInsecureLink(mutationRecord.target);



function onElementMutation(mutationRecords)
const addedElementsList = mutationRecords.map(mutationRecordElements),
addedElements = .concat.apply(, addedElementsList);

processNode(commonAncestor(addedElements));


function mutationRecordElements(mutationRecord)
return Array.from(mutationRecord.addedNodes).filter(isElement);


function processNode(node)
getLinks(node).forEach(highlightInsecureLink);


function highlightInsecureLink(element)
if (
hasInsecureHrefAttribute(element, location.protocol)

browser.storage.local.get(defaultOptions).then(onConfigurationRetrieved);
());


url.js:



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));






share|improve this question





















  • @Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
    – l0b0
    May 10 at 0:49
















up vote
5
down vote

favorite












My first Firefox add-on puts a red border around insecure links, including plain HTTP links and links with a JavaScript event handler. The code is linted and appears to have good unit and acceptance test coverage. I'm mostly worried about breaking WebExtensions or JavaScript rules or conventions.



manifest.json:




"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.19",
"author": "Victor Engmark",
"homepage_url": "https://github.com/l0b0/insecure-links-highlighter",
"content_scripts": [

"matches": [
"<all_urls>"
],
"js": [
"defaultOptions.js",
"dom.js",
"url.js",
"highlight.js"
],
"all_frames": true

],
"options_ui":
"browser_style": true,
"page": "options.html"
,
"permissions": [
"storage"
],
"icons":
"48": "icons/48.png",
"96": "icons/96.png"
,
"default_locale": "en",
"applications":
"gecko":
"id": "da90161a-9c5c-4315-adae-2eedbe24810a"





defaultOptions.js:



(function (exports) 
exports.defaultOptions =
borderColor: 'red',
elementsWithEventHandlersAreInsecure: true,
class: 'insecure-links-highlighter-highlighted',
;
(this));


dom.js (trimmed most of eventHandlerAttributes for brevity):



(function (exports) 
'use strict';

const eventHandlerAttributes = [
'onabort',
'onwheel',
];

function commonAncestor(elements)
const ancestorLists = elements.map(ancestors);
let commonAncestorIndex = 0,
commonAncestor;

function hasNextAncestor(ancestors)
return ancestors[commonAncestorIndex + 1] === commonAncestor;


do
commonAncestor = ancestorLists[0][commonAncestorIndex];
commonAncestorIndex++;
while (ancestorLists.every(hasNextAncestor));

return commonAncestor;


function ancestors(element)
let ancestors = [element];
while (element.parentElement !== null)
let parent = element.parentElement;
ancestors.unshift(parent);
element = parent;

return ancestors;


function hasInsecureHrefAttribute(element, protocol)
return element.hasAttribute('href') && !isSecureURL(element.getAttribute('href'), protocol);


function hasNonDefaultEventHandler(element)
function hasEventHandler(handlerAttribute)
const attribute = element[handlerAttribute];
return attribute !== undefined && attribute !== null;


return eventHandlerAttributes.some(hasEventHandler);


function highlight(element, configuration)
if (element.style.cssText !== '')
element.style.cssText += '; ';


element.classList.add(configuration.class);
element.style.cssText += `border-color: $configuration.borderColor !important; border-style: solid !important; border-width: medium !important;`;


function getLinks(node)
return Array.from(node.getElementsByTagName('a'));


function isElement(node)
return node.nodeType === Node.ELEMENT_NODE;


exports.ancestors = ancestors;
exports.commonAncestor = commonAncestor;
exports.getLinks = getLinks;
exports.hasInsecureHrefAttribute = hasInsecureHrefAttribute;
exports.hasNonDefaultEventHandler = hasNonDefaultEventHandler;
exports.highlight = highlight;
exports.isElement = isElement;
(this));


highlight.js:



(function () 
'use strict';
let configuration;

function onConfigurationRetrieved(items)
configuration = items;
processAndObserveDocument();


function processAndObserveDocument()
const attributeObserver = new MutationObserver(onAttributeMutation),
elementObserver = new MutationObserver(onElementMutation);

processNode(document);

attributeObserver.observe(document.body, 'attributes': true, 'subtree': true);
elementObserver.observe(document.body, 'childList': true, 'subtree': true);


function onAttributeMutation(mutationRecords)
mutationRecords.forEach(processAttributeMutationRecord);


function processAttributeMutationRecord(mutationRecord)
if (mutationRecord.attributeName === 'href')
highlightInsecureLink(mutationRecord.target);



function onElementMutation(mutationRecords)
const addedElementsList = mutationRecords.map(mutationRecordElements),
addedElements = .concat.apply(, addedElementsList);

processNode(commonAncestor(addedElements));


function mutationRecordElements(mutationRecord)
return Array.from(mutationRecord.addedNodes).filter(isElement);


function processNode(node)
getLinks(node).forEach(highlightInsecureLink);


function highlightInsecureLink(element)
if (
hasInsecureHrefAttribute(element, location.protocol)

browser.storage.local.get(defaultOptions).then(onConfigurationRetrieved);
());


url.js:



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));






share|improve this question





















  • @Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
    – l0b0
    May 10 at 0:49












up vote
5
down vote

favorite









up vote
5
down vote

favorite











My first Firefox add-on puts a red border around insecure links, including plain HTTP links and links with a JavaScript event handler. The code is linted and appears to have good unit and acceptance test coverage. I'm mostly worried about breaking WebExtensions or JavaScript rules or conventions.



manifest.json:




"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.19",
"author": "Victor Engmark",
"homepage_url": "https://github.com/l0b0/insecure-links-highlighter",
"content_scripts": [

"matches": [
"<all_urls>"
],
"js": [
"defaultOptions.js",
"dom.js",
"url.js",
"highlight.js"
],
"all_frames": true

],
"options_ui":
"browser_style": true,
"page": "options.html"
,
"permissions": [
"storage"
],
"icons":
"48": "icons/48.png",
"96": "icons/96.png"
,
"default_locale": "en",
"applications":
"gecko":
"id": "da90161a-9c5c-4315-adae-2eedbe24810a"





defaultOptions.js:



(function (exports) 
exports.defaultOptions =
borderColor: 'red',
elementsWithEventHandlersAreInsecure: true,
class: 'insecure-links-highlighter-highlighted',
;
(this));


dom.js (trimmed most of eventHandlerAttributes for brevity):



(function (exports) 
'use strict';

const eventHandlerAttributes = [
'onabort',
'onwheel',
];

function commonAncestor(elements)
const ancestorLists = elements.map(ancestors);
let commonAncestorIndex = 0,
commonAncestor;

function hasNextAncestor(ancestors)
return ancestors[commonAncestorIndex + 1] === commonAncestor;


do
commonAncestor = ancestorLists[0][commonAncestorIndex];
commonAncestorIndex++;
while (ancestorLists.every(hasNextAncestor));

return commonAncestor;


function ancestors(element)
let ancestors = [element];
while (element.parentElement !== null)
let parent = element.parentElement;
ancestors.unshift(parent);
element = parent;

return ancestors;


function hasInsecureHrefAttribute(element, protocol)
return element.hasAttribute('href') && !isSecureURL(element.getAttribute('href'), protocol);


function hasNonDefaultEventHandler(element)
function hasEventHandler(handlerAttribute)
const attribute = element[handlerAttribute];
return attribute !== undefined && attribute !== null;


return eventHandlerAttributes.some(hasEventHandler);


function highlight(element, configuration)
if (element.style.cssText !== '')
element.style.cssText += '; ';


element.classList.add(configuration.class);
element.style.cssText += `border-color: $configuration.borderColor !important; border-style: solid !important; border-width: medium !important;`;


function getLinks(node)
return Array.from(node.getElementsByTagName('a'));


function isElement(node)
return node.nodeType === Node.ELEMENT_NODE;


exports.ancestors = ancestors;
exports.commonAncestor = commonAncestor;
exports.getLinks = getLinks;
exports.hasInsecureHrefAttribute = hasInsecureHrefAttribute;
exports.hasNonDefaultEventHandler = hasNonDefaultEventHandler;
exports.highlight = highlight;
exports.isElement = isElement;
(this));


highlight.js:



(function () 
'use strict';
let configuration;

function onConfigurationRetrieved(items)
configuration = items;
processAndObserveDocument();


function processAndObserveDocument()
const attributeObserver = new MutationObserver(onAttributeMutation),
elementObserver = new MutationObserver(onElementMutation);

processNode(document);

attributeObserver.observe(document.body, 'attributes': true, 'subtree': true);
elementObserver.observe(document.body, 'childList': true, 'subtree': true);


function onAttributeMutation(mutationRecords)
mutationRecords.forEach(processAttributeMutationRecord);


function processAttributeMutationRecord(mutationRecord)
if (mutationRecord.attributeName === 'href')
highlightInsecureLink(mutationRecord.target);



function onElementMutation(mutationRecords)
const addedElementsList = mutationRecords.map(mutationRecordElements),
addedElements = .concat.apply(, addedElementsList);

processNode(commonAncestor(addedElements));


function mutationRecordElements(mutationRecord)
return Array.from(mutationRecord.addedNodes).filter(isElement);


function processNode(node)
getLinks(node).forEach(highlightInsecureLink);


function highlightInsecureLink(element)
if (
hasInsecureHrefAttribute(element, location.protocol)

browser.storage.local.get(defaultOptions).then(onConfigurationRetrieved);
());


url.js:



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));






share|improve this question













My first Firefox add-on puts a red border around insecure links, including plain HTTP links and links with a JavaScript event handler. The code is linted and appears to have good unit and acceptance test coverage. I'm mostly worried about breaking WebExtensions or JavaScript rules or conventions.



manifest.json:




"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.19",
"author": "Victor Engmark",
"homepage_url": "https://github.com/l0b0/insecure-links-highlighter",
"content_scripts": [

"matches": [
"<all_urls>"
],
"js": [
"defaultOptions.js",
"dom.js",
"url.js",
"highlight.js"
],
"all_frames": true

],
"options_ui":
"browser_style": true,
"page": "options.html"
,
"permissions": [
"storage"
],
"icons":
"48": "icons/48.png",
"96": "icons/96.png"
,
"default_locale": "en",
"applications":
"gecko":
"id": "da90161a-9c5c-4315-adae-2eedbe24810a"





defaultOptions.js:



(function (exports) 
exports.defaultOptions =
borderColor: 'red',
elementsWithEventHandlersAreInsecure: true,
class: 'insecure-links-highlighter-highlighted',
;
(this));


dom.js (trimmed most of eventHandlerAttributes for brevity):



(function (exports) 
'use strict';

const eventHandlerAttributes = [
'onabort',
'onwheel',
];

function commonAncestor(elements)
const ancestorLists = elements.map(ancestors);
let commonAncestorIndex = 0,
commonAncestor;

function hasNextAncestor(ancestors)
return ancestors[commonAncestorIndex + 1] === commonAncestor;


do
commonAncestor = ancestorLists[0][commonAncestorIndex];
commonAncestorIndex++;
while (ancestorLists.every(hasNextAncestor));

return commonAncestor;


function ancestors(element)
let ancestors = [element];
while (element.parentElement !== null)
let parent = element.parentElement;
ancestors.unshift(parent);
element = parent;

return ancestors;


function hasInsecureHrefAttribute(element, protocol)
return element.hasAttribute('href') && !isSecureURL(element.getAttribute('href'), protocol);


function hasNonDefaultEventHandler(element)
function hasEventHandler(handlerAttribute)
const attribute = element[handlerAttribute];
return attribute !== undefined && attribute !== null;


return eventHandlerAttributes.some(hasEventHandler);


function highlight(element, configuration)
if (element.style.cssText !== '')
element.style.cssText += '; ';


element.classList.add(configuration.class);
element.style.cssText += `border-color: $configuration.borderColor !important; border-style: solid !important; border-width: medium !important;`;


function getLinks(node)
return Array.from(node.getElementsByTagName('a'));


function isElement(node)
return node.nodeType === Node.ELEMENT_NODE;


exports.ancestors = ancestors;
exports.commonAncestor = commonAncestor;
exports.getLinks = getLinks;
exports.hasInsecureHrefAttribute = hasInsecureHrefAttribute;
exports.hasNonDefaultEventHandler = hasNonDefaultEventHandler;
exports.highlight = highlight;
exports.isElement = isElement;
(this));


highlight.js:



(function () 
'use strict';
let configuration;

function onConfigurationRetrieved(items)
configuration = items;
processAndObserveDocument();


function processAndObserveDocument()
const attributeObserver = new MutationObserver(onAttributeMutation),
elementObserver = new MutationObserver(onElementMutation);

processNode(document);

attributeObserver.observe(document.body, 'attributes': true, 'subtree': true);
elementObserver.observe(document.body, 'childList': true, 'subtree': true);


function onAttributeMutation(mutationRecords)
mutationRecords.forEach(processAttributeMutationRecord);


function processAttributeMutationRecord(mutationRecord)
if (mutationRecord.attributeName === 'href')
highlightInsecureLink(mutationRecord.target);



function onElementMutation(mutationRecords)
const addedElementsList = mutationRecords.map(mutationRecordElements),
addedElements = .concat.apply(, addedElementsList);

processNode(commonAncestor(addedElements));


function mutationRecordElements(mutationRecord)
return Array.from(mutationRecord.addedNodes).filter(isElement);


function processNode(node)
getLinks(node).forEach(highlightInsecureLink);


function highlightInsecureLink(element)
if (
hasInsecureHrefAttribute(element, location.protocol)

browser.storage.local.get(defaultOptions).then(onConfigurationRetrieved);
());


url.js:



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));








share|improve this question












share|improve this question




share|improve this question








edited May 9 at 23:07









Jamal♦

30.1k11114225




30.1k11114225









asked May 9 at 10:27









l0b0

3,580922




3,580922











  • @Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
    – l0b0
    May 10 at 0:49
















  • @Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
    – l0b0
    May 10 at 0:49















@Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
– l0b0
May 10 at 0:49




@Jamal The title and tag were very deliberate, because this is a cross-browser add-on. It works at least in Chromium without modification, for example.
– l0b0
May 10 at 0:49










1 Answer
1






active

oldest

votes

















up vote
1
down vote













Bloat



I started reviewing the code, most of it was good with a quick glance, I was going to comment on the long variable names and suggest you consider using common abbreviations to make the code more readable.



As I looked deeper I started to find more and more bloat. There is a point where code granularity is a burden on the source quality. One line functions called from only one location is not a good way to use functions. It make the code harder to follow, especial that the names are so long they all look the same and need to be read to find, rather than a quick scan.



The example



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));


It was not until I read it that I realized most of it is completely unneeded.



With identical functionality is the following



;(function (exports) 
'use strict';
const secure = ['https', 'mailto', 'news', 'nntp', 'snews', 'tel'];
const protoPrefix = /^[a-z]+:///;

exports.isSecureURL = (url, protocol) =>
(this));


The rest is similar with many redundancies and bad use of functions (too granular)






share|improve this answer





















  • I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
    – l0b0
    May 9 at 19:41











  • @l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
    – Blindman67
    May 9 at 22:14










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193999%2ffirefox-add-on-for-highlighting-insecure-links%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Bloat



I started reviewing the code, most of it was good with a quick glance, I was going to comment on the long variable names and suggest you consider using common abbreviations to make the code more readable.



As I looked deeper I started to find more and more bloat. There is a point where code granularity is a burden on the source quality. One line functions called from only one location is not a good way to use functions. It make the code harder to follow, especial that the names are so long they all look the same and need to be read to find, rather than a quick scan.



The example



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));


It was not until I read it that I realized most of it is completely unneeded.



With identical functionality is the following



;(function (exports) 
'use strict';
const secure = ['https', 'mailto', 'news', 'nntp', 'snews', 'tel'];
const protoPrefix = /^[a-z]+:///;

exports.isSecureURL = (url, protocol) =>
(this));


The rest is similar with many redundancies and bad use of functions (too granular)






share|improve this answer





















  • I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
    – l0b0
    May 9 at 19:41











  • @l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
    – Blindman67
    May 9 at 22:14














up vote
1
down vote













Bloat



I started reviewing the code, most of it was good with a quick glance, I was going to comment on the long variable names and suggest you consider using common abbreviations to make the code more readable.



As I looked deeper I started to find more and more bloat. There is a point where code granularity is a burden on the source quality. One line functions called from only one location is not a good way to use functions. It make the code harder to follow, especial that the names are so long they all look the same and need to be read to find, rather than a quick scan.



The example



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));


It was not until I read it that I realized most of it is completely unneeded.



With identical functionality is the following



;(function (exports) 
'use strict';
const secure = ['https', 'mailto', 'news', 'nntp', 'snews', 'tel'];
const protoPrefix = /^[a-z]+:///;

exports.isSecureURL = (url, protocol) =>
(this));


The rest is similar with many redundancies and bad use of functions (too granular)






share|improve this answer





















  • I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
    – l0b0
    May 9 at 19:41











  • @l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
    – Blindman67
    May 9 at 22:14












up vote
1
down vote










up vote
1
down vote









Bloat



I started reviewing the code, most of it was good with a quick glance, I was going to comment on the long variable names and suggest you consider using common abbreviations to make the code more readable.



As I looked deeper I started to find more and more bloat. There is a point where code granularity is a burden on the source quality. One line functions called from only one location is not a good way to use functions. It make the code harder to follow, especial that the names are so long they all look the same and need to be read to find, rather than a quick scan.



The example



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));


It was not until I read it that I realized most of it is completely unneeded.



With identical functionality is the following



;(function (exports) 
'use strict';
const secure = ['https', 'mailto', 'news', 'nntp', 'snews', 'tel'];
const protoPrefix = /^[a-z]+:///;

exports.isSecureURL = (url, protocol) =>
(this));


The rest is similar with many redundancies and bad use of functions (too granular)






share|improve this answer













Bloat



I started reviewing the code, most of it was good with a quick glance, I was going to comment on the long variable names and suggest you consider using common abbreviations to make the code more readable.



As I looked deeper I started to find more and more bloat. There is a point where code granularity is a burden on the source quality. One line functions called from only one location is not a good way to use functions. It make the code harder to follow, especial that the names are so long they all look the same and need to be read to find, rather than a quick scan.



The example



(function (exports) 
'use strict';

const protocolPrefixRegex = new RegExp('^[a-z]+://'),

// Known secure protocols handled by the browser
internalSecureProtocols = ['https'],

// Presumed secure since they are handled externally (see network.protocol-handler.external.[protocol])
externallyHandledProtocols = ['mailto', 'news', 'nntp', 'snews'],

// Presumed secure, commonly handled by add-ons or externally
expectedExternallyHandledProtocols = ['tel'],

secureProtocols = .concat(
internalSecureProtocols,
externallyHandledProtocols,
expectedExternallyHandledProtocols
);

function isSecureURL(url, protocol)

function hasExplicitProtocol(url)
return protocolPrefixRegex.test(url.toLowerCase());


exports.hasExplicitProtocol = hasExplicitProtocol;
exports.isSecureURL = isSecureURL;
(this));


It was not until I read it that I realized most of it is completely unneeded.



With identical functionality is the following



;(function (exports) 
'use strict';
const secure = ['https', 'mailto', 'news', 'nntp', 'snews', 'tel'];
const protoPrefix = /^[a-z]+:///;

exports.isSecureURL = (url, protocol) =>
(this));


The rest is similar with many redundancies and bad use of functions (too granular)







share|improve this answer













share|improve this answer



share|improve this answer











answered May 9 at 14:29









Blindman67

5,3111320




5,3111320











  • I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
    – l0b0
    May 9 at 19:41











  • @l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
    – Blindman67
    May 9 at 22:14
















  • I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
    – l0b0
    May 9 at 19:41











  • @l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
    – Blindman67
    May 9 at 22:14















I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
– l0b0
May 9 at 19:41





I'd still keep names like secureProtocols for clarity and maintainability, and I disagree that pulling out things like hasExplicitProtocol is a bad idea (for the same reason), but joining those variables might be an option. I still want to make sure a maintainer understands why nntp is considered "safe", when it isn't (or rather wasn't) normally served via an end-to-end encrypted channel. I know the JavaScript norm is functions with many lines, but I strongly consider that an antipattern.
– l0b0
May 9 at 19:41













@l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
– Blindman67
May 9 at 22:14




@l0b0 The place for technical information regarding a product is not in the code. It is in the product documentation that provides a indexed, cross referenced, single, authoritative spec, (including details regarding abstractions and reasoning). The anti-pattern is splitting spec, the danger is conflict between two sources, which is highly likely if more than one coder is editing source. Or worse if the source is all there is you can not guarantee the information you have in-bedded add-hock within the code will be maintained. Source code is not an information store..
– Blindman67
May 9 at 22:14












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193999%2ffirefox-add-on-for-highlighting-insecure-links%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Will my employers contract hold up in court?