前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Electron加载插件支持Flash

Electron加载插件支持Flash

作者头像
码客说
发布2022-03-24 08:10:06
3.6K1
发布2022-03-24 08:10:06
举报
文章被收录于专栏:码客

创建项目

代码语言:javascript
复制
git clone https://gitee.com/psvmc/electron-quick-start.git
# 重命名
ren electron-quick-start electron-flash-demo
cd electron-flash-demo
# 删除原来的git文件夹
rmdir /s/q .git
rmdir /s/q .github
npm install
npm start

下载32位的Electron

项目根目录中添加.npmrc

代码语言:javascript
复制
arch=ia32
registry=https://registry.npm.taobao.org

设置Flash插件

下载插件

下载pepflashplayer插件

注意

这个插件一定要用老版本,新版本的flash由于中国代理商要赚钱,会检测一个服务是否启动,不启动就会报错,强行让更新新版本。

如图

image-20220317135705691
image-20220317135705691

老版本的Chrome下载 里面带有pepflashplayer插件

https://www.slimjet.com/chrome/google-chrome-old-version.php

这里推荐下载32位的最老的版本

Version

Size

Date

48.0.2564.97

40.76 MB

2020-04-29

这个插件已经很难下载到了,我的方法是下载个360浏览器带极速内核的版本,打开一个带有flash的网页,它就会自动下载插件

在浏览器的安装目录下搜索pepflashplayer,就会找到对应的dll文件。

或者下载下面的DLL

pepflashplayer32_20_0_0_286.dll

链接:https://pan.baidu.com/s/1_eMRkJ8m6jILi40BHSH-4Q 提取码:psvm

注意

这个插件是32位的,一定要保证Electron是32位的。

配置插件

把下载的插件放在项目根目录下libs文件夹下,如图所示:

image-20220315231050276
image-20220315231050276

main.js中添加以下代码

代码语言:javascript
复制
let pluginName
switch (process.platform) {
    case 'win32':
        pluginName = 'pepflashplayer.dll'
        break
    case 'darwin':
        pluginName = 'PepperFlashPlayer.plugin'
        break
    case 'linux':
        pluginName = 'libpepflashplayer.so'
        break
}

let plugins_path = path.join(__dirname, "libs", "ppflash", pluginName);
if (__dirname.includes(".asar")) {
    plugins_path = path.join(process.resourcesPath, "libs", "ppflash", pluginName)
}

app.commandLine.appendSwitch('ppapi-flash-path', plugins_path);

注意:

这里一定要进行判断,因为打包前后的路径是不一致的。

不显示菜单栏

代码语言:javascript
复制
const electron = require('electron')
/*获取electron窗体的菜单栏*/
const Menu = electron.Menu
/*隐藏electron创听的菜单栏*/
Menu.setApplicationMenu(null)

页面配置

官方文档:

可用于测试Flash的页面:https://sc.chinaz.com/donghua/220315391630.htm

方式1

这种方式最为简单。

主进程 BrowserWindow

BrowserWindow添加webPreferences配置

代码语言:javascript
复制
const mainWindow = new BrowserWindow({
    width: 1366,
    height: 768,
    webPreferences: {
        webviewTag: true,
        javascript: true,
        plugins: true,
        webSecurity: false
    }
})

plugins: true 这个配置项是必须的。

如果使用的是webview,在标签里添加 plugins 属性。

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Flash</title>
</head>
<body>
<webview src="https://sc.chinaz.com/donghua/220315391630.htm" allowpopups plugins></webview>

<style lang="text/css">
    body {
        margin: 0;
        padding: 0;
    }

    webview {
        display: flex;
        width: 100vw;
        height: 100vh;

    }
</style>
</body>
</html>

请注意,webview 标签的样式使用 display:flex; 来确保 iframe在传统和 flex 布局一起使用的情况下填充其 webview 容器的全部高度和宽度。

在devtools的控制台输入以下命令检查Pepper Flash插件是否被加载。

代码语言:javascript
复制
navigator.plugins

注意

这个只能判断是否加载插件,不能判断插件是否可用,比如没有dll就不可用,但是插件列表中已经存在。

方式2

这种方式能控制访问的连接。

首先我们看四种打开新页面的方式

代码语言:javascript
复制
<a href="https://www.psvmc.cn" target="_blank">_blank</a>
<span onclick="javascript:window.open('https://www.psvmc.cn')">open</span>

分别是:

  1. _blank
  2. .open

实际运行情况是:

在正常的浏览器中,这两种情况都是能新开窗口的。但是,部分浏览器里面可能会拦截.open这种方式。但是绝对没有任何浏览器会拦截_blank这种。

electronwebview中,

  • 对于_blank是默认拦截的,不会自动打开。
  • 对于.open, 添加allowpopups 就会自动用新窗口打开。

所以添加allowpopups 属性,就可以解决面的情况,

_blank的页面添加allowpopups后也无法打开

为了保证两种方式都能正常打开,页面中添加JS,注意

这时候不要添加allowpopups,否则会打开两个页面。 因为new-window能同时监听到这两种方式。

示例

代码语言:javascript
复制
<webview src="https://sc.chinaz.com/donghua/220315391630.htm" plugins></webview>
<script>
  onload = () => {
  const webview = document.querySelector('webview')

  const new_window = (e) => {
    const protocol = (new URL(e.url)).protocol;
    if (protocol === 'http:' || protocol === 'https:') {
      //webview.loadURL(e.url)
      if(e.url.indexOf("sc.chinaz.com")!==-1){
        window.open(e.url)
      }
    }
  }

  const will_navigate = (e) => {
    const protocol = (new URL(e.url)).protocol;
    if (protocol === 'http:' || protocol === 'https:') {
      console.info("will_navigate",e.url);
      if(e.url.indexOf("sc.chinaz.com")===-1){
        webview.reload();
      }
    }
  }

  webview.addEventListener('new-window', new_window);
  webview.addEventListener('will-navigate', will_navigate);
}
  </script>

注意

new-window只能监听到页面内_blank.open,页面的重定向是监听不到的。

方式3

这种方式不但能够控制访问的连接,还能设置窗口属性。

默认的方式其实也是新的进程,和下面的方式一样,但是这种方式我们可以做一些窗口属性的设置。

渲染进程

代码语言:javascript
复制
<script>
    const ipcRenderer = window.require('electron').ipcRenderer
    onload = () => {
        const webview = document.querySelector('webview')
        const loadstart = () => {
            console.log("开始加载");
        }

        const loadstop = () => {
            console.log("加载完成");
        }

        const new_window = (e) => {
            const protocol = (new URL(e.url)).protocol;
            if (protocol === 'http:' || protocol === 'https:') {
                //window.open(e.url)
                ipcRenderer.send('open_url',e.url);
            }
        }

        webview.addEventListener('did-start-loading', loadstart);
        webview.addEventListener('did-stop-loading', loadstop);
        webview.addEventListener('new-window', new_window);
    }
</script>

主进程

代码语言:javascript
复制
let mainWindow;
function createWindow() {
    // Create the browser window.
     mainWindow = new BrowserWindow({
        width: 1366,
        height: 768,
        webPreferences: {
            webviewTag: true,
            javascript: true,
            plugins: true,
            webSecurity: false,
            nodeIntegration: true,
            enableRemoteModule: true,
            contextIsolation: false,
        }
    })

    // and load the index.html of the app.
    mainWindow.loadFile('index.html')

    // Open the DevTools.
    //mainWindow.webContents.openDevTools()
}

const ipcMain = require('electron').ipcMain
let new_win;
ipcMain.on('open_url',(event, arg)=>
{
    new_win = new BrowserWindow({
        width: 1366,
        height: 768,
        title: "",
        webPreferences: {
            webviewTag: true,
            javascript: true,
            plugins: true,
            webSecurity: false
        },
        frame:true,
        parent: mainWindow,
    })
    new_win.loadURL(arg); 
    new_win.on('closed',()=>{new_win = null})
})

注意

主窗口要设置Node环境nodeIntegration: true,

禁止外链跳转

方式1

按照逻辑我们要限制跳转,只要监听will-navigate事件,阻止它e.preventDefault();就行了,但是实际上这并没有用。

如下(这样写并不生效)

代码语言:javascript
复制
const will_navigate = (e) => {
  const protocol = (new URL(e.url)).protocol;
  if (protocol === 'http:' || protocol === 'https:') {
    console.info("will_navigate",e.url);
    if(e.url.indexOf("sc.chinaz.com")===-1){
      e.preventDefault();
    }
  }
}

webview.addEventListener('will-navigate', will_navigate);

原因是

所有的 event.preventDefault() 都应该从主进程中呼叫而不是渲染进程。

所以我们就要在主进程中做如下操作

  1. 最外层 BrowserWindowwebContents 上监听 did-attach-webview 事件,获取新挂上去的 <webview>webContents
  2. 使用获取到的 webContents 监听 will-navigate事件。

这时候,我们就可以在 will-navigate 事件中使用 e.preventDefault() 阻止 <webview> 导航至其他网页了

代码如下:

代码语言:javascript
复制
mainWindow.webContents.on('did-attach-webview', (e, wc)=>{
  const will_navigate = (e, url)=>{
    console.info(url);
    if (url.indexOf("sc.chinaz.com") === -1) {
      e.preventDefault();
      wc.reload();
    }
  }

  wc.on('will-navigate', will_navigate);
})

方式2

当然换个思路,虽然我们阻止不了,我们直接重新加载不就行了吗。

代码语言:javascript
复制
onload = () => {
  const webview = document.querySelector('webview')

  const new_window = (e) => {
    const protocol = (new URL(e.url)).protocol;
    if (protocol === 'http:' || protocol === 'https:') {
      //webview.loadURL(e.url)
      if(e.url.indexOf("10.88.8.90:9080")!==-1){
        window.open(e.url)
      }
    }
  }

  const will_navigate = (e) => {
    const protocol = (new URL(e.url)).protocol;
    if (protocol === 'http:' || protocol === 'https:') {
      console.info("will_navigate",e.url);
      if(e.url.indexOf("10.88.8.90:9080")===-1){
        webview.reload();
      }
    }
  }

  webview.addEventListener('new-window', new_window);
  webview.addEventListener('will-navigate', will_navigate);
}

我的方案

下面的两种方案 我最终的选择是

上面页面配置的方式3和禁止跳转的方式1相结合,这样就可以同时处理主页面和子页面的跳转限制。

主进程

代码语言:javascript
复制
let mainWindow;
function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1366,
    height: 768,
    webPreferences: {
      webviewTag: true,
      javascript: true,
      plugins: true,
      webSecurity: false,
      nodeIntegration: true,
      enableRemoteModule: true,
      contextIsolation: false,
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  //mainWindow.webContents.openDevTools()
  addListener(mainWindow);
}

const ipcMain = require('electron').ipcMain
let new_win;
ipcMain.on('open_url',(event, arg)=>
{
  new_win = new BrowserWindow({
    width: 1366,
    height: 768,
    title: "",
    webPreferences: {
      webviewTag: true,
      javascript: true,
      plugins: true,
      webSecurity: false
    },
    frame:true,
    parent: mainWindow,
  })
  new_win.loadURL(arg);
  new_win.on('closed',()=>{new_win = null})
  addListener(new_win);
})

function addListener(win){
  //主页面中的重载
  win.webContents.on('did-attach-webview', (e, wc)=>{
    const will_navigate = (e, url)=>{
      if (url.indexOf("10.88.8.90:9080") === -1) {
        e.preventDefault();
        wc.reload();
      }
    }
    wc.on('will-navigate', will_navigate);
  })

  // 子页面中的重载
  const will_navigate = (e, url)=>{
    if (url.indexOf("10.88.8.90:9080") === -1) {
      e.preventDefault();
      win.webContents.reload();
    }
  }
  win.webContents.on('will-navigate', will_navigate);
}

渲染进程

代码语言:javascript
复制
<webview src="http://10.88.8.90:9080/AtomLocal/common/login.faces" disablewebsecurity plugins></webview>
<script>
  const ipcRenderer = window.require('electron').ipcRenderer
  onload = () => {
    const webview = document.querySelector('webview');
    let lastUrl = "";
    const new_window = (e) => {
      // 防止同样的地址,多次调用
      if(!lastUrl){
        const protocol = (new URL(e.url)).protocol;
        if (protocol === 'http:' || protocol === 'https:') {
          if(e.url.indexOf("10.88.8.90:9080")!==-1){
            ipcRenderer.send('open_url',e.url);
            lastUrl = e.url;
            setTimeout(()=>{
              lastUrl = "";
            },1000)
          }
        }
      }
    }
    webview.addEventListener('new-window', new_window);
  }
</script>

打包

添加依赖

代码语言:javascript
复制
npm install electron-builder@22.9.1 --save-dev

在pakage.json中,我们build的配置下面内容:

代码语言:javascript
复制
{
  "name": "flashapp",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "dist": "electron-builder --win --ia32",
    "dist_dir": "electron-builder --win --ia32 --dir"
  },
  "build": {
    "appId": "cn.psvmc.flashapp",
    "productName": "Flash加载",
    "icon": "app.ico",
    "asar": true,
    "files": [
      "main.js",
      "*.html",
      "app.ico",
      "node_modules/**/*"
    ],
    "mac": {
      "icon": "app.ico",
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "icon": "app.ico",
      "target": [
        "zip"
      ],
      "extraResources": "./libs/**/*"
    },
    "nsis": {
      "oneClick": false,
      "allowElevation": true,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "app.ico",
      "uninstallerIcon": "app.ico",
      "installerHeaderIcon": "app.ico",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "license": "LICENSE.txt"
    }
  },
  "devDependencies": {
    "electron": "^11.1.1",
    "electron-builder": "22.9.1"
  }
}

其中最重要的配置就是 "extraResources": "./libs/**/*" 这样的话我们的所有配置就算完成了。

注意NodeJS的版本要在14以上

代码语言:javascript
复制
nvm install 14.17.1
nvm use 14.17.1

依赖版本号

代码语言:javascript
复制
"electron-builder": "22.9.1"
"electron-builder": "~22.9.1"
"electron-builder": "^22.9.1"

其中

  1. 前面不带符号则版本号的3个数字都匹配
  2. ~则版本号的前2个数字匹配
  3. ^则版本号的第一个数字匹配

建议

使用~+版本号

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建项目
  • 下载32位的Electron
  • 设置Flash插件
    • 下载插件
      • 配置插件
      • 不显示菜单栏
      • 页面配置
        • 方式1
          • 方式2
            • 方式3
            • 禁止外链跳转
              • 方式1
                • 方式2
                • 我的方案
                • 打包
                • 依赖版本号
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档