Electron: Как открыть URL-адрес <a>в браузере ОС по умолчанию?</a>

Созданный на 1 апр. 2015  ·  26Комментарии  ·  Источник: electron/electron

Самый полезный комментарий

Я нашел этот фрагмент кода на 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);
    });

Бросил его в свой основной индексный файл, кажется, он работает, насколько я могу судить, даже для динамически генерируемых ссылок. Я слишком новичок в электронике, чтобы знать, есть ли у этого недостатки, которых я должен остерегаться. Мысли?

Все 26 Комментарий

Документы @luicaps находятся здесь https://github.com/atom/atom-shell/blob/master/docs/api/shell.md#shellopenexternalurl

В своей настройке я попробовал как shell.openExternal('http://example.com') и shell.openItem('http://example.com') и оба открыли веб-сайт в фоновом режиме.

В итоге я использовал child_process.execSync('start http://example.com') в Win32 и child_process.execSync('open http://example.com') в Дарвине, так что браузер действительно всплывает и получает фокус.

В Linux вы можете использовать xdg-open:
child_process.execSync('xdg-open http://example.com')

Я действительно решил использовать node-open . Вы должны попробовать, если не хотите связываться с побегом и тому подобным.

Ребята, но у вас отличные решения, но мне интересно, как перехватить попытку открыть url типа « http://someurl.com », а затем открыть с помощью shell.openExternal ? Service worker позволяет улавливать только запросы к файлам в одном домене. Есть ли возможность это сделать? / cc @maxogden @AlicanC

Тот же вопрос, что и @havenchyk , есть ли способ указать электрону открывать внешние ссылки по умолчанию?

Если ваше приложение использует только одно окно, и вы можете гарантировать, что каждая внешняя ссылка в вашем приложении открывается в новом окне (например, через target="_blank" ), вы можете сделать что-то вроде:

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

Где webContents - это ваш основной веб-контент BrowserWindow, а open - это функция, которая открывает URL-адрес в вашем браузере (я использую node-open, как рекомендовано AlicanC).

Было бы неплохо, если бы при нажатии _любой_ ссылки происходило событие, чтобы приложение могло решить, должно ли оно открываться в браузере, но я не нашел такого события, если оно существует.

Я нашел этот фрагмент кода на 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);
    });

Бросил его в свой основной индексный файл, кажется, он работает, насколько я могу судить, даже для динамически генерируемых ссылок. Я слишком новичок в электронике, чтобы знать, есть ли у этого недостатки, которых я должен остерегаться. Мысли?

Я использую этот фрагмент кода:

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)

Сначала объявите процесс появления

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

}]) `

и перед вызовом метода

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

Есть ли у shell.openExternal проблемы с безопасностью? Например, если ссылки выходят из сети, тогда необработанные сетевые данные передаются в shell.openExternal или любую из других функций, указанных выше. shell.openExternal гарантирует, что ничего плохого не случится? Мне нужно фильтровать схемы?

Основываясь на коде из

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

Затем вам просто нужно добавить класс open-in-browser к каждому элементу, который вы хотите открыть в браузере.

Вот тот, который не требует JQuery, на случай, если кто-то за ним охотится. Он автоматически откроет любую ссылку, которая начинается с «http» во внешнем браузере.

Поместите это в свой процесс рендеринга:

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

Если вы хотите, чтобы ВСЕ теги <a> открывались в браузере по умолчанию, попробуйте это в своем main.ts:

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

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

Предполагается, что у вас есть одностраничное приложение, подобное мне. В противном случае вам потребуется дополнительная дезинфекция.

Я просто хочу повторить, что использование этого с пользовательским контентом без белого списка, вероятно, является зияющей дырой в безопасности. Я не знаю, что делают все различные схемы и каковы их входы, но просто в качестве простого примера приведу ссылку, подобную этой

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

Будет запрашивать пользователя в Chrome и Safari на macOS, но с указанным выше кодом Electron просто откроет приложение.

Похоже, что сам Electron должен по умолчанию быть более безопасным, а не предоставлять каждому программисту самостоятельно решать, как сделать это безопасным.

Как минимум вы, вероятно, захотите что-то вроде

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 См. открытый тип внешнего разрешения в https://electronjs.org/docs/api/session#sessetpermissionrequesthandlerhandler

Вы можете заблокировать их 👍

Привет, я использую vue.js и решаю эту проблему, вдохновленную приведенным выше обсуждением. Если у кого-то вроде меня, использующего vue, также есть такая же проблема, я вставляю сюда свой код.

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

На основе комментария @alangrainger - версия ts:

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

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

А как насчет URL-адресов данных?

Версия Angular 7 (с живыми перезагрузками):

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

Часть url.match(/.*localhost.*/gi) === null необходима, потому что в противном случае, когда вы что-то измените в своем приложении angular, оно откроет новое окно / вкладку в вашем браузере ОС вместо перезагрузки в электронном приложении.

Все методы работают нормально, но только в электронном приложении без root, что я могу использовать, чтобы открыть внешний URL-адрес в браузере ОС по умолчанию в корневом процессе с повышенными правами?

Просто хотел опубликовать ответ для других пользователей 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>

Просто хотел опубликовать ответ для других пользователей 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>

Спасибо.

На 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);
    });
});

Вам необходимо установить открытый пакет :

npm i open --save

Просто хотел опубликовать ответ для других пользователей Vue.js.

@ travis5491811 Откроется еще одно окно Electron с правой страницей. Это ожидаемое поведение?

Нет, при правильной реализации мой пост должен отвечать на тикет потока «Как открыть URL-адрес из браузера ОС по vue .

Просто хотел опубликовать ответ для других пользователей Vue.js.

@ travis5491811 Откроется еще одно окно Electron с правой страницей. Это ожидаемое поведение?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги