(とりわけ)トランザクションに署名する電子暗号アプリがあります。

他のWebサイトには、その電子アプリを開くボタンがあり、いくつかのパラメーター(トランザクション情報)が事前に入力されている必要があります。

フローは次のとおりです。

  1. ユーザーがsome-crypto-site.comで「取引を行う」をクリックします
  2. 電子アプリは事前に入力されたパラメータで開きます
  3. ユーザーがelectronアプリで[トランザクションに署名]をクリックします
  4. 電子アプリは舞台裏で何かをします
  5. 電子アプリが閉じて、some-crypto-site.comにメッセージを送信します

これは、実行時またはインストール時に実行できます。

私が試したこと(Linux、Chrome)

この要点app.setAsDefaultProtocolClientのコードで呼び出します。これは基本的に次のとおりです。

app.setAsDefaultProtocolClient("my-app")

しかしmy-app://foo?bar=baz、Chromeブラウザーに入れた後、次のポップアップが表示され、open-xdgを押しても何も起こりません(ポップアップを閉じる以外は)

ここに画像の説明を入力してください

調べた

  1. アプリ内プロトコルのみを処理するように見える電子プロトコルAPI
  2. webtorrent .desktop fileこれが進むべき道かもしれませんが、どうすればよいかわかりません。

たぶん、電子ビルダーを介してインストール時にそうする方法がありますか?

助けてくれてありがとう、私はここでどのように進めるのか分かりません!

役立つかもしれないリソース

  1. mac+windowの例を使用したgithubリポジトリ
  2. Linux用のgithubコメント
  3. Linux2のgithubコメント
  4. 3つのOSすべてに答える
  5. SOウィンドウの答え
  6. Windows登録用のnpmパッケージ
  7. SOマックの答え
  8. SOLinuxの回答
  9. Windows用のMicrosoftドキュメント
  10. Windowsの記事
  11. Windows用のgithubコメント
  12. Mac用のgithubコメント
  13. info.plst for mac
  14. Mac用の古いリポジトリと勝利
応答

これは私が仕事でしていることに関連しているかもしれないので、私はそれをやってみることにしました。私はこれをOSXでしかテストしていません!

app.setAsDefaultProtocolClientのドキュメントを調べたところ、次のようになっています。

Note: On macOS, you can only register protocols that have been added to your app's info.plist, which can not be modified at runtime. You can however change the file with a simple text editor or script during build time. Please refer to Apple's documentation for details.

これらのプロトコルは、アプリをでパッケージ化するときに定義できますelectron-builder参照してくださいbuild

{
  "name": "foobar",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "dist": "electron-builder"
  },
  "devDependencies": {
    "electron": "^3.0.7",
    "electron-builder": "^20.38.2"
  },
  "dependencies": {},
  "build": {
    "appId": "foobar.id",
    "mac": {
      "category": "foo.bar.category"
    },
    "protocols": {
      "name": "foobar-protocol",
      "schemes": [
        "foobar"
      ]
    }
  }
}

メインスレッド:

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

let mainWindow;

function createWindow () {
  mainWindow = new BrowserWindow({width: 800, height: 600})
  mainWindow.loadFile('index.html');
}

app.on('ready', createWindow);

var link;

// This will catch clicks on links such as <a href="foobar://abc=1">open in foobar</a>
app.on('open-url', function (event, data) {
  event.preventDefault();
  link = data;
});

app.setAsDefaultProtocolClient('foobar');

// Export so you can access it from the renderer thread
module.exports.getLink = () => link;

レンダラースレッド:

メインスレッドでエクスポートされた関数にアクセスするためのリモートAPIの使用に注意してくださいgetLink

<!DOCTYPE html>
<html>
  <body>
    <p>Received this data <input id="data"/></p>
    <script>
      const {getLink} = require('electron').remote.require('./main.js');
      document.querySelector('#data').value = getLink();
    </script>
  </body>
</html>

<a href="foobar://abc=1">open in foobar</a>

ここに画像の説明を入力してください

これにより、コマンドラインから起動することもできます。

open "foobar://xyz=1"

ここに画像の説明を入力してください

どのようにして元の発信者に戻りますか?

アプリを起動するときに、発信者のURLを含めることができると思います。

<a href="foobar://abc=1&caller=example.com”>open in foobar</a>

電子アプリがデータの処理を終了すると、そのURLにpingを返すだけです。

クレジット

私の調査結果のほとんどは以下に基づいています:

上記とは少し異なります。

open-urlはreadyイベントの前に起動するため、変数に格納して未亡人のdid-finish-load内で使用できます。

let link;

let mainWindow;

function createWindow() {
    mainWindow = new BrowserWindow({
        width: 1280,
        height: 720,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    });
    mainWindow.openDevTools();
    mainWindow.setContentProtection(true);
    mainWindow.loadFile('index.html');
    mainWindow.webContents.on("did-finish-load", function() {
        mainWindow.webContents.send('link', link);
    });
}

app.on('ready', createWindow);

// This will catch clicks on links such as <a href="protocols://abc=1">open in foobar</a>
app.on('open-url', function(event, url) {
    link = url;
    if (mainWindow?.webContents) {
        mainWindow.webContents.send('link', link);
    }
});

app.setAsDefaultProtocolClient('protocols');

次に、このようにレンダリングhtmlの値を使用できます。

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <script>
            const ipc = require("electron").ipcRenderer;
            ipc.on("link", function (event, url) {
                console.log(url);
                console.log(parseQuery(decodeURI(url)));
            });
            function parseQuery(queryString) {
                queryString = queryString.substring(queryString.indexOf("://") + 3);
                var query = {};
                var pairs = (queryString[0] === "?" ? queryString.substr(1) : queryString).split("&");
                for (var i = 0; i < pairs.length; i++) {
                    var pair = pairs[i].split("=");
                    query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
                }
                return query;
            }
        </script>
    </body>
</html>