92130
### 全体のやりたいこと

サイト内の通知でフィッシングサイトに遷移してしまうのを抑制するために、サイト内で通知が検知された場合はNotification
apiを用いた通知のtitleとbodyの内容、遷移先のurlを取得して、ブラックリスト(.json)と照合して一致した際は通知の処理をオーバーライド、不一致の際はそのまま表示させたい。

### 質問したいこと

サイト内でNotification API
で実装されたものとブラウザ拡張がJavaScriptで同名のメソッドを定義したら後で定義したものに上書きされることは分かったのですが、サイト内で実装された方の
title と body をブラウザ拡張で実装したNotificationで拾うことが出来ません。

### 有識者とやり取りをする機会があったときに言っていたこと

・引数をコピーする必要はありません．元のメソッドに  
渡されるはずの引数は，同名のメソッド呼び出しにそのまま渡されます．  
・あるWebページを読み込んだ際に，ブラウザ拡張が js を挿入し，  
挿入した js には Notification() が定義されています．  
そのWebページに Notification オブジェクトが作成された際には，  
挿入した Notification() が呼び出されるようになります．  
・ですので，Webページのロードが完了した段階で Notification() が  
呼び出されると，挿入した方の Notification() が実行されます．  
その処理の中で，引数で渡された title と body を取得します．

サイト内で実装してあるnotification.js

```

      function showNotification() {
        const notify = new Notification("Hi there", {
          body: "通知のテストです。",
          icon: "assets/notifications.png"
        });
    
        notify.onclick = (e) => {
          //window.location.href = "https://github.com/"; //ページをリダイレクトさせる
          window.open('https://github.com/', '_blank');   //別タブで開く
        };
      }
    
```

ブラウザ拡張のcontent.js

```

    Notification = (function(Notification) {
      console.log("point-0")
      function MyNotification(...args) {
        console.log("point-1")
        console.log("title: ", args[0]);
        console.log("body: ", args[1].body);
        console.log("icon: ", args[1].icon);
      };
      console.log("point-2")
      Object.assign(MyNotification, Notification);
      MyNotification.prototype = Notification.prototype;
      return MyNotification;
    })(Notification);
    
```

manifest.json

```

    {
      "name": "Blocking phishing sites",
      "description": "Control method for web push notification by browser extension",
      "version": "1.0",
      "manifest_version": 2,
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["js/content.js"]
        }
      ],
      "permissions": [
        "*://*/*",
        "tabs",
        "webRequest",
        "webRequestBlocking",
        "webNavigation"
      ]
    }
    
```

これで動かしたところconsole.logには何も表示されませんでした。

前述の通り、

> ・引数をコピーする必要はありません．元のメソッドに  
>  渡されるはずの引数は，同名のメソッド呼び出しにそのまま渡されます．

と言っていたのでnotification.jsのtitleやbodyの部分がcontent.jsのargs[0]とargs[1].bodyに渡されると思っていたのですが。  
通知を一旦取得した後に、title,bodyとurlはブラックリストと比較したいのでどこかで変数に代入できればと思っています。（変数に代入しなくても比較できるならそれでも可）

お時間あるときにご回答いただければ幸いです。
CC BY-SA 4.0
2022-11-09T03:43:00.563
92099
2022-11-10T16:28:37.570
2022-11-10T16:28:37.570
3060
55256
question
javascript google-chrome chrome-extension
ブラウザ拡張でサイト内で実装されたJavaScriptを上書きしたい
ブラウザ拡張のコンテンツスクリプトは「[Work in isolated
worlds](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#isolated_world)」ということで、グーバル変数などを共有していません。ですので、対象のページと同じ環境で動かすコードは何らかの手段で、対象のページに挿入する必要が有ります。

### コードを挿入する処理の例

参考: <https://stackoverflow.com/questions/9515704/access-variables-and-
functions-defined-in-page-context-using-a-content-script>

`js/content.js`:  
このファイルに、対象のページに挿入したいコードが書かれているものとします。内容は省略。

`js/inject.js`:  
コンテンツスクリプトとして実行され、対象のページに `js/content.js`
を挿入します。下のコード例は実行のタイミング（`manifest.json` の `run_at` など）により、`html`
要素の直下に挿入されるダーティーな物です。`MutationObserver` などを使って洗練してもよいでしょう。

```

    console.log("-- inject script --");
    const script = document.createElement("script");
    script.src = chrome.runtime.getURL("js/content.js");
    (document.head || document.documentElement).insertAdjacentElement("afterbegin", script);
    
```

`manifest.json`:

マニフェストのバージョンが 2 の場合は `"web_accessible_resources": ["js/content.js"],` とします。

```

    {
        "manifest_version": 3,
        "name": "Notify Wrapper",
        "description": "Replace the global variable `Notification` with a wrapper object.",
        "version": "0.1",
        "web_accessible_resources": [
            {
                "resources": ["js/content.js"],
                "matches": ["https://ja.stackoverflow.com/*"]
            }
        ],
        "content_scripts": [
            {
                "matches": ["https://ja.stackoverflow.com/*"],
                "run_at": "document_start",
                "js": ["js/inject.js"]
            }
        ]
    }
    
```
CC BY-SA 4.0
2022-11-10T08:55:13.847
92130
2022-11-10T08:55:13.847
3054
92099
answer