I'm writing Windows Forms application on C# and trying to get current URL from Chrome in this application. I find active process, and if it's name is "chrome" I try anything, but unsuccessfully. All solutions i've found works only for previous versions of Chrome. As far as I understand, it's better to use Google Chrome Extention for this (but I have never write any of them and I'm superficially familiar with JS).
So, I tried to write an Extension:
manifest.js:
{
"manifest_version": 3,
"name": "URL collector",
"version": "0.11",
"description": "Собирает URL посещенных ресурсов",
"permissions": [
"tabs",
"activeTab",
"webNavigation",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"app.js"
]
}
]}
background.js:
chrome.runtime.onInstalled.addListener(() => {
async function getCurrentTab() {
let queryOptions = { active: true, lastFocusedWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
alert(window.getCurrentTab());});
app.js:
chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) {
var tab = tabs[0];
console.log(tab.url);
alert(tab.url);});
Also I've tried such code:
;(function() {
var pushState = history.pushState;
var replaceState = history.replaceState;
history.pushState = function() {
pushState.apply(history, arguments);
window.dispatchEvent(new Event('pushstate'));
window.dispatchEvent(new Event('locationchange'));
};
history.replaceState = function() {
replaceState.apply(history, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('locationchange'));
};
window.addEventListener('popstate', function() {
window.dispatchEvent(new Event('locationchange'))
});})();
window.addEventListener('locationchange', function(){
console.log('onlocationchange event occurred!');
alert(chrome.tabs.getCurrent(tab => tab.url));})
Everything I have tried in app.js I also tried in background.js and vice versa. And either I did not understand how to track the Extension triggering, or it does not work (probably the second). In general, I tried to catch URL change events, for example, switching tabs or following a link. Well, so far nothing has come of it. Actually, the first question is this: how to make such Extension?
It seems, I totally do not understand the topic, therefore I will also be extremely grateful for links to materials on it.
Well, and the second question is, what is the best way to pass a URL to a Windows Forms application?
Sorry for my English, it seems to be really bad.
in my app.js, I'm using current.Window rather than lastFocusedWindow
button_element.addEventListener('click', () => {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
arr.push(tabs[0].url)
localStorage.setItem("example", JSON.stringify(arr) )
render(arr)
})
})
That works for pushing the current tab to local storage
Related
There are plenty of issues open on the subject, but I couldn't find an explanation in my case. Here is a minimal test case:
Here is my manifest.json
{
"manifest_version": 3,
"name": "Test",
"version": "1.0",
"description": "Test extension",
"icons": {
"48": "dark.png"
},
"background": {
"service_worker": "button.js"
},
"permissions": [
"activeTab"
],
"action": {
"default_icon": "dark.png",
"default_title": "DarkTheme"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"dark.js"
]
}
]
}
button.js
chrome.action.onClicked.addListener(tab => {
console.log('clicked')
chrome.tabs.sendMessage(tab.id, { value: false })
});
dark.js
chrome.runtime.onMessage.addListener(request => {
console.log('received', request)
})
So, basically, my listener is set right at the start, and only when I press the button do I send a message. How come I can receive this error when I press the button?
Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
Tested on Chromium Version 100.0.4896.75 (Build officiel) snap (64 bits)
Thanks for posting, I also had a similar issue and for my particular problem I could not find a proper answer in particular for Google Chrome Extension Manifest Version 3.
In my case, I want to send the idle state with chrome.idle.onStateChanged from a background.js to a contentScript.js. As I am building an extension for reddit, the contentScript.js is only injected into pages which match the URL pattern for reddit.
chrome.idle.onStateChanged.addListener(
(browserActivityState) => {
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { browserActivityState: browserActivityState });
});
}
)
Then I got the same error as you.
Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
I realized while reading the error message, that this happened because I want to send a message to a page which does not have contentScript.js.
I also noticed that it occurred for when I had Chrome but not a reddit page open, I then for example locked my screen which triggers an idle change event and hence my background.js tries send a message to a page.
The problem is, reddit has not been open in the last active tab and therefore the tab to which this message has been sent does not have a contentScript.js injected.
As preliminary solution, not sure if this is the best style but it does the job, I check if the tab I am sending a message to does match the URL of pages where I am injecting the contentScript.js into with if (tabs[0].url.match('https:\/\/.*.reddit.com\/.*')).
chrome.idle.onStateChanged.addListener(
(browserActivityState) => {
console.log('browserActivityState changed')
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
if (tabs[0].url.match('https:\/\/.*.reddit.com\/.*')) {
chrome.tabs.sendMessage(tabs[0].id, { browserActivityState: browserActivityState });
}
});
}
)
This ensures, I am not sending a message to a tab with 'no receiving end' and so far the error is gone.
Maybe you can look in this direction as well for your problem solving.
I hope I was able to help a bit.
When sending message from content script to background, it should be like below.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
Link: https://developer.chrome.com/docs/extensions/mv3/messaging/
I had some issues with this followed the docs here as stated above https://developer.chrome.com/docs/extensions/mv3/messaging/ this works for v3
popup.js
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.scripting.executeScript({
target: {
tabId: tabs[0].id
},
function: sendData,
});
});
const sendData = async () => {
chrome.runtime.sendMessage({
count: 12,
data: []
}, function(response) {
console.log(response.received);
});
}
Background.js
chrome.runtime.onMessage.addListener((data, sender, sendResponse) => {
if (data) {
// Do something amazing
}
sendResponse({
received: true
});
});
It took me hours to figure out the cause of this error because everything in my code seems correct. Turns out I just need to refresh both the extension and the webpage to see it working.
To improve my workflow I'm trying to create a small Chrome extension that will run a JS script on a website that contains a specific string in the URL. I've never worked with JS and I'm a rather inexperienced hobbyist, so this code may make little to no sense.
The onInstalled event is executed without an issue, but I can't get onUpdated to trigger properly.
Here are all of the files:
hide.js
chrome.runtime.onInstalled.addListener(() => {
console.log('Extension initialized');
});
chrome.tabs.onUpdated.addListener(() => {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
var tabUrl = activeTab.url;
});
if(tabUrl.includes('website')){
chrome.scripting.executeScript({target: {tabId: activeTab.id}, function: code()});
}
});
function code(){
console.log('code executed')
}
manifest.json
{
"manifest_version": 3,
"name": "Hide",
"version": "0.1",
"background": {
"service_worker": "hide.js"
},
"permissions": ["storage", "tabs", "scripting"]
}
I have seen many similar questions, but none have solved my issue. I have a page running that has a specific div that changes every 5 seconds. I have a function in my popup.js script, which contacts my contentscript.js and asks for the value of that div. I am having a weird problem where the results from my content script on my localhost server are totally fine, but running this on the same html hosted on my domain is throwing a Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist, which leads to an undefined value . I know people said they had solutions such as disabling other extensions, but that is not a feasible solution since I plan on publishing this extension and can't force users to do that in order for it to work. I know the domain hosted on AWS works totally fine, since I can work around the website and make api calls to it through Postman etc.
popup.js
var currentNumber = 1000;
var lastUpdated = 1000;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "getNumber"}, function(response) {
currentNumber = response.current;
lastUpdated = response.lastUp;
});
contentscript.js
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request.method == "getNumber") {
var currentNumber = document.getElementById("1MainPart_lbUsersInLineAheadOfYou").innerText;
var lastUpdated = document.getElementById("MainPart_lbLastUpdateTimeText").innerText;
sendResponse({current: currentNumber, lastUp : lastUpdated})
return true;
}
return true;
});
manifest.json
{
"manifest_version": 2,
"name": "Extension",
"version": "0.1.0",
"permissions": [
"activeTab",
"tabs",
"storage",
"http://localhost/*",
"*Link to my domain*"
],
"content_scripts": [{
"js": ["contentscript.js"],
"matches": ["http://localhost/*", "*Link to my domain*"]
}],
"externally_connectable": {
"ids": [*inserted id*],
"matches": ["*Link to my domain*"],
"accepts_tls_channel_id": false
},
"background" : {
"scripts" : ["backgroundscript.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
Well according to the docs under...
https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessageExternal
It says...
onMessageExternal
runtime.onMessageExternal.addListener(listener: function)
Fired when a message is sent from another extension/app (by
sendMessage). Cannot be used in a content script.
So that only leaves a background script.
I need to turn alert notification off by my extension. The alert function is a javascript built-in function and i override it like below in content script but it still works.
content script:
window.alert = function(){}
It does not turn it off. The problem is realy simple but it does not work and i am going crazy :)
manifest.json:
"content_scripts": [
{
"js": [ "assets/js/jquery-1.12.4.min.js", "assets/js/common.js", "assets/js/handlers.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_start"
}
],
handler.js:
window.alert = function (msg) {
debugger;
console.log(msg);
}
You can't switch off notifications globally in Chrome (at least, not that way).
By doing
window.alert = function(){}
you simply switch off notifications for your own extension (= your own window context). You can't do this globally for security reasons (think what malicious extension could do if this was possible).
Edit: you actually can inject your code into the content pages; but this is still not a "global" change that you seek. If you still want this, then:
manifest.js of your extension:
{
"name": "MyExtension",
...
"permissions": ["tabs", "http://*/*"],
"content_scripts" : [{
"js" : ["script.js"]
}]
}
And your script.js:
window.alert = function(){}
As Dmitriy mention it must be injected to the page. It works great please vote for Dimitry i just added the answer for sharing my code.
contend script:
function override_alert() {
window.alert = function alert(msg) {
console.log('Hidden Alert ' + msg);
};
}
if (!document.xmlVersion) {
var script = document.createElement('script');
script.appendChild(document.createTextNode('(' + override_alert + ')();'));
document.documentElement.appendChild(script);
}
Could you try something like this?
$(document).ready( function() {
window.alert = function(){};
});
So I've found several pages on here, as well as various blog posts that seem to do pretty much exactly what I want to do, but they are all a few years old and seem really easy but don't work.
As the title says, On thisdomain.com there is a iframe from thatdomain.com and I want to get the value in a div in that iframe.
Manifest.json
{
"manifest_version": 1,
"name": "MyExtention",
"version": "1.0",
"description": "Nothing Yet",
"permissions": [
"storage",
"tabs",
"unlimitedStorage",
"webRequest",
"webNavigation",
"*://*.match-both-iframe-and-main-domain.com/*",
"*://*/*"
],
"background": {
"scripts": ["listener.js"],
"persistent": true
},
"content_scripts":
[
{
"matches": ["*://*.matchnothing.shshdjdjffkdj.com/*"],
"js": ["mainscript.js"],
"all_frames": true
}
]
}
The content script url matches nothing because it is fired from a listener (which works). Basically it waits for a request from one of 2 urls before it activates.
listener.js
var chrome = chrome || {};
var callback = function(listenerRes) {
console.log(listenerRes.url);
if (listenerRes.url.indexOf("listenurl1") > -1 ||
listenerRes.url.indexOf("listenurl2") > -1) {
chrome.tabs.get(listenerRes.tabId, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "mainscript.js"});
});
}
};
chrome.webRequest.onBeforeRequest.addListener( callback, {urls: ["*://*.google.com/*"]} );
mainscript.js
var chrome = chrome || {};
... // helper functions and such
var iframe = document.getElementsByid('myiframe');
// Get all data.
var datas = [];
try {
datas = iframe.contentWindow.document.getElementsByClassName('mydata'); // error is here
}catch(e){
console.log(e);
}
... // do stuff with the data
On the commented line it throws a "Blocked a frame with origin URL from accessing a cross-origin frame."
So I am under the impression that some combination of all_frames = true, the chrome.tabs.executeScript, and the domains in the permissions should allow for this to work. But it doesn't.
It might be important to note, the reason for this listener is because the iframe isnt on the page to start.
Please help, Im an experienced web developer but this is my 1st foray into Chrome Extentions.