Shujis1964
@Shujis1964 (Shuji Sunano)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

chrome-extensionでbackgroundから開いた特定URLのTabのドキュメントを取得したいです。

解決したいこと

chrome拡張でコンテキストメニューから特定のURLを開いたときにそのURLのページの内容を取得しようとしていますが、contextMenus.onClickedが発生したときに新しくcreateしたtabへsendMessageを送ろうとしているのですが、cntent-script.js側で旨く受信できません。

chrom拡張のプログラムは初めて作成しているので殆ど未経験です。

解決方法を教えて下さい。

発生している問題・エラー

Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

該当するソースコード

※Google JavaScript スタイルガイドを参考に、コードの修正をしました。

// background.jp

const app_url = 'https://ja.wikipedia.org/wiki/';
const msg1 = 'displayWiki';

chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: 'url_open',
    title: 'TEST MENU URLをOPEN',
    type  : 'normal',
    contexts : ['page']
  });
});

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if(info.menuItemId = 'url_open'){
    console.log('url_open clicked (menuItemId=' + info.menuItemId + ')');
    let creating = chrome.tabs.create({url: app_url},(tab) => {
      chrome.tabs.sendMessage(tab.id,msg1,(responce) => {
        console.log(responce);
      });
    });
  };
});

content-script.jp

const msg1 = 'displayWiki';

console.log('content-script run');
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    let retMes = '(null)';
    console.log('called onMessage');
    console.log(sender);
    if (request.name === msg1) {
        console.log('resive displayWiki');
        retMes = 'resive displayWiki';
    };
    sendResponse(retMes);
    return true;
});


manifest.json

{
    "manifest_version": 3,
    "name": "url_jump",
    "description": "url_jump",
    "version": "1.0.0",
    "background" : {
     "service_worker" : "background.js"
    },

    "action":{},
    "permissions" : [
      "activeTab",
      "scripting",
      "storage",
      "contextMenus",
      "tabs"
    ],
    "host_permissions": [
      "https://*/*"
    ],

    "content_scripts": [
      {
        "matches": ["https://ja.wikipedia.org/*"],
        "js": ["content-script.js"]
      }
    ]
}

自分で試したこと

そもそもsendMessageを使わないと出来ないのかも判りませんが、最初は開いたURLのドキュメントオブジェクトを取得する方法が見つからず、探している内にsendMessageで実現できるような解説を幾つか見つけて試しているが旨くいかないといった情況です。
よろしくお願いします。

0

1Answer

まず、スタイルガイドを意識なさった方がよろしいかと。

どこからかコピペしてきたかのようにダブルクオート、シングルクオートが混ざり演算子間スペースが有ったり無かったり。
そういう状況ですから、ifの各所で比較演算子==の所を代入演算子=にしてしまって間違えているのです。

0Like

Comments

  1. @Shujis1964

    Questioner

    ご指摘有り難うございます。わかりやすいサイトを教えて頂き助かります。
    仰るとおり、取りあえず公表されているサンプルを持ってきて動かすところから始めましたので、凄く汚いコーディングになっていました。大変お恥ずかしい話です。
    それなりに修正はしたのですが、エラーは変わらないので、単なるタイプミスといった類いでは無いのだと思います。
    そもそもメッセージのやり取りとか、十分に理解できずに模索している状態です。
    よろしくお願いします。

  2. chrome.runtime.onMessage.addListener()が実行されるよりも前にchrome.tabs.sendMessage()が先走っている(早すぎる)から「Could not establish connection.」と言われ、自らメッセージを送信できない状態にしてるのです。

    コピーなさったサンプルコードを掲載していたページではchrome.contextMenus.onClicked.addListener()内部でsendMessage()していましたか?
    恐らくそのような書き方していないと思われるので、そちらよく確認なさってください。

  3. @Shujis1964

    Questioner

    有り難うございます。非同期の処理になれていないと言うことなのでしょうけど、
    参考にしたのは
    https://teratail.com/questions/137046
    でして、今回は右クリックからメニュー選択で対象URLを開くようにしているので、結果的にchrome.contextMenus.onClicked.addListener()の内部に参考例のsendMessage()を入れる事になったのですが、それが良くないと言うことなのでしょうか。
    この場合、sendMessage()は何処に持って行けば良いのでしょう。

  4. 日付もよく確認して下さい。とても古い情報です。
    manifest_version2であなたのは3です。2何れ使えなくなる手法です。

    上記に参考リンクを貼りましたが、そちら確認していますか?
    さもなければ次のコードを理解することができません。
    日本語で解説してるところもあるはずなので探してみて下さい。

    background.js
    chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
      if (changeInfo.status === chrome.tabs.TabStatus.COMPLETE && tab.url.startsWith('http')) {
        chrome.tabs.sendMessage(tabId, "displayWiki").catch((error) => {
          console.error(error);
        });
      }
    });
    

    chrome.tabs.onUpdated.addListener()を使ってタブステータスが完了chrome.tabs.TabStatus.COMPLETEしたならsendMessageする手法になります。

    これであればcontent-script.jsを先に解釈するので送信可能です。

    非同期処理になれてないと言うことですが、この先も必ずつきまとう問題ですから、自己学習なさってください。ここではその点についてふれません。

  5. @Shujis1964

    Questioner

    onUpdatedを使ってそこでCOMPLETEを確認出来たらtabの情報を得ることが出来ました。

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
      if (tab.status === 'complete') {
        console.log('tab complete');
        console.log(tab.title);
      }
    });
    

    開いたtabの情報を得るのが目的だったので、これで大丈夫です。sendMessageもする必要が無かったです。

    助かりました。

Your answer might help someone💌