Giter Club home page Giter Club logo

electron-extensions's Introduction

electron-extensions

electron-extensions will allow you to use Chrome extensions APIs with Electron.

Installation

$ npm install electron-extensions

Usage

The library is really easy-to-use. All you have to do is to put the following code in your main process:

import { ExtensibleSession } from 'electron-extensions/main';
import { app } from 'electron';

const extensions = new ExtensibleSession();

(async () => {
  await app.whenReady();
  extensions.loadExtension('C:/.../abcdefghijklmnoprstuwxyz'); // Path to the extension to load
})();

Documentation

Class ExtensibleSession main

new ExtensibleSession(options: IOptions)

  • options object
    • partition string - By default null. It's used for injecting preloads to load content_scripts in all webContents within a given Electron session. Must be called in app ready event.
    • preloadPath string - Path to content preload script. The option can be useful for bundlers like webpack if you're using CopyWebpackPlugin.
    • blacklist string[] - List of URLs or glob patterns preventing from injecting content_scripts to. For example [wexond://*/*].

It's only for the main process. It's used to load extensions and handle their events.

Instance methods

loadExtension(path: string)

Loads an extension from a given path.

addWindow(window: Electron.BrowserWindow)

Adds a BrowserWindow to send and observe UI related events such as

  • chrome.browserAction.onClicked

Instance properties

blacklist string[]

List of URLs or glob patterns preventing from injecting content_scripts to. For example [wexond://*].

Events

set-badge-text

Emitted when chrome.browserAction.setBadgeText has been called in an extension.

Returns:

  • extensionId string
  • details chrome.browserAction.BadgeTextDetails

create-tab

Emitted when chrome.tabs.create has been called in an extension.

Example:
import { extensionsRenderer } from 'electron-extensions';

extensionsRenderer.on('create-tab', (details, callback) => {
  const tab = createTab(details); // Some create tab method...
  callback(tab.id);
});

Returns:

  • details chrome.tabs.CreateProperties
  • callback (tabId: number) => void - Must be called with the created tab id as an argument. Also, the tabId must be the same as any attached webContents id

Object extensionsRenderer

Usage in renderer

import { extensionsRenderer } from 'electron-extensions/renderer';

Instance methods

browserAction.onClicked(extensionId: string, tabId: number)

Emits chrome.browserAction.onClicked event in a given extension.

electron-extensions's People

Contributors

dependabot[bot] avatar ianwieds avatar sentialx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

electron-extensions's Issues

adding crx

Is it possible to load extension from a .crx extension file, like that:

 const extensions = new ExtensibleSession(session.defaultSession);
 extensions.loadExtension('uBlock-Origin_v1.23.0.crx');

I tried with that code and didn't work

chrome.tabs.getSelected() should not return an array on 7.0.0-beta.2

I noticed this method is returning an array but the chrome docs specify that a Tab object should be returned: https://developer.chrome.com/extensions/tabs#method-getSelected

./src/browser/tabs.ts

public getSelected(windowId: number) {
  if (typeof windowId === 'number') {
    return this.query({ windowId, active: true });
  }
  return this.query({ active: true });
}

Should be...

public getSelected(windowId: number) {
  if (typeof windowId === 'number') {
    return this.query({ windowId, active: true })[0];
  }
  return this.query({ active: true })[0];
}

It's a very easy fix since the chrome.tabs.query() method will always return an array we just need to get the first element and return that.

Wanted to make a pull request but for some reason I can't find the code anymore for 7.0.0-beta.2, did it get taken down or something? It's not available on NPM...

Skipping extension with invalid URL

when i used extension:
electron-extension://2.3.4.2_0 [15560:0924/141115.615:ERROR:CONSOLE(7946)] "Skipping extension with invalid URL: electron-extension ://2.3.4.2_0", source: devtools://devtools/bundled/shell.js (7946)

Unable to load ublock origin

[email protected], [email protected], [email protected]

I'm trying to run ublock origin within my extension. There's no apparent errors while loading, but I'm unable to load the electron-extension:// page for the popupPage, and when I try to invoke extension.backgroundPage.webContents.showDevTools(), it opens up to a blank page navigated to chrome-error://chromewebdata/ without any sources loaded.

I'm downloaded ublock origin's chromium build and extracted a folder locally. I'm pointing to the folder for extensions.loadExtension().

In my app, I'm using persist:web-content for my web content and I passed that down to the extension in the constructor. I'm using the same partition for loading the popup.

What's interesting is that my extension web-palette is working fine, but that might be because it's only relying on content scripts.

Could I maybe be missing a step somewhere? I'm registering custom protocol handlers in my app, could that be interfering with the protocol handlers for electron-extension://?

Not working with Electron 5?

Problem:

I can't seem to get it working (content scripts work, but not my WebRequest background.js)

Reproduction:

  1. Create a new electron-forge app.
npx create-electron-app my-app
cd my-app
  1. Install electron-extensions
npm i electron-extensions
  1. Add code to index.js
await extension.loadExtension(
	"/path/to/normal/extension/"
);
  1. Start app
npm start

You should get this error:

 electron-extension://name
[12692:0727/103022.600:ERROR:CONSOLE(7817)] "Skipping extension with invalid URL: electron-extension://name", source: chrome-devtools://devtools/bundled/shell.js (7817)

but the content script should still load.

Write tests

Despite the complexity of Chrome APIs. currently electron-extensions has no tests. It's really easy to find bugs in the current APIs implementation unless it will have tests. However it's really hard work, so it would be great to see some support by opening Pull Requests.

Support promise responses in WebRequest

According to MDN, Firefox 52 added support for returning promises from listeners in onBeforeRequest.

Would you be down for a PR to add support for this functionality? I still don't know how to use the latest code in master in an app, but I'd be happy to submit a PR for both the 6.x.y branch and another one for master :P

Question: Can we load extensions from Web Stor?

I tried loading Grammarly from the file system, I don't get any errors but I don't see Grammarly active either. Usually, Chrome doesn't like extensions loaded from the filesystem.

Can you give me an example of how to load any of the Web Store extensions if that is possible?

How to properly open windows for browser Action popups

Hey! I'm loving the library. I'm currently working on getting darkreader to run, and I'm having a problem with the popup action.

I'm opening a page to the popupPage URL, and it's loading, but it's stuck on a loading page.

Similarly, when I try to load the beastify webextension example, it's giving me the error browser is not defined. Is there some additional setup I need to do for these pages to make them work correctly? Like, do I need to manually inject the preload script into them?

I'm using electron-extension 6.0.4 and electron 9.2.0

Cannot use import statement outside a module

I had installed the electron-extensions package in my existing working Electron sample.

Pasted below lines into main process:
`import { ExtensibleSession } from 'electron-extensions/main';
import { app } from 'electron';

const extensions = new ExtensibleSession();

(async () => {
await app.whenReady();
extensions.loadExtension('C:/.../abcdefghijklmnoprstuwxyz'); // Path to the extension to load
})();`

I am getting the above mentioned error, I tried adding type:module to the package.json file.
Nothing helped, may be I need to play around a bit.
Any suggestions?

Known supported extensions

  • uBlock Origin
  • Grammarly
  • LastPass
  • Dark Reader
  • TamperMonkey
  • 1Password X
  • Simplify Gmail
  • Boomerang
  • Zoom Scheduler
  • Dropbox for Gmail
  • Full Page Screen Capture
  • Mixmax
  • Gmelius
  • Todoist for Gmail
  • Streak CRM
  • Mailtrack
  • HubSpot Sales
  • GoToMeeting

Please write in the comments below if you'd like to see support for some extension that isn't listed above.

Getting the tab information from electron window

Hi! First things first, huge thank you for developing the package and actually discussing with Electron dev team in regards of supporting chrome extensions (non devtools ones) natively.

I have an extension that needs to access tab.audible - though without chrome.tabs.query working properly I don't know how to access the only "tab" that is open in electron window.

background.js

chrome.runtime.onConnect.addListener(async function (port) {
  port.onMessage.addListener(async function handler(msg, sender) {
      // is it possible to access the tab info that sent the message here?
  });
});

I am not even sure if I do get the tab instance, will audible property be working...

If you could guide me in that matter - that would be great, and if it's not possible, I am willing to try and implement this piece of API, though I would need some guidance as well.

Thanks again for the great package and working on electron+chrome extensions combo!

electron-extensions 7.0.0

This version is a complete rewrite of the package to use the new Electron's native-backed extensions system directly from Chromium. The API will completely change.

Expect it to:

  • be more stable
  • be much more performant, since the important parts like background pages or content_scripts aren't implemented in JS anymore
  • be smaller in bundle size
  • have more APIs
  • have more user-friendly API to use in an Electron app

Support darkreader

  • chrome.browserAction.setBadgeText
  • chrome.runtime.onConnect
  • chrome.tabs.query
  • chrome.runtime.onMessage
  • chrome.tabs.sendMessage
  • chrome.storage.*
  • chrome.i18n.getMessage

Active loaded extension

I have two extensions and i loaded them like this
image

The first question is: where my extension was loaded?
If it was loaded at my main BrowserWindow object, how can i active it?

Does it work with content scripts that do not run in background page?

For example, if I have a config like this:

{
  "manifest_version": 2,
  "name": "my extension",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": [
        "https://*.google.com/*"
      ],
      "js": [
        "content.js"
      ]
    }
  ]
}

Will this inject my script when I open google.com and allow the script to work with the DOM?

Thank you

Tracking issue for Chrome APIs

Update: some of the extensions APIs are supported by the new Electron native Chrome extensions system, for reference: https://github.com/electron/electron/blob/master/docs/api/extensions.md

Aside that, this package brings support for more APIs and provides a way to handle UI related actions.

List of currently and planned to be supported APIs:
It also can be found here.

  • tabs
    • onCreated
    • onUpdated
    • onActivated
    • onRemoved
    • insertCSS
    • get
    • getCurrent
    • getAllInWindow
    • getSelected
    • update
    • query
    • create
    • reload
    • detectLanguage
    • duplicate
    • highlight
    • move
    • discard
    • goForward
    • goBack
    • onMoved
    • onSelectionChanged
    • onActiveChanged
    • onHighlightChanged
    • onHighlighted
    • onDetached
    • onAttached
    • onReplaced
  • windows
    • onCreated
    • onFocusChanged
    • onRemoved
    • get
    • getCurrent
    • getAll
    • create
    • update
    • remove
    • getLastFocused
  • webNavigation
    • onBeforeNavigate
    • onCommitted
    • onCompleted
    • onCreatedNavigationTarget
    • onDOMContentLoaded
    • onReferenceFragmentUpdated
    • onTabReplaced
    • onHistoryStateUpdated
    • getFrame
    • getAllFrames
  • webRequest
    • onBeforeRequest
    • onBeforeSendHeaders
    • onHeadersReceived
    • onSendHeaders
    • onCompleted
    • onErrorOccurred
    • onResponseStarted
    • onBeforeRedirect
  • cookies
    • onChanged
    • get
    • getAll
    • set
    • remove
    • getAllCookieStores
  • browserAction
  • contextMenus

Not working

I used the example code in the readme and it gave me this error

App threw an error during load
TypeError: electron_1.protocol.registerSchemesAsPrivileged is not a function
    at Object.exports.registerProtocols (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\main\services\protocols.js:8:25)
    at new ExtensionsMain (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\main\index.js:20:20)
    at Object.<anonymous> (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\main\index.js:71:26)
    at Object.<anonymous> (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\main\index.js:73:3)
    at Module._compile (internal/modules/cjs/loader.js:693:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:704:10)
    at Module.load (internal/modules/cjs/loader.js:602:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:541:12)
    at Function.Module._load (internal/modules/cjs/loader.js:533:3)
    at Module.require (internal/modules/cjs/loader.js:640:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\index.js:6:10)
    at Object.<anonymous> (C:\Users\ender\Desktop\Dot Browser\desktop\node_modules\electron-extensions\build\index.js:8:3)
    at Module._compile (internal/modules/cjs/loader.js:693:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:704:10)
    at Module.load (internal/modules/cjs/loader.js:602:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:541:12)
    at Function.Module._load (internal/modules/cjs/loader.js:533:3)
    at Module.require (internal/modules/cjs/loader.js:640:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at f (C:\Users\ender\Desktop\Dot Browser\desktop\build\main.js:2040:1092)
    at u (C:\Users\ender\Desktop\Dot Browser\desktop\build\main.js:2040:1430)`

objectToArray function mangles requestHeaders and responseHeaders

The following function in web-request.ts returns unexpected results:

const objectToArray = (obj: any): any[] => {
  const arr: any = [];
  Object.keys(obj).forEach(k => {
    if (obj[k]) {
      arr.push({ name: k, value: obj[k][0] });
    }
  });
  return arr;
};

Rather than returning correct header value, it returns the first symbol of every header value.
Dropping the [0] fixes the problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.