diff --git a/example-web/my-app/package-lock.json b/example-web/my-app/package-lock.json
index 68cf8ba1..18f8c7d6 100644
--- a/example-web/my-app/package-lock.json
+++ b/example-web/my-app/package-lock.json
@@ -14,6 +14,7 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "eslint": "^8.56.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
@@ -2531,9 +2532,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.55.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz",
- "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==",
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
+ "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
@@ -7795,14 +7796,14 @@
}
},
"node_modules/eslint": {
- "version": "8.55.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz",
- "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==",
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
+ "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.4",
- "@eslint/js": "8.55.0",
+ "@eslint/js": "8.56.0",
"@humanwhocodes/config-array": "^0.11.13",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
diff --git a/example-web/my-app/package.json b/example-web/my-app/package.json
index 165c7953..78e4c384 100644
--- a/example-web/my-app/package.json
+++ b/example-web/my-app/package.json
@@ -9,6 +9,7 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "eslint": "^8.56.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
@@ -24,7 +25,10 @@
"extends": [
"react-app",
"react-app/jest"
- ]
+ ],
+ "globals": {
+ "chrome": true
+ }
},
"browserslist": {
"production": [
diff --git a/example-web/my-app/src/App.js b/example-web/my-app/src/App.js
index 2cf0b771..531583f3 100644
--- a/example-web/my-app/src/App.js
+++ b/example-web/my-app/src/App.js
@@ -12,6 +12,16 @@ function App() {
window.postMessage({ type: "init-req-credential" }, "*");
};
+ const handleSyncRequest = () => {
+ // TODO extension Id harcoded just for testing, need to find a way to get it dynamically
+ chrome.runtime.sendMessage("fklmfbmpaimbgjplbambkdjphdadbmed", {data: "test"},
+ function(response) {
+ if (!response.success)
+ console.log(response.data)
+ alert("Signed headers received\n"+ JSON.stringify(response.data.headers, null, 2));
+ });
+ };
+
return (
@@ -25,6 +35,9 @@ function App() {
+
diff --git a/manifest.json b/manifest.json
index b4557b28..b3cc0729 100755
--- a/manifest.json
+++ b/manifest.json
@@ -19,23 +19,14 @@
"permissions": [
"activeTab",
"storage",
- "tabs",
"alarms"
],
"content_scripts": [
{
- "matches": [
- "http://*/*",
- "https://*/*",
- ""
- ],
+ "matches": [""],
"run_at": "document_end",
- "js": [
- "src/pages/content/index.tsx"
- ],
- "css": [
- "contentStyle.css"
- ]
+ "js": ["src/pages/content/index.tsx"],
+ "css": ["contentStyle.css"]
}
],
"web_accessible_resources": [
@@ -48,5 +39,8 @@
],
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'"
+ },
+ "externally_connectable": {
+ "matches": [""]
}
}
\ No newline at end of file
diff --git a/src/components/main.tsx b/src/components/main.tsx
index 5aa74e0b..0531e5ed 100644
--- a/src/components/main.tsx
+++ b/src/components/main.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { Sidebar } from "@components/sidebar";
import { SelectIdentifier } from "@components/selectIdentifier";
import { SelectCredential } from "@components/selectCredential";
-import { APP_STATE } from "@pages/popup/constants";
+import { TAB_STATE } from "@pages/popup/constants";
import { IdentifierList } from "@components/identifierList";
import { CredentialList } from "@components/credentialList";
import { SigninList } from "@components/signinList";
@@ -13,29 +13,31 @@ interface IMain {
export function Main(props: IMain): JSX.Element {
const [activeSidebar, setActiveSidebar] = useState("Identifiers");
- const [tabState, setTabState] = useState(APP_STATE.DEFAULT);
+ const [tabState, setTabState] = useState(TAB_STATE.DEFAULT);
const fetchTabState = async () => {
- const { data } = await chrome.runtime.sendMessage({
- type: "tab",
- subtype: "get-tab-state",
- });
- if (!data) return;
+ chrome.tabs.query({ active: true, currentWindow: true }, async function (tabs) {
+ const { data } = await chrome.tabs.sendMessage(
+ tabs[0].id!,
+ { type: "tab", subtype: "get-tab-state" }
+ );
+ if (!data) return;
if (data?.appState) {
setTabState(data?.appState);
if (
- data?.appState === APP_STATE.SELECT_IDENTIFIER ||
- data?.appState === APP_STATE.SELECT_CREDENTIAL
+ data?.appState === TAB_STATE.SELECT_IDENTIFIER ||
+ data?.appState === TAB_STATE.SELECT_CREDENTIAL
) {
setActiveSidebar(
- data?.appState === APP_STATE.SELECT_IDENTIFIER
+ data?.appState === TAB_STATE.SELECT_IDENTIFIER
? "Identifiers"
: "Credentials"
);
}
}
+ });
};
useEffect(() => {
@@ -43,9 +45,9 @@ export function Main(props: IMain): JSX.Element {
}, []);
const renderItems = () => {
- if (tabState === APP_STATE.SELECT_IDENTIFIER) return ;
+ if (tabState === TAB_STATE.SELECT_IDENTIFIER) return ;
- if (tabState === APP_STATE.SELECT_CREDENTIAL) return ;
+ if (tabState === TAB_STATE.SELECT_CREDENTIAL) return ;
switch (activeSidebar) {
case "Credentials":
@@ -60,8 +62,8 @@ export function Main(props: IMain): JSX.Element {
const isSidebarDisabled = () => {
return (
- tabState === APP_STATE.SELECT_IDENTIFIER ||
- tabState === APP_STATE.SELECT_CREDENTIAL
+ tabState === TAB_STATE.SELECT_IDENTIFIER ||
+ tabState === TAB_STATE.SELECT_CREDENTIAL
);
};
diff --git a/src/components/selectCredential.tsx b/src/components/selectCredential.tsx
index c07fa1f2..b6a3bc52 100644
--- a/src/components/selectCredential.tsx
+++ b/src/components/selectCredential.tsx
@@ -1,7 +1,6 @@
import { useState, useEffect } from "react";
import { CredentialCard } from "@components/credentialCard";
import { IMessage } from "@pages/background/types";
-import { APP_STATE } from "@pages/popup/constants";
export function SelectCredential(): JSX.Element {
const [credentials, setCredentials] = useState([]);
@@ -13,20 +12,18 @@ export function SelectCredential(): JSX.Element {
setCredentials(data.credentials);
};
- const createSigninWithCredential = async (credential) => {
- const { data } = await chrome.runtime.sendMessage>({
+ const createSigninWithCredential = async (credential: any) => {
+ await chrome.runtime.sendMessage>({
type: "create-resource",
subtype: "signin",
data: {
credential,
},
});
- await chrome.runtime.sendMessage({
- type: "tab",
- subtype: "set-app-state",
- data: {
- appState: APP_STATE.DEFAULT,
- },
+ chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
+ chrome.tabs.sendMessage(
+ tabs[0].id!,
+ { type: "tab", subtype: "reload-state" });
});
window.close();
};
diff --git a/src/components/selectIdentifier.tsx b/src/components/selectIdentifier.tsx
index 638d5daa..746ebd2a 100644
--- a/src/components/selectIdentifier.tsx
+++ b/src/components/selectIdentifier.tsx
@@ -1,7 +1,6 @@
import { useState, useEffect } from "react";
import { IdentifierCard } from "@components/identifierCard";
import { IMessage } from "@pages/background/types";
-import { APP_STATE } from "@pages/popup/constants";
export function SelectIdentifier(): JSX.Element {
const [aids, setAids] = useState([]);
@@ -14,29 +13,19 @@ export function SelectIdentifier(): JSX.Element {
setAids(data.aids);
};
- const createSigninWithIdentifiers = async (aid) => {
- const { data } = await chrome.runtime.sendMessage>({
+ const createSigninWithIdentifiers = async (aid: any) => {
+ await chrome.runtime.sendMessage>({
type: "create-resource",
subtype: "signin",
data: {
identifier: aid,
},
});
- await chrome.runtime.sendMessage({
- type: "tab",
- subtype: "set-app-state",
- data: {
- appState: APP_STATE.DEFAULT,
- },
- });
- console.log("data.signins", data.signins);
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(
- tabs[0].id,
- { type: "tab", subtype: "reload-state" },
- function (response) {}
- );
+ tabs[0].id!,
+ { type: "tab", subtype: "reload-state" });
});
window.close();
};
diff --git a/src/pages/background/index.ts b/src/pages/background/index.ts
index 8a5fec74..c075e58f 100644
--- a/src/pages/background/index.ts
+++ b/src/pages/background/index.ts
@@ -1,5 +1,4 @@
import { browserStorageService } from "@pages/background/services/browser-storage";
-import { webappService } from "@pages/background/services/webapp";
import { configService } from "@pages/background/services/config";
import { userService } from "@pages/background/services/user";
import { signifyService } from "@pages/background/services/signify";
@@ -9,6 +8,12 @@ import { getCurrentDomain } from "@pages/background/utils";
console.log("Background script loaded");
+chrome.runtime.onInstalled.addListener(function (object) {
+ if (object.reason === chrome.runtime.OnInstalledReason.INSTALL) {
+ console.log("Signify Browser Extension installed");
+ }
+});
+
// Handle messages
chrome.runtime.onMessage.addListener(function (
message: IMessage,
@@ -18,7 +23,7 @@ chrome.runtime.onMessage.addListener(function (
(async () => {
// Handle mesages from content script on active tab
- if (sender.tab && sender.tab.active) {
+ if (sender.tab && sender.tab.active) {
console.log(
"Message received from content script at " +
@@ -92,19 +97,6 @@ chrome.runtime.onMessage.addListener(function (
}
}
- if (message.type === "tab" && message.subtype === "get-tab-state") {
- const currentDomain = await getCurrentDomain();
- const appData = await webappService.getAppData(currentDomain!.origin);
- sendResponse({ data: appData });
- }
-
- if (message.type === "tab" && message.subtype === "set-app-state") {
- const currentDomain = await getCurrentDomain();
- await webappService.setAppData(currentDomain!.origin, message.data);
- const appData = await webappService.getAppData(currentDomain!.origin);
- sendResponse({ data: appData });
- }
-
if (message.type === "create-resource" && message.subtype === "signin") {
const signins = await browserStorageService.getValue("signins") as any[];
const currentDomain = await getCurrentDomain();
@@ -158,3 +150,26 @@ chrome.runtime.onMessage.addListener(function (
// return true to indicate chrome api to send a response asynchronously
return true;
});
+
+chrome.runtime.onMessageExternal.addListener(
+ async function(request, sender, sendResponse) {
+ console.log("Message received from external source: " + sender.url);
+ // if (sender.url === blocklistedWebsite)
+ // return; // don't allow this web page access
+ // if (request.openUrlInEditor)
+ // openUrl(request.openUrlInEditor);
+ // sendResponse({data: "received"})
+ const origin = sender.url!;
+ const signins = await browserStorageService.getValue("signins") as any;
+ // Validate that message comes from a page that has a signin
+ if (origin.startsWith(signins[0].domain)) {
+ const signedHeaders = await signifyService.signHeaders(signins[0].identifier.name, origin);
+ let jsonHeaders: { [key: string]: string; } = {};
+ for (const pair of signedHeaders.entries()) {
+ jsonHeaders[pair[0]] = pair[1];
+ }
+ sendResponse({ data: { headers: jsonHeaders } });
+
+ }
+
+ });
diff --git a/src/pages/background/services/config.ts b/src/pages/background/services/config.ts
index 4b22ad2f..dea41c09 100644
--- a/src/pages/background/services/config.ts
+++ b/src/pages/background/services/config.ts
@@ -6,7 +6,7 @@ const CONFIG_ENUMS = {
const Config = () => {
const getUrl = async (): Promise => {
- return await browserStorageService.getValue(CONFIG_ENUMS.KERIA_URL);
+ return await browserStorageService.getValue(CONFIG_ENUMS.KERIA_URL) as string;
}
const removeUrl = async () => {
diff --git a/src/pages/background/services/webapp.ts b/src/pages/background/services/webapp.ts
deleted file mode 100644
index 142116fa..00000000
--- a/src/pages/background/services/webapp.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { browserStorageService } from "@pages/background/services/browser-storage";
-
-const Webapp = () => {
- const getAppData = async (domain: string) => {
- return await browserStorageService.getValue(domain);
- };
-
- const setAppData = async (domain: string, newData = {}) => {
- let appData = (await getAppData(domain)) ?? {};
- appData = { ...appData, ...newData };
- return await browserStorageService.setValue(domain, appData);
- };
-
- return {
- getAppData,
- setAppData,
- };
-};
-
-export const webappService = Webapp();
diff --git a/src/pages/background/utils.ts b/src/pages/background/utils.ts
index 0aac359c..8e678042 100644
--- a/src/pages/background/utils.ts
+++ b/src/pages/background/utils.ts
@@ -23,6 +23,7 @@ export const getCurrentTab = (): Promise => {
export const getCurrentDomain = async () => {
const currentTab = await getCurrentTab();
+ console.log("Current tab: ", currentTab)
return currentTab ? new URL(currentTab.url!) : null;
};
diff --git a/src/pages/content/index.tsx b/src/pages/content/index.tsx
index be3f973a..99a54e1f 100644
--- a/src/pages/content/index.tsx
+++ b/src/pages/content/index.tsx
@@ -2,6 +2,9 @@ import { createRoot } from "react-dom/client";
import { IMessage } from "@pages/background/types";
import "./style.css";
import Dialog from "../dialog/Dialog";
+import { TAB_STATE } from "../popup/constants";
+
+var tabState = TAB_STATE.NONE;
// Handle messages from web page
window.addEventListener(
@@ -16,6 +19,7 @@ window.addEventListener(
switch (event.data.type) {
case "init-req-identifier":
case "init-req-credential":
+ setTabState(TAB_STATE.DEFAULT)
const { data } = await chrome.runtime.sendMessage>({
type: "authentication",
subtype: "check-agent-connection",
@@ -30,7 +34,7 @@ window.addEventListener(
data.isConnected,
data.tabUrl,
tabSigninResp?.data?.signins,
- "init-req-identifier"
+ event.data.type
);
break;
default:
@@ -55,23 +59,35 @@ chrome.runtime.onMessage.addListener(async function (
message.subtype
);
if (message.type === "tab" && message.subtype === "reload-state") {
- removeDialog();
- const { data } = await chrome.runtime.sendMessage>({
- type: "authentication",
- subtype: "check-agent-connection",
- });
- const tabSigninResp = await chrome.runtime.sendMessage>({
- type: "fetch-resource",
- subtype: "tab-signin",
- });
- insertDialog(
- data.isConnected,
- data.tabUrl,
- tabSigninResp?.data?.signins,
- "init-req-identifier"
- );
+ if (getTabState() !== TAB_STATE.NONE) {
+ removeDialog();
+ const { data } = await chrome.runtime.sendMessage>({
+ type: "authentication",
+ subtype: "check-agent-connection",
+ });
+ const tabSigninResp = await chrome.runtime.sendMessage>({
+ type: "fetch-resource",
+ subtype: "tab-signin",
+ });
+ insertDialog(
+ data.isConnected,
+ data.tabUrl,
+ tabSigninResp?.data?.signins,
+ ""
+ );
+ }
+
}
+
+ if (message.type === "tab" && message.subtype === "get-tab-state") {
+ sendResponse({data: {appState:getTabState()}});
+ }
+
+ if (message.type === "tab" && message.subtype === "set-tab-state") {
+ setTabState(message.data.appState);
+ }
}
+
});
function insertDialog(isConnected: boolean, tabUrl: string, signins: any, eventType: string) {
@@ -95,3 +111,13 @@ function removeDialog() {
const element = document.getElementById("__root");
if (element) element.remove();
}
+
+export function setTabState(state: string) {
+ console.log("setTabState: " + state)
+ tabState = state;
+}
+
+export function getTabState() {
+ console.log("getTabState: " + tabState)
+ return tabState;
+}
\ No newline at end of file
diff --git a/src/pages/dialog/Dialog.tsx b/src/pages/dialog/Dialog.tsx
index 492a29fc..27910cc7 100644
--- a/src/pages/dialog/Dialog.tsx
+++ b/src/pages/dialog/Dialog.tsx
@@ -1,7 +1,8 @@
-import React, { useState, useEffect } from "react";
-import { APP_STATE } from "@pages/popup/constants";
+import { useState, useEffect } from "react";
+import { TAB_STATE } from "@pages/popup/constants";
import { PopupPrompt } from "./popupPrompt";
import { SigninItem } from "./signin";
+import { setTabState } from "@pages/content/index";
export default function Dialog({
isConnected = false,
@@ -12,35 +13,25 @@ export default function Dialog({
const logo = chrome.runtime.getURL("src/assets/img/128_keri_logo.png");
const [showPopupPrompt, setShowPopupPrompt] = useState(false);
- const setAppState = async (state: string) => {
- await chrome.runtime.sendMessage({
- type: "tab",
- subtype: "set-app-state",
- data: {
- appState: state,
- },
- });
- };
-
const getEventTypeAppState = () => {
return eventType === "init-req-identifier"
- ? APP_STATE.SELECT_IDENTIFIER
+ ? TAB_STATE.SELECT_IDENTIFIER
: eventType === "init-req-credential"
- ? APP_STATE.SELECT_CREDENTIAL
- : APP_STATE.DEFAULT;
+ ? TAB_STATE.SELECT_CREDENTIAL
+ : TAB_STATE.DEFAULT;
};
const handleClick = () => {
- setAppState(getEventTypeAppState());
+ setTabState(getEventTypeAppState());
setShowPopupPrompt(true);
};
useEffect(() => {
if (!signins?.length) {
- setAppState(getEventTypeAppState());
+ setTabState(getEventTypeAppState());
setShowPopupPrompt(true);
} else if (!isConnected) {
- setAppState(APP_STATE.DEFAULT);
+ setTabState(TAB_STATE.DEFAULT);
setShowPopupPrompt(true);
}
}, []);
diff --git a/src/pages/dialog/signin.tsx b/src/pages/dialog/signin.tsx
index 86c7ee21..428775b4 100644
--- a/src/pages/dialog/signin.tsx
+++ b/src/pages/dialog/signin.tsx
@@ -1,3 +1,6 @@
+import { TAB_STATE } from "@pages/popup/constants";
+import { setTabState } from "@pages/content/index";
+
// TODO do not pass the full signins stored object (only AID name, schema name, web url)
export const SigninItem = ({ signin }: { signin: any }): JSX.Element => {
@@ -11,6 +14,7 @@ export const SigninItem = ({ signin }: { signin: any }): JSX.Element => {
});
const element = document.getElementById("__root");
if (element) element.remove();
+ setTabState(TAB_STATE.NONE);
// Communicate headers to web page
window.postMessage({ type: "signify-signature", data: headers.data }, "*");
};
diff --git a/src/pages/popup/Popup.tsx b/src/pages/popup/Popup.tsx
index e5073073..e0bdeb90 100644
--- a/src/pages/popup/Popup.tsx
+++ b/src/pages/popup/Popup.tsx
@@ -5,7 +5,7 @@ import { Signin } from "@src/components/signin";
import { Loader } from "@components/loader";
import { Main } from "@components/main";
-// TODO Harcoded for initial development. Must be removed soon
+// TODO Harcoded for initial development. Will be removed soon
const url = "https://keria-dev.rootsid.cloud/admin";
const boot_url = "https://keria-dev.rootsid.cloud";
const password = "CqjYb60NT9gZl8itwuttD9";
@@ -43,10 +43,10 @@ export default function Popup(): JSX.Element {
if (data.isConnected) {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
if (tabs.length === 1) {
+ console.log("realoading tab")
chrome.tabs.sendMessage(
tabs[0].id!,
- { type: "tab", subtype: "reload-state" },
- function (response) {}
+ { type: "tab", subtype: "reload-state" }
);
}
});
diff --git a/src/pages/popup/constants.ts b/src/pages/popup/constants.ts
index 9e99323a..7d2fa88d 100644
--- a/src/pages/popup/constants.ts
+++ b/src/pages/popup/constants.ts
@@ -1,6 +1,6 @@
-export const APP_STATE = {
+export const TAB_STATE = {
DEFAULT: "default",
SELECT_IDENTIFIER: "select-identifier",
SELECT_CREDENTIAL: "select-credential",
- KERIA_CONNECT: "keria-connect",
+ NONE: "none"
}
\ No newline at end of file