GithubHelp home page GithubHelp logo

mozilla / webextension-polyfill Goto Github PK

View Code? Open in Web Editor NEW
2.6K 44.0 212.0 287 KB

A lightweight polyfill library for Promise-based WebExtension APIs in Chrome

License: Mozilla Public License 2.0

JavaScript 100.00%

webextension-polyfill's Introduction

WebExtension browser API Polyfill

This library allows extensions that use the Promise-based WebExtension/BrowserExt API being standardized by the W3 Browser Extensions group to run on Google Chrome with minimal or no changes.

CircleCI codecov devDependency Status npm version

This library doesn't (and it is not going to) polyfill API methods or options that are missing on Chrome but natively provided on Firefox, and so the extension has to do its own "runtime feature detection" in those cases (and then eventually polyfill the missing feature on its own or enable/disable some of the features accordingly).

Table of contents

Supported Browsers

Browser Support Level
Chrome Officially Supported (with automated tests)
Firefox Officially Supported as a NO-OP (with automated tests for comparison with the behaviors on Chrome)
Opera / Edge (>=79.0.309) Unofficially Supported as a Chrome-compatible target (but not explicitly tested in automation)

The polyfill is being tested explicitly (with automated tests that run on every pull request) on officially supported browsers (that are currently the last stable versions of Chrome and Firefox).

On Firefox, this library is actually acting as a NO-OP: it detects that the browser API object is already defined and it does not create any custom wrappers. Firefox is still included in the automated tests, to ensure that no wrappers are being created when running on Firefox, and for comparison with the behaviors implemented by the library on Chrome.

Installation

A new version of the library is built from this repository and released as an npm package.

The npm package is named after this repo: webextension-polyfill.

For the extension that already include a package.json file, the last released version of this library can be quickly installed using:

npm install --save-dev webextension-polyfill

Inside the dist/ directory of the npm package, there are both the minified and non-minified builds (and their related source map files):

  • node_modules/webextension-polyfill/dist/browser-polyfill.js
  • node_modules/webextension-polyfill/dist/browser-polyfill.min.js

For extensions that do not include a package.json file and/or prefer to download and add the library directly into their own code repository, all the versions released on npm are also available for direct download from unpkg.com:

and linked to the Github releases:

Basic Setup

In order to use the polyfill, it must be loaded into any context where browser APIs are accessed. The most common cases are background and content scripts, which can be specified in manifest.json (make sure to include the browser-polyfill.js script before any other scripts that use it):

{
  // ...

  "background": {
    "scripts": [
      "browser-polyfill.js",
      "background.js"
    ]
  },

  "content_scripts": [{
    // ...
    "js": [
      "browser-polyfill.js",
      "content.js"
    ]
  }]
}

For HTML documents, such as browserAction popups, or tab pages, it must be included more explicitly:

<!DOCTYPE html>
<html>
  <head>
    <script type="application/javascript" src="browser-polyfill.js"></script>
    <script type="application/javascript" src="popup.js"></script>
  </head>
  <!-- ... -->
</html>

And for dynamically-injected content scripts loaded by tabs.executeScript, it must be injected by a separate executeScript call, unless it has already been loaded via a content_scripts declaration in manifest.json:

browser.tabs.executeScript({file: "browser-polyfill.js"});
browser.tabs.executeScript({file: "content.js"}).then(result => {
  // ...
});

Basic Setup with ES6 module loader

The polyfill can also be loaded using the native ES6 module loader available in the recent browsers versions.

Be aware that the polyfill module does not export the browser API object, but defines the browser object in the global namespace (i.e. window).

<!DOCTYPE html>
<html>
  <head>
    <script type="module" src="browser-polyfill.js"></script>
    <script type="module" src="background.js"></script>
  </head>
  <!-- ... -->
</html>
// In background.js (loaded after browser-polyfill.js) the `browser`
// API object is already defined and provides the promise-based APIs.
browser.runtime.onMessage.addListener(...);

Basic Setup with module bundlers

This library is built as a UMD module (Universal Module Definition), and so it can also be used with module bundlers (and explicitly tested on both webpack and browserify) or AMD module loaders.

src/background.js:

var browser = require("webextension-polyfill");

browser.runtime.onMessage.addListener(async (msg, sender) => {
  console.log("BG page received message", msg, "from", sender);
  console.log("Stored data", await browser.storage.local.get());
});

browser.browserAction.onClicked.addListener(() => {
  browser.tabs.executeScript({file: "content.js"});
});

src/content.js:

var browser = require("webextension-polyfill");

browser.storage.local.set({
  [window.location.hostname]: document.title,
}).then(() => {
  browser.runtime.sendMessage(`Saved document title for ${window.location.hostname}`);
});

By using require("webextension-polyfill"), the module bundler will use the non-minified version of this library, and the extension is supposed to minify the entire generated bundles as part of its own build steps.

If the extension doesn't minify its own sources, it is still possible to explicitly ask the module bundler to use the minified version of this library, e.g.:

var browser = require("webextension-polyfill/dist/browser-polyfill.min");

...

Usage with webpack without bundling

The previous section explains how to bundle webextension-polyfill in each script. An alternative method is to include a single copy of the library in your extension, and load the library as shown in Basic Setup. You will need to install copy-webpack-plugin:

npm install --save-dev copy-webpack-plugin

In webpack.config.js, import the plugin and configure it this way. It will copy the minified file into your output folder, wherever your other webpack files are generated.

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  /* Your regular webpack config, probably including something like this:
  output: {
    path: path.join(__dirname, 'distribution'),
    filename: '[name].js'
  },
  */
  plugins: [
    new CopyWebpackPlugin({
      patterns: [{
        from: 'node_modules/webextension-polyfill/dist/browser-polyfill.js',
      }],
    })
  ]
}

And then include the file in each context, using the manifest.json just like in Basic Setup.

Using the Promise-based APIs

The Promise-based APIs in the browser namespace work, for the most part, very similarly to the callback-based APIs in Chrome's chrome namespace. The major differences are:

  • Rather than receiving a callback argument, every async function returns a Promise object, which resolves or rejects when the operation completes.

  • Rather than checking the chrome.runtime.lastError property from every callback, code which needs to explicitly deal with errors registers a separate Promise rejection handler.

  • Rather than receiving a sendResponse callback to send a response, onMessage listeners simply return a Promise whose resolution value is used as a reply.

  • Rather than nesting callbacks when a sequence of operations depend on each other, Promise chaining is generally used instead.

  • The resulting Promises can be also used with async and await, rather than dealt with directly.

Examples

The following code will retrieve a list of URLs patterns from the storage API, retrieve a list of tabs which match any of them, reload each of those tabs, and notify the user that is has been done:

browser.storage.local.get("urls").then(({urls}) => {
  return browser.tabs.query({url: urls});
}).then(tabs => {
  return Promise.all(
    Array.from(tabs, tab => browser.tabs.reload(tab.id))
  );
}).then(() => {
  return browser.notifications.create({
    type: "basic",
    iconUrl: "icon.png",
    title: "Tabs reloaded",
    message: "Your tabs have been reloaded",
  });
}).catch(error => {
  console.error(`An error occurred while reloading tabs: ${error.message}`);
});

Or, using an async function:

async function reloadTabs() {
  try {
    let {urls} = await browser.storage.local.get("urls");

    let tabs = await browser.tabs.query({url: urls});

    await Promise.all(
      Array.from(tabs, tab => browser.tabs.reload(tab.id))
    );

    await browser.notifications.create({
      type: "basic",
      iconUrl: "icon.png",
      title: "Tabs reloaded",
      message: "Your tabs have been reloaded",
    });
  } catch (error) {
    console.error(`An error occurred while reloading tabs: ${error.message}`);
  }
}

It's also possible to use Promises effectively using two-way messaging. Communication between a background page and a tab content script, for example, looks something like this from the background page side:

browser.tabs.sendMessage(tabId, "get-ids").then(results => {
  processResults(results);
});

And like this from the content script:

browser.runtime.onMessage.addListener(msg => {
  if (msg == "get-ids") {
    return browser.storage.local.get("idPattern").then(({idPattern}) => {
      return Array.from(document.querySelectorAll(idPattern),
                        elem => elem.textContent);
    });
  }
});

or:

browser.runtime.onMessage.addListener(async function(msg) {
  if (msg == "get-ids") {
    let {idPattern} = await browser.storage.local.get("idPattern");

    return Array.from(document.querySelectorAll(idPattern),
                      elem => elem.textContent);
  }
});

Or vice versa.

Usage with TypeScript

There are multiple projects that add TypeScript support to your web-extension project:

Project Description
@types/webextension-polyfill Types and JS-Doc are automatically generated from the mozilla schema files, so it is always up-to-date with the latest APIs. Formerly known as webextension-polyfill-ts.
web-ext-types Manually maintained types based on MDN's documentation. No JS-Doc included.
@types/chrome Manually maintained types and JS-Doc. Only contains types for chrome extensions though!

Known Limitations and Incompatibilities

This library tries to minimize the amount of "special handling" that a cross-browser extension has to do to be able to run on the supported browsers from a single codebase, but there are still cases when polyfillling the missing or incompatible behaviors or features is not possible or out of the scope of this polyfill.

This section aims to keep track of the most common issues that an extension may have.

No callback supported by the Promise-based APIs on Chrome

While some of the asynchronous API methods in Firefox (the ones that return a promise) also support the callback parameter (mostly as a side effect of the backward compatibility with the callback-based APIs available on Chrome), the Promise-based APIs provided by this library do not support the callback parameter (See "#102 Cannot call browser.storage.local.get with callback").

No promise returned on Chrome for some API methods

This library takes its knowledge of the APIs to wrap and their signatures from a metadata JSON file: api-metadata.json.

If an API method is not yet included in this "API metadata" file, it will not be recognized. Promises are not supported for unrecognized APIs, and callbacks have to be used for them.

Chrome-only APIs have no promise version, because extensions that use such APIs would not be compatible with Firefox.

File an issue in this repository for API methods that support callbacks in Chrome and Firefox but are currently missing from the "API metadata" file.

Issues that happen only when running on Firefox

When an extension that uses this library doesn't behave as expected on Firefox, it is almost never an issue in this polyfill, but an issue with the native implementation in Firefox.

"Firefox only" issues should be reported upstream on Bugzilla:

API methods or options that are only available when running in Firefox

This library does not provide any polyfill for API methods and options that are only available on Firefox, and they are actually considered out of the scope of this library.

tabs.executeScript

On Firefox browser.tabs.executeScript returns a promise which resolves to the result of the content script code that has been executed, which can be an immediate value or a Promise.

On Chrome, the browser.tabs.executeScript API method as polyfilled by this library also returns a promise which resolves to the result of the content script code, but only immediate values are supported. If the content script code result is a Promise, the promise returned by browser.tabs.executeScript will be resolved to undefined.

MSEdge support

MSEdge versions >= 79.0.309 are unofficially supported as a Chrome-compatible target (as for Opera or other Chrome-based browsers that also support extensions).

MSEdge versions older than 79.0.309 are unsupported, for extension developers that still have to work on extensions for older MSEdge versions, the MSEdge --ms-preload manifest key and the Microsoft Edge Extension Toolkit's Chrome API bridge can be used to be able to load the webextension-polyfill without any MSEdge specific changes.

The following Github repository provides some additional detail about this strategy and a minimal test extension that shows how to put it together:

Contributing to this project

Read the contributing section for additional information about how to build the library from this repository and how to contribute and test changes.

webextension-polyfill's People

Contributors

akhilpanchal avatar dependabot[bot] avatar dgp1130 avatar diox avatar exe-boss avatar fregante avatar gudahtt avatar infokiller avatar josephfrazier avatar kmaglione avatar lusito avatar lydell avatar manvel avatar mozilla-github-standards avatar muffinresearch avatar poziworld avatar regseb avatar renovate-bot avatar renovate[bot] avatar rob--w avatar rpl avatar serv-inc avatar shubhamchinda avatar siddharth1698 avatar tima1702 avatar treora avatar vapier avatar willdurand avatar xeenon avatar yfdyh000 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  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

webextension-polyfill's Issues

browser.permissions.request doesn't return a promise

Browser: Chrome 58
Library version: 0.1.1

I'm using this code on an extension options page:

browser.permissions.request({
            origins: ["<all_urls>"]
        }).then(function (granted) {
                // do something
            })

The popup request is showing, but the code throws the error:

Uncaught TypeError: Cannot read property 'then' of undefined

Error with tabs.sendMessage when no response

A Promise that will be fulfilled with the JSON response object sent by the handler of the message in the content script, or with no arguments if the content script did not send a response.

When nothing is returned from the content script, Chrome throws an error. The polyfill should presumably implicitly return something if the content script doesn't, or otherwise suppress this error.

Error outside of promise with button notification

browser.notifications.create(notification_id, options)
	.catch(error=>{
		reject(error);
	})
;

I use a catch method to detect if the plateform support the buttons on notification (Firefox/Opera does not support them yet).
There's one problem with browser.notifications.create. In Firefox, this function use a Promise that should send the errors that the buttons are not supported in the catch of the Promise, and that's not the case.

browser.tabs.getCurrent() resolves to empty array instead of undefined

According to the docs browser.tabs.getCurrent() should return a promise which resolves to undefined when called from a context that has no browser tab. The API works as expected on Firefox, but resolves to an empty array on Chrome.

browser.tabs.getCurrent().then(function(tab) {
    console.log(1, tab);
  })
chrome.tabs.getCurrent(function(tab) {
  console.log(2, tab);
});

Firefox background or popup script:

1 undefined
2 undefined

Chrome background or popup script:

1 Array(0)
2 undefined

ESLint causes build on windows to fail with default git settings

Because ESLINT is set to need linefeeds set to LF, by default on windows building this will fail.

There's a few possible workarounds - the easiest being setting global git config core.autocrlf to force linefeeds to LF. However, this can break other programs' builds. A local git config can also be used but that doesn't help if using NPM to pull this repo.

I'm going to do a pull request for adding a .gitattributes file which forces line feeds to LF regardless of the git config for *.js files in the repo.

Uncaught ReferenceError: module is not defined at browser-polyfill.js:363

Guys, I just added the library in my extension for using it from a background script from chrome. I added a first line before importing the browser-polyfill.js file, since there is no browser object in chrome:
browser = (window.chrome)? window.chrome : browser;
But then, I am receiving the following error:
Uncaught ReferenceError: module is not defined at browser-polyfill.js:363

How can I solve this? Is anything extra that I should do before importing the file?
Thanks in advance

sendResponse undefined when executing browser.runtime.onMessage.addListener((message, sender, sendResponse)

Am I missing something here? According to the docs (https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage), onMessage should always have a third 'sendResponse' function parameter. The code around https://github.com/mozilla/webextension-polyfill/blob/master/src/browser-polyfill.js#L330 suggests that I need to define the listener as following:

browser.runtime.onMessage.addListener((message, sender) => {
    return new Promise((resolve, reject) => {

    })
})

Doesn't this break for browsers without the polyfill? (e.g. Firefox/Edge)

Broken?

The current master doesn't seem to work.
At least not for me.

When I add the unminimized distribution to manifest.json (see below), the output is as follows:

Error: Error: Invocation of form runtime.sendNativeMessage(string, string, function) doesn't match definition runtime.sendNativeMessage(string application, object message, optional function responseCallback)

utilizing the minimized version, I receive the following error output

browser-polyfill.min.js:18 Uncaught SyntaxError: Unexpected token {

An excerpt from my manifest.json

"background": {
    "scripts": ["webextension-polyfill/dist/browser-polyfill.js",
                "background.js"]
  },

Browser: Chrome 54.0.2840.99

Support page action show_matches/hide_matches

page action now has a nice show/hide_matches feature. It would be great to polyfill this. I could imagine doing so by having the add-on read the manifest.json, pull out the hide_matches lines, and then install a tabs updated and activaged listener that shows/hides the page action.

Provide dist files at a static url for people to download without building

Although not strictly necessary for Firefox, I have seen the polyfill being used in webextensions. And I think it's reasonable to do so. Developers want to have as few differences as possible between the chrome and the firefox version of their add-on.

We could save developers and reviewers some time (and possible mistakes), if authoritative dist files would be available for people to download and use. Our validation tools can verify the checksum and mark the files as trusted automatically during review.

Developers don't need to build the polyfill.
Reviewers don't need to review it.
Everybody wins. ๐ŸŽ‰

Can't send runtime messages in Firefox; Error: "TypeError: promise.then is not a function"

I'm getting the following error in Firefox when I try to send a runtime message from a content script to a background script:

Unhandled promise rejection 
TypeErrorโ€‹columnNumber: 9โ€‹
fileName: "resource://gre/modules/ExtensionCommon.jsm"โ€‹
lineNumber: 490โ€‹
message: "promise.then is not a function"
โ€‹stack: "wrapPromise/<@resource://gre/modules/ExtensionCommon.jsm:490:9_@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:69770
wrapPromise@resource://gre/modules/ExtensionCommon.jsm:489:14
callAsyncFunction@resource://gre/modules/ExtensionCommon.jsm:697:12
stub@resource://gre/modules/Schemas.jsm:2297:22
t/<@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96454
b@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:50347
A/o._invoke@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:50137
E/</t[n]@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:50523
e@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96739
i/<@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96722
_@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:69770
i@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96680
u<@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96912
@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:96983
r@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:105
@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:97021
r@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:105
@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:517
@moz-extension://63f25ebd-93c8-554e-bc69-b002724886b7/content_script.js:1:2
inject@resource://gre/modules/ExtensionContent.jsm:483:18
injectInto@resource://gre/modules/ExtensionContent.jsm:388:14
"โ€‹__proto__: Object { stack: "", โ€ฆ } content_script.js:1:69061
// content_script.js

import browser from "webextension-polyfill";

async function sendMessage() {
  const { response } = await browser.runtime.sendMessage({
    kind: "LOREM",
    data: "ipsum"
  });

  console.log("content_script: response:", response);
}

sendMessage();
// background_page.js

import browser from "webextension-polyfill";

browser.runtime.onMessage.addListener(async ({ kind, data }) => {
  if (kind === "LOREM") {
    return Promise.resolve({ response: data });
  }

  return false;
});

I'm using webpack with babel-polyfill to include the generator runtime:

module.exports = {
  entry: {
    background_page: ["babel-polyfill", "./src/background_page.js"],
    content_script: ["babel-polyfill", "./src/content_script.js"]
  },

  output: {
    path: path.resolve(__dirname + "/dist"),
    filename: "[name].js"
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["babel-preset-env"]
          }
        }
      }
    ],
  }
}

It works fine in Chrome. What am I missing?

How not to include in Firefox

My add-on sends webextension-polyfill dynamically to the active tab from a popup or sidebar. I would like to stop including the polyfill in Firefox releases of my add-on. How can I not send the polyfill in Firefox while still sending it to Chromium?

Prevent accidentally using a source version of the polyfill

In mdn/webextensions-examples#131 the developer accidentally included the polyfill source file instead of a built source file. RTFM'ing will prevent this from happening in most cases but could we also prevent it in another way? I think it will cut down on invalid bug reports. Ideas:

  • log an error that says "this is the wrong file" (or something) if you run the polyfill from source file.
  • ... or completely die with an exception when polyfilling from source
  • figure out how to strip these errors out in the dist file

browser.devtools.* isn't polyfilled

First of all, thanks for writing and maintaining this polyfill!

However...I'm trying to port a Chrome extension to Firefox and having a difficult time, as it seems that not all API methods are polyfilled. One example is browser.devtools.panels.create, which uses a callback signature in Chrome but is promise-based in Firefox. I've got the compiled polyfill implemented and Chrome is throwing an error:

Uncaught TypeError: Cannot read property 'then' of undefined
    at Object.2../actions/inspect (devtools.js:39)
    at s (devtools.js:1)
    at e (devtools.js:1)
    at devtools.js:1

That line points to this code:

browser.devtools.panels.create(name, '', 'panel/index.html').then((extensionPanel)  => {
//....
})

Is there a list of all the polyfilled methods somewhere, and/or perhaps a status for when the missing methods will be implemented?

Edit: I see the metadata file does not include any devtools APIs. Bummer.

browser.webRequest.onAuthRequired.addListener does not accept Promises on chrome

Chrome does not support Promises in and uses callback function instead so the code below will not work on chrome

browser.webRequest.onAuthRequired.addListener(
	someCallbackFunctionThatReturnsPromise,
	{urls: ['<all_urls>']},
	['blocking']
);

browser.webRequest.onAuthRequired.addListener should rewrite 'blocking' into 'asyncBlocking' and call chrome's callback function when provided Promise is resolved.

Can't import (and not use) with webpack

I'm writing code which I share between a web page and an extension, and I'm using webpack. So this presents a giant problem for me in that I can't import browser from 'webextension-polyfill' in shared code because it tries to do things like poke at chrome on import.
I'm trying to use dynamic imports but that's really a sub-par solution.

I'd like to be able to import webextension-polyfill without it crashing a web page on import.

I get this in Safari: https://user-images.githubusercontent.com/245131/37903693-7a0bee60-3101-11e8-99a3-e5e5d4389cea.png

browser-polyfill.min.js not working with Chrome

When I use the non-minified version in /dist my extension works fine. When I switch out to use browser-polyfill.min.js instead, I get the following errors:

Uncaught SyntaxError: Unexpected token { browser-polyfill.min.js:18

The minified version seems to have a problem? Anyone else seeing this?

Cannot call browser.storage.local.get with callback; Error: Expected at most 1 argument for get(), got 2

Hi,

I've found this polyfill and tried to convert a Firefox addon to AMO but it don't work, it throw error in the console window: each time I load the extension in Chromium: https://i.imgur.com/l9JZ5dB.png

I've load the polyfill via the manifest.json like in the exemple on the readme.

Here's a link to the source of the addon in case you need it: https://dl.dropboxusercontent.com/s/68ph7gwzoltrktv/TranslateExtension.zip

Regards :octocat:

Typescript typings

There are typings for the callback based API at @types/chrome but not for the promise based API.

browser.menus is undefined

browser.menus is undefined, this should presumably just alias to browser.contextMenus for compatibility.

clipboardWrite in manifest.json produces error in Chrome with v0.2.1 of the polyfill

I have a browser extension that requires clipboardWrite permission under Firefox.
(copying under Chrome works without any additional permissions)

Everything works fine with webextension-polyfill v0.1.2 (the same code running in both Firefox and Chrome) but if I update webextension-polyfill to v0.2.1 it fails to load in Chrome due to this error:

chrome.clipboard is not supported on this platform or manifest version

chrome.clipboard is not supported on this platform or manifest version

If I remove clipboardWrite permission from manifest.json then it loads correctly in Chrome, but clipboard manipulation stops working in Firefox ๐ŸŒต

Looks like a bug, but maybe I missing something obvious here?
Let me know if I can test something or provide more debug information.

Deferred.resolve not passing data... Works in chrome.

Extension pop up window sends message requesting important info:

let Params = { Event: 'CreateNewPostInit' };

browser.runtime.sendMessage(Params).then(function (response) {
	console.log(response.ImportantInfo);
});

Background page receives:

browser.runtime.onMessage.addListener(GotMessage);

function GotMessage(request, sender) {
	var defd = null;

	switch (request.Event) {
		case "CreateNewPostInit":
			defd = $.Deferred();
			CreateNewPostInit(request, sender, defd);
			return defd.promise();
			break;
	}
}

function CreateNewPostInit(request, sender, defd) {
	defd.resolve({ ImportantInfo: "42" });
}

In Chrome "42" is logged to the console from the line in the then after the sendMessage. Firefox throws a "TypeError: response is undefined".

Thanks for the assistance in advance.

Bug with identity.launchWebAuthFlow

identity.launchWebAuthFlow should return a Promise fulfilled with the redirect URL.

Error: Invocation of form identity.launchWebAuthFlow(object) doesn't match definition identity.launchWebAuthFlow(object details, function callback)

runtime.sendMessage/onMessage

Hello

I'm running into problems when trying to use browser.runtime.sendMessage and browser.runtime.onMessage with this polyfill on Chrome 61.

I have this code that works fine:

// in background script, run when the extension is loaded
chrome.runtime.onMessage.addListener((message, sender) => {
  console.log("background script got message", message, "from", sender);
});

// in content script, run when the user presses a button
chrome.runtime.sendMessage({type: "event", eventName: "THE_EVENT"});

If I replace chrome with browser in the background script, I get this in its console:

image

and the listener is not run.

Independently, if I replace chrome with browser on the content script side, I get this in the console of the page:

image

but the listener is run.

If I replace chrome with browser on both sides, then the content script says this instead:

image

and the background script message remains unchanged.

I'm new to writing browser extensions so I'm not sure if this might be a bug in the polyfill or if not using the API quite right.

Offer an easier way to upgrade the polyfill in a WebExtension

The documentation currently suggests this approach for installing the polyfill in a WebExtension:

  • Clone the webextension-polyfill repo
  • Build the polyfill distribution
  • Copy the distribution into your WebExtension source

This works fine the first time but it doesn't offer an easy way to upgrade the polyfill when the upstream source changes.

Can you document (or implement) a better way? There would be a couple ways to approach it. The first thing that comes to mind is this:

  • Add a package.json to the WebExtension
  • Declare webextension-polyfill as a dependency
  • Configure the WebExtension project with babel to allow imports from node_modules and build an es6-friendly distribution for your WebExtension source files
  • Every time the dependencies are upgraded, the polyfill will be upgraded

Perhaps there is a simpler way that does not involve babel transpilation. Maybe with bower ?

Chrome: Error in event handler for tabs.onUpdated: Error: Expected at most 0 arguments for show(), got 1

Screenshot

My extension works without any errors in the latest version of Firefox. In Chrome I get this error.
Honestly, I'm not sure what is causing this error. I am using tabs.onUpdated and within that I'm using pageAction.show(). If you need more information, tell me.

Edit:
Maybe the issue is that I'm calling browser.pageAction.show() with a tab id in as the first argument as required by Firefox. I guess Chrome doesn't support it?
I tried to work around it using browser.pageAction.show(browser.pageAction.show.length?tabId:undefined).
But that didn't make any difference.

Edit2:
It seems to be a misconfiguration in the browser-polifill library. Setting minArgs and maxArgs of show under pageAction to 1 seems to fix it.

Edit3:
Actually I'm still getting an error:
Error: Invocation of form pageAction.show(integer, function) doesn't match definition pageAction.show(integer tabId)

Edit4:
Here is the code causing the error:

browser.tabs.query({}).then( tabs => {
    if (!tabs)
        return
    let promiseArray = []
    tabs.forEach(tab => {
        let tabId = tab.id
        promiseArray.push(browser.pageAction.show(tabId).then(()=>{
            return browser.pageAction.setIcon({tabId: tabId, path: 'disabled.ico'})
        }))
    })
    return Promise.all(promiseArray)
}).then(()=>{
    /* ... */
}).catch(console.error)

Publish to npm for use with browserify/webpack/etc.

For new WebExtension developers its a bit tedious to download, install dependencies, grunt, and then copy out the built JS file. It would be nicer to npm i --save-dev or something.

Alternatively, hosting a built copy here in releases--even if marked pre-release--would make using this much easier for newcomers.

Thanks!
๐ŸŽฉ

README.md example is misleading

The example says browser.storage.get but in firefox is browser.storage.local.get is this stating that polyfill creates a different API than the actual browser API?

runtime.onMessage is broken

Error in event handler for runtime.onMessage: TypeError: sendResponse is not a function
    at runtime.onMessage.addListener (chrome-extension://oommdnlanbpnfobibbnfmnmobfddkofp/background.js:4:2)
    at onMessage (chrome-extension://oommdnlanbpnfobibbnfmnmobfddkofp/browser-polyfill.js:1338:22)

https://github.com/mozilla/webextension-polyfill/blob/master/src/browser-polyfill.js#L314-L328
I'm not sure this is due to API changes or something. The wrapper of listener looks completely nonsense to me. Shouldn't it just invoke the listener directly?

      return function onMessage(message, sender, sendResponse) {
        return listener(message, sender, sendResponse);
      };

Export as module

I would like to use this as a module in webpack. Would it be possible to publish a version that exports browser?

I made an attempt on this PR and it did work when I consume it as a module, however the way the tests load the script don't work: #28

Nested runtime.sendMessage/tabs.sendMessage calls fail

I've put together this test case real quick. This demonstrates how the sendMessage handler within onMessage handler is never triggered after the message being received from the initial sendMessage call from the content script.

I don't want to delve into the nastiness of where any of this gets swollen up within the chain of Proxys and wrapper functions, but it's definitely not right.

To see the problem open the background tab and click the browser action icon. The expected order of logged lines is okty plsRespond, followed by success, but instead success is logged immediately and also a "Could not establish connection. Receiving end does not exist." error.

Any way to load webextension-polyfill as a module?

I would like to load webextension-polyfill as a module, with import of require. Is this possible? I was not able to find any example of that. Most references I've found were loading it via manifest.json.

What I want to do is to detect whether browser is defined (typeof browser === "undefined") in a background script. Then, depending on the result, I will decide wither to inject polyfill to a tab or not.
But, since polyfill is already loaded via manifest.json, browser is always defined and my approach does not work.

My idea was to do browser support detection first, and then load polyfill as a module import, but I can't find any information anywhere about whether it is possible and how this can be done. What I've tried failed so far. Or am I approaching it in a wrong way?

Building in bash on Windows 10 fails with closure-compile error

$ grunt
Running "eslint:src" (eslint) task

Running "eslint:test" (eslint) task

Running "replace:dist" (replace) task
>> 5 replacements in 1 file.

Running "closure-compiler:dist" (closure-compiler) task
Warning: Compilation error Use --force to continue.

Aborted due to warnings.

Works fine in the Linux Subsystem (lxss) though. Worth a look for Windows-based builders (like myself).

Thanks for building this!

Release should contain final built versions

Hi,

The releases tab here in Github should contain the built versions of the polyfill including the final compressed version. The way it is now, it forces all users to download and build their own version which is basically equal to everyone else version.

Cheers

runtime namespace becomes undefined after certain sequence of requests

manifest.json:

{
  "manifest_version": 2,
  "name": "Test",
  "version": "1.0.0",
  "background": {
    "scripts": [ "browser-polyfill.js", "background.js" ]
  },
  "permissions": [ "storage" ]
}

background.js:

var someUrl = browser.runtime.getURL("background.js");
var storageResult = browser.storage.local.get();

When loading the extension, the background page gives the following warning 11 times:

Previous API instantiation failed.

and the following error once:

(BLESSED_EXTENSION context for oanfllegiohelcgnppacfjannjilkjpm) extensions::lastError:98: Uncaught Error: runtime namespace is null or undefined{Error: runtime namespace is null or undefined
    at assertRuntimeIsAvailable (extensions::lastError:98:11)
    at Object.clear (extensions::lastError:84:3)
    at handleResponse (extensions::sendRequest:77:15)}

This error appears every time a request is made to browser.storage. If however, I remove the someUrl line, storage requests keep working fine.

I've tried with both the minified and non minified version of the polyfill. Both using the latest release. I've been able to reproduce this issue in Google Chrome, Chromium and Vivaldi. All tests passed when building both polyfill scripts.

npm install fails due to wrong linebreaks [Windows 10 x64]

Hello,
I just cloned this repository and executed npm install and I see the following error:

$ npm install
npm WARN prepublish-on-install As of npm@5, prepublish scripts will run only for npm publish.
npm WARN prepublish-on-install (In npm@4 and previous versions, it also runs for npm install.)
npm WARN prepublish-on-install See the deprecation note in npm help scripts for more information.

[email protected] prepublish C:\Users\Juraj\git\addons\webextension-polyfill
npm run build && npm run test

[email protected] build C:\Users\Juraj\git\addons\webextension-polyfill
grunt

Running "eslint:src" (eslint) task

C:\Users\Juraj\git\addons\webextension-polyfill\src\browser-polyfill.js
1:48 error Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style
393:2 error Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style

C:\Users\Juraj\git\addons\webextension-polyfill\Gruntfile.js
1:62 error Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style
109:3 error Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style

โœ– 502 problems (502 errors, 0 warnings)
502 errors, 0 warnings potentially fixable with the --fix option.

Warning: Task "eslint:src" failed. Use --force to continue.

Aborted due to warnings.

I would expect the build procedure to be platform independent.

Replace API Metadata Database with Runtime Discovery

Manually listing functions seems inefficient and unnecessary. It is probably possible to detect whether a function should be converted by whether it returns anything and if it throws a "Invocation of form..." error

npm install fails with eslint error message

On a fresh clone ...

groovecoder:webextension-polyfill lcrouch$ npm i
npm WARN prefer global [email protected] should be installed with -g

> [email protected] prepublish /Users/lcrouch/code/webextension-polyfill
> npm run build && npm run test


> [email protected] build /Users/lcrouch/code/webextension-polyfill
> grunt

Running "eslint:src" (eslint) task

/Users/lcrouch/code/webextension-polyfill/Gruntfile.js
  36:1  error  Expected indentation of 18 spaces but found 28  indent
  37:1  error  Expected indentation of 18 spaces but found 28  indent

โœ– 2 problems (2 errors, 0 warnings)
  2 errors, 0 warnings potentially fixable with the `--fix` option.

Warning: Task "eslint:src" failed. Use --force to continue.

Aborted due to warnings.

npm ERR! Darwin 15.6.0
npm ERR! argv "/Users/lcrouch/.nvm/versions/node/v7.0.0/bin/node" "/Users/lcrouch/.nvm/versions/node/v7.0.0/bin/npm" "run" "build"
npm ERR! node v7.0.0
npm ERR! npm  v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: `grunt`
npm ERR! Exit status 3
npm ERR!
npm ERR! Failed at the [email protected] build script 'grunt'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the webextension-polyfill package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     grunt
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs webextension-polyfill
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls webextension-polyfill
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/lcrouch/code/webextension-polyfill/npm-debug.log

npm ERR! Darwin 15.6.0
npm ERR! argv "/Users/lcrouch/.nvm/versions/node/v7.0.0/bin/node" "/Users/lcrouch/.nvm/versions/node/v7.0.0/bin/npm" "i"
npm ERR! node v7.0.0
npm ERR! npm  v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! [email protected] prepublish: `npm run build && npm run test`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] prepublish script 'npm run build && npm run test'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the webextension-polyfill package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     npm run build && npm run test
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs webextension-polyfill
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls webextension-polyfill
npm ERR! There is likely additional logging output above.

Use in non-extensions?

It would be nice to use this in web page content scripts and web pages as well, for message passing.

I don't know about other browsers but in chrome you're permitted to use runtime.sendMessage/connect from a web page if an extension ID is provided. Unfortunately there is no such way to provide this and upon import I get the error:
Uncaught (in promise) Error: chrome.runtime.connect() called from a webpage must specify an Extension ID (string) for its first argument in chrome.

In Safari, I get the error:
screen shot 2018-03-26 at 14 24 49

I'm importing via import browser from webextension-polyfill`.

dist files for 0.2.1 seems to be missing changes from src

I've noticed that dist/browser-polyfill.js does not match the src/browser-polyfill.js. While src version incorporates the latest fix for #64 (const targetObject = Object.assign({}, chrome);), dist version misses it, still having const targetObject = Object.create(chrome);.

I think dist was probably not built to incorporate the latest changes.

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.