Electron: Wie öffne ich eine URL <a>im Standardbrowser des Betriebssystems?</a>

Erstellt am 1. Apr. 2015  ·  26Kommentare  ·  Quelle: electron/electron

Hilfreichster Kommentar

Ich habe dieses Code-Snippet auf SO gefunden:

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

Ich habe es in meiner Hauptindexdatei abgelegt, es scheint, soweit ich das beurteilen kann, sogar für dynamisch generierte Links zu funktionieren. Ich bin zu noob bei Elektron, um zu wissen, ob es irgendwelche Nachteile gibt, auf die ich achten sollte. Die Gedanken?

Alle 26 Kommentare

In meinem Setup habe ich sowohl shell.openExternal('http://example.com') als auch shell.openItem('http://example.com') ausprobiert und beide haben die Website im Hintergrund geöffnet.

Am Ende habe ich child_process.execSync('start http://example.com') unter Win32 und child_process.execSync('open http://example.com') unter Darwin verwendet, sodass der Browser tatsächlich auftaucht und den Fokus erhält.

Unter Linux können Sie xdg-open verwenden:
child_process.execSync('xdg-open http://example.com')

Ich habe mich tatsächlich für die Verwendung von node-open entschieden . Sie sollten es versuchen, wenn Sie sich nicht mit Flucht und dergleichen herumschlagen wollen.

Leute, aber Ihre Lösungen sind großartig, aber ich frage mich, wie Sie den Versuch abfangen können, eine URL wie " http://someurl.com " zu öffnen und dann mit shell.openExternal öffnen? Service Worker ermöglicht es, nur Anfragen an die Dateien in derselben Domäne abzufangen. Gibt es die Möglichkeit dazu? /cc @maxogden @AlicanC

Gleiche Frage hier wie @havenchyk , gibt es eine Möglichkeit, Elektron

Wenn Ihre App nur ein Fenster verwendet und Sie sicherstellen können, dass jeder externe Link in Ihrer App in einem neuen Fenster geöffnet wird (z. B. über target="_blank" ), können Sie Folgendes tun:

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

Wobei webContents der WebContent Ihres BrowserWindows ist und open eine Funktion ist, die die URL in Ihrem Browser öffnet (ich verwende node-open wie von AlicanC empfohlen).

Es wäre schön, wenn beim Klicken auf einen _jeden_ Link ein Ereignis ausgelöst würde, damit die App entscheiden könnte, ob es im Browser geöffnet werden soll, aber ich habe kein solches Ereignis gefunden, wenn es existiert.

Ich habe dieses Code-Snippet auf SO gefunden:

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

Ich habe es in meiner Hauptindexdatei abgelegt, es scheint, soweit ich das beurteilen kann, sogar für dynamisch generierte Links zu funktionieren. Ich bin zu noob bei Elektron, um zu wissen, ob es irgendwelche Nachteile gibt, auf die ich achten sollte. Die Gedanken?

Ich verwende diesen 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)

Deklarieren Sie zuerst einen Spawn-Prozess

`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)
     });
  }

}])`

und vor Aufruf der Methode

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

Hat shell.openExternal Sicherheitsprobleme? Wenn beispielsweise Links aus dem Netz kommen, werden rohe Netzdaten an shell.openExternal oder eine der anderen oben genannten Funktionen übergeben. Stellt shell.openExternal sicher, dass nichts Schlimmes passiert? Muss ich nach Schemas filtern?

Basierend auf dem Code von Folgendes verwendet:

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

Dann müssen Sie nur noch die Klasse 'open-in-browser' auf jedes Element ziehen, das Sie im Browser öffnen möchten.

Hier ist eine, die JQuery nicht benötigt, falls jemand anderes danach sucht. Es öffnet automatisch alle Links, die mit 'http' beginnen, im externen Browser.

Fügen Sie dies in Ihren Renderer-Prozess ein:

// 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)
  }
})

Wenn Sie möchten, dass ALLE <a> Tags im Standardbrowser geöffnet werden, versuchen Sie dies in Ihrer main.ts:

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

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

Dies setzt voraus, dass Sie eine Single-Page-App wie ich haben. Wenn nicht, müssen Sie zusätzliche Desinfektionsmaßnahmen durchführen.

Ich möchte nur wiederholen, dass die Verwendung dieser Funktion mit Benutzerinhalten ohne Whitelist wahrscheinlich eine klaffende Sicherheitslücke ist. Ich weiß nicht, was alle verschiedenen Schemata tun und was ihre Eingaben sind, aber nur als einfaches Beispiel ein Link wie dieser

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

Fordert den Benutzer in Chrome und Safari unter macOS auf, aber mit dem obigen Code öffnet Electron einfach die App.

Es fühlt sich fast so an, als ob Electron selbst hier standardmäßig sicherer sein sollte, anstatt es jedem einzelnen Programmierer zu überlassen, selbst herauszufinden, wie er es sicher machen kann.

Zumindest willst du wahrscheinlich so etwas wie

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 Siehe den offenen externen Berechtigungstyp in https://electronjs.org/docs/api/session#sessetpermissionrequesthandlerhandler

Diese kannst du blockieren

Hallo, ich verwende vue.js und löse dieses Problem, das von der obigen Diskussion inspiriert wurde. Falls jemand wie ich, der vue verwendet, auch das gleiche Problem hat, füge ich meinen Code hier ein.

<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>

Basierend auf einem Kommentar von @alangrainger - ts-Version:

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

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

Was ist mit Daten-URLs?

Angular 7-Version (mit Live-Reloads):

        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);

Der Teil url.match(/.*localhost.*/gi) === null ist notwendig, da sonst, wenn Sie etwas in Ihrer Winkelanwendung ändern, ein neues Fenster/Tab in Ihrem Betriebssystembrowser geöffnet wird, anstatt es in der Elektron-App neu zu laden.

Alle Methoden funktionieren einwandfrei, aber nur bei Nicht-Root-Elektronen-Apps. Was kann ich verwenden, um eine externe URL im Standard-Betriebssystembrowser in einem Root-Prozess mit erhöhten Rechten zu öffnen?

Wollte nur eine Antwort für andere Vue.js-Benutzer posten.

<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>

Wollte nur eine Antwort für andere Vue.js-Benutzer posten.

<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>

Danke schön.

Auf 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);
    });
});

Sie müssen das offene Paket installieren:

npm i open --save

Wollte nur eine Antwort für andere Vue.js-Benutzer posten.

@travis5491811 Dies öffnet ein weiteres Electron-Fenster mit der rechten Seite. Ist das das erwartete Verhalten?

Nein, wenn richtig implementiert, sollte mein Beitrag das Thread-Ticket "Wie öffne ich eine URL im Standard-OS-Browser " beantworten Die Antwort, die ich bereitgestellt habe, funktioniert in meiner App Electron v5.0.11 , Vue v2.6.10 , die in der Produktion auf mehreren Windows 10- und Linux-Desktop-Rechnern getestet wurde

Wollte nur eine Antwort für andere Vue.js-Benutzer posten.

@travis5491811 Dies öffnet ein weiteres Electron-Fenster mit der rechten Seite. Ist das das erwartete Verhalten?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen