chrome.declarativeContent.PageStateMatcher conditions not - javascript

I'm starting to learn how to develop a chrome extention (manifest 3) and I have some result I don't understand.
My final goal is to get the cookie value when a specific website is open, to send a request to this web site (fetch) and to show the json received in a new tab (I developed a javascript to send the request and it's working but I now want to get the cookie automaticaly with a chrome extention).
To start my learning, first step is to open a new tab when I'm on the website. I tried the below code in my background.js but the new tab is created when I activate my extention even if the website is not open and no new tab created after even if my condition is ok. Then I think I missed something but I don't knwo what.
Could someone explain me why, where I'm wrong and if not the good way, which chrome API I should see ?
chrome.runtime.onInstalled.addListener(function () {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: "www.google.com", schemes: ["https"] },
}),
],
actions: [chrome.tabs.create({})],
},
]);
});
});

Your code actions: [chrome.tabs.create({})] is wrong. The method chrome.tabs.create will be called when the extension installed. Maybe you want to trigger your popup.html when clicking the extension. If so, you can use actions: [ new chrome.declarativeContent.ShowPageAction() ]. Then use chrome.action.onClicked.addListener, see here.
If you want to automatically open a new tab when some website is opened, you can use chrome.tabs.onCreated.addListener, see here, handle the event, filter the url, then do sth.

Related

Exception Using chrome.desktopCapture.chooseDesktopMedia

In Chrome Manifest V2 I was able to easily capture the desktop. Attempting this in Manifest version 3 I have had no luck. I feel I may be missing something here in attempting this in Manifest V3.
I have been using this as a reference. https://developer.chrome.com/docs/extensions/reference/desktopCapture/
My manifest has these permissions granted to it
"permissions": [
"idle",
"tabs",
"storage",
"notifications",
"alarms",
"desktopCapture"
],
This is the sample code I have been testing just to see if I can get the screen selector to come up. I have not included the tabs.tab as this is labeled as optional and I wanted to see if I could have the plugin trigger the screen recording feature on its own.
chrome.desktopCapture.chooseDesktopMedia(["screen"], (streamID, options) => {console.log(id)});
I have been attempting to have this run in my background.js file.
Each time it runs chrome crashes completely with no errors given.
Reviewing the crash dump I can see the following information.
Exception Code: 0xC0000005
Exception Information: The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
I solve it this way for Manifest v3.
It was giving me errors too. When I checked the documentation, chooseDesktopMedia it wanted three parameters.
DesktopCaptureSourceType[]
Tab
Callback Function
I see in your question your have put 1 and 3. I did the same it was giving me errors. So I made sure I get the active tab first before calling chrome.desktopCapture.chooseDesktopMedia in the background script.
So the code looks like this
chrome.tabs.query({ active: true }, (tabs) => {
if (tabs.length) {
const tab = tabs[0];
var pending = chrome.desktopCapture.chooseDesktopMedia(["window"], tab, (streamId) => {
//console.log(streamId, tab);
});
}
return false;
})
And it worked. I hope this helps

How to write a Thunderbird extension (webextension) to modify the message display?

I'd like to write an extension for Thunderbird that modifies the message display (e.g. insert/replace text/markup/image).
Unfortunately, the documentation is lacking (due to recent changes?).
https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Thunderbird_extensions
is outdated
https://developer.thunderbird.net/
does not have useful examples (yet)
https://thunderbird-webextensions.readthedocs.io/
no examples either
Some examples can be found at
https://github.com/thundernest/sample-extensions
Building on https://github.com/thundernest/sample-extensions/tree/master/messageDisplay
I've modified background.js
browser.messageDisplay.onMessageDisplayed.addListener((tabId, message) => {
console.log(`Message displayed in tab ${tabId}: ${message.subject}`);
console.log(message.id);
browser.messages.getFull(message.id).then((messagepart) => {
console.log(messagepart);
body = messagepart['parts'][0]['parts'][0]['body'];
console.log(body);
body += "modified!";
console.log(body);
});
browser.windows.getCurrent().then((window)=>{
console.log(window.type);
});
browser.tabs.getCurrent().then((tab)=>{
console.log("tab",tab);
});
});
which gives me the message body (using magic indexes) but expectedly, the change is not reflected in the message display.
The window type returned is normal, not messageDisplay.
The tab is undefined despite adding permissions
"permissions": [
"messagesRead",
"activeTab",
"tabs",
"tabHide"
],
but I assume that's because the script is running as background.
So I'd need a script running on the content / access to the tab and then some hints on how to modify the displayed message content (I do not want to modify the message).
Where would I find the equivalent documentation to
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts
specific to Thunderbird?
Specifying content_scripts in manifest.json causes "Error: Error reloading addon messageDisplay#sample.extensions.thunderbird.net: undefined".
executeScript() from background does not seem to work either, even with tabId specified.
This was not possible to do when you wrote your question, the API for modifying displayed messages was missing.
As of this writing (September 2020), the browser.messageDisplayScripts API landed a few days ago, see bug 1504475 and related patch for examples. It works as follows: You can register your content script (to modify the displayed messages) like this
let myPromise = browser.messageDisplayScripts.register({
css: [{
file: "/style.css",
}],
js: [{
file: "/content_script.js",
}],
});
And you can later unregister with
myPromise.then((script) => { script.unregister(); });
You need to register the script just once for all messages (you do not need a listener that would load it each time a message is displayed).
Note that your manifest.json needs to include the messagesModify permission for this to work.
The new API will be in Thunderbird version 82, so if I understand the release process correctly it should be in stable version 88 (unless it is backported before that). You can try it already (v82 is the current EarlyBird).
Documentation https://thunderbird-webextensions.readthedocs.io/en/68/tabs.html#getcurrent
says:
May be undefined if called from a non-tab context (for example: a background page or popup view).
Since the background.js is not called from a tab context the tab is undefined.

Chrome Extension - Getting "tab was closed" error on injecting a script

I am writing a chrome extension which detects the type of file being opened and based on that injects a script on the page which does many other things. Here is the part of my code for the background.js which is injecting the script:
chrome.webRequest.onHeadersReceived.addListener(function(details){
console.log("Here: " + details.url + " Tab ID: " + details.tabId);
if(toInject(details))
{
console.log("PDF Detected: " + details.url);
if(some-condition)
{
//some code
}
else
{
chrome.tabs.executeScript(details.tabId, { file: "contentscript.js", runAt: "document_start"}, function(result){
if(chrome.runtime.lastError)
{
console.log(chrome.runtime.lastError.message + " Tab ID: " + details.tabId);
}
});
}
return {
responseHeaders: [{
name: 'X-Content-Type-Options',
value: 'nosniff'
},
{
name: 'X-Frame-Options',
/*
Deny rendering of the obtained data.
Cant use {cancel:true} as we still need the frame to be accessible.
*/
value: 'deny'
}]
};
}
}, {
urls: ['*://*/*'],
types: ['main_frame', 'sub_frame']
}, ['blocking', 'responseHeaders']);
Here is the manifest file:
{
"manifest_version": 2,
"name": "ABCD",
"description": "ABCD",
"version": "1.2",
"icons": {
"16" : "images/16.png",
"32" : "images/32.png",
"48" : "images/48.png",
"128" : "images/128.png"
},
"background": {
"scripts": ["chrome.tabs.executeScriptInFrame.js", "background.js"],
"persistent": true
},
"permissions": [
"webRequest",
"<all_urls>",
"webRequestBlocking",
"tabs",
"nativeMessaging"
],
"web_accessible_resources": [ "getFrameId", "aux.html", "chrome-extension:/*", "images/*.png", "images/*.gif", "style.css"]
}
The problem is that when injecting script the last error part runs and it shows the tab was closed and the script is not injected. If I press enter on the omnibox a several times the script is injected and things work fine. Here is a sample run of events:
Sorry for my naive photo editing :P
There are a few more things we can deduce from this image:
The first thing being loaded in the tab with tab id 86 is something related to my google account. I have logged out and also turned off the prerender feature of chrome.
On pressing enter several times the tab was closed error goes but the script which maintains a chrome.runtime connection with the background.js gets disconnected.
And then finally things work fine.
I have been banging my head around this for days. No other question on SO addresses this problem. Nor anywhere else on the internet as well.
EDIT:
One more thing to note: The sample run shown in the image above is one such. There are many different behaviors. Sometimes 3 enters wouldn't make it work. Sometimes just one will. Is there something wrong because of the custom headers i am sending?
UPDATE #1
One must notice the headers I am returning in OnHeadersReceived. It's being done to stop chrome from rendering the document. But on doing that all the data of the file is dumped on the screen and I don't want that to appear. So i think I need document_start so that I can hide the dumped data before my content script does other things like putting a custom UI on the page.
UPDATE #2
Noticed one more thing. If I open a new tab, and then paste a url there and then press enter the following is the output of the background page on the console.
So I guess, the location of the window is updated at a later time by chrome. Am I right? Any workarounds?
"The tab was closed" error message is a bit misleading, because the tab obviously is not closed. In chrome sources the variable with the string is called kRendererDestroyed. So the error is because the corresponding renderer is being destroyed for some reason.
I was getting the error if the the page opened in tab redirected (thus one renderer destroyed, another one created for the same tab, but different url this time), in this case extension will got tab updates with statuses like:
loading url: 'example.com', here tab is already returned to callbacks etc, but will get the error, if tried to inject script
loading url: 'example.com/other_url'
title: 'some title'
complete
I managed to get around by injecting script only after receiving status: 'complete' (but probably injecting on title should also do)
Did not try with pdfs, but chrome probably will replace renderer for those too like with a redirect. So look more into page statuses and redirects/renderer replaces. Hope this helps anyone stumbling upon this question.
A simple setTimeout call to wait for the page to load worked for me.

Open chrome://newtab from a Chrome extension

I try to write a Google Chrome extension that simply opens a new tab when I click left-right in a short interval. The JavaScript is no problem but I implemented this as a "content_scripts" script.
In some other threads I read that I can't access the chrome.* APIs from content_scripts (except the chrome.extension API).
Even if it's not necessary to access the chrome.tabs API to open a new window (window.open should do the job) it seems I need it though for opening a new tab with the new tab page which obviously isn't possible via window.open.
So I can't really figure out what is the best way to do that. I could use a background page which I could call from the content_script but I think there should be a much more simple way to do that, I just don't get it.
Anyone have an idea?
I think your content script will have to send a message to your background page to invoke chrome.tabs.create - content scripts cannot use the chrome api, nor can they directly communicate with the background page.
Here's a reference about message passing inside Chrome extensions for further detail, but here's the example code ( modified from the example in said reference )
// in background
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
switch ( request.action) {
case 'newTab' : {
//note: passing an empty object opens a new blank tab,
//but an object must be passed
chrome.tabs.create({/*options*/});
// run callback / send response
} break;
}
return true; //required if you want your callback to run, IIRC
});
// in content script:
chrome.extension.sendMessage({action: "newTab"}, function(response) {
//optional callback code here.
});
simple and easy
document.body.onclick = function openNewWindow( ) {
window.location.href = 'javascript:void window.open( "chrome://newtab" )';
}
manifest:
,"permissions":[
"http://*/*"
,"https://*/*"
]
,"manifest_version": 2
,"content_scripts":[{
"matches":[
"http://*/*"
,"https://*/*"
]
,"js":[
"js/openWindow.js"
]
}]
alright i miss understanding the question... modified

How to modify current url location in chrome via extensions

I want to create an extension that redirects the user to another website if he clicks on the extension button. So far I have only seen extensions which create a new tab for each click.
Is it possible to redirect the user to another website using the active tab?
I tried something like this:
chrome.browserAction.onClicked.addListener(function(tab) {
var url = "https://www.mipanga.com/Content/Submit?url="
+ encodeURIComponent(tab.url)
+ "&title=" + encodeURIComponent(tab.title);
document.location.href = url; // <-- this does not work
});
Attention: If you develop cross-browser extensions (I hope you do!), I recommend that you use chrome.tabs.query(). Please see Jean-Marc Amon's answer for more information. This answer still works in both Firefox and Chrome, but query() is more commonly used, has more options, and works in background pages and popup views.
From the chrome.tabs API, you can use getCurrent(), query(), or update().
Right now, I prefer update() as this allows you to update the current tab without needing to do much else.
NB: You cannot use update() from content scripts.
If updating the url from a content script is required then you should look to use query instead. Jean-Marc Amon's answer provides a wonderful example of how to get the active tab in this case (don't forget to upvote him!).
update()
let myNewUrl = `https://www.mipanga.com/Content/Submit?url=${encodeURIComponent(tab.url)}&title=${encodeURIComponent(tab.title)}`;
chrome.tabs.update(undefined, { url: myNewUrl });
Here, we have set the first argument of update to undefined. This is the tab id that you're wanting to update. If it's undefined then Chrome will update the current tab in the current window.
Please see Domino's answer for more information on update and also note that undefined is not needed. Again, please don't forget to upvote their answer as wellif you find it useful.
getCurrent()
getCurrent also cannot be called from a non-tab context (eg a background page or popup view).
Once you have the current tab, simply pass update().
chrome.tabs.getCurrent(function (tab) {
//Your code below...
let myNewUrl = `https://www.mipanga.com/Content/Submit?url=${encodeURIComponent(tab.url)}&title=${encodeURIComponent(tab.title)}`;
//Update the url here.
chrome.tabs.update(tab.id, { url: myNewUrl });
});
NB: In order to use this this functionality, you must ensure that you have the tabs permission enabled in your manifest.json file:
"permissions": [
"tabs"
],
You can use chrome.tabs.query too
chrome.tabs.query({currentWindow: true, active: true}, function (tab) {
chrome.tabs.update(tab.id, {url: your_new_url});
});
The chrome.tabs.update method will automatically run on the current active tab if no tab id is passed.
This has the added advantage of not requiring the tabs permission. Extensions with this permission warn the user that they can read the browsing history, so you should avoid asking for it if you don't need to.
Changing the current tab's URL is as simple as writing this:
chrome.tabs.update(undefined, {url: 'http://example.com'});
Or as mentionned by farwayer in the comments, you don't need to put two arguments at all.
chrome.tabs.update({url: 'http://example.com'});
The answers given here no longer work: the Chrome Tabs API can no longer be used by content scripts, only by service workers and extension pages.
Instead, you can send a message to a service worker to get it to update the location of the current tab: see https://stackoverflow.com/a/62461987.
See this for a simple working example.

Categories