0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Browser Extension で storage を使う

0
Last updated at Posted at 2025-05-26

目的

Chrome Extension の HelloWorld のような簡単なプログラムで storage からのデータ取得をテストします。

Chrome Extension のファイル構成

browser-extension-storage/
│-- manifest.jsoon ....... Browser Extensionの設定ファイル
│-- content_scripts.js ... HTMLページで実行するMainプログラム
│-- options.js ..... Storage の変更をするプログラム
│-- options.html ... Storage の変更をするためのUI
│-- constants.js ... Storage に保管する変数処理のプログラム

それぞれのファイル内容の説明は、後で説明をしますがここでは manifest.json の内容を記載します。

manifest.json
{
  "manifest_version": 3,
  "name": "Hello World Storage Extension",
  "version": "2025.5.25",
  "description": "Hello World Storage Extension.",
   "content_scripts": [
    {
        "matches": ["https://qiita.com/*"],
        "js": ["content_scripts.js"]
    }
  ],
  "web_accessible_resources": [
    {
        "matches": ["https://qiita.com/*"],
        "resources": ["constants.js"]
    }
  ],
  "options_page": "options.html",
  "permissions": ["storage"]
}

Main ページを動作させるのに content_scripts を指定し、storage 処理をするためにpermissionが必要になります。

即時実行関数式

storage から取得したデータを使用するのに、取得を待つ(await)ので、即時実行関数で async処理をさせます。

content_scripts.js の以下の部分

content_scripts.js
var constants = "";
(async () => {
  console.log("Content script initializing...");
  constants = await import(chrome.runtime.getURL("constants.js"));
  await constants.init();
  console.log("Message from constants.getMessage() : " + constants.getMessage());
})();

動的インポート

上のコードで使用されていますが、content_scripts.js では import が使用できないので、動的importでの処理になっています。constants.jsに役割を分けるために使用しました。manifest.json の "web_accessible_resources" を指定する必要があります。

オプションページ

Storage への変数保管や変更にBrowser Extensionの options_page を使用します。manifest.json に指定します。

options.js
/*
 * Local variables 
 */
import * as constants from "./constants.js";   
var message;

/*
 * Code executed when js is loaded.
 * Load timing is defined in the html.
 */
(async () => {
  console.log("Options js initializing...");
  await constants.init();

  message = document.getElementById("message");
  message.value = constants.getMessage();

  message.addEventListener("change", () => {
    constants.setMessageToStorage(message.value);
  });

})();

動的import の必要はない事、options.jsの初期化の処理がoptions.htmlの読み込み状況に依存する場合にはHTMLの記述とあわせて調整します。今回は処理するHTMLの記述の後にscriptを書きました。これ以外だと

  • scriptでdefer <script type="module" src="options.js" defer></script>
  • js 側で document.addEventListener("DOMContentLoaded, () => {...

とする様です。

options.html
<!DOCTYPE html>
<html>
<head>
  <title>Hello World Storage Extension Options</title>
</head>
<body>
  <h1>Hello World Storage Extension Options</h1>
  <label for="message">Message</label>
  <input type="text" id="message">
  <script type="module" src="options.js"></script>
  <hr />
  <br />
  The changes will be automatically saved.
</body>
</html>

変数用スクリプト

変数を管理するスクリプトを作成して、管理がいろいろなソースコードに分散しないように考慮します。気をつけた点は

  • Setter, Getterを用意する
  • Storageからの Getter は asyncにして取得待ちができるようにする

です。以下のようなコードになりました。関数は export しましたが、制限をしてもいいかもしれません。

constants.js
/*
 * Constants and variables of Chrome extension
 */
const DEFAULT_message="Hello World";
var message=DEFAULT_message;

/*
 * Funtion to initialize variables
 */
export async function init() {
    message = await getMessageFromStorage() || DEFAULT_message;
    console.log("constants.init message : " + message);
}

/*
 * Setter of message. async is not required.
 */
export function setMessageToStorage(msg) {
    message = msg;
    chrome.storage.local.set({ "message" : msg }, () => {
        console.log("constants.setMessageToStorage message : " + msg)
    });
}

export function setMessage(msg) {
    message = msg;
}

/*
 * Getter of message. async is required to gete from the storage. 
 */
export async function getMessageFromStorage() {
    return new Promise((resolve) => {
        chrome.storage.local.get("message", (result) => {
            console.log("constants.getMessageFromStorage message : " + result.message);
            resolve(result.message);
        });
    });
}

export function getMessage() {
    return message;
}

Storage変更の検知

Browser Extensionの再起動をしなくてもStorage変更後の値でどうさするように content_scripts.jsを更新します。以下のような Event Listenerを記載しました。

content_scripts.js
chrome.storage.onChanged.addListener((changes, areaName) => {
    console.log(`Storage area "${areaName}" changed.`);
    for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
        console.log(`Key "${key}" changed from "${oldValue}" to "${newValue}".`);
    }
    (async () => {
        await constants.init();
        console.log("Message from constants.getMessage() : " + constants.getMessage());
    })();
});

検知した値をデバッグ目的で出力し、そのままの値は使用せずに constants の初期化をすることでデータを更新するようにしました。

サンプルの実行結果

初期化時の BrowserのF12で確認できるコンソール

image.png

オプションページから更新したときのF12コンソール

image.png

Storage からのデータを取得して、動作できているのが確認できます。

まとめ

Browser Extensionを構成するファイルとその内容を説明しました。コードを各際には各処理とファイルの連携を考慮するので1つのファイルのみの処理のみを考えることはないです。動作するサンプルをもとに自分のアプリケーションでの処理を考えることになるかと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?