📘

Webアプリでユーザー切り替えを簡単にするChrome拡張機能を作った

2024/07/05に公開

はじめに

  • Webアプリを手動テストする際、複数ユーザーを操作する必要があり、ログイン/ログアウトが手間でした。
  • Chrome拡張機能でセッションを切り替えれば、ログイン/ログアウトの手間を省けることに気づきました。
  • 既存のChrome拡張機能もあるようですが、拡張機能のインストールにはリスクがあるため、今回は自作しました。

注意事項

  • この記事の内容は、作成者の環境で動作確認していません。
    • 誤りがあれば、ご指摘いただけると幸いです。
  • ソースコードを利用する際は、内容を理解して使用してください。拡張機能は悪用される可能性もあるため、理解していないものをインストールしないでください。
  • ソースコードの使用によって生じた不利益については責任を負いません。
  • 今回のソースコードは localStorage と cookie のみを取得しています。sessionStorage など他の情報が必要な場合はソースコードを修正してください。
  • 登録したトークン等の有効期限が切れると使用できなくなります。

ソースコード

manifest.json
{
  "manifest_version": 3,
  "name": "SwitchSession",
  "version": "1.0",
  "description": "",
  "permissions": [
    "activeTab",
    "storage",
    "cookies",
    "scripting"
  ],
  "host_permissions": [
    "https://*/*"
  ],
  "action": {
    "default_title": "popup",
    "default_popup": "popup.html"
  }
}
popup.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
</head>
<body style="width: 500px;">
  <select id="select"></select>
  <button id="switch">切り替え</button>
  <button id="delete">削除</button>

  <div style="margin-top: 2em;">
    <input type="text" id="name">
    <button id="set">登録</button>
  </div>

  <script src="popup.js"></script>
</body>
</html>
popup.js
const selectDom = document.getElementById('select')
const nameInputDom = document.getElementById('name')
let currentTab
let sessions = {}

const displaySelectSessions = () => {
  selectDom.innerHTML = ''
  let html = ''
  Object.keys(sessions).forEach((key) => {
    html += `
      <option value="${key}">
        ${key}
      </option>
    `
  })

  selectDom.insertAdjacentHTML('beforeend', html)
}

const setSession = async (session, name) => {
  sessions = {
    ...sessions,
    [name]: session
  }
  await chrome.storage.local.set({sessions})
}

const loadSessionByCurrentTab = async () => {
  const [{result}] = await chrome.scripting.executeScript(
    {
      target: {tabId: currentTab.id},
      function: () => {
        let localStorageData = {}
        for (let index = 0; index < localStorage.length; index++) {
          const key = localStorage.key(index)
          const value = localStorage.getItem(key)
          localStorageData = {
            ...localStorageData,
            [key]: value
          }
        }

        return {
          localStorage: localStorageData,
          cookie: document.cookie
        }
      }
    }
  )
  return result
}

const switchSessionByCurrentTab = async (session) => {
  await chrome.scripting.executeScript(
    {
      target: {tabId: currentTab},
      function: (session) => {
        localStorage.clear()
        Object.keys(session.localStorage).forEach((key) => {
          localStorage.setItem(key, session.localStorage[key])
        })

        document.cookie = ''
        session.cookie.split(';').forEach((cookie) => {
          document.cookie = `${cookie}; path=/; secure`
        })
      },
      args: [session]
    }
  )
}

document.getElementById('set').addEventListener('click', async () => {
  const name = nameInputDom.value
  nameInputDom.value = ''
  const session = await loadSessionByCurrentTab()
  await setSession(session, name)
  displaySelectSessions()
})

document.getElementById('delete').addEventListener('click', async () => {
  const key = selectDom.options[selectDom.selectedIndex].value
  delete sessions[key]

  await chrome.storage.local.set({sessions})
  displaySelectSessions()
})

document.getElementById('switch').addEventListener('click', async () => {
  const key = selectDom.options[selectDom.selectedIndex].value
  await switchSessionByCurrentTab(sessions[key])
  await chrome.tabs.update({url: new URL(currentTab.url).origin}) // ここではドメインを開いていますが、リロードのほうが良いかもしれません
})

document.addEventListener('DOMContentLoaded', async () => {
  const items = await chrome.storage.local.get(['sessions'])
  sessions = items.sessions ?? {}
  displaySelectSessions()

  const [tab] = await chrome.tabs.query({active: true, currentWindow: true})
  currentTab = tab
})

使い方

拡張機能の読み込み

  1. chrome://extensions/ にアクセスし、デベロッパーモードをONにする
  2. パッケージ化されていない拡張機能を読み込む 押下
  3. ソースコードを格納したフォルダを選択
  4. 読み込まれた拡張機能の 詳細 ボタン押下
  5. ツールバーに固定する をONにする

セッションの登録

  1. セッションを登録したいサイトを開き、登録したいユーザーでログインする
  2. ツールバーに表示されている読み込んだ拡張機能のアイコン押下
  3. テキストボックスにユニークな文字列を入力
    ※ユニークでない場合、登録内容が上書きされます。
    ※エラーハンドリング/バリデーションは行っていません。
  4. 登録ボタン押下

セッションの切り替え

  1. ログインしたいサイトを開く
  2. ツールバーに表示されている読み込んだ拡張機能のアイコン押下
  3. プルダウンから登録しているセッションを選択
  4. 切り替えボタン押下

セッションの削除

  1. ツールバーに表示されている読み込んだ拡張機能のアイコン押下
  2. プルダウンから登録しているセッションを選択
  3. 削除ボタン押下

Discussion