From 13019ab673a387f7423fb50865e8cbd3b669a752 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Tue, 9 May 2023 21:01:07 +0800 Subject: [PATCH 01/31] views/HomeView: Remove negative report btn --- src/views/HomeView.vue | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 3f56804..7a992cb 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -66,14 +66,9 @@ - There is deceptive design on this page + Report deceptive design on this page - - - - No deceptive design on this page - From dc6d9b0ac33efbc7dcc37ca89b632df32bfcf27d Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Wed, 10 May 2023 00:02:26 +0800 Subject: [PATCH 02/31] background: Split into multiple files; use IndexedDB --- background/api/classifier.js | 13 ++ background/api/request.js | 35 +++++ background/api/stats.js | 16 +++ background/background.js | 183 ++------------------------- background/browser/badge.js | 33 +++++ background/browser/getAction.js | 8 ++ background/browser/storage.js | 77 +++++++++++ background/listeners/index.js | 9 ++ background/listeners/message.js | 65 ++++++++++ background/listeners/tabChange.js | 24 ++++ background/listeners/tabUrlChange.js | 9 ++ package-lock.json | 4 +- src/views/HomeView.vue | 15 ++- 13 files changed, 308 insertions(+), 183 deletions(-) create mode 100644 background/api/classifier.js create mode 100644 background/api/request.js create mode 100644 background/api/stats.js create mode 100644 background/browser/badge.js create mode 100644 background/browser/getAction.js create mode 100644 background/browser/storage.js create mode 100644 background/listeners/index.js create mode 100644 background/listeners/message.js create mode 100644 background/listeners/tabChange.js create mode 100644 background/listeners/tabUrlChange.js diff --git a/background/api/classifier.js b/background/api/classifier.js new file mode 100644 index 0000000..6d75ad7 --- /dev/null +++ b/background/api/classifier.js @@ -0,0 +1,13 @@ +import { ApiPost } from "./request"; + +export const classifyText = (text, callback) => { + ApiPost('/classify/text', { text }, callback, () => { + console.error('api/calliope: Could not classify cookie banner text'); + }); +}; + +export const classifyImage = (imageData, callback) => { + ApiPost('/classify/image', { image_data: imageData }, callback, () => { + console.error('api/janus: Could not classify cookie banner screenshot'); + }); +}; diff --git a/background/api/request.js b/background/api/request.js new file mode 100644 index 0000000..2466381 --- /dev/null +++ b/background/api/request.js @@ -0,0 +1,35 @@ +const baseUrl = import.meta.env.VITE_API_URL + '/api/v1'; + +export const ApiGet = (endpoint, callback, errorCallback) => { + if (typeof callback !== 'function') { + console.error('api/request(ApiGet): Expected function callback, got ' + typeof callback); + } + + fetch(baseUrl + endpoint, { + method: 'GET' + }).then((response) => response.json()) + .then((data) => callback(data)) + .catch((error) => { + console.error('api/request(ApiGet) Error fetching ' + endpoint + ':', error); + if (typeof errorCallback === 'function') errorCallback(error); + }); +} + +export const ApiPost = (endpoint, body, callback, errorCallback) => { + if (typeof callback !== 'function') { + console.error('api/request(ApiPost): Expected function callback, got ' + typeof callback); + } + + fetch(baseUrl + endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }).then((response) => response.json()) + .then((data) => callback(data)) + .catch((error) => { + console.error('api/request(ApiPost) Error fetching ' + endpoint + ':', error); + if (typeof errorCallback === 'function') errorCallback(error); + }); +} diff --git a/background/api/stats.js b/background/api/stats.js new file mode 100644 index 0000000..c17b461 --- /dev/null +++ b/background/api/stats.js @@ -0,0 +1,16 @@ +import { ApiPost } from './request'; +import { updateBadgeText } from '../browser/badge'; +import { setTransaction } from '../browser/storage'; + +export const getStats = (tabUrl, successCallback, errorCallback) => { + ApiPost('/reports/by-url', {'page_url': tabUrl}, (data) => { + console.log('api/stats: Got stats for URL ' + tabUrl + ':', data); + setTransaction('stats', { + url: tabUrl, + stats: data + }).then(() => { + updateBadgeText(data); + if (successCallback !== undefined) successCallback(data); + }).catch((e) => errorCallback(e)) + }, errorCallback); +} diff --git a/background/background.js b/background/background.js index 91e8be2..83ce549 100644 --- a/background/background.js +++ b/background/background.js @@ -1,175 +1,10 @@ import * as browser from 'webextension-polyfill'; - -class AriadneBackground { - constructor() { - this._tabStates = []; - this._reportStats = {}; - this._API_URL = import.meta.env.VITE_API_URL + '/api/v1'; - - // Alias if browser.action is defined, i.e. in Manifest V3 - this.BrowserAction = browser.browserAction; - if (browser.action !== undefined) { - this.BrowserAction = browser.action; - } - } - - addListeners() { - // Update badge on tab change - browser.tabs.onActivated.addListener((activeInfo) => { - // Get URL of active tab - browser.tabs.get(activeInfo.tabId) - .then((tab) => { - console.log('[bg] Tab changed to', tab.url); - this.toggleBadge(this._tabStates[activeInfo.tabId]); - this.updateBadgeText(this._reportStats[tab.url]); - this.getStats(tab.url); - }); - }); - - // Tab URL change listener - browser.tabs.onUpdated.addListener((tabId, changeInfo, _) => { - if (changeInfo.url) { - // Request fresh stats - console.log('[bg] Tab ' + tabId + ' URL changed to', changeInfo.url); - this.getStats(changeInfo.url); - } - }); - - // Message listeners - browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - console.log("[bg] Received message with action", request.action); - if (request.action === "updateBadge") { - // Listen to updateBadge requests - this.toggleBadge(request.args.enabled); - - // Update the tab state - this._tabStates[sender.tab.id] = request.args.enabled; - } else if (request.action === "detection") { - // Listen to detection requests from content scripts - const cookieBannerText = request.args.body; - console.log('[bg] Detection request received from tab', sender.tab.id, 'with body:', cookieBannerText); - - // POST to API - fetch(this._API_URL + '/classify/text', { - method: 'POST', - body: JSON.stringify({ - text: cookieBannerText - }), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()) - .then((data) => { - console.log('[bg] Detection result from API:', data); - sendResponse(data); - }); - } else if (request.action === "visualDetection") { - // Listen to visual detection requests from content scripts - const imageData = request.args.screenshot; - console.log('[bg] Visual detection request received from tab', sender.tab.id); - - // POST to API - fetch(this._API_URL + '/classify/image', { - method: 'POST', - body: JSON.stringify({ - image_data: imageData - }), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()) - .then((data) => { - console.log('[bg] Detection result from API:', data); - sendResponse(data); - }); - } else if (request.action === "requestStats") { - console.log("[bg] Received stats request from popup", request, sender); - - // If we have cached stats, send them before requesting new ones - const tabUrl = request.args.url; - let deferSending = false; - if (this._reportStats[tabUrl]) { - console.log("[bg] Sending cached stats to tab", tabUrl, this._reportStats[tabUrl]); - sendResponse(this._reportStats[tabUrl]); - deferSending = true; - } - - this.getStats(tabUrl, (stats) => { - if (!deferSending) { - console.log('[bg] Sending stats to tab', tabUrl, this._reportStats[tabUrl]) - sendResponse(stats); - } else { - console.log('[bg] Revalidated cache for tab', tabUrl, this._reportStats[tabUrl]) - } - }, (error) => { - sendResponse({ - success: false, - error - }); - }); - } - - return true; - }); - } - - toggleBadge(state) { - if (state) { - this.BrowserAction.setBadgeBackgroundColor({ - color: "#B677FA", - }); - } else { - this.BrowserAction.setBadgeBackgroundColor({ - color: "#2A272A", - }); - } - } - - updateBadgeText(stats) { - console.log('[bg] Updating badge text with stats:', stats); - if (stats !== undefined && stats.hasOwnProperty("success") && - stats.hasOwnProperty("specific_reports") && stats["success"]) { - const count = stats.specific_reports.count; - console.log('[bg] Badge count:', count) - if (count > 0) { - this.BrowserAction.setBadgeText({ - text: count.toString(), - }); - return; - } - } - this.BrowserAction.setBadgeText({ - text: "0", - }); - } - - getStats(tabUrl, successCallback, errorCallback) { - fetch(this._API_URL + '/reports/by-url', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - 'page_url': tabUrl - }) - }) - .then((response) => response.json()) - .then((data) => { - console.log('[bg] Report stats from API:', data); - this._reportStats[tabUrl] = data; - - // Update badge text - this.updateBadgeText(data); - - if (successCallback !== undefined) successCallback(data); - }) - .catch((error) => { - console.error('[bg] Error fetching report stats:', error); - if (errorCallback !== undefined) errorCallback(error); - } - ); - } -} - -const ariadneBackground = new AriadneBackground(); -ariadneBackground.addListeners(); +import { + messageListener, + tabChangeListener, + tabUrlChangeListener +} from './listeners'; + +browser.runtime.onMessage.addListener(messageListener); +browser.tabs.onActivated.addListener(tabChangeListener); +browser.tabs.onUpdated.addListener(tabUrlChangeListener); diff --git a/background/browser/badge.js b/background/browser/badge.js new file mode 100644 index 0000000..b921dc7 --- /dev/null +++ b/background/browser/badge.js @@ -0,0 +1,33 @@ +import { getAction } from './getAction'; + +const action = getAction(); + +export const toggleBadge = (state) => { + if (state) { + action.setBadgeBackgroundColor({ + color: "#B677FA", + }); + } else { + action.setBadgeBackgroundColor({ + color: "#2A272A", + }); + } +} + +export const updateBadgeText = (stats) => { + console.log('browser/badge: Updating badge text with stats:', stats); + if (stats !== undefined && stats.hasOwnProperty("success") && + stats.hasOwnProperty("specific_reports") && stats["success"]) { + const count = stats.specific_reports.count; + console.log('browser/badge: Badge count:', count) + if (count > 0) { + action.setBadgeText({ + text: count.toString(), + }); + return; + } + } + action.setBadgeText({ + text: "0", + }); +} diff --git a/background/browser/getAction.js b/background/browser/getAction.js new file mode 100644 index 0000000..59b0244 --- /dev/null +++ b/background/browser/getAction.js @@ -0,0 +1,8 @@ +import * as browser from 'webextension-polyfill'; + +export const getAction = () => { + if (chrome.runtime.getManifest().manifest_version === 3) { + return browser.action; + } + return browser.browserAction; +} diff --git a/background/browser/storage.js b/background/browser/storage.js new file mode 100644 index 0000000..163c3da --- /dev/null +++ b/background/browser/storage.js @@ -0,0 +1,77 @@ +const openDatabase = () => new Promise((res, rej) => { + const request = indexedDB.open('ariadne', 1); + request.onerror = (event) => { + console.error(`browser/storage: Error ${event.target.errorCode}`) + rej(); + }; + + // Declare schema + request.onupgradeneeded = (event) => { + db = event.target.result; + + // Create storage for stats per URL + const urlStatsStore = db.createObjectStore('stats', { keyPath: 'url' }) + urlStatsStore.createIndex('url', 'url', { unique: true }) + urlStatsStore.transaction.oncomplete = (_) => { + console.log('browser/storage(stats): Transaction complete'); + } + + // Create storage for badge states per tab + const badgeStateStore = db.createObjectStore('badgeStates', { keyPath: 'tabId' }) + badgeStateStore.createIndex('tabId', 'tabId', { unique: true }) + badgeStateStore.transaction.oncomplete = (_) => { + } + } + + request.onsuccess = (event) => { + console.log('browser/storage: Database ready'); + res(event.target.result); + } +}); + + +export const setTransaction = async (store, data) => { + console.log('browser/storage(set): Opening DB'); + + const db = await openDatabase(); + const t = db.transaction(store, 'readwrite'); + const s = t.objectStore(store); + return await new Promise((res, rej) => { + t.oncomplete = () => console.log('browser/storage(set): Complete'); + t.onerror = (e) => rej(e); + + const r = s.put(data); + r.onsuccess = () => res(); + }); +} + +export const getTransaction = async (store, key) => { + console.log('browser/storage(get): Opening DB'); + + const db = await openDatabase(); + const t = db.transaction(store, 'readonly'); + const s = t.objectStore(store); + return await new Promise((res, rej) => { + t.oncomplete = () => console.log('browser/storage(get): Complete'); + t.onerror = (ev) => rej(ev); + + const r = s.get(key); + r.onsuccess = (e) => res(e.target.result); + }); +} + +export const deleteTransaction = async (store, key) => { + console.log('browser/storage(delete): Opening DB'); + + const db = await openDatabase(); + const t = db.transaction(store, 'readwrite'); + const s = t.objectStore(store); + return await new Promise((res, rej) => { + t.oncomplete = () => { + console.log('browser/storage(delete): Complete'); + res(); + }; + t.onerror = (e) => rej(e); + s.delete(key); + }); +} diff --git a/background/listeners/index.js b/background/listeners/index.js new file mode 100644 index 0000000..7cdb280 --- /dev/null +++ b/background/listeners/index.js @@ -0,0 +1,9 @@ +import messageListener from './message'; +import tabChangeListener from './tabChange'; +import tabUrlChangeListener from './tabUrlChange'; + +export { + messageListener, + tabChangeListener, + tabUrlChangeListener +} diff --git a/background/listeners/message.js b/background/listeners/message.js new file mode 100644 index 0000000..0c17d0d --- /dev/null +++ b/background/listeners/message.js @@ -0,0 +1,65 @@ +import { toggleBadge } from "../browser/badge"; +import { getTransaction, setTransaction } from "../browser/storage"; +import { getStats } from "../api/stats"; +import { classifyImage, classifyText } from "../api/classifier"; + +export default (request, sender, sendResponse) => { + if (request.action === "updateBadge") { + // Save and apply the badge state + setTransaction('badgeStates', { + tabId: sender.tab.id, + enabled: request.args.enabled + }).then(() => toggleBadge(request.args.enabled)); + } else if (request.action === "detection") { + // Listen to detection requests from content scripts + const cookieBannerText = request.args.body; + console.log('listeners/message: Calliope request received from tab', sender.tab.id, 'with body:', cookieBannerText); + + // POST to API + classifyText(cookieBannerText, (data) => { + console.log('listeners/message: Calliope result from API:', data); + sendResponse(data); + }); + } else if (request.action === "visualDetection") { + // Listen to visual detection requests from content scripts + const imageData = request.args.screenshot; + console.log('listeners/message: Janus request received from tab', sender.tab.id); + + // POST to API + classifyImage(imageData, (data) => { + console.log('listeners/message: Janus result from API:', data); + sendResponse(data); + }); + } else if (request.action === "requestStats") { + console.log("listeners/message: Received stats request from popup", request, sender); + + // If we have cached stats, send them before requesting new ones + const tabUrl = request.args.url; + let deferSending = false; + getTransaction('stats', tabUrl) + .then((stats) => { + console.log("listeners/message: Sending cached stats to tab", tabUrl, stats); + sendResponse(stats); + deferSending = true; + }) + .catch((e) => { + console.error(e); + }) + .finally(() => getStats(tabUrl, (newStats) => { + if (!deferSending) { + console.log('listeners/message: Sending stats to tab', tabUrl, this._reportStats[tabUrl]) + sendResponse(newStats); + } else { + console.log('listeners/message: Revalidated cache for tab', tabUrl, this._reportStats[tabUrl]) + } + }, (error) => { + sendResponse({ + success: false, + error + }); + }) + ) + } + + return true; +} diff --git a/background/listeners/tabChange.js b/background/listeners/tabChange.js new file mode 100644 index 0000000..d5500af --- /dev/null +++ b/background/listeners/tabChange.js @@ -0,0 +1,24 @@ +import * as browser from 'webextension-polyfill'; +import { toggleBadge, updateBadgeText } from "../browser/badge"; +import { getStats } from "../api/stats"; +import { getTransaction } from '../browser/storage'; + +export default (activeInfo) => { + // Get URL of active tab + browser.tabs.get(activeInfo.tabId) + .then((tab) => { + console.log('listeners/tabChange: Tab changed to', tab.url); + + // Fetch latest stats + return new Promise((res, rej) => { + getStats(tab.url, () => res(tab.url), rej); + }) + }) + .then(async (url) => { + console.log('listeners/tabChange: Stats refreshed'); + const { enabled } = await getTransaction('badgeStates', activeInfo.tabId); + const { stats } = await getTransaction('stats', url); + toggleBadge(enabled); + updateBadgeText(stats); + }); +} diff --git a/background/listeners/tabUrlChange.js b/background/listeners/tabUrlChange.js new file mode 100644 index 0000000..f4bce50 --- /dev/null +++ b/background/listeners/tabUrlChange.js @@ -0,0 +1,9 @@ +import { getStats } from "../api/stats"; + +export default (tabId, changeInfo, _) => { + if (changeInfo.url) { + // Request fresh stats + console.log('listeners/tabUrlChange: Tab ' + tabId + ' changed to', changeInfo.url); + getStats(changeInfo.url); + } +} diff --git a/package-lock.json b/package-lock.json index 569bc47..460f601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ariadne", - "version": "0.0.1", + "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ariadne", - "version": "0.0.1", + "version": "0.1.0", "dependencies": { "@heroicons/vue": "^2.0.16", "html2canvas": "^1.4.1", diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 7a992cb..5ff19e1 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -150,13 +150,14 @@ export default defineComponent({ action: 'requestStats', args: { url } }) - .then((response) => { - this.generalReports = response.general_reports.count - this.specificReports = response.specific_reports.count - this.types.unclearLanguage.count = response.specific_reports.by_type.unclear_language - this.types.prefilledOptions.count = response.specific_reports.by_type.prefilled_options - this.types.weightedOptions.count = response.specific_reports.by_type.weighted_options - this.types.other.count = response.specific_reports.by_type.other + .then((response) => response.stats) + .then((stats) => { + this.generalReports = stats.general_reports.count + this.specificReports = stats.specific_reports.count + this.types.unclearLanguage.count = stats.specific_reports.by_type.unclear_language + this.types.prefilledOptions.count = stats.specific_reports.by_type.prefilled_options + this.types.weightedOptions.count = stats.specific_reports.by_type.weighted_options + this.types.other.count = stats.specific_reports.by_type.other this.isLoading = false }) }) From be1eb29a366c3d8281e5215997aaf3fb0791ab06 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Wed, 10 May 2023 00:07:34 +0800 Subject: [PATCH 03/31] views/ReportPositive: Disable prefilled options type --- src/components/Checkbox.vue | 11 +++++++++-- src/views/ReportPositiveView.vue | 14 ++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/components/Checkbox.vue b/src/components/Checkbox.vue index 0d4b61a..1c198a6 100644 --- a/src/components/Checkbox.vue +++ b/src/components/Checkbox.vue @@ -7,10 +7,12 @@ import { MinusIcon, PlusIcon } from '@heroicons/vue/24/outline' @click="handleChange" class="group rounded-lg box-border border-2 px-4 py-3 flex flex-row justify-between items-start - transition-colors cursor-pointer select-none" + transition-colors select-none" :class="{ 'bg-adn-dark border-adn-dark': isChecked, - 'bg-white border-adn-border': !isChecked + 'bg-white border-adn-border': !isChecked, + 'cursor-not-allowed opacity-30': disabled, + 'cursor-pointer': !disabled }" >
@@ -42,11 +44,16 @@ export default defineComponent({ checkboxKey: { type: String, required: true + }, + disabled: { + type: Boolean, + default: false } }, emits: ['update:value'], methods: { handleChange(e) { + if (this.disabled) { return } this.isChecked = !this.isChecked this.$emit('update:value', { key: this.checkboxKey, diff --git a/src/views/ReportPositiveView.vue b/src/views/ReportPositiveView.vue index 8f2e4ce..704c280 100644 --- a/src/views/ReportPositiveView.vue +++ b/src/views/ReportPositiveView.vue @@ -19,6 +19,7 @@ v-for="reason in reasons" :key="reason.key" :checkbox-key="reason.key" + :disabled="reason.disabled" :value="selectedReasons.includes(reason.key)" @update:value="handleReasonChange" class="mb-4" @@ -89,22 +90,27 @@ export default defineComponent({ { key: 'unclear_language', text: 'Unclear language', - description: 'The cookie banner does not explicitly or clearly ask for my consent to use cookies' + description: 'The cookie banner does not explicitly or clearly ask for my consent to use cookies', + disabled: false }, { key: 'prefilled_options', text: 'Pre-filled options', - description: 'The cookie banner has options that were filled out for me, e.g., pre-checked checkboxes for different types of cookies' + // description: 'The cookie banner has options that were filled out for me, e.g., pre-checked checkboxes for different types of cookies', + description: 'Not currently supported', + disabled: true }, { key: 'weighted_options', text: 'Weighted options', - description: 'The controls on the cookie banner are weighted, i.e., designed to bring more visual emphasis on one option over another' + description: 'The controls on the cookie banner are weighted, i.e., designed to bring more visual emphasis on one option over another', + disabled: false }, { key: 'other', text: 'Others', - description: 'I noticed another type of deceptive design on the cookie banner that wasn\'t included above' + description: 'I noticed another type of deceptive design on the cookie banner that wasn\'t included above', + disabled: false } ] } From 39f07b4a28b9df37ca8e3f895e6b26572c346879 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Wed, 10 May 2023 00:55:03 +0800 Subject: [PATCH 04/31] PillCount: Highlight with teal instead of purple Reserve the purple for the detection result banner --- src/components/PillCount.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PillCount.vue b/src/components/PillCount.vue index 02f5396..a25eea3 100644 --- a/src/components/PillCount.vue +++ b/src/components/PillCount.vue @@ -2,7 +2,7 @@
{ if (request.action === "updateBadge") { @@ -18,7 +19,15 @@ export default (request, sender, sendResponse) => { // POST to API classifyText(cookieBannerText, (data) => { console.log('listeners/message: Calliope result from API:', data); - sendResponse(data); + + // Save result + browser.tabs.get(sender.tab.id) + .then((tab) => tab.url) + .then((url) => setTransaction('calliope', { + url, + tripped: !data.is_good + })) + .then(() => sendResponse(data)); }); } else if (request.action === "visualDetection") { // Listen to visual detection requests from content scripts @@ -28,29 +37,56 @@ export default (request, sender, sendResponse) => { // POST to API classifyImage(imageData, (data) => { console.log('listeners/message: Janus result from API:', data); - sendResponse(data); + + // Save result + browser.tabs.get(sender.tab.id) + .then((tab) => tab.url) + .then((url) => setTransaction('janus', { + url, + tripped: data.classification === 'weighted' + })) + .then(() => sendResponse(data)); }); } else if (request.action === "requestStats") { console.log("listeners/message: Received stats request from popup", request, sender); - // If we have cached stats, send them before requesting new ones - const tabUrl = request.args.url; - let deferSending = false; - getTransaction('stats', tabUrl) - .then((stats) => { - console.log("listeners/message: Sending cached stats to tab", tabUrl, stats); + (async () => { + const tabUrl = request.args.url; + let calliopeResult = false; + let janusResult = false; + + // Try fetching results from DB + try { + const cachedCalliope = await getTransaction('calliope', tabUrl); + calliopeResult = cachedCalliope.tripped; + } catch (_) { + // do nothing + } + try { + const cachedJanus = await getTransaction('janus', tabUrl); + janusResult = cachedJanus.tripped; + } catch (_) { + // do nothing + } + + // If we have cached stats, send them before requesting new ones + let deferSending = false; + let stats = { calliopeResult, janusResult }; + try { + stats = { ...stats, ...await getTransaction('stats', tabUrl) }; + console.log('listeners/message: Sending stats to tab', tabUrl, stats) sendResponse(stats); deferSending = true; - }) - .catch((e) => { + } catch (e) { console.error(e); - }) - .finally(() => getStats(tabUrl, (newStats) => { + } finally { + getStats(tabUrl, (newStats) => { + stats = { ...stats, ...newStats }; if (!deferSending) { - console.log('listeners/message: Sending stats to tab', tabUrl, this._reportStats[tabUrl]) - sendResponse(newStats); + console.log('listeners/message: Sending stats to tab', tabUrl, stats) + sendResponse(stats); } else { - console.log('listeners/message: Revalidated cache for tab', tabUrl, this._reportStats[tabUrl]) + console.log('listeners/message: Revalidated cache for tab', tabUrl) } }, (error) => { sendResponse({ @@ -58,7 +94,8 @@ export default (request, sender, sendResponse) => { error }); }) - ) + } + })(); } return true; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 5ff19e1..4b59aea 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -24,6 +24,32 @@
+ +
+
+ +

{{ tripped ? 'D' : 'No d' }}eceptive design
detected here

+ + +
+ + +
+
+

+ Ariadne's automated detector determined that the cookie banner on this page might + be making use of {{ trippedText }}. +

+

+ Ariadne's automated detector determined that cookie banners on this page, + if any, are not making use of deceptive design. +

+
+
@@ -70,12 +96,20 @@
+ +

+ By clicking the thumbs buttons or the report button above, you allow Ariadne to submit a report + to the remote Ariadne server containing information about this page. + + Click here to view our privacy policy. + +

\ No newline at end of file From bb04e3aba21d6870eb6f4763163698748d558a37 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 01:01:53 +0800 Subject: [PATCH 14/31] views: `ReportPositive` -> `ManualReport` --- src/router/index.js | 6 +++--- src/views/HomeView.vue | 2 +- src/views/{ReportPositiveView.vue => ManualReportView.vue} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/views/{ReportPositiveView.vue => ManualReportView.vue} (99%) diff --git a/src/router/index.js b/src/router/index.js index f1c6690..3053a1d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -17,13 +17,13 @@ const router = createRouter({ }, }, { - path: '/report-positive', - name: 'report-positive', + path: '/report-manual', + name: 'report-manual', meta: { title: 'Report Deceptive Design' }, // route level code-splitting // this generates a separate chunk (About.[hash].js) for this route // which is lazy-loaded when the route is visited. - component: () => import('../views/ReportPositiveView.vue') + component: () => import('../views/ManualReportView.vue') } ] }) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 4b59aea..c9a78a8 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -90,7 +90,7 @@
- + Report deceptive design on this page diff --git a/src/views/ReportPositiveView.vue b/src/views/ManualReportView.vue similarity index 99% rename from src/views/ReportPositiveView.vue rename to src/views/ManualReportView.vue index 704c280..18e42c4 100644 --- a/src/views/ReportPositiveView.vue +++ b/src/views/ManualReportView.vue @@ -65,7 +65,7 @@ import Checkbox from '@/components/Checkbox.vue' import Overlay from '@/components/Overlay.vue' export default defineComponent({ - name: 'ReportPositiveView', + name: 'ManualReportView', components: { BigButton, Checkbox, From a7be29ffaa6287e656aedbf1f9c2f76678fae9d9 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:08:47 +0800 Subject: [PATCH 15/31] content: Call Janus unconditionally --- content/content.js | 54 ++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/content/content.js b/content/content.js index 3218f95..c11c25f 100644 --- a/content/content.js +++ b/content/content.js @@ -1,6 +1,28 @@ import html2canvas from 'html2canvas'; import * as browser from 'webextension-polyfill'; +function canvasHandler(canvas) { + const screenshot = canvas.toDataURL("image/png"); + console.log("[content] Screenshot taken, sending to service worker"); + + // Send screenshot to service worker for detection + browser.runtime.sendMessage({ + action: "visualDetection", + args: { screenshot } + }) + .then((response) => { + console.log("[content] Result from Janus API:", response); + + // Update badge + return browser.runtime.sendMessage({ + action: "updateBadge", + args: { + enabled: response["classification"] == "weighted" + } + }); + }); +} + let bannerDiv = null; function performDetection() { // Look for floating divs, i.e. divs with position: fixed|absolute|sticky @@ -43,13 +65,14 @@ function performDetection() { .then((response) => { console.log("[content] Badge updated:", response); }); + break; } } - // No banner found + // Perform visual detection if (bannerDiv === null) { - console.log("[content] No banner found"); + console.log("[content] No banner found, taking screenshot of viewport"); // Take screenshot of viewport html2canvas(document.body, { @@ -57,28 +80,13 @@ function performDetection() { y: window.scrollY, width: window.innerWidth, height: window.innerHeight, - }).then((canvas) => { - const screenshot = canvas.toDataURL("image/png"); - console.log("[content] Screenshot taken, sending to service worker"); - - // Send screenshot to service worker for detection - browser.runtime.sendMessage({ - action: "visualDetection", - args: { screenshot } - }) - .then((response) => { - console.log("[content] Result from Janus API:", response); - - // Update badge - return browser.runtime.sendMessage({ - action: "updateBadge", - args: { - enabled: response["classification"] == "weighted" - } - }); - }); - }); + }).then(canvasHandler); return; + } else { + console.log("[content] Taking screenshot of banner"); + + // Take screenshot of banner + html2canvas(bannerDiv).then(canvasHandler); } } From 6f917d3d310e2a7c6a49fa7faf38db9999861c85 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:09:24 +0800 Subject: [PATCH 16/31] bg/listeners(message): Store and send classifier inputs --- background/listeners/message.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/background/listeners/message.js b/background/listeners/message.js index 4e142cc..26f010f 100644 --- a/background/listeners/message.js +++ b/background/listeners/message.js @@ -25,6 +25,7 @@ export default (request, sender, sendResponse) => { .then((tab) => tab.url) .then((url) => setTransaction('calliope', { url, + cookieBannerText, tripped: !data.is_good })) .then(() => sendResponse(data)); @@ -43,7 +44,8 @@ export default (request, sender, sendResponse) => { .then((tab) => tab.url) .then((url) => setTransaction('janus', { url, - tripped: data.classification === 'weighted' + imageData, + result: data.classification })) .then(() => sendResponse(data)); }); @@ -54,24 +56,28 @@ export default (request, sender, sendResponse) => { const tabUrl = request.args.url; let calliopeResult = false; let janusResult = false; + let cookieBannerText = ''; + let imageData = ''; // Try fetching results from DB try { const cachedCalliope = await getTransaction('calliope', tabUrl); calliopeResult = cachedCalliope.tripped; + cookieBannerText = cachedCalliope.cookieBannerText; } catch (_) { // do nothing } try { const cachedJanus = await getTransaction('janus', tabUrl); - janusResult = cachedJanus.tripped; + janusResult = cachedJanus.result; + imageData = cachedJanus.imageData; } catch (_) { // do nothing } // If we have cached stats, send them before requesting new ones let deferSending = false; - let stats = { calliopeResult, janusResult }; + let stats = { calliopeResult, janusResult, cookieBannerText, imageData }; try { stats = { ...stats, ...await getTransaction('stats', tabUrl) }; console.log('listeners/message: Sending stats to tab', tabUrl, stats) From 945164477984e79890ad9f81aa5a152363085353 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:18:32 +0800 Subject: [PATCH 17/31] stores: Save classifier input and results --- src/stores/ariadne.js | 12 +++++++++++- src/views/HomeView.vue | 17 +++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/stores/ariadne.js b/src/stores/ariadne.js index dc3cacc..b8170c7 100644 --- a/src/stores/ariadne.js +++ b/src/stores/ariadne.js @@ -6,7 +6,11 @@ export const useAriadneStore = defineStore('ariadne', { currentFavicon: '', currentPath: '', currentURL: '', - isRunningInExtension: false + isRunningInExtension: false, + calliopeTripped: false, + calliopeText: '', + janusResult: '', + janusScreenshot: '' }), actions: { setDomain(domain) { @@ -23,6 +27,12 @@ export const useAriadneStore = defineStore('ariadne', { }, setRunningInExtension(isRunningInExtension) { this.isRunningInExtension = isRunningInExtension; + }, + setDetectionData({ calliopeTripped, calliopeText, janusResult, janusScreenshot }) { + this.calliopeTripped = calliopeTripped; + this.calliopeText = calliopeText; + this.janusResult = janusResult; + this.janusScreenshot = janusScreenshot; } } }) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index c9a78a8..677d4a7 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -156,16 +156,17 @@ export default defineComponent({ count: 0 } }, - calliopeTripped: false, - janusTripped: false } }, computed: { + janusTripped() { + return this.store.janusResult === 'weighted' + }, tripped() { - return this.calliopeTripped || this.janusTripped + return this.store.calliopeTripped || this.janusTripped }, trippedText() { - if (this.calliopeTripped) { + if (this.store.calliopeTripped) { if (this.janusTripped) { return 'unclear language and weighted options' } @@ -203,8 +204,12 @@ export default defineComponent({ args: { url } }) .then((response) => { - this.calliopeTripped = response.calliopeResult - this.janusTripped = response.janusResult + this.store.setDetectionData({ + calliopeTripped: response.calliopeResult, + calliopeText: response.cookieBannerText, + janusResult: response.janusResult, + janusScreenshot: response.imageData + }) return response.stats }) .then((stats) => { From b937a8f4af4b5bd2808d9fa0263a0d02841d43db Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:19:16 +0800 Subject: [PATCH 18/31] views(ManualReport): Don't log submission --- src/views/ManualReportView.vue | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/views/ManualReportView.vue b/src/views/ManualReportView.vue index 18e42c4..fb5a023 100644 --- a/src/views/ManualReportView.vue +++ b/src/views/ManualReportView.vue @@ -44,7 +44,8 @@ + @click="submitReport" + > Submit @@ -137,12 +138,6 @@ export default defineComponent({ submitReport(e) { e.preventDefault() if (this.incompleteReport) return - console.log('Submitting report', { - selectedReasons: this.selectedReasons, - customReason: this.customReason, - url: this.store.url, - isRunningInExtension: this.store.isRunningInExtension - }) // Send report to backend via POST this.isLoading = true From 3e3f3dcb8ae6bd4165cf7d72067cd0e8769ed6e2 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:19:43 +0800 Subject: [PATCH 19/31] views: Create AutoReportView --- src/router/index.js | 9 +- src/views/AutoReportView.vue | 161 +++++++++++++++++++++++++++++++++++ src/views/HomeView.vue | 50 ++++++++++- 3 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 src/views/AutoReportView.vue diff --git a/src/router/index.js b/src/router/index.js index 3053a1d..74d60bb 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -20,10 +20,13 @@ const router = createRouter({ path: '/report-manual', name: 'report-manual', meta: { title: 'Report Deceptive Design' }, - // route level code-splitting - // this generates a separate chunk (About.[hash].js) for this route - // which is lazy-loaded when the route is visited. component: () => import('../views/ManualReportView.vue') + }, + { + path: '/report-auto', + name: 'report-auto', + meta: { title: 'Submit Detection Feedback' }, + component: () => import('../views/AutoReportView.vue') } ] }) diff --git a/src/views/AutoReportView.vue b/src/views/AutoReportView.vue new file mode 100644 index 0000000..5ddef0c --- /dev/null +++ b/src/views/AutoReportView.vue @@ -0,0 +1,161 @@ + + + \ No newline at end of file diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 677d4a7..d294be6 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -36,8 +36,50 @@
- - + + + + + + + +

@@ -114,6 +156,7 @@ import { useAriadneStore } from '@/stores/ariadne' import BigButton from '@/components/BigButton.vue' import Overlay from '@/components/Overlay.vue' import PillCount from '@/components/PillCount.vue' +import Tooltip from '@/components/Tooltip.vue' import * as browser from 'webextension-polyfill' export default defineComponent({ @@ -125,7 +168,8 @@ export default defineComponent({ HandThumbUpIcon, NoSymbolIcon, Overlay, - PillCount + PillCount, + Tooltip }, setup() { return { From c6cc52c715b9120960dfceefcf44d87ae46e4fd1 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:23:38 +0800 Subject: [PATCH 20/31] router: Scroll to top after nav --- src/router/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/router/index.js b/src/router/index.js index 74d60bb..7fdd872 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -28,7 +28,11 @@ const router = createRouter({ meta: { title: 'Submit Detection Feedback' }, component: () => import('../views/AutoReportView.vue') } - ] + ], + scrollBehavior(to, from, savedPosition) { + // always scroll to top + return { top: 0 } + }, }) export default router From 87e51c7332b53e9d7d6cc71a9f5483d644882c62 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:48:55 +0800 Subject: [PATCH 21/31] views(HomeView): Shorter detection result text --- src/views/HomeView.vue | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index d294be6..7b389c5 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -83,12 +83,11 @@

- Ariadne's automated detector determined that the cookie banner on this page might - be making use of {{ trippedText }}. + The cookie banner on this page might be making use of + {{ trippedText }}.

- Ariadne's automated detector determined that cookie banners on this page, - if any, are not making use of deceptive design. + The cookie banner on this page, if any, is not making use of deceptive design.

From ad1fab571299e8d73c34f68d542d0f5a6758c391 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:51:32 +0800 Subject: [PATCH 22/31] views: Move privacy statement to report views --- src/views/AutoReportView.vue | 15 +++++++++++++++ src/views/HomeView.vue | 10 +--------- src/views/ManualReportView.vue | 11 +++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/views/AutoReportView.vue b/src/views/AutoReportView.vue index 5ddef0c..3699e22 100644 --- a/src/views/AutoReportView.vue +++ b/src/views/AutoReportView.vue @@ -54,6 +54,20 @@ + +

+ As the extracted cookie banner text and screenshot may contain personal + information, Ariadne will only submit them if you explicitly allow it to do so. +

+

+ By clicking Submit, you allow Ariadne to submit a report to the Dionysus server + at {{ dionysusUrl }} containing information about this page, + along with any attachments and remarks you have provided. + + Click here to view our privacy policy. + +

+
@@ -97,6 +111,7 @@ export default defineComponent({ }, data() { return { + dionysusUrl: import.meta.env.VITE_API_URL, isLoading: false, remarks: '', attachText: false, diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 7b389c5..cb0b497 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -132,19 +132,11 @@
- + Report deceptive design on this page
- -

- By clicking the thumbs buttons or the report button above, you allow Ariadne to submit a report - to the remote Ariadne server containing information about this page. - - Click here to view our privacy policy. - -

diff --git a/src/views/ManualReportView.vue b/src/views/ManualReportView.vue index fb5a023..fd25e85 100644 --- a/src/views/ManualReportView.vue +++ b/src/views/ManualReportView.vue @@ -38,6 +38,16 @@ >
+ +

+ By clicking Submit, you allow Ariadne to submit a report to the Dionysus server + at {{ dionysusUrl }} containing information about this page, + along with any remarks you have provided. + + Click here to view our privacy policy. + +

+
@@ -74,6 +84,7 @@ export default defineComponent({ }, data() { return { + dionysusUrl: import.meta.env.VITE_API_URL, selectedReasons: [], customReason: '', isLoading: false From a3bd8daa611aca713f8fc9e0b71f31a56fc1efc6 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 02:52:00 +0800 Subject: [PATCH 23/31] components(Header): Hide settings icon for now --- src/components/Header.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Header.vue b/src/components/Header.vue index 1d92d1b..db50dec 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -31,7 +31,7 @@ import { Cog6ToothIcon } from '@heroicons/vue/24/outline'
-
-
+
--> ALPHA From b31bc7cb53839ed0db6be7b2a1e79f721f63195d Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:27:03 +0800 Subject: [PATCH 24/31] bg/listeners(message): Janus default result is blank --- background/listeners/message.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/background/listeners/message.js b/background/listeners/message.js index 26f010f..ce909a5 100644 --- a/background/listeners/message.js +++ b/background/listeners/message.js @@ -55,7 +55,7 @@ export default (request, sender, sendResponse) => { (async () => { const tabUrl = request.args.url; let calliopeResult = false; - let janusResult = false; + let janusResult = ''; let cookieBannerText = ''; let imageData = ''; From 89014467d9a2e274a3ccf2446c698ae7be9b17d2 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:27:15 +0800 Subject: [PATCH 25/31] content: Don't screenshot if no banner found --- content/content.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/content/content.js b/content/content.js index c11c25f..9564858 100644 --- a/content/content.js +++ b/content/content.js @@ -71,22 +71,11 @@ function performDetection() { } // Perform visual detection - if (bannerDiv === null) { - console.log("[content] No banner found, taking screenshot of viewport"); - - // Take screenshot of viewport - html2canvas(document.body, { - x: window.scrollX, - y: window.scrollY, - width: window.innerWidth, - height: window.innerHeight, - }).then(canvasHandler); - return; - } else { + if (bannerDiv !== null) { console.log("[content] Taking screenshot of banner"); - - // Take screenshot of banner html2canvas(bannerDiv).then(canvasHandler); + } else { + console.log("[content] No banner div found, skipping visual detection"); } } From 21c2c687169b407e6cef7264c12809d53b476340 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:31:45 +0800 Subject: [PATCH 26/31] bg/listeners(message): Make default Calliope result empty --- background/listeners/message.js | 2 +- src/stores/ariadne.js | 2 +- src/views/HomeView.vue | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/background/listeners/message.js b/background/listeners/message.js index ce909a5..e7a5b09 100644 --- a/background/listeners/message.js +++ b/background/listeners/message.js @@ -54,7 +54,7 @@ export default (request, sender, sendResponse) => { (async () => { const tabUrl = request.args.url; - let calliopeResult = false; + let calliopeResult = ''; let janusResult = ''; let cookieBannerText = ''; let imageData = ''; diff --git a/src/stores/ariadne.js b/src/stores/ariadne.js index b8170c7..f18b809 100644 --- a/src/stores/ariadne.js +++ b/src/stores/ariadne.js @@ -7,7 +7,7 @@ export const useAriadneStore = defineStore('ariadne', { currentPath: '', currentURL: '', isRunningInExtension: false, - calliopeTripped: false, + calliopeResult: '', calliopeText: '', janusResult: '', janusScreenshot: '' diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index cb0b497..b550b27 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -194,14 +194,17 @@ export default defineComponent({ } }, computed: { + calliopeTripped() { + return this.store.calliopeResult === true + }, janusTripped() { return this.store.janusResult === 'weighted' }, tripped() { - return this.store.calliopeTripped || this.janusTripped + return this.calliopeTripped || this.janusTripped }, trippedText() { - if (this.store.calliopeTripped) { + if (this.calliopeTripped) { if (this.janusTripped) { return 'unclear language and weighted options' } @@ -240,7 +243,7 @@ export default defineComponent({ }) .then((response) => { this.store.setDetectionData({ - calliopeTripped: response.calliopeResult, + calliopeResult: response.calliopeResult, calliopeText: response.cookieBannerText, janusResult: response.janusResult, janusScreenshot: response.imageData From 54012538c75b6b3ed3fe4dfbcaa066927535f9ed Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:46:39 +0800 Subject: [PATCH 27/31] bg/listeners(message): Store calliopeTripped as string --- background/listeners/message.js | 2 +- src/stores/ariadne.js | 2 +- src/views/HomeView.vue | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/background/listeners/message.js b/background/listeners/message.js index e7a5b09..7d2d482 100644 --- a/background/listeners/message.js +++ b/background/listeners/message.js @@ -62,7 +62,7 @@ export default (request, sender, sendResponse) => { // Try fetching results from DB try { const cachedCalliope = await getTransaction('calliope', tabUrl); - calliopeResult = cachedCalliope.tripped; + calliopeResult = JSON.stringify(cachedCalliope.tripped); cookieBannerText = cachedCalliope.cookieBannerText; } catch (_) { // do nothing diff --git a/src/stores/ariadne.js b/src/stores/ariadne.js index f18b809..e9dc815 100644 --- a/src/stores/ariadne.js +++ b/src/stores/ariadne.js @@ -7,7 +7,7 @@ export const useAriadneStore = defineStore('ariadne', { currentPath: '', currentURL: '', isRunningInExtension: false, - calliopeResult: '', + calliopeTripped: '', calliopeText: '', janusResult: '', janusScreenshot: '' diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index b550b27..69858bb 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -195,7 +195,7 @@ export default defineComponent({ }, computed: { calliopeTripped() { - return this.store.calliopeResult === true + return this.store.calliopeTripped === 'true' }, janusTripped() { return this.store.janusResult === 'weighted' @@ -243,7 +243,7 @@ export default defineComponent({ }) .then((response) => { this.store.setDetectionData({ - calliopeResult: response.calliopeResult, + calliopeTripped: response.calliopeResult, calliopeText: response.cookieBannerText, janusResult: response.janusResult, janusScreenshot: response.imageData From b9f0b8e63adbca5e948b5f54e0dd6e415f030d3c Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:47:19 +0800 Subject: [PATCH 28/31] views(AutoReport): Make classifier results optional --- src/views/AutoReportView.vue | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/views/AutoReportView.vue b/src/views/AutoReportView.vue index 3699e22..5e6f2ab 100644 --- a/src/views/AutoReportView.vue +++ b/src/views/AutoReportView.vue @@ -142,14 +142,15 @@ export default defineComponent({ // Assemble request body const body = { page_url: 'http://' + this.store.currentDomain + this.store.currentPath, - calliope_tripped: this.store.calliopeTripped, - janus_result: this.store.janusResult, vote: this.vote } - console.log(body) + if (this.store.calliopeTripped !== '') { + body.calliope_tripped = this.store.calliopeTripped === 'true' + } + if (this.store.janusResult !== '') body.janus_result = this.store.janusResult + if (this.attachText && this.store.calliopeText !== '') body.calliope_text = this.store.calliopeText + if (this.attachImage && this.store.janusScreenshot !== '') body.janus_screenshot = this.store.janusScreenshot if (this.remarks !== '') body.remarks = this.remarks - if (this.attachText) body.calliope_text = this.store.calliopeText - if (this.attachImage) body.janus_screenshot = this.store.janusScreenshot // Send report to backend via POST this.isLoading = true From c357889fbbcfce48cac7571a765838e33e88a6c8 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:47:59 +0800 Subject: [PATCH 29/31] views(AutoReport): Autohide attachments; display classifier results --- src/views/AutoReportView.vue | 95 +++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 38 deletions(-) diff --git a/src/views/AutoReportView.vue b/src/views/AutoReportView.vue index 5e6f2ab..adfc72d 100644 --- a/src/views/AutoReportView.vue +++ b/src/views/AutoReportView.vue @@ -13,8 +13,12 @@

{{ store.currentPath }}

-

Reporting as

-

{{ reportType }}

+

Calliope result

+

Likely {{ calliopeResult }}

+

Janus result

+

Likely {{ store.janusResult || 'no banner present' }}

+

Reporting as

+

{{ reportType }} detection

-

Attachments

-

- You can choose to include the items below in your report by clicking them. - This will help us improve Ariadne in the future. -

- - - - - - - - +
+

Attachments

+

+ You can choose to include the items below in your report by clicking them. + This will help us improve Ariadne in the future. +

+ + + + + + + + + +

+ As the extracted cookie banner text and screenshot may contain personal + information, Ariadne will only submit them if you explicitly allow it to do so. +

+
-

- As the extracted cookie banner text and screenshot may contain personal - information, Ariadne will only submit them if you explicitly allow it to do so. -

-

+

By clicking Submit, you allow Ariadne to submit a report to the Dionysus server at {{ dionysusUrl }} containing information about this page, along with any attachments and remarks you have provided. @@ -119,6 +127,17 @@ export default defineComponent({ } }, computed: { + attachmentsPresent() { + return this.store.calliopeText !== '' || this.store.janusScreenshot !== '' + }, + calliopeResult() { + console.log(this.store.calliopeTripped) + if (this.store.calliopeTripped !== '') { + return this.store.calliopeTripped === 'true' ? 'unclear language' : 'clear language' + } else { + return 'no banner present' + } + }, reportType() { return this.vote ? 'Correct' : 'Incorrect' }, From 7a0a97b32c899add25723c1edf7ff7533f0f8c26 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:53:02 +0800 Subject: [PATCH 30/31] views(AutoReport): Don't truncate text --- src/views/AutoReportView.vue | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/views/AutoReportView.vue b/src/views/AutoReportView.vue index adfc72d..98d8f2a 100644 --- a/src/views/AutoReportView.vue +++ b/src/views/AutoReportView.vue @@ -39,8 +39,8 @@ @update:value="handleCheckboxChange" :disabled="this.store.calliopeText === ''" > - - + + 100 - ? this.store.calliopeText.substring(0, 100) + '...' - : this.store.calliopeText } }, methods: { From 1129aa7e034abd5c910f0eba677c673573cd7f62 Mon Sep 17 00:00:00 2001 From: Jared Dantis Date: Sat, 13 May 2023 03:56:33 +0800 Subject: [PATCH 31/31] Version 0.1.1 --- manifest/v2.json | 2 +- manifest/v3.json | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/manifest/v2.json b/manifest/v2.json index 9b4d131..43c851d 100644 --- a/manifest/v2.json +++ b/manifest/v2.json @@ -3,7 +3,7 @@ "short_name": "__MSG_appShortName__", "description": "__MSG_appDescription__", "homepage_url": "https://ariadne.dantis.me", - "version": "0.1.0", + "version": "0.1.1", "manifest_version": 2, "default_locale": "en", "permissions": [ diff --git a/manifest/v3.json b/manifest/v3.json index d935b90..f4c4790 100644 --- a/manifest/v3.json +++ b/manifest/v3.json @@ -3,8 +3,8 @@ "short_name": "__MSG_appShortName__", "description": "__MSG_appDescription__", "homepage_url": "https://ariadne.dantis.me", - "version": "0.1.0", - "version_name": "0.1.0", + "version": "0.1.1", + "version_name": "0.1.1", "manifest_version": 3, "default_locale": "en", "minimum_chrome_version": "88", diff --git a/package-lock.json b/package-lock.json index 34d01ab..3c750c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ariadne", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ariadne", - "version": "0.1.0", + "version": "0.1.1", "dependencies": { "@heroicons/vue": "^2.0.16", "flowbite": "^1.6.5", diff --git a/package.json b/package.json index 1940730..6c38460 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ariadne", "description": "Detect deceptive design on the Web", - "version": "0.1.0", + "version": "0.1.1", "homepage": "https://ariadne.dantis.me", "author": "Juris Hannah Adorna & Aurel Jared Dantis", "repository": {