2
1

More than 3 years have passed since last update.

Chrome Extensions をMV3に移行しなくちゃ、ね。

Posted at

はじめに

MV3で何が変わるの、か?

Chromeオフィシャルサイトによると大まかには以下が変更点という、ことらしい。

機能の概要

  • サービスワーカーによるバックグラウンドページの置き換え。
  • ネットワークリクエストの変更は、declarativeNetRequestAPIで処理される。
  • リモートでホストされたコードは許可されず、パッケージに含まれているJavaScriptのみを実行可能。
  • 多くのメソッドにPromiseのサポートを追加。



えーっと、、とりあえずわかったふりをしつつ、、。

やってみよう

今回MV3に移行するExtensionsでは、バックグラウンド処理としてはコンテキストメニューのみ。ただ、formをDOM生成してPOST送信している。だが、DOMは扱えない、んだ。

どうするのか?

解決策としては2つ。

  1. 個人情報は扱ってなく、受信側もPOST・GET両方に対応させてるので、GET送信に変更。
  2. 新しくTabページを開いてPOST送信。


まずは、manifest.jsonの更新

manifest.json
{
-   "manifest_version": 2,
+   "manifest_version": 3,
    ...
-   "browser_action": {
+   "action": {
        "default_icon": {
            "16": "img/icon16.png",
            "32": "img/icon32.png",
            "48": "img/icon48.png",
            "128": "img/icon128.png"
        },
        "default_title": "__TITLE__",
        "default_popup": "popup.html"
    },
-   "content_scripts": [
-       {
-           "matches": [ "http://*/*", "https://*/*" ],
-           "js": [ "js/jquery-3.6.0.min.js", ... ]
-       }
-   ],
    "permissions" : [
        "activeTab",
-       "contextMenus",
+       "contextMenus"
-       "http://*/*",
-       "https://*/*"
    ],
+   "host_permissions": [
+       "http://*/*",
+       "https://*/*"
+   ],
    "background": {
-       "scripts": [ "background.js" ],
-       "persistent": false
+       "service_worker": "background.js"
    }
}

content_scriptsの理解が出来てなく、パッケージ内で使用してるjsを全て書いていたので削除しました。


バックグラウンド処理

GETで送信 に変更する場合
background.js
chrome.contextMenus.removeAll(function() {
    chrome.contextMenus.create({
        id: '__ID__',
        title: '__TITLE__',
        contexts: ['image', 'video'],
        type: 'normal'
    });
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId == '__ID__') {
-       var frm = document.createElement('form');
-       frm.setAttribute('method', 'POST');
-       frm.setAttribute('target', '_blank');
-       frm.setAttribute('action', '__URL__');
-       var req = document.createElement('input');
-       req.setAttribute('type', 'hidden');
-       req.setAttribute('name', 'img_url');
-       req.setAttribute('value', info.srcUrl);
-       frm.appendChild(req);
-       document.body.appendChild(frm);
-       frm.submit();
+       chrome.tabs.create({ url: '__URL__?img_url=' + info.srcUrl });
    }
});

GETメソッドで扱えるデータに上限があるので、今回はPOSTを選択。

POSTで送信 する場合
background.js
chrome.contextMenus.removeAll(function() {
    ...
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId == '__ID__') {
-       ...
+       postForm('__URL__', {'img_url': info.srcUrl});
+
+       function postForm(url, data) {
+           chrome.tabs.create(
+               { url: chrome.runtime.getURL('postform.html') },
+               function(tab) {
+                   var handler = function(tabId, changeInfo) {
+                       if(tabId == tab.id && changeInfo.status == "complete"){
+                           chrome.tabs.onUpdated.removeListener(handler);
+                           chrome.tabs.sendMessage(tabId, {url: url, data: data});
+                       }
+                   }
+                   chrome.tabs.onUpdated.addListener(handler);
+                   chrome.tabs.sendMessage(tab.id, {url: url, data: data});
+               }
+           );  
+       }
    }
});

新しくTabページを開き、ServiceWorkerとページ間でメッセージのやり取りが可能なので、開いたページ(postform.html)にdataを渡します。

postform.html
<html><body><script src="js/postform.js"></script></body></html>

開いたページではDOM操作が可能だが、インラインJavaScriptは書くことが出来ないので注意が必要です。

postform.js
var onMessageHandler = function(message){
  chrome.runtime.onMessage.removeListener(onMessageHandler);
  var frm = document.createElement('form');
  frm.setAttribute('method', 'post');
  frm.setAttribute('action', message.url);
  for(var key in message.data) {
    var req = document.createElement('input');
    req.setAttribute('type', 'hidden');
    req.setAttribute('name', key);
    req.setAttribute('value', message.data[key]);
    frm.appendChild(req);
  }
  document.body.appendChild(frm);
  frm.submit();
}

chrome.runtime.onMessage.addListener(onMessageHandler);

メッセージを受け取ったらformをDOM生成しPOST送信。

まとめ

バックグラウンドでDOMが扱えなくなった、んだ。どうにかDOMを扱うことは出来ないのか?、、fake-domのようなもので代替出来ないのか?、、、、試行錯誤し、、模索し、あきらめかけましたが、、新しく開いたページではDOM操作が可能という事だったので、MV2と同じ機能のままMV3に移行することが出来ました。

今回MV3に移行したChrome Extensions

2
1
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
2
1