Electron: Comment ouvrir une URL à partir <a>du navigateur du système d'exploitation par défaut ?</a>

Créé le 1 avr. 2015  ·  26Commentaires  ·  Source: electron/electron

Commentaire le plus utile

J'ai trouvé cet extrait de code sur SO :

    var shell = require('electron').shell;
    //open links externally by default
    $(document).on('click', 'a[href^="http"]', function(event) {
        event.preventDefault();
        shell.openExternal(this.href);
    });

Je l'ai déposé dans mon fichier d'index principal, il semble fonctionner pour autant que je sache, même pour les liens générés dynamiquement. Je suis trop novice en électrons pour savoir s'il y a des inconvénients à ce que je devrais surveiller. Les pensées?

Tous les 26 commentaires

Sur ma configuration, j'ai essayé à la fois shell.openExternal('http://example.com') et shell.openItem('http://example.com') et les deux ont ouvert le site Web en arrière-plan.

J'ai fini par utiliser child_process.execSync('start http://example.com') sur Win32 et child_process.execSync('open http://example.com') sur Darwin afin que le navigateur s'affiche et se concentre.

Sous Linux, vous pouvez utiliser xdg-open :
child_process.execSync('xdg-open http://example.com')

J'ai en fait décidé d'utiliser node-open . Vous devriez essayer si vous ne voulez pas vous embêter avec l'évasion et ainsi de suite.

Les gars, mais vos solutions sont excellentes, mais je me demande comment intercepter la tentative d'ouverture d'une URL telle que " http://someurl.com ", puis l'ouvrir avec shell.openExternal ? Le service worker permet de n'attraper que les requêtes vers les fichiers sur le même domaine. Existe-t-il la possibilité de le faire ? /cc @maxogden @AlicanC

Même question ici que @havenchyk , existe-t-il un moyen de dire à electron d'ouvrir des liens externes par défaut?

Si votre application n'utilise qu'une seule fenêtre et que vous pouvez garantir que chaque lien externe de votre application s'ouvre dans une nouvelle fenêtre (via par exemple target="_blank" ), vous pouvez faire quelque chose comme :

webContents.on('new-window', function(event, url){
  event.preventDefault();
  open(url);
});

webContents est le contenu web de votre BrowserWindow principal et open est une fonction qui ouvre l'url dans votre navigateur (j'utilise node-open comme recommandé par AlicanC).

Ce serait bien s'il y avait un événement déclenché lorsque _n'importe quel_ lien est cliqué, afin que l'application puisse décider si elle doit s'ouvrir dans le navigateur, mais je n'ai pas trouvé un tel événement s'il existe.

J'ai trouvé cet extrait de code sur SO :

    var shell = require('electron').shell;
    //open links externally by default
    $(document).on('click', 'a[href^="http"]', function(event) {
        event.preventDefault();
        shell.openExternal(this.href);
    });

Je l'ai déposé dans mon fichier d'index principal, il semble fonctionner pour autant que je sache, même pour les liens générés dynamiquement. Je suis trop novice en électrons pour savoir s'il y a des inconvénients à ce que je devrais surveiller. Les pensées?

J'utilise ce bout de code :

var handleRedirect = (e, url) => {
  if(url != webContents.getURL()) {
    e.preventDefault()
    require('electron').shell.openExternal(url)
  }
}

webContents.on('will-navigate', handleRedirect)
webContents.on('new-window', handleRedirect)

Déclarez d'abord un processus de spawn

`app.controller('GuideCtrl', ['$scope', ($scope)=>{
const spawn = require('child_process').spawn;

  $scope.openBrowser=(url)=>{
     let exec = spawn('explore', [url], {});
     exec.stdout.on('data', (data)=> {
        console.log('stdout: ' + data)
     });
  }

}])`

et avant d'appeler la méthode

<a ng-click="openBrowser('https://google.com')">Goto google</a>

shell.openExternal a-t-il des problèmes de sécurité ? Par exemple, si des liens sortent du réseau, les données réseau brutes sont transmises à shell.openExternal ou à l'une des autres fonctions ci-dessus. Est-ce que shell.openExternal s'assure que rien de mal n'arrive ? Dois-je filtrer les schémas ?

Sur la base du code de @rubencodes , j'ai utilisé :

const shell = require('electron').shell; $('.open-in-browser').click((event) => { event.preventDefault(); shell.openExternal(event.target.href); });

Ensuite, il vous suffit de déposer la classe 'open-in-browser' pour chaque élément que vous souhaitez ouvrir dans le navigateur.

En voici un qui ne nécessite pas JQuery, au cas où quelqu'un d'autre le rechercherait. Il ouvrira automatiquement tout lien commençant par 'http' dans le navigateur externe.

Mettez ceci dans votre processus de rendu :

// Open all links in external browser
let shell = require('electron').shell
document.addEventListener('click', function (event) {
  if (event.target.tagName === 'A' && event.target.href.startsWith('http')) {
    event.preventDefault()
    shell.openExternal(event.target.href)
  }
})

Si vous voulez que TOUTES les balises <a> s'ouvrent dans le navigateur par défaut, essayez ceci dans votre main.ts :

const shell = require('electron').shell;

mainWin.webContents.on('will-navigate', (event, url) => {
  event.preventDefault()
  shell.openExternal(url)
});

Cela suppose que vous ayez une application d'une seule page comme moi. Sinon, vous devrez faire un peu plus de désinfection.

Je veux juste réitérer que l'utiliser avec du contenu utilisateur sans liste blanche est probablement une faille de sécurité béante. Je ne sais pas ce que font tous les différents schémas et quelles sont leurs entrées, mais juste à titre d'exemple simple, un lien comme celui-ci

 <a href="imessage:hello">click me</a>

Invitera l'utilisateur dans Chrome et Safari sur macOS, mais avec le code ci-dessus, Electron ouvrira simplement l'application.

On a presque l'impression qu'Electron lui-même devrait par défaut être plus sécurisé ici plutôt que de laisser à chaque programmeur le soin de déterminer comment le sécuriser par lui-même.

Au minimum, vous voulez probablement quelque chose comme

function isSafeishURL(url) {
  return url.startsWith('http:') || url.startsWith('https:');
}

mainWin.webContents.on('will-navigate', (event, url) => {
  event.preventDefault();
  if (isSafeishURL(url)) {
    shell.openExternal(url);
  }
});

@greggman Voir le type d'autorisation externe ouvert dans https://electronjs.org/docs/api/session#sessetpermissionrequesthandlerhandler

Vous pouvez les bloquer

Salut, j'utilise vue.js et je résous ce problème en m'inspirant de la discussion ci-dessus, au cas où quelqu'un comme moi utilisant vue aurait également le même problème, je colle mon code ici.

<template>
<div class="board-item" v-for="element in list" :key="element.id">
<span><a class='board-item-a' :href='element.url' target='_blank'>{{element.title}}</a></span>
</div>
</template>

<script>
mounted () {
this.$el.querySelectorAll('.board-item-a').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault()
require('electron').shell.openExternal(e.target.href)
})
})
},
</script>

Basé sur le commentaire de @alangrainger - ts version :

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

...
mainWindow.webContents.on('new-window', function(event, url){
   event.preventDefault();
   shell.openExternal(url);
});

Qu'en est-il des URL de données ?

Version angulaire 7 (avec rechargements en direct) :

        const openExternalLinksInOSBrowser = (event, url) => {
            if (url.match(/.*localhost.*/gi) === null && (url.startsWith('http:') || url.startsWith('https:'))) {
                event.preventDefault();
                shell.openExternal(url);
            }
        };
        win.webContents.on('new-window', openExternalLinksInOSBrowser);
        win.webContents.on('will-navigate', openExternalLinksInOSBrowser);

La partie url.match(/.*localhost.*/gi) === null est nécessaire car sinon, lorsque vous modifiez quelque chose dans votre application angulaire, une nouvelle fenêtre/un nouvel onglet s'ouvrira dans le navigateur de votre système d'exploitation au lieu de le recharger dans l'application électronique.

Toutes les méthodes fonctionnent correctement, mais uniquement sur les applications électroniques non root, que puis-je utiliser pour ouvrir une URL externe sur le navigateur du système d'exploitation par défaut sur un processus root élevé ?

Je voulais juste poster une réponse pour les autres utilisateurs de Vue.js.

<template>
  <div>
    <a href="https://google.com" target="_blank" @click.prevent="openExternalBrowser">Google.com Status</a>
  </div>
</template>

<script>
const { remote } = require('electron');

export default {
  name: 'HelloWorld',
  methods: {
    openExternalBrowser(e) {
      remote.shell.openExternal(e.target.href);
    },
  },
};
</script>

Je voulais juste poster une réponse pour les autres utilisateurs de Vue.js.

<template>
  <div>
    <a href="https://google.com" target="_blank" @click.prevent="openExternalBrowser">Google.com Status</a>
  </div>
</template>

<script>
const { remote } = require('electron');

export default {
  name: 'HelloWorld',
  methods: {
    openExternalBrowser(e) {
      remote.shell.openExternal(e.target.href);
    },
  },
};
</script>

Merci.

Sur main.js :

app.on('web-contents-created', (e, contents) => {
    contents.on('new-window', (e, url) => {
      e.preventDefault();
      require('open')(url);
    });
    contents.on('will-navigate', (e, url) => {
      if (url !== contents.getURL()) e.preventDefault(), require('open')(url);
    });
});

Vous devez installer open package :

npm i open --save

Je voulais juste poster une réponse pour les autres utilisateurs de Vue.js.

@ travis5491811 Cela ouvre une autre fenêtre Electron avec la bonne page. Est-ce le comportement attendu?

Non, lorsqu'il est correctement implémenté, mon message devrait répondre au ticket de fil "Comment puis-je ouvrir une URL à partir du navigateur du système d'exploitation par défaut ", mais pour les utilisateurs de vue .

Je voulais juste poster une réponse pour les autres utilisateurs de Vue.js.

@ travis5491811 Cela ouvre une autre fenêtre Electron avec la bonne page. Est-ce le comportement attendu?

Cette page vous a été utile?
0 / 5 - 0 notes