iframeでChrome拡張機能の機密情報を安全に表示する
annoのマーカーやアイコンは、Chrome拡張機能によってWebページ上に表示させている。
機密情報が含まれたコメントを、そのままWebページのDOMに置いてはいけない。
Chrome拡張機能が置いたDOMは、Webページ上で実行されるJavaScriptからも読み取れるため。
Webページの制作者は、機密情報を盗聴するスクリプトを仕込める。
annoでは以下のようなDOMをWebページに注入して、マーカーやアイコンを表示している。
html
<mark>マークしたテキスト</mark>
<iframe
src="chrome-extension://knaeipbflmbfcmjpekonjedhmfkobdop/annotation.html?id=annodata-3eb6d5edd7091aa5bc234b54e60579d97aa7c4027a523c265b87a8a507133fc5"
sandbox="allow-popups allow-popups-to-escape-sandbox allow-scripts"
style="width: 28px; height: 28px"
></iframe>
Web Accessible Resourceは、拡張機能とWebページの両方からアクセスできるファイルである。
annotation.html
<!DOCTYPE html>
<html>
<body>
<script type="module" src="dist/annotation.js"></script>
</body>
</html>
Web Accessible Resourceとして用意した
annotation.js
にて、chrome.storageからデータを取り出してアイコンを表示する。(一部)anno/src/annotation.ts
const searchParams = new URLSearchParams(location.search);
const id = searchParams.get("id");
const { [id]: annodata } = await chrome.storage.local.get(id);
const { url, description, iconURL, iconWidth, iconHeight } =
annodata as Annodata;
const linkElement = document.createElement("a");
linkElement.href = url;
linkElement.rel = "noopener";
linkElement.target = "_blank";
linkElement.title = description;
const imageElement = document.createElement("img");
imageElement.src = iconURL;
imageElement.style.verticalAlign = "middle";
imageElement.style.width = `${iconWidth}px`;
imageElement.style.height = `${iconHeight}px`;
linkElement.append(imageElement);
document.body.append(linkElement);
WebサイトとWeb Accessible Resourceは別オリジンになる。
CORSエラーになるため、WebページのJavaScriptからiframe内へのアクセスを防げる。
コメントには機密情報が含まれるため、iframe内で扱う必要がある。
コメントを、iframe内に置いたアイコンをhoverしたときのツールチップとして表示する。
DOMとしてツールチップを描画すると、iframeの領域をはみ出して表示できない。
ブラウザ標準のツールチップを使えば、iframeの領域をはみ出して表示できる。
iframe内のアイコンimgにtitle属性をセットすれば、ツールチップを表示できる。