Cordova Android で iframe 内のリンクをシステムデフォルトブラウザで開く方法
はじめに
Cordova Android で iframe 内のリンクをシステムデフォルトブラウザで開く方法。
前置きなどは 親 Window で iframe からのデータ受信、イベント検出する方法 の「前置き」と同じ。
以下はとあるプロジェクトの要件など。
- Cordova で iOS/Android まとめて開発
- コンテンツ内部は先方が作成
- コンテンツ内に先方管理外のサイトへのリンクがある
- ガワはこちらで作成して、コンテンツを
iframe
で読み込むiframe
内のリンクをシステムデフォルトブラウザで開きたいiOS は問題なかった(意図通りに動作した)が、Android だけ上手く動かなかった。具体的には、リンクをタップすると
iframe
内で開こうとするが、X-Frame-Options の設定によりnet::ERR_BLOCKED_BY_RESPONSE
となる、というもの。
TL;DR
iframe
側:postMessage
でリンク先 URL を送信- 送信後
preventDefault
で元イベント(リンク先をiframe
内で開こうとするアクション)を抑止
- 送信後
- アプリ(Cordova App)側: apache/cordova-plugin-inappbrowser でシステムデフォルトのブラウザを呼び出す
- 他ページで余計な動作をしないように注意
- 今回は Vue なので
created
,beforeDestroy
フックでイベントリスナを 追加/削除
- 今回は Vue なので
目次
環境・条件
1 | $ sw_vers |
Android 検証機: Huawei nova lite 2 (Android 9) (公式)
詳細
セットアップ
apache/cordova-plugin-inappbrowser をインストール
1 | $ cordova plugin add cordova-plugin-inappbrowser |
結論(実装サンプル)
基本的な仕組み自体は前回(親 Window で iframe からのデータ受信、イベント検出する方法)とほぼ同じ。
postMessage
でリンク先 URL を送って、アプリ(Cordova App)側で apache/cordova-plugin-inappbrowser を経由してシステムデフォルトのブラウザを呼び出す。
iframe
側
iframe
で読み込まれていたら(= window.parent
が存在していたら) postMessage
でリンク先を送信して、preventDefault
で元イベント(リンク先を iframe
内で開こうとするアクション)を抑止する。
iframe.html
1 | <a href="https://google.co.jp"> |
親(Cordova)側
Vue + Vue Router + Cordova でいつも実装しているので、サンプルコードも Vue で書く。
iframe.html
を https://example.com
から読み込む場合、メッセージハンドラ(messageHandlerFromIframe
)内で event.origin
が https://example.com
かどうかをチェック(前回と同じ)。
他ページで余計な動作をしないように、created
, beforeDestroy
フックでイベントリスナの 追加/削除 を実施。
Cordova 環境の場合のみ apache/cordova-plugin-inappbrowser を利用。
parent.vue
1 | <template> |
まとめ
iframe
側:postMessage
でリンク先 URL を送信- 送信後
preventDefault
で元イベント(リンク先をiframe
内で開こうとするアクション)を抑止
- 送信後
- アプリ(Cordova App)側: apache/cordova-plugin-inappbrowser でシステムデフォルトのブラウザを呼び出す
- 他ページで余計な動作をしないように注意
- 今回は Vue なので
created
,beforeDestroy
フックでイベントリスナを 追加/削除
- 今回は Vue なので
その他・メモ
以下記事で「config.xml
(apache/cordova-plugin-whitelist)の設定で解決した」みたいなことが書かれていたので試したが、回答時から時間が経って環境(バージョン)が変わっているせいか自分の方では上手くいかなかった。
参考文献
- window.postMessage - Web API | MDN
- Event.preventDefault() - Web API | MDN
- apache/cordova-plugin-inappbrowser: Apache Cordova Plugin inappbrowser
- インスタンスライフサイクルフック - Vue インスタンス — Vue.js
関連記事
- Cordova アプリに Twitter Timeline の埋め込み
- Cordova で Repro とカスタム URL スキームを使ってディープリンクを扱う
- Chart.js(vue-chartjs) でツールチップの表示内容を変更
- Vue.js で日本語変換での誤発火を抑止しつつ Enter キーで Submit
- Vue で子コンポーネントのメソッドをコールする
- apertureless/vue-chartjs でチャートの高さ(や幅、サイズ)を変更
- JavaScript で URL のクエリパラメータを操作する方法
- jQuery Select2 で、初期値の設定と選択状態のクリア