[Electron] リンクをクリックすると標準Webブラウザで開く

Eletronでアプリを開発していると、ユーザーをWebブラウザに飛ばしたなるときがあります。

これ実装は非常にかんたんなのですが、最近はセキュリティの関係で描画以外の処理はメインプロセスで行う流れになってきていることもあり、今回はメインプロセスでイベントを補足して標準ブラウザで開くところまでをまとめます。

基本的な原理

イベントを捕捉する

BrowserWindow内でHTMLを描画している際に、リンクをクリックすると以下の2つのイベントが発生します。

will-navigate
リンクをクリックした直後に発生します。次の処理が開始する前に処理を挟むことができます。
new-window
target="_blank"などで新しいウィンドウを開こうとした際に発生します。

あとはこのイベントをwebContents.on()で補足して処理を挟むだけ。

const { app, BrowserWindow } = require('electron')

const win = new BrowserWindow({
  width: 800,
  height: 600
})

win.webContents.on('will-navigate', (e, url)=>{
  // リンククリック時の処理
});
win.webContents.on('new-window', (e, url)=>{
  // 新しいウィンドウを開こうとした際の処理
});

win.loadFile('index.html')

標準ブラウザを起動する

Electronのshellの機能を利用します。たったこれでGoogleを標準ブラウザで開くことができます。

const { shell } = require('electron')
shell.openExternal('https://www.google.com/')

サンプル「お肉VIEWER」

httpから始まるリンクをクリックすると標準ブラウザが立ち上がり、アプリ内部のファイルを参照する場合はそのままウィンドウが書き換わるサンプルです。

最終的なファイル

ファイル一式はGitHubへアップしています。適宜ご利用くださいませ。 github.com

メインプロセス

const { app, BrowserWindow, shell } = require('electron')
const path = require('path')

function createWindow (file='index.html') {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true
    }
  })

  // リンクをクリックするとWebブラウザで開く
  const handleUrlOpen = (e, url)=>{
    if( url.match(/^http/)){
      e.preventDefault()
      shell.openExternal(url)
    }
  }
  win.webContents.on('will-navigate', handleUrlOpen);
  win.webContents.on('new-window', handleUrlOpen);

  win.loadFile(`public/${file}`)
}

app.whenReady().then( ()=>{
  createWindow()
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

レンダラープロセス

<!DOCTYPE html>
<html>
<head>
  <meta charset=&quot;UTF-8&quot;>
  <title>Let's クリック</title>
  <meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;script-src 'self' 'unsafe-inline';&quot; />
</head>
<body>

<h1>クリックテスト</h1>

<ul>
  <li><a href=&quot;./meet.html&quot;>内部リンク(お肉)</a></li>
  <li><a href=&quot;https://www.google.com/search?q=%E3%82%B9%E3%83%86%E3%83%BC%E3%82%AD&tbm=isch&quot;>外部リンク(Google)</a></li>
</ul>

</body>
</html>

参考ページ