chrome extension: page loaded event and update url - javascript

I want to change the url of current tab in chrome and reload the page.
I tried this code but not work, any help here will be greatly appreciated.
background.js:
function updateUrl(){
chrome.tabs.getCurrent(function (tab) {
var tabUrl = encodeURIComponent(tab.url);
var myNewUrl = tabUrl + "some text";
chrome.tabs.update(tab.id, {url: myNewUrl});
})
}
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
updateUrl();
}
})
manifest.json:
{
"name": "test",
"version": "0.1",
"manifest_version": 2,
"permissions": [
"tabs",
"webNavigation",
"http://www.example.com/*"
],
"background": { "scripts": ["background.js"] },
"content_scripts":
[
{
"matches": ["http://www.example.com/*"],
"js": ["background.js", "jquery.js"]
}
]
}

From your manifest it looks like you're trying to include background.js as a content script and a background script. chrome.tabs isn't available in content scripts so this won't work.
Depending on your specific use case, if you want to append a specific URL you could use the chrome.webRequest API to achieve this.
background.js:
chrome.webRequest.onBeforeRequest.addListener(function (details) {
return {
redirectUrl: details.url + "some text"
}
}, {
urls: ["http://www.example.com/*"]
}, ["blocking"]);
manifest.js:
{
"name": "test",
"version": "0.1",
"manifest_version": 2,
"permissions": [
"webRequest",
"webRequestBlocking",
"http://www.example.com/*"
],
"background": {
"scripts": [
"background.js"
]
}
}
This will add "some text" to the end of every request the browser makes to "http://www.example.com/*"
If you do want to use a content script to do this, then you'll need to take a look at message passing. This will allow you to make a call to the background script (which can use chrome.tabs) from your content script. Once the message has been sent the background page could then update the tab.

chrome.tabs.getCurrent is used to get the tab that this script is being made from. It will return undefined if called from a non-tab context (for example: a background page or popup view).
Since you have got the tab inside chrome.tabs.onUpdated handler, you could directly use it without the need to retrieve it again.
function updateUrl(tabId, tabUrl){
var myNewUrl = encodeURIComponent(tabUrl) + "some text";
chrome.tabs.update(tabId, {url: myNewUrl});
}
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
updateUrl(tab.id, tab.url);
}
});
From you manifest.json, background.js are used for both background page and content scripts, that's a bad design though not the root cause for this question.
It would be better if you could divide the logic into two parts, content script used for manipulating current web page DOM and background page used for extension related things.

Related

Firefox Extension / Webextensions: Why doesn't the MDN example of Connection Based Messaging work?

This is the first time I read about writing Firefox extensions.
What I need is obviously only viable via WebExtensions and both a background and a contentscript. I actually only want to write all open tabs as links in a new tab and then File->Save it. Another alternative Idea was to put it into a JSON Object and save that through a dialog, then I probably could even spare the contentscript but I haven't found anything in the API to download a JSON Object via asking the user to download it via Download Dialog.
Whatever. I think I need to communicate with the content-script then.
I tried to run the following example, but it is not working. When I load the manifest file and open the debugger for extensions, it doesn't log anything and nothing has happened except that the variables myPort and portFromCS seem to be declared without any value.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#connection-based_messaging
// manifest.json
{
"manifest_version": 2,
"name": "Save Open Tabs",
"version": "1.0",
"description": "Save my tabs",
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"]
}
],
"permissions": [
"activeTab",
"tabs"
]
}
// content.js
let myPort=browser.runtime.connect({name:"port-from-cs"});
myPort.postMessage({greeting: "hello from content script"});
myPort.onMessage.addListener((m) => {
console.log("In content script, received message from background script: ");
console.log(m.greeting);
});
// background.js
let portFromCS;
function connected(p) {
portFromCS = p;
portFromCS.postMessage({greeting: "hi there content script!"});
portFromCS.onMessage.addListener((m) => {
portFromCS.postMessage({greeting: "In background script, received message from content script:" + m.greeting});
});
}
browser.runtime.onConnect.addListener(connected);
Why doesn't the example work? Maybe wrong URL matching in the manifest file?

How do you detect changes in url with a chrome extension?

I am learning to make chrome extensions. I ran into a problem where context scripts that I want to run, even just alert("test");, are unable to when onload is not activated. This also occurs when you press the back arrow to visit the last visited page. I notice that the url changed, but nothing activates. How do I detect this? If the answer is with service workers, a detailed explanation would be greatly appreciated.
maifest version 2.0
Try using chrome.tabs.onUpdated.addListener((id, change, tab)=>{}). This should run every time the URL changes! Here is a minimalistic example of some code that injects js to a site when the URL changes.
background.js:
// inject code on change
chrome.tabs.onUpdated.addListener((id, change, tab) => {
// inject js file called 'inject.js'
chrome.tabs.executeScript(id, {
file: 'inject.js'
});
});
mainfest version 3.0
You can do it by using chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {}). However, this will actually trigger multiple times when a page URL is changed So you need to add a check for the URL in the changeInfo variable, so it only triggers once!
manifest.json:
{
"name": "URL change detector",
"description": "detect a URL change in a tab, and inject a script to the page!",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting",
"tabs"
],
"host_permissions": [
"http://*/*",
"https://*/*"
],
"background": {
"service_worker": "background.js"
}
}
background.js:
// function that injects code to a specific tab
function injectScript(tabId) {
chrome.scripting.executeScript(
{
target: {tabId: tabId},
files: ['inject.js'],
}
);
}
// adds a listener to tab change
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// check for a URL in the changeInfo parameter (url is only added when it is changed)
if (changeInfo.url) {
// calls the inject function
injectScript(tabId);
}
});
inject.js:
// you can write the code here that you want to inject
alert('Hello world!');

How to run background.js only on specific links?

I'm trying to write a chrome extension that closes tabs when they're loaded if their links contain specific words / strings. My intention was to solve that using the matches statement in the manifest.json. Unfortuantely this doesn't work. My manifest.json looks like this:
{
"manifest_version": 2,
"name": "Chrome Extension",
"version": "0.1",
"permissions": [
"tabs"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"background": {
"matches": [
"https://www.google.de/",
"https://sghm.eu/iserv/login"
],
"scripts": ["background.js"],
"persistent": true
}
}
And my background.js like this:
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
console.log('background running');
chrome.tabs.remove(tabId, function() { });
}
})
In my opinion I've expressed clearly that the script only runs on google and sghm.eu, so why does it run on every loaded page?
Problems:
The "background" section can't have "matches" as you can see in the documentation. The background script runs in a separate hidden background page that's not related to tabs.
The content script declared in your manifest.json runs on all URLs. For the task you want to achieve you don't need a content script at all.
Solution consists of several steps:
Remove "content_scripts" section
Remove "matches" from "background" section
Switch to an event page script by specifying "persistent": false
Add "webNavigation" permission in manifest.json and use it to detect URL navigation.
background.js:
chrome.webNavigation.onCompleted.addListener(closeTab, {
url: [
{urlPrefix: 'https://www.google.de/'},
{urlPrefix: 'https://sghm.eu/iserv/login'},
]
});
function closeTab(e) {
if (!e.frameId) {
chrome.tabs.remove(e.tabId);
}
}

Which URLs are restricted to operate on with Chrome extensions? [duplicate]

I have created a Chrome extension that, as part of it's operation, opens a new tab with a specified url.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
(Full code available on GitHub)
This works fine on tabs with webpages, but I cannot get it to work on empty tabs, for example: chrome://apps/ To clarify, if I have a tab open and it is on stackoverflow.com, then when I click on my extension button it opens a new tab loading a generated url. When I am on a new tab, or a tab where the url begins with chrome:// then the extension does not work.
What permissions do I need to include to allow the extension to open in ANY tab? Including new tabs and any chrome:// tab?
Manifest.json:
{
"manifest_version": 2,
"name": "MyMiniCity Checker",
"short_name": "MyMiniCity Checker",
"description": "Checks what your city needs most and redirects the browser accordingly.",
"version": "0.2",
"author":"Richard Parnaby-King",
"homepage_url": "https://github.com/richard-parnaby-king/MyMiniCity-Checker/",
"icons": {
"128": "icon-big.png"
},
"options_page": "options/options.html",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": ["tabs","storage","http://*.myminicity.com/","http://*/*", "https://*/*"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [ {
"matches": [ "http://*/*", "https://*/*"],
"js": [ "jquery-1.11.3.min.js" ]
}]
}
Background.js:
//When user clicks on button, run script
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "jquery-1.11.3.min.js" }, function() {
chrome.tabs.executeScript(null, { file: "contentscript.js" });
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
It appears as though the background.js file is not being executed. I suspect this to be a permissions. What permissions do I need in order to run this extension in every tab?
Well, this message is supposed to come from a content script you're trying to inject into the current tab.
The widest permission you can request is "<all_urls>", however, there are still URLs that are excluded from access.
You can only normally access http:, https:, file: and ftp: schemes.
file: scheme requires the user to manually approve the access in chrome://extensions/:
Chrome Web Store URLs are specifically blacklisted from access for security reasons. There is no override.
chrome:// URLs (also called WebUI) are excluded for security reasons. There is a manual override in the flags: chrome://flags/#extensions-on-chrome-urls, but you can never expect it to be there.
There is an exception to the above, chrome://favicon/ URLs are accessible if you declare the exact permission.
All in all, even with the widest permissions you cannot be sure you have access. Check for chrome.runtime.lastError in the callback of executeScript and fail gracefully.
As I was wanting this to run on EVERY page it meant I could not have the code in the content script. I moved all the code into the background script:
chrome.browserAction.onClicked.addListener(function(tab) {
//...
chrome.tabs.create({"url": newTabUrl});
//...
});
So when I click on my button the above code is called, using the enclosed jquery script.

Develop a Google Chrome extension

I have to update a url using chrome extension.
Here is my manifest file
{
"name": "My First Extension",
"version": "1.0",
"description": "The first extension that I made.",
"browser_action": {
"default_icon": "cwins.png"
},
"permissions": [
"http://www.google.co.in/",
"http://www.google.co.in/#hl=en&biw=1920&bih=955&q=anushka&aq=f&aqi=g10&aql=&oq=&fp=5f42a1c1d2fc35ec"
],
"content_scripts": [
{
"matches": ["http://www.google.co.in/"],
"js": ["jquery.js", "myscript.js"]
}
]
}
here is my content_scripts (myscripts.js)
alert('hi');
chrome.tabs.getSelected({}, function(tab) {
chrome.tabs.update(tab.id, {
url: 'http://www.google.co.in/#hl=en&biw=1920&bih=955&q=anushka&aq=f&aqi=g10&aql=&oq=&fp=5f42a1c1d2fc35ec'
});
});
alert('bye');
ITS NOT UPDATING THE URL
I can see a couple issues: you can't access chrome.tabs in a content script, and chrome.tabs.getSelected requires the "tabs" permission.
Setting window.location should work in the content script though, so if that's all you need to do, myscripts.js could be as simple as:
window.location = 'http://www.google.co.in/#hl=en&biw=1920...';
If you do need to use chrome.tabs.update, you can access it from a background page. Basically, you would need to set up an onRequest event handler in the background page, and send a request using chrome.extension.sendRequest from the content script.
So basically you'd have this for your content script (myscript.js):
chrome.extension.sendRequest({ url: 'http://www.google.co.in/#hl=en...' });
and your background page would have a script element with something like this:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
chrome.tabs.update(sender.tab.id, { url: request.url });
});

Categories

Resources