リンクをブラウザ機能で開いた場合window.openerはnullになる

代案は`localStorage`・`WebSocket`・強制を検討。

# 一応の結論

同一オリジンなら`localStorage`を`window.postMessage`代わりに使うのがお手軽。
おそらく個人開発規模で複数ドメインを手がけることも少ないと思われるので、一旦最有力としておきます。

# 扱わないこと

`target="_blank"`は危険だよ！
という`noopener`周りの話

[リンクを作る時の target="_blank" の危険性 - 隙あらば寝る](https://yoru9zine.hatenablog.com/entry/2017/03/17/230729)

>まとめ
>
自分の管理下にあるサイトであればリスクはかなり低いと思われる。
>
一方で外部へのリンクをtarget="_blank" で作成している場合は対策を行っておいたほうが良い。
(後略)

* [target="_blank"には気をつけよう - Qiita](https://qiita.com/Apprentice_engineer/items/5db19a6d9bd4e7978aec)
* [target="_blank" で開くリンクには rel="noopener" をつける - Qiita](https://qiita.com/memolog/items/9913b0067e4e6883ed17)
* [Firefox security: rel=noopener for target=_blank - gHacks Tech News](https://www.ghacks.net/2018/11/30/firefox-security-relnoopener-for-target_blank/)


# あらまし

`<a target="_blank">`(や`window.open`)
なクリックすることで別タブ(window)で開くリンク先で`window.opener`を使ったリンク元との通信・連携を記述していた。
しかし、マウスの中央ボタンクリックや右クリックメニューの`リンクを新しいタブで開く`によるopenでは`window.opener`がnullになってしまう。

`window.opener`に依存しない連携の必要を検討しなければならなかった。

もともと使おうとしていた機能は`window.postMessage`なのでクロスオリジンにも一応留意する。


右クリックはともかくバックエンドでタブを開く中央ボタンクリックは`<a target="_blank">`の有無関係なしに多用する機能なので、左クリックを強制されると使用感が損なわれる。※個人の感想です‘

***

という検討を机上の空論で行います。

# 環境

Firefox 68.0.1

# 二つの代案の共通問題点

以下に書く代案での問題として、ページ間の親子関係がないことがあげられる。
`window.opener`がnullだからしかたないのだが、親ページを複数開いていた場合にはリンクをクリックした親ページ以外の各ページで反応してしまうと思われる。
(ページごとにランダム生成したユニークな値をリンク先のgetパラメーターに含めるとか無理やりな考えもできないくもなさそうだけど捨て置く)

あくまで
親ページは子ページを開く役割を自覚している。
子ページも親ページから開かれることを自覚している。
という前提でスクリプトを書く。
だからどちらかといえば一般的なページではなくローカルな自作HTMLやユーザースクリプトとして書いている場合の話です。

(ついでにiframeを使った力業も考慮しません。)

# `localStorage`を使う

`window.postMessage`によるイベント駆動の代案として`localStorage`が考えられる。

[Web Storage API を使用する - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API)

`localStorage`には`StorageEvent`が用意されているので、子ページでStorageに書き込むことでメッセージ送信かのように扱うことができる。

`localStorage`を使った似たような問題解決の手法として
`localStorage`をポーリングで監視する手法が紹介されていたが、
[window.openerがiOS版Chromeで使えない問題に対処するには？](http://www.site-convert.com/archives/822)
一瞥したかぎりではイベントのほうがよさそうに思える。

実際に組んだことがないので実用上の問題があるのか、記事が2016年のものなので機能がなかったのかは不明。

## 問題点

### ゴミが残る。
`localStorage`はデータ永続用のStorageなので通信用の使い終わった値が掃除しない限りは残ってしまう。
もちろん`Storage.removeItem()`は用意されているので変更を検知したらつど削除でもよい。

永続として不要なデータが残るor毎回掃除している
ということが感覚的に気持ち悪い場合は採用しにくいか？

なお、自動的に削除される`sessionStorage`には変更イベントは用意されていない。ページ(session)単位のStorageなので致し方ない。

### クロスオリジンできない

Web Storage APIはあくまでドメインごとのStorageを提供する機能なので別ドメインでのStorage操作を検知することはできない。
`window.postMessage`は安全にクロスドメイン通信を可能にすることがウリのひとつなので、そのために使っていた場合は代案になりえない。

# `WebSocket`を使う

**君なんでも`WebSocket`使うよね**
まーまー通信という意味ではお手軽です。
双方向通信機能を使ってやりとりが出来ない理由がないです。
同様にクロスオリジンの問題もなし。

## 問題点

`WebSocket`そのものの話ですが

### サーバーが必要

なのだが、個人利用では
[手元にサーバー不要でWebSocket Client間で通信できるフリーサーバー Achex, Websocket.in が便利そう - Qiita](https://qiita.com/khsk/items/113a2781881ac2e480c0)
で回避するのでまあまあ。

あとページがセキュアならそこも面倒に。片方だけhttpsで引っかかるなんてことも万が一あるかも。

[FirefoxでhttpsからWebSocket接続(ws)するにはnetwork.websocket.allowInsecureFromHTTPS - Qiita](https://qiita.com/khsk/items/87a60b1e425f871bf71a)


### 接続管理が必要

信頼性は体感高いものの、絶対connectionできる、接続が維持され続けるといえるものではないのである程度管理用にコード量が増加すると思われる。

これも個人利用ならまあ杜撰でも許容範囲ですが。

# 左クリックを強制させる

`window.opener`を担保したい方向。
ユーザーに不便を押し付ける形に。
`a`要素を使わずにすべてクリックイベントで`window.open`にされたら一般ユーザーにはなかなか手出しは難しいと思います。

`a`要素を使っても左クリック以外をイベントでキャンセルしちゃえば。なつかしの右クリック禁止ですね。

それらをかいくぐるならもう多少の不都合はユーザーの責任ですし。

問題はそれらの手法がとても私の好みではないということと、
利用者=自分なのでただただ自分が不便になるだけという悲しみ。