Electron: Como abro um url <a>no navegador do sistema operacional padrão?</a>

Criado em 1 abr. 2015  ·  26Comentários  ·  Fonte: electron/electron

Comentários muito úteis

Encontrei este snippet de código no 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);
    });

Coloquei no meu arquivo de índice principal, parece estar funcionando, até onde posso dizer, mesmo para links gerados dinamicamente. Eu sou muito novato em elétrons para saber se há alguma desvantagem nisso que eu deva tomar cuidado. Pensamentos?

Todos 26 comentários

Na minha configuração, tentei shell.openExternal('http://example.com') e shell.openItem('http://example.com') e ambos abriram o site em segundo plano.

Acabei usando child_process.execSync('start http://example.com') no Win32 e child_process.execSync('open http://example.com') no Darwin, então o navegador realmente aparece e obtém o foco.

No Linux, você pode usar xdg-open:
child_process.execSync('xdg-open http://example.com')

Na verdade, decidi usar o nó aberto . Você deve tentar se não quiser mexer com a fuga e tal.

Pessoal, mas suas soluções são ótimas, mas estou me perguntando como interceptar tentativa de abrir url como " http://someurl.com " e depois abrir com shell.openExternal ? O Service Worker permite capturar apenas solicitações para arquivos no mesmo domínio. Existe habilidade para fazer isso? / cc @maxogden @AlicanC

A mesma pergunta aqui que @havenchyk , há uma maneira de dizer ao elétron para abrir links externos por padrão?

Se seu aplicativo usa apenas uma janela e você pode garantir que todos os links externos em seu aplicativo sejam abertos em uma nova janela (por exemplo, target="_blank" ), você pode fazer algo como:

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

Onde webContents é o conteúdo da web do seu BrowserWindow principal e open é uma função que abre a url no seu navegador (eu uso o node-open conforme recomendado pela AlicanC).

Seria bom se houvesse um evento disparado quando _qualquer_ link fosse clicado, para que o aplicativo pudesse decidir se deveria abrir no navegador, mas não encontrei tal evento, se ele existir.

Encontrei este snippet de código no 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);
    });

Coloquei no meu arquivo de índice principal, parece estar funcionando, até onde posso dizer, mesmo para links gerados dinamicamente. Eu sou muito novato em elétrons para saber se há alguma desvantagem nisso que eu deva tomar cuidado. Pensamentos?

Estou usando este código:

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)

Primeiro declare um processo de desova

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

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

}]) `

e antes de chamar o método

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

shell.openExternal tem algum problema de segurança? Por exemplo, se os links saem da rede, os dados brutos da rede estão sendo passados ​​para shell.openExternal ou qualquer uma das outras funções acima. shell.openExternal garante que nada de ruim aconteça? Eu preciso filtrar por esquemas?

Com base no código de @rubencodes , usei:

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

Em seguida, você apenas tem que soltar a classe 'abrir no navegador' para cada elemento que deseja abrir no navegador.

Aqui está um que não requer JQuery, caso alguém esteja procurando por ele. Ele abrirá automaticamente qualquer link que comece com 'http' no navegador externo.

Coloque isso em seu processo de renderização:

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

Se você quiser que TODAS as tags <a> abram no navegador padrão, tente isso em seu main.ts:

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

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

Isso pressupõe que você tenha um aplicativo de página única como eu. Caso contrário, você precisará fazer alguma higienização extra.

Só quero reiterar que usar isso com conteúdo do usuário sem uma lista de permissões é provavelmente uma brecha de segurança. Eu não sei o que todos os vários esquemas fazem e quais são suas entradas, mas apenas como um exemplo simples de um link como este

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

Irá perguntar ao usuário no Chrome e Safari no macOS, mas com o código acima, o Electron apenas abrirá o aplicativo.

Parece que o próprio Electron deveria ser mais seguro aqui, em vez de deixar que cada programador descubra como torná-lo seguro por conta própria.

No mínimo, você provavelmente quer algo como

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 Veja o tipo de permissão externa aberta em https://electronjs.org/docs/api/session#sessetpermissionrequesthandlerhandler

Você pode bloquear aqueles 👍

Olá, estou usando o vue.js e resolvo esse problema inspirado na discussão acima, caso alguém como eu usando o vue também tenha o mesmo problema, colo meu código aqui.

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

Com base no comentário de @alangrainger - versão ts:

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

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

E quanto aos URLs de dados?

Versão Angular 7 (com recargas ao vivo):

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

A parte url.match(/.*localhost.*/gi) === null é necessária porque, caso contrário, quando você alterar algo em seu aplicativo angular, ele abrirá uma nova janela / guia em seu navegador do sistema operacional em vez de recarregá-lo no aplicativo eletrônico.

Todos os métodos funcionam bem, mas apenas em aplicativos eletrônicos sem raiz. O que posso usar para abrir uma url externa no navegador do sistema operacional padrão em um processo com raiz elevada?

Só queria postar uma resposta para outros usuários do 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>

Só queria postar uma resposta para outros usuários do 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>

Obrigada.

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

Você precisa instalar o pacote aberto :

npm i open --save

Só queria postar uma resposta para outros usuários do Vue.js.

@ travis5491811 Isso abre outra janela Electron com a página certa. Este é o comportamento esperado?

Não, quando implementado corretamente, meu post deve responder ao tíquete do tópico "Como abro uma url no navegador do sistema operacional padrão ", mas para vue usuários.

Só queria postar uma resposta para outros usuários do Vue.js.

@ travis5491811 Isso abre outra janela Electron com a página certa. Este é o comportamento esperado?

Esta página foi útil?
0 / 5 - 0 avaliações