Why promise is undefined? chrome.tabs.query().then(); [duplicate] - google-chrome-extension

I've been writing some browser extensions in the last few weeks and until today I thought that a WebExtension for Firefox should work pretty much automatically in Chrome. So I tried to write my code according to Mozilla's examples.
But today I realized that there is no mention of Promises in the API documentation for Chrome Extensions.
I have strictly used Promises throughout the code for all my Extensions.
So now my question is, will my code work in Chrome? Or would it work if I add a var browser = chrome declaration at the very top?
Or does Chrome not support Promises on the API at all?
If Chrome doesn't support Promises on the API functions yet, will it support them in the future?
Note, I am aware of this project: https://github.com/mozilla/webextension-polyfill
But I'm not willing to go through the hassle of including that library everywhere. Also, it has annoying bugs in it.
And besides that I don't have Chrome or Chromium and I can't install them for privacy and security reasons.
Edit: They're finally starting to implement support for promises.

Official promise support is finally coming and has already been implemented on some of the APIs. At the time of writing:
browserAction
cookies
action
windows
storage
tabs
management
On GoogleChrome's Github you can already find a Hello world example using the chrome.tabs API with Promises (await):
chrome.runtime.onInstalled.addListener(async () => {
let url = chrome.runtime.getURL("hello.html");
let tab = await chrome.tabs.create({ url });
console.log(`Created tab ${tab.id}`);
});
As you can see, the promise support has simply been implemented on the chrome object, which now supports both Promises and callbacks. Firefox still uses the browser object for the promise API.

...until today I thought that a WebExtension for Firefox should work pretty much automatically in Chrome.
WebExtensions were created with backward compatibility with Chrome extensions in mind. chrome.* namespace is available for supported APIs. The goal here is to ease porting existing extensions to FF to quickly bootstrap the ecosystem.
However, Mozilla disregards forward compatibility with browser.* namespace. Mozilla decided to go with a promise-based approach for the API, but only for that new namespace.
So now my question is, will my code work in Chrome?
Or would it work if I add a var browser = chrome declaration at the very top?
No; they behave differently and have different signatures. Chrome will reject calls without required explicit callbacks. browser.* variants will emit a Promise instead.
Or does Chrome not support Promises on the API at all?
If Chrome doesn't support Promises on the API functions yet, will it support them in the future?
As mentioned in comments, Promise-based rewrite of the API is considered by Chrome, and it has been implemented, or started to be implemented, for MV3 extensions. However, there exist polyfills, including the one you mentioned. Other than wrapping methods yourself to create your own polyfill, there's no other solution.
And besides that I don't have Chrome or Chromium and I can't install them for privacy and security reasons.
Then you can't properly test your ports anyway; that's not a good approach for your potential users. You're better off not porting in this case.

I haven't looked at the browser API, so I may be off-base, but if the only difference is that the Firefox APIs return promises instead of using callbacks, the chrome-promise library might be able to help. It wraps all the API calls that require callbacks in functions that return promises instead.
You could then do something like this in Chrome:
var browser = new ChromePromise();
And then make promise calls:
browser.storage.local.get(null).then(data => console.log(data));
If you define the browser variable as a global and include that script before any others, you can just use it as a global and not have to include the polyfill in every file where you want to use it.
Edit: the author of chrome-promise is no longer maintaining it, other than fixing bugs. They list some alternative libraries here, including the Mozilla webextension-polyfill rejected by the OP. That library's readme explains how to make it available as a global variable in the various extension contexts where it's needed.

I created this library https://github.com/lawlietmester/webextension to make this without one general rule like in webextension-polyfill.
My library is crossbrowser way to make one Browser object without modification of original chrome/browser. Like jQuery in old time.
To use it only one time - import it in background process and make it global for background, then for other imports (from popup for example) use import from
( typeof browser === 'undefined' ? chrome : browser ).extension.getBackgroundPage().Browser

My approach on Spellbook has been to turn the necessary methods to return promises and check chrome.runtime.lastError on a wrapped callback.
But now I just go through all suitable chrome API methods, and turn them into promise based methods with the above approach.
Here is a relevant commit on Spellbook.
I am planning to extract this into a small library called Rosegarden, because Mozilla's webextension-polyfill seems too complicated...

Related

Register custom file protocols in Chrome/Firefox extension?

I want to register a custom file protocol in Chrome or Firefox, much like the way Electron does (please see their API for doing this: https://www.electronjs.org/docs/api/protocol). I am wondering if there is a way to implement this as a browser extension, or I have to modify the source code of the browsers.
I expect that the API would look like this (just a pseudocode to help explain what I mean):
registerHandler('myprotocol://', req => {
response('<body>You requested: ' + req.url);
});
Clarification: navigator.registerProtocolHandler is NOT what I need. What it does is to register a protocol that, when clicked, opens an external application to deal with that. But what I want is a protocol handler scheme that works in a request--response way, e.g. can be used in JS/CSS/HTML queries and responds with a content that can be rendered within the browser.
I would answer my own question because I found exactly what I need here: https://github.com/mozilla/libdweb
This is an experimental feature of Firefox Nightly that allows one to register a custom protocol and serve all requests to that protocol using firefox addon. This is not a WebExtension standard nor does it work on browser other than Nightly, but I'm glad to hear that someone is doing this.

Modifying content delivered by node-http-proxy

Due to some limitations about the web services I am proxying, I have to inject some JS code so that it allows the iframe to access the parent window and perform some actions.
I have built a proxy system with node-http-proxy which works pretty nicely. However I have spent unmeasurable hours trying to modify the content (on my own, using harmon as well, etc) that is being sent to the user without any success. I have found some articles and even some questions here but all of them are outdated and are not useful anymore.
I was wondering if someone can give me an actual example about how to do this, because I am unable to do it and maybe it is just that it is impossible to do at this point?
I haven't tried harmon, but I did try cheerio and it works.
However, I used http-mitm-proxy and not node-http-proxy.
If you are using http-mitm-proxy, you need to return a promise in the response handler. Otherwise, the proxy continues to send the original response without picking up your changes.
I have recently written another proxy at:
https://github.com/noeltimothy/noelsproxy
I'm going to add response handling to this soon. This one uses a callback mechanism, which means it wont return the response until the caller signals it to.
You should be able to use 'cheerio' and alter the content in JQuery style.

is there an URL filter API in chrome extensions?

Old Opera 12 had an easy option to build own ad-blocking extension: http://dev.opera.com/articles/view/extensions-api-urlfilter/
My question is: Is there a similar thing in google chrome extension format ? (also this should apply for new opera series)
(This is a question also about how various adblocks for chrome are made. I mean do these extensions actually block traffic before the browser sends request ? Is this capacity available in chrome extensions ?)
There are two APIs that can be used for blocking web content:
The chrome.webRequest API.
The chrome.declarativeWebRequest API.
The declarativeWebRequest is currently only available on the dev channel, but I expect that it will become available on the stable channel within a few releases. Although it's possible to block requests using the webRequest API, I recommend to use the declarative one, because it's more efficient, in two ways: it allows you to use event pages instead of background pages, and the filters are fully implemented in native code.
The format of the URL filters of the declarativeWebRequest API are very expressive, its format can be found at https://developer.chrome.com/extensions/events.html#type-UrlFilter.
The format of the URL filter in the declarativeWebRequest API follows the format of a match pattern (similar to Opera's url filter).
I've posted a simple example of both APIs at Block URL with a specific word somewhere in the subdomain. Don't forget to declare the right permissions in the manifest file. Either "declarativeWebRequest" or "webRequest", "webRequestBlocking". To block an URL using the webRequest API, you must also request permissions to access the URLs you want to block in the manifest file.

chrome.runtime has no method 'connectNative'

I am working on a Chrome extension that needs to call a native application.
As per Google documentation, we are using the chrome.runtime.connectNative method.
However in our extension, it seems that the chrome.runtime object has no method 'connectNative'. When we display the list of methods of the chrome.runtime object, we get the following list (printed by console.log("" + Object.getOwnPropertyNames(chrome.runtime));
getManifest,getURL,reload,requestUpdateCheck,connect,sendMessage,onConnect,onMessage,id
We are using Chrome 31.0.1650.63 on MacOS X 10.8.5 . We have also tried with Chrome Canary (version 34.0.1767.0 canary), we have the same error, with a slightly different list of methods for chrome.runtime:
getManifest,getURL,setUninstallUrl,reload,requestUpdateCheck,connect,sendMessage,onConnect,onMessage,id
So, in both cases (regular Chrome and Chrome Canary), we don't have the 'connectNative' method.
This does not seem to be a permissions problem, our extension manifest does have "nativeMessaging" in the permissions attribute. When we click on the permissions link in the Chrome extension settings, we can see that the extension can "communicate with cooperating native applications".
(sorry I couldn't post screenshots or the full manifest, StackOverflow won't let me paste things that even remotely look like I'm posting an image since I don't have enough reputation....)
Are we missing something ?
The list of properties of chrome.runtime you are getting indicates that your code is running as a content script. Most chrome.* APIs are not available to content scripts. They can only be used from background or event pages, popups, or other extension views you define. So you can use regular extension messaging from your content script to a background or event page, which in its turn can call your native app.

Which language is used to make google docs and box.net?

I want to know how and which things are used to make google docs and box.net ?
Most of the UI functionality comes from using Javascript and HTML's DOM together with AJAX, a technique for using JS to make additional requests of the server without reloading the page.
In terms of the back-end languages (that provide the dynamic content) box.net returns PHPSESSID as part of it's set-cookie http response. They're also running nginx. So I would suspect one of the many PHP frameworks as being in use.
As for google docs, Google are known to use python quite extensively. Google's "App Engine" uses Python or Java as its languages (I believe Python was added first). So I suspect they use some customised form of python based on their own instance of their own app engine. Their http headers give nothing away, except that the Server: GSE line.
According to HowStuffWorks, Google Docs uses Java for the backend and JavaScript for the front end. Of course, HTML is in the mix there as well.
As for the database it uses, Google won't say. It will use the cloud though, we can be sure of that.

Resources