diff --git a/source/common/background/cookiestore.js b/source/common/background/cookiestore.js
index 58a0d990ddd0908faeca319771935502a0d5576c..a9bdd21e0f41874c6f635843b38a2ba38fcb4c89 100644
--- a/source/common/background/cookiestore.js
+++ b/source/common/background/cookiestore.js
@@ -4,7 +4,7 @@ const platform = require("../libraries/platform").platform
 
 const cookie = require("cookie")
 
-const parseResponseHeaderStrictTransportSecurity = require("../libraries/hsts/hsts").parseResponseHeaderStrictTransportSecurity
+const hsts = require("../libraries/hsts/hsts")
 
 const thirdparty = require("../libraries/thirdparty/thirdparty").thirdparty
 
@@ -15,31 +15,28 @@ const urlPopup = window.location.origin + "/pages/popup/popup.html"
 // TODO: make an actual datasructure.
 var cookieDatabase = {"example":"example"}
 
-/* Structure of tabObservations is as follows:
-	tabObservations is a dictionaty with keys tabId and values objects
-		originUrl (string) - sanity check that page is correct
-		domains - a dictionary with keys domains and values objects
-			thirdparty (boolean) - if this should be displayed on "Primary resources" or "Third-party resources"
-				this is assigned when record is created
-			status (string)
-				this is assigned/updated when record is requested by UI
-				status has one of the following values:
-					"secure"   -- domain is already protected, e.g. by HSTS or CSP
-					"enabled"  -- we protect vulnerable domain
-					"disabled" -- we let vulnerable domain be vulnerable
-					"insecure" -- domain does not support HTTPS (hopeless case)
-				// reason - string explanation, to be put on tooltip CSP HSTS
-			cookies - dictionary of cookies with key cookie name and value object
-				(it is summary to be displayed in the popup)
-			events - all things that ever happened
-*/
+/**
+ * Structure of tabObservations is as follows:
+ * tabObservations is a dictionaty with keys tabId and values objects
+ *     originUrl {string} - sanity check that page is correct
+ *     domains - a dictionary with keys domains and values objects
+ *         thirdparty {boolean} - if this should be displayed on "Primary resources" or "Third-party resources"
+ *             this is assigned when record is created
+ *         status (string)
+ *             this is assigned/updated when record is requested by UI
+ *             status has one of the following values:
+ *             	   "secure"   -- domain is already protected, e.g. by HSTS or CSP
+ *             	   "enabled"  -- we protect vulnerable domain
+ *                 "disabled" -- we let vulnerable domain be vulnerable
+ *                 "insecure" -- domain does not support HTTPS (hopeless case)
+ *             // reason - string explanation, to be put on tooltip CSP HSTS
+ *             (it is summary to be displayed in the popup)
+ *     events - all things that ever happened
+ *         usefull for debugging, but very memory-heavy
+ */
 var tabObservations = {}
 
-// Disctionary with keys domains and values the current HSTS record
-// TODO: remember time of record creation
-var hstsObservations = {}
-
-/*
+/**
  * Prepare datastructures of the newly installed extension
  */
 platform.runtime.onInstalled.addListener (function() {
@@ -75,7 +72,6 @@ platform.runtime.onInstalled.addListener (function() {
 							console.log("Popup open: Security, preparing report")
 							let report = tabObservations[message.tabId]
 							console.log("REPORT BEFORE", report)
-							console.log(hstsObservations)
 							for (const domain in report.domains){
 								// Update domain status
 								switch(report.domains[domain].status){
@@ -85,29 +81,12 @@ platform.runtime.onInstalled.addListener (function() {
 									case null:
 										// Need to update security assessment
 										// TODO: which check CSP and differentiate between "disabled" and "insecure"
-										// REFACTOR: Move to "library"?
 										var status = null
 
-										// Check HSTS
-										const subDomains = domain.split(".")
-										const numSubDomains = subDomains.length
-										var currSubDomain = ""
-										for (var i=1; i<=numSubDomains; i++){
-											// Update subdomain
-											currSubDomain = subDomains[numSubDomains-i] + currSubDomain
-											// Check against the HSTS records
-											if (hstsObservations[currSubDomain] !== undefined && hstsObservations[currSubDomain].content.maxAge > 0){
-												// TODO: take into account time of record creation
-												// TODO: take into account consistency
-												// TODO: take into account includeSubdomains directve if currSubDomain !== domain
-												// TODO: take into account preload list
-												status = "secure"
-											}
-											console.log(domain, subDomains, currSubDomain, hstsObservations[currSubDomain])
-											// Prepare for the next iteration
-											currSubDomain = "." + currSubDomain
-										}
-										// Check CSP
+										// Check HSTS status
+										status = hsts.queryStatus(domain)
+
+										// Check CSP status
 										// TODO!
 										report.domains[domain].status = status
 										break
@@ -138,14 +117,16 @@ platform.runtime.onInstalled.addListener (function() {
 	})
 })
 
-/*
+/**
  * Observe the network activity around coookies
  */
 function onPermissionWebRequestGranted(){
 	const urls = ["http://*/*", "https://*/*"]
 
-	/*
+	/**
 	 * Remembers observations about tabs (pages)
+	 * @param request {Object} - request details obtained from API
+	 * @param observationa {Object} - array of observation objects
 	 * TODO: make this into a Promise
 	 * TODO: avoid passing `request` (pick out only the necessary parts in caller)
 	 */
@@ -170,21 +151,7 @@ function onPermissionWebRequestGranted(){
 		for (var observation of observations){
 			switch (observation.type){
 				case "HSTS":
-					// TODO: Is consistency critera good?
-					if (hstsObservations[resourceDomain] === undefined){
-						// this is first HSTS header encountered
-						hstsObservations[resourceDomain] = {
-							consistent: true,
-							content: observation.content,
-							createdTime: null // TODO: remember time
-						}
-					} else {
-						// this domain already has HSTS policy
-						if (hstsObservations[resourceDomain] && hstsObservations[resourceDomain].maxAge !== observation.content)
-							hstsObservations[resourceDomain].consistent = false
-						hstsObservations[resourceDomain].content = observation.content
-						hstsObservations[resourceDomain].createdTime = null // TODO: remember time
-					}
+					hsts.record(resourceDomain, observation.content)
 					break
 				case "CSP":
 					break
@@ -194,11 +161,12 @@ function onPermissionWebRequestGranted(){
 		}
 	}
 
-	/*
+	/**
 	 * Observe the Cookie header containing cookies being sent to the server
+	 * @param   details {Object} - the details of request obtained from API
+	 * @returns {Object} the redacted headers
 	 */
 	function watchCookiesSent(details){
-//		console.log("Request")
 		var observations = []
 
 		const protocol = new URL(details.url).protocol
@@ -219,27 +187,29 @@ function onPermissionWebRequestGranted(){
 		}
 
 		rememberTabObservation(details, observations)
-//		console.log("Request processed")
 		return {requestHeaders: details.requestHeaders}
 	}
 
-	/*
+	/**
 	 * Observe the Set-Cookie header in response from the server
+	 * @param   details {Object} - the details of request obtained from API
+	 * @returns {Object} the redacted headers
 	 */
 	// TODO: Difference between "set-cookie" and "Set-Cookie"
 	// TODO: support protocols other than HTTP(S)
 	function watchResponse(details){
-
-//		console.log("Response")
 		var observations = []
 
 		// Get additional parameters
 		const url = new URL(details.url).protocol
+		// Look through all headers one at a time
 		for (var i = 0; i < details.responseHeaders.length; ++i) {
 			const headerName = details.responseHeaders[i].name.toLowerCase()
 			const headerValue = details.responseHeaders[i].value
 			switch (headerName){
 				case "set-cookie":
+					// TODO: Record cookie details
+					// TODO: Block cookie, if user opted for the corresponding setting
 					const name = headerValue.substring(0, headerValue.indexOf("="))
 					observations.push({type: "Cookie", content: "Cookie set: "+name})
 					cookieDatabase[name] = {secureOrigin: url.protocol === "https:", httpOnly: true}
@@ -248,8 +218,7 @@ function onPermissionWebRequestGranted(){
 				case "strict-transport-security":
 					// Remember HSTS header for later reference in the popup
 					// Parsing library options: did not find any, had to write my own
-					var hstsAttributes = parseResponseHeaderStrictTransportSecurity(headerValue)
-					observations.push({type: "HSTS", content: hstsAttributes})
+					observations.push({type: "HSTS", content: headerValue})
 					break
 
 				case "content-security-policy":
@@ -279,15 +248,15 @@ function onPermissionWebRequestGranted(){
 					break
 				default:
 					// Header not interesting
+					// TODO: See what falls here?
 			}
 		}
 		rememberTabObservation(details, observations)
-//		console.log ("Observations", details, observations)
-//		console.log("Response processed")
 		return {responseHeaders: details.responseHeaders}
 	}
 
 	function logError(details){
+		// TODO: Is this informative in any way?
 		console.log("Network error, e.g. other extension blocked")
 	}
 
diff --git a/source/common/libraries/hsts/hsts-test.js b/source/common/libraries/hsts/hsts-test.js
index 84e80ced18304e76f5db9f7694feb1579995862c..5e06fdf7dda3aec54a5d16d5b2d49c9bbef500bf 100644
--- a/source/common/libraries/hsts/hsts-test.js
+++ b/source/common/libraries/hsts/hsts-test.js
@@ -1,4 +1,4 @@
-const parseResponseHeaderStrictTransportSecurity = require("./hsts").parseResponseHeaderStrictTransportSecurity
+const hsts = require("./hsts")
 
 // TODO: Actual test infrastructure
 
@@ -30,6 +30,6 @@ const testParseResponseHeaderStrictTransportSecurity = [
 ]
 
 for (const testcase of testParseResponseHeaderStrictTransportSecurity){
-	console.log (parseResponseHeaderStrictTransportSecurity(testcase.input))
+	console.log (hsts.parseHSTSHeader(testcase.input))
 	console.log (testcase.answer)
 }
\ No newline at end of file
diff --git a/source/common/libraries/hsts/hsts.js b/source/common/libraries/hsts/hsts.js
index eaa6684f263b447af890dc7ca66e95fd7de8d044..6d58461542f8c3bc105e53f6ebe4a03d3524aa8b 100644
--- a/source/common/libraries/hsts/hsts.js
+++ b/source/common/libraries/hsts/hsts.js
@@ -1,15 +1,121 @@
-/*
- * Parse HTTP Strict Transport Security response header
- * @param   value - string from the header
- * @returns object {"max-age": non-negative int, "includeSubDomains": boolean, "preload": boolean}
+/**
+ * Parse HTTP Strict Transport Security response header, remembers them and allows queries
+ * For now, we use only record() and queryStatus().
  */
 
-module.exports = {parseResponseHeaderStrictTransportSecurity: parseResponseHeaderStrictTransportSecurity}
+// TODO: low priority, enhancement
+// Align more with formal spec, e.g. look at how Chromium dos it in
+// function ParseHSTSHeader in net/http/http_security_headers.cc
+// https://github.com/chromium/chromium/blob/6f2047142487aa72d83197950205eff3f022f725/net/http/http_security_headers.cc
 
-function parseResponseHeaderStrictTransportSecurity (headerValue){
-	var parsedAttributes = {"maxAge": 0, "includeSubDomains": false, "preload": false}
+// TODO: low priority, but should do eventually
+// take into account preload lists
+// TODO: Is consistency critera good?
+
+// TODO: do we need a function for a direct query for HSTS record?
+
+module.exports = {queryStatus: queryStatus, record: record, query: null, parseHSTSHeader: parseStrictTransportSecurity}
+
+/**
+ * Dictionary with keys domains and values HSTS directive objects
+ * @private
+ * HSTS diretive object contains:
+ *     consistent {boolean}
+ *     content {Object}
+ *         maxAge {number} - non-negative integer representing record lifetime in seconds
+ *         includeSubDomains {boolean} - whether or not this record applies to subdomains
+ *         preload {boolean} - whether or not domain asks to be preloaded (not used so far)
+ */
+// TODO: remember time of record creation
+var hstsStore = {}
+
+/**
+ * Query the HSTS store
+ * @param   {string} domain - domain name to look up
+ * @returns {Object} HSTS record
+ */
+function queryStatus(domain){
+	// Domain matching is case-insensitive
+	domain = domain.trim().toLowerCase()
+
+	var status = null
+
+	// Check against the HSTS records for superdomain match
+	// Iterate over all domain suffixes in case some domain has HSTS directive with includeSubdomains
+	const subDomains = domain.split(".")
+	const numSubDomains = subDomains.length
+	var currSubDomain = ""
+	for (var i=1; i<numSubDomains; i++){
+		// Update subdomain
+		currSubDomain = subDomains[numSubDomains-i] + currSubDomain
+		const hstsRecord = hstsStore[currSubDomain]
+		if (hstsRecord !== undefined /*&& hstsRecord.consistent*/ && hstsRecord.content.includeSubdomains && hstsRecord.content.maxAge > 0){
+			// TODO: take into account time of record creation
+			// TODO: take into account consistency
+			// TODO: take into account includeSubdomains directve if currSubDomain !== domain
+			// TODO: take into account preload list
+			status = "secure"
+			// Break only if we consider HSTS header sufficiently secure; otherwise carry on
+			break
+		}
+		// Prepare for the next iteration
+		currSubDomain = "." + currSubDomain
+	}
+
+	// Check against the HSTS records for congruent domain match
+	const hstsRecord = hstsStore[domain]
+	if (status === null && hstsRecord !== undefined /*&& hstsRecord.consistent*/ && hstsRecord.content.maxAge > 0){
+		status = "secure"
+	}
+	return status
+}
+
+/**
+ * Record the HSTS header into the store
+ * @param   {string} domain - domain name to look up
+ * @param   {string} headerValue - HSTS header exactly as it appers in the response
+ * @returns {Object} HSTS record
+ */
+function record(domain, headerValue){
+	// Domain matching is case-insensitive
+	domain = domain.trim().toLowerCase()
+
+	// Parse HSTS header
+	const parsed = parseStrictTransportSecurity(headerValue)
+
+	if (hstsStore[domain]){
+		// This domain already has HSTS policy
+
+		// Decide if HSTS policy is consistenst
+		if (hstsStore[domain].maxAge !== parsed.maxAge)
+			hstsStore[domain].consistent = false
+		// Update the HSTS policy
+		hstsStore[domain].content = parsed
+		hstsStore[domain].createdTime = null // TODO: remember time
+	} else {
+		// This domain does not have HSTS policy yet
+		// Just save the HSTS policy
+		hstsStore[domain] = {
+			consistent: true,
+			content: parsed,
+			createdTime: null // TODO: remember time
+		}
+	}
+}
+
+/**
+ * This function parses a string HSTS header and converts it into object
+ * @param   {string} headerValue - the header as it appears in the request
+ * @returns {Object} HSTS record
+ */
+function parseStrictTransportSecurity (headerValue){
+	var parsedAttributes = {maxAge: 0, includeSubDomains: false, preload: false}
 	const attributes = headerValue.split(";")
+	// Go through directives one at a time,
+	// "The order of appearance of directives is not significant." (p. 15)
 	for (var attribute of attributes){
+		// Collate names to lower case because
+		// "Directive names are case-insensitive." (p. 15)
 		attribute = attribute.trim().toLowerCase()
 		if (attribute === "")
 			continue
diff --git a/source/common/libraries/thirdparty/thirdparty.js b/source/common/libraries/thirdparty/thirdparty.js
index 9d3564f460808ae47bae104c8eb2c87ffd8a0c0c..b02f9c7af056d2660790e431beae9673bd0d27a4 100644
--- a/source/common/libraries/thirdparty/thirdparty.js
+++ b/source/common/libraries/thirdparty/thirdparty.js
@@ -1,4 +1,4 @@
-/*
+/**
  * Determine if resource is a third-party based only on domain names
  * @param   origin - string, domain of the orgin page or frame
  * @param   resource - string, domain of the resource