Chrome Blocking Redirect to Extension Page - javascript

I am trying to make a chrome extension that blocks users from accessing sites by redirecting them to the extension's custom HTML block page. The user can then choose to click "Unblock" to exclude the current tab from being checked by the filter.
The extension works as expected. For example, if you try to access https://www.youtube.com/ while "youtube.com" is in the blocked list, it will redirect you to "blocked.html".
However, it seems that the extension only works on the CURRENT TAB that you are working with. If you try to shift click a hyperlink (Which opens the link in a new tab) which leads to https://www.youtube.com, it will redirect to "blocked.html", but Chrome would block the redirect and give you this screen:
Even if you now focus on the tab and press refresh, "blocked.html" still does not load.
I believe this may be because I am missing permissions in my manifest file, however, I looked at the docs for the permissions page and I could not find any relevant permissions I could add.
Thanks in advance.
Note: Interestingly, the yellow error message shown above only appears on pages that have been blocked by chrome. The message is this: "crbug/1173575, non-JS module files deprecated."
Also, if you try to refresh the page, the line number that the message appears becomes higher. (I refreshed a few times and right now it is at VM712:7146). Not sure if this message is related to the error.
manifest.json
"manifest_version": 2,
"background": {
"service_worker": "background.js"
},
"options_page": "options.html",
"permissions": [
"storage",
"activeTab",
"tabs",
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
"page_action": {
"default_popup": "popup.html"
}
blocked.js (Shortened)
// Unblock button redirect
let unblockButton = document.getElementById("unblockButton");
updateOriginalUrl();
chrome.runtime.onMessage.addListener(function update(message) {
updateOriginalUrl();
chrome.runtime.onMessage.removeListener(update);
})
function updateOriginalUrl() {
chrome.storage.sync.get("originalUrl", (result) => {
console.log("Unblock button URL set to: " + result.originalUrl);
unblockButton.addEventListener("click", () => {
location.href = result.originalUrl;
chrome.runtime.sendMessage("exclude")
})
});
}
background.js
chrome.webRequest.onBeforeRequest.addListener((details) => {
console.log("New request detected")
console.log("Request URL: " + details.url);
if(enabled && !excludedTabs.includes(details.tabId)) {
for(let blockedUrl of blockedList) {
if(details.url.includes(blockedUrl)) {
console.log("Match detected, redirecting");
chrome.storage.sync.set( {"originalUrl": details.url}, () => {
chrome.runtime.sendMessage("updateOriginalUrl");
});
return {
redirectUrl: chrome.runtime.getURL("blocked.html")
};
}
}
}
}, {
urls: ["<all_urls>"],
types: ["main_frame"]
}, ["blocking"]);

Thanks #wOxxOm:
Either add blocked.html to web_accessible_resources in manifest.json or switch to using declarativeNetRequest API.
This worked.

Related

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!');

Can't successfully run executeScript from the background script unless I load the popup page/script first

I've trying to run execute script from my background script using keyboard shortcuts, it doesn't work and returns:
Error: No window matching {"matchesHost":[]}
But if I just open the popup page, close it, and do the same, everything works.
I've recreated the problem in using the Beastify example with minimal changes. Here's the code:
manifest.json
{
... (not interesting part, same as in beastify)
"permissions": [
"activeTab"
],
"browser_action": {
"default_icon": "icons/beasts-32.png",
"default_title": "Beastify",
"default_popup": "popup/choose_beast.html"
},
"web_accessible_resources": [
"beasts/frog.jpg",
"beasts/turtle.jpg",
"beasts/snake.jpg"
],
My additions start here:
"background": {
"scripts": ["background_scripts/background_script.js"]
},
"commands": {
"run_content_test": {
"suggested_key": {
"default": "Alt+Shift+W"
}
}
}
}
popup/choose_beast.js (same as in original)
/*
Given the name of a beast, get the URL to the corresponding image.
*/
function beastNameToURL(beastName) {
switch (beastName) {
case "Frog":
return browser.extension.getURL("beasts/frog.jpg");
case "Snake":
return browser.extension.getURL("beasts/snake.jpg");
case "Turtle":
return browser.extension.getURL("beasts/turtle.jpg");
}
}
/*
Listen for clicks in the popup.
If the click is on one of the beasts:
Inject the "beastify.js" content script in the active tab.
Then get the active tab and send "beastify.js" a message
containing the URL to the chosen beast's image.
If it's on a button wich contains class "clear":
Reload the page.
Close the popup. This is needed, as the content script malfunctions after page reloads.
*/
document.addEventListener("click", (e) => {
if (e.target.classList.contains("beast")) {
var chosenBeast = e.target.textContent;
var chosenBeastURL = beastNameToURL(chosenBeast);
browser.tabs.executeScript(null, {
file: "/content_scripts/beastify.js"
});
var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
gettingActiveTab.then((tabs) => {
browser.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
});
}
else if (e.target.classList.contains("clear")) {
browser.tabs.reload();
window.close();
return;
}
});
background_scripts/background_script.js (added by me)
browser.commands.onCommand.addListener(function(command) {
var executing = browser.tabs.executeScript(
null,
{file: "/content_scripts/content_test.js"});
executing.then(
function (res){
console.log("started content_test.js: " + res);
},
function (err){
console.log("haven't started, error: " + err);
});
});
content_scripts/content_test.js (added by me)
alert("0");
I'm skipping the whole content_scripts/beastify.js cause it has nothing to do with it (IMO), but it can be found here.
Now, I know that the background script runs and receives the messages even when the popup page hasn't been opened before, because I see it failing executing the script. I have no idea what causes this behavior and if there's a way to fix it.
Note: I tried adding permissions such as "tabs" and even "all_urls", but it didn't change anything.
Note 2: I'm running the add-on as a temporary add-on from the about:debugging page, but I'm trying to execute the script on a normal non-restricted page (on this page for example I can recreate the problem).
Thanks a lot guys!
// in manifest.json
"permissions": [
"<all_urls>",
"activeTab"
],
DOES work for me (Firefox 50, Mac OS X 10.11.6).
I had gotten the exact same error message you described when I had used the original
"permissions": [
"activeTab"
],
So the addition of "<all_urls>" seems to fix the problem. However, you said that you were still experiencing the issue when you included "all_urls" in your permissions, so I am not sure whether the way I did it fixes the issue in your own setup.
edit: Whether giving any webextension such broad permissions would be wise in terms of the security risks it might pose is a separate, important consideration, I would imagine.
(I would have posted this as a comment, but I don't have enough reputation yet to be able to add comments.)

Chrome Extension: Edit the current url on click and then redirect to the edited one

I am a psychology student and I read papers very often. The university libraries provide the access to the databases but I need to use library search engine and log in every time. Quite annoying. I found a way to avoid jumping around the pages.
Here is the method:
I add "ezp.lib.unimelb.edu.au" to the end of the target database address after I found a paper in Google Scholar, then it will redirect to the library login page.
For example, the paper's address is:
http://www.sciencedirect.com/science/article/pii/S0006899315008550
I modified it as:
http://www.sciencedirect.com.ezp.lib.unimelb.edu.au/science/article/pii/S000689315008550
I want to create a Chrome Extension to finish this job on click (too lazy). I tried for hours but it does not work.
Here is what I have done:
I have three files in a folder:
First file: manifest.json
{
"manifest_version": 2,
"name": "Damn! Take me to the library!",
"description": "This extension automatically adds the 'ezp.lib.unimelb.edu.au' to the browser's address, allowing you to visit the databases bought by the library quickly",
"version": "1.0",
"browser_action": {
"default_icon": "unimelb.png",
"default_title": "Damn! Take me to the library!"
},
"background":{
"scripts":["popup.js"]
},
"permissions": [
"activeTab",
"tabs"
]
}
Second file: popup.js
function getCurrentTabUrlthenChangeIt(callback) {
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
var url = tab.url;
callback(url);
var newurl = url.replace('/',"ezp.lib.unimelb.edu.au/");
window.location.replace(newurl);
});
}
Third file: unimelb.png
When I load this folder into Chrome, it does not work.
It's the first time I use JS, anyone has any suggestions?
Thanks!
You can do this even without clicking. You can use the content script for this URL pattern so that your script gets injected to this page. Then you can send a message to the background script using chrome.runtime.sendMessage() and your listener will create a link you want here and then just reload the tab using chrome.tabs.update() with the new URL.
manifest.json
{
"name": "My extension",
...
"content_scripts": [{
"matches": ["http://www.sciencedirect.com/science/article/pii/*"],
"js": ["content-script.js"]
}],
...
}
content-script.js
chrome.runtime.sendMessage({loadURL: true});
background.js
chrome.runtime.onMessage.addListener(function(message, sender, response) {
if (message.loadURL) {
var newurl = sender.tab.url.replace("/", "ezp.lib.unimelb.edu.au/");
chrome.tabs.update(sender.tab.id, {url: newURL})
}
);
This is my first answer to the StackOverflow Community, I hope it helps.
Instead of making an extension, it would be a lot easier to make a bookmarklet which can be used in any browser...
Right click on the bookmark bar
Choose "Add page..."
Under "Name", enter whatever you want "Journal redirect" or whatever
Under "URL", copy and paste the following code (no spaces)
javascript:(function(){location.href=location.href.replace('sciencedirect.com/','sciencedirect.com/ezp.lib.unimelb.edu.au/');})();
Now when you're on the page, click that bookmark and it'll redirect you.
Update: Try this code in the URL for other domains
javascript:(function(){var%20l=location;l.href=l.origin+l.href.replace(l.origin,'ezp.lib.unimelb.edu.au/');})();
manifest.json
{
"manifest_version": 2,
"name": "Damn! Take me to the library!",
"description": "This extension automatically adds the 'ezp.lib.unimelb.edu.au' to the browser's address, allowing you to visit the databases bought by the library quickly",
"version": "1.0",
"browser_action": {
"default_icon": "unimelb.png",
"default_title": "Damn! Take me to the library!"
},
"background":{
"scripts":["background.js"]
},
"permissions": [
"activeTab",
"tabs"
]
}
background.js
//Wait for click
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {
"file": "popup.js"
}, function(){
"popup.js";
console.log("Script Executed ...");
});
})
popup.js
// Change the url to library when on click
var l=location;l.href=l.origin+l.href.replace(l.origin, '.ezp.lib.unimelb.edu.au');
They work well.
It's so cool to finish the first chrome extension. Thank for the help from Mottie.
Anyone looking to edit the url based on some pattern can use the chrome extension Edit Url by Regex
For example for the scenario in this post, while using the extension, you can provide the regex as http.*/science/ and the value as http://www.sciencedirect.com.ezp.lib.unimelb.edu.au/science/
and click submit. The url will get updated as expected.

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.

Chrome extension that acts only when clicked on certain webpages

I'm trying to get my Chrome extension to pop up an alert when the user is on http://google.com/ and clicks on the extension icon.
I have the following manifest:
{
"manifest_version": 2,
"name": "One Megahurt",
"version": "0.1",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["bg.js"],
"persistent": false
},
"browser_action": {
"default_icon": "icon.png"
}
}
and this is bg.js:
chrome.browserAction.onClicked.addListener(function(tab) {
alert('Test!');
})
This code will allow popup an alert on any website, as I don't have any restrictions on which websites this works on. I tried using
if(tab.url === "https://google.com/")
between the first and second lines, but that didn't work.
I'm not sure if I should even be using a background script rather than a content script. I looked in Google's examples and tried using the implementation in "Page action by URL", but that didn't work for me either.
Any help would be appreciated. I should note that I don't really care about the specific issues with the URL--google.com is merely an example. I want to learn to use this for other projects and websites.
EDIT: Adding urls to permissions doesn't restrict which websites the alert pops up on, either.
I ended up using page actions for my solution, per Felix King's suggestion. In retrospect, this was the best solution to use because it doesn't load the extension on every page and cause browser slowdowns (as far as I know).
In addition to adding domains to permissions in the manifest, add a the following code to a background.js.
// When the extension is installed or upgraded ...
chrome.runtime.onInstalled.addListener(function() {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL matches one of the following ...
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: 'http://google.com/' }, // use https if necessary or add another line to match for both
}),
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: 'http://facebook.com/*' },
}) // continue with more urls if needed
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction()]
}
]);
});
});
chrome.pageAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "script.js" });
});
Key sections to add in manifest.js are:
"background": {
"scripts": ["res/background.js"],
"persistent": false
}
&
"permissions": [
"declarativeContent", "tabs", "activeTab", "http://google.com", "http://facebook.com/*"
]
I don't have much experience with this, but looking at the example manifests that I've seen, they usually have the a list of domains under permissions. I'm betting that if you used:
"permissions": ["http://www.google.com/", "https://www.google.com/", https://google.com, https://google.com],
it would only run the code on the permissible pages.
Pulled example from:
http://developer.chrome.com/extensions/overview
More detailed info here:
http://developer.chrome.com/extensions/declare_permissions

Categories

Resources