Tool to replace URL with custom content - google-chrome

Is there a development tool or Chrome / Firefox extension that lets you replace the contents of a specific URL with my own custom content?
I'm not looking for a simple /etc/hosts file change, because I want to replace a URL, not just a domain.

In a Chrome extension, the webRequest API can be used to redirect URLs to a different URL. This other URL can be another online page, but also a page within your Chrome extension.
A simple example for the webRequest API, and a list of other options can be found in this answer.
Note: If you just want to add / change something on a specific page, Content scripts may be more suitable. You can then change the content of a specific page by standard DOM methods.
In Firefox, you can use the page-mod module of the Addon SDK to implement the Content script.

chrome.tab API will let you to make any related changes to a tab in a window.
References:
a) Tabs API
b) Basic Chrome Extension architecture.
You can refer this Sample Extension for changing all URL's in a current tab to Google.co.in
manifest.json
This is a core file where we register all chrome extension content, ensure it is with all permissions.
{
"name":"Tabs Demo",
"description":"This Demonstrates Demo of Tabs",
"browser_action":{
"default_icon":"screen.png",
"default_popup":"popup.html"
},
"permissions":["tabs"],
"manifest_version":2,
"version":"1"
}
popup.html
Trivial HTML file referring to a JS file to pass CSP.
<!doctype html>
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
function tabsfunction() {
//fetching all tabs in window
chrome.tabs.getAllInWindow(function (tabs) {
// Iterating through tabs
for (tab in tabs) {
//Updating each tab URL to custom url
chrome.tabs.update(tabs[tab].id, {
"url": /*You can place any URL you want here*/
"https://www.google.co.in/"
}, function () {
//Call back
console.log("Completed");
});
}
});
}
//Binging a function on document events
document.addEventListener("DOMContentLoaded", tabsfunction);
Let me know if you need more information.

Related

Chrome Automatically Highlighting Address Bar On New Tab Open [duplicate]

With Chrome 27, it seems that extensions that override Chrome's New Tab Page can't take focus away from Chrome's Omnibox like they used to in previous versions of Chrome.
Is there a new way to focus an input box in a New Tab Page, or has this functionality been disabled completely? :(
To test this, create an extension folder with three files:
1. manifest.json:
{
"name": "Focus Test",
"version": "0",
"minimum_chrome_version": "27",
"chrome_url_overrides": {
"newtab": "newTab.html"
},
"manifest_version": 2
}
2. focus.js:
document.getElementById('foo').focus();
3. newTab.html:
<html>
<body>
<input id="foo" type="text" />
<script type="text/javascript" src="focus.js"></script>
</body>
</html>
Then, when you load the extension and open a new tab, the input field does not get focused on the new tab page.
I have also tried adding the autofocus attribute to the input field, but no luck either. The extension's new tab page can't take focus away from Chrome's Omnibox.
Any ideas? Is this a bug or a new "feature"?
ManifestV3 update
This answer is adapted from https://stackoverflow.com/a/11348302/1754517.
This has been tested with both Manifest V2 and V3.
Tested in Google Chrome 99.0.4844.51 64-bit (Windows 10).
Replace the content of focus.js with:
if (location.search !== "?x") {
location.search = "?x";
throw new Error; // load everything on the next page;
// stop execution on this page
}
Add the autofocus attribute to the <input>.
Go to the Extensions page in Chrome and click the Load unpacked button. Choose the folder of your extension.
Open your new tab page. You might see a modal dialogue reading Change back to Google?. Click Keep it to keep your custom new tab page.
Inline Javascript - Manifest V2 only
If you're inlining the Javascript in the HTML file, then you'll need to take some extra steps:
After adding your inline Javascript to your HTML file, open DevTools (F12 key) and observe the error output in the Console. Example output you should see:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem:".
Either the 'unsafe-inline' keyword, a hash ('sha256-MK0Gypb4mkZTI11eCOtWT+mGYcJNpN5zccvhfeaRb6E='), or a nonce ('nonce-...') is required to enable inline execution.
Select & copy this hash.
Add a line to manifest.json to allow the JS to run, pasting in the hash you just copied between the single-quotes. E.g.:
"content_security_policy": "script-src 'self' 'sha256-MK0Gypb4mkZTI11eCOtWT+mGYcJNpN5zccvhfeaRb6E='"
Go to the Extensions page again. Remove the extension, then re-add it using the Load unpacked button.
Open your new tab page. Your extension should now autofocus on the <input>.
Note inlining only works with Manifest V2; Manifest V3 returns a failure message when attempting to load the extension (even with a properly formed "content_security_policy" object in manifest.json, to replace the Manifest V2 "content_security_policy" string):
Failed to load extension
File C:\path\to\extension
Error 'content_security_policy.extension_pages': Insecure CSP value "'sha256-...'" in directive 'script-src'.
Could not load manifest.
As per the Chrome Extension Documentation,
Don't rely on the page having the keyboard focus.
The address bar always gets the focus first when the user creates a new tab.
See reference here: Override Pages
Here's the solution for Manifest v3
chrome.tabs.onCreated.addListener((tab) => {
if (tab.pendingUrl === 'chrome://newtab/') {
chrome.tabs.remove(tab.id)
chrome.tabs.create({
url: '/index.html',
})
}
})
I saw a pretty old blog which updates the new tab conditionally. However, simply updating the tab does not steal the focus. I had to close the pending tab and open a new one.
Cons: An ugly chrome-extension://akfdobdepdedlohhjdalbeadhkbelajj/index.html in the URL bar.
I have a cheap work around that allows stealing focus from address bar focus. It's not for everyone. I do actually do use this because I want to control a new tab focus just that bad in my own custom new tab solution:
<script>
alert('Use enter key to cancel this alert and then I will control your focus');
document.getElementById('...AckerAppleIsCrafty...').focus()
</script>
USE CASE: I built my own HTML chrome custom tab that has a search input that custom searches my history and bookmarks the way I like it too.
Cash me focusing outside how bout dat?

How does a Chrome web extension use chrome.scripting.executeScript to inject a javascript function into a webpage?

I have a Chrome Manifest V3 web extension that needs to inject javascript into a webpage on page load of every page (not fussy as to exactly when the javascript is run).
This is so that javascript on the webpage can optionally call the function defined by the web extension.
According to the docs at https://developer.chrome.com/docs/extensions/reference/scripting/, the chrome.scripting.executeScript will do what I need:
You can use the chrome.scripting API to inject JavaScript and CSS into websites.
The chrome.scripting.executeScript function takes a tabId as a mandatory parameter, but nothing in the docs indicates where to get the tabId from. The docs make reference to an unspecified function getTabId(), but otherwise say nothing.
In addition, the docs do not say where the chrome.scripting.executeScript function is to be run. In the content script? In theory that won't work as the tab ID is not accessible. In the background service worker? What happens if the service worker is not running when the page is loaded?
Note that the following questions are not related to this question:
How would I inject code from my Chrome extension into a webpage? (closed, no reference to Manifest v3)
Use a content script to access the page context variables and functions (opposite question)
How to access the webpage DOM rather than the extension page DOM? (nothing to do with the DOM)
To get the tabId --
In Manifest V3, you pass it as a value.
chrome.action.onClicked.addListener((tab) => {
if(!tab.url.includes("chrome://")) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: reddenPage
});
}
});
Check out Google's Chrome Extension example "Page Redder" for the full code

Checking tab status in a chrome extension with a popup without the tabs permission

I'm currently trying to build my first chrome extension and I only need it to interact with pages of a few domains, so I want to avoid using the "tabs" permission since I understand it would have me request access to all information and all domains.
Instead I want to restrict myself to using the aciveTab permission and, if need be, a content script.
In short, what I want to do is display a "Subscribe button" in my extension's popup if the currently selected tab's url is of the domain(s) I'm interested in.
I can get the url of the page when it's created using a content script but I don't know how to make sure the user is still on that page when my extension is clicked.
I haven't managed to get anything done with activeTab.
Thanks in advance for any piece of advice you can give, I'll check on the answers (if any) after work.
A working example with the activeTab permisison:
In your popup.js
chrome.tabs.query({lastFocusedWindow: true, active: true}, function(tabs) {
if (tabs && tabs[0] && tabs[0].url) {
var match = tabs[0].url.match(/^[^:]+:\/\/([^\/]+)/);
if (match) {
var domain = match[1];
if (domain == 'stackoverflow.com')
alert('test');
}
}
});
Note:
You have to declare the "activeTab" permission in your manifest (of course).
JavaScript code must be in a standalone file and included in popup.html with <script src="..."></script>. Inline JavaScript is not allowed due to CSP.

Add JavaScript file to all sites I browse

I'm new to Chrome extension development, I need to make something sample with extension.
I Need to add JavaScript file to all sites I browse when the extension enabled, this is the code i want to add to all pages
<script type="text/javascript" src="web-retina-emulator.js"></script>
This file make pages look like when the website on retina display.
Is there easy way to make this happen?
You can use this basic structure to add JavaScript file to all sites when the extension enabled.
Method 1
If web-retina-emulator.js is an individual file which do not use global variables or functions of pages where it is injected it is suggested to use this method
Advantage:
It has access to certain sections of chrome API*
Draw Back
It can not use javascript variables and functions of pages where it is injected.
Demonstration
manifest.json
{
"name":"Custom Script",
"description":"http://stackoverflow.com/questions/14165629/add-javascript-file-to-all-sites-i-browse",
"version":"1",
"manifest_version":2,
"content_scripts":[{
"matches":["<all_urls>"],
"js":["web-retina-emulator.js"],
}
]
}
Method 2
If web-retina-emulator.js need some javascript methods or variables of pages, use this approach
Advantage:
It has access to javascript variables and methods of pages
Draw Back
It can not use chrome API*.
Demonstration
manifest.json
{
"name":"Custom Script",
"description":"http://stackoverflow.com/questions/14165629/add-javascript-file-to-all-sites-i-browse",
"version":"1",
"manifest_version":2,
"content_scripts":[{
"matches":["<all_urls>"],
"js":["myscript.js"],
}
]
}
myscript.js
var script = document.createElement('script'); // Create a Script Tag
script.src = chrome.extension.getURL("web-retina-emulator.js"); //Fetch the content script
script.onload = function () {
this.parentNode.removeChild(this); //Remove script after script executed
};
(document.head || document.documentElement).appendChild(script); //ADD script tag
//to head or Html element
Method 3
Inserting code into a page programmatically is useful when your JavaScript or CSS code shouldn't be injected into every single page that matches the pattern — for example, if you want a script to run only when the user clicks a browser action's icon.
Demonstration
background.html
chrome.tabs.executeScript(null,
{file:"web-retina-emulator.js"});
manifest.json
Ensure permissions are set in manifest file
"permissions": [
"tabs", "http://*/*"
],
References
Content Scripts
Execute Script API
Check out tampermonkey. It's the chrome equivalent to greasemonkey.

Could I make a Google Chrome extension for chrome pages (downloads, extensions etc)?

I'd like to make a very simple extensions that slightly alters how the Downloads page looks. Changing the History page might be interesting too, but that's for later.
Is there a way to do that?
I tried making a Content Script extension, with "chrome://downloads" as match in manifest.json. Chrome won't allow that and responds with an error when packaging the extension.
Is there another simple way? It has to be simple, because changes would be simple, because all chrome:// pages are built with HTML, JS and CSS.
edit
After trying with background scripts a little...
I can't get chrome.tabs.executeScript to work! I added in background.html:
chrome.browserAction.onClicked.addListener(function(tab) {
alert(this.document.body.innerHTML);
alert(chrome.tabs.executeScript(null, {
code : "document.body.style.backgroundColor = 'red';"
}));
});
And I added this in manifest.json to add a (invisible) 'browser action button':
,"browser_action": {
/* "popup": "background.html",*/
"name": "Alter page"
}
The onClicked event fires both alerts (first is background.html's body, second is undefined). But the code (a string with document.body.style.backgroundColor = 'red';) doesn't execute! And ofcourse there's no debugging for extensions like this =)
Any tips anyone? I'm trying to get a hold of the tab's window.document (not background.html's window.document!). An injected script (that's what chrome.tabs.executeScript is supposed to do) should do that.
PS
I'm stealing from make_page_red/manifest and make_page_red/background.html
The 'extension' I have so far: http://hotblocks.nl/js/downloads.rar
EDIT
I found out what I want to achieve is possible with just CSS. I don't need to inject javascript. Does that make it easier? Does that make it possible? =)
According to this documentation, chrome:// URLs are an invalid scheme so they won't be matched:
A match pattern is essentially a URL that begins with a permitted scheme (http, https, file, or ftp), and that can contain '*' characters.
I would look into using override pages instead.
As requested, here's my extension that can at least load when chrome://downloads is loaded, although as I said, I don't think you can modify the page even if you know that's the page you're viewing.
manifest.json
{
"name": "Test",
"version": "0.0.1",
"background_page": "background.html",
"permissions": [
"tabs"
]
}
background.html
<script>
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
{
if (tab.status == "complete")
{
alert(tab.url);
// should alert 'chrome://downloads' on that page. You can
// check for this url here and then do whatever you want
}
});
</script>
Update: Since Chrome 31 there is an API for extensions that allows access to Chrome's downloads: https://developer.chrome.com/extensions/downloads
There's also an API that allows access to list and manage other installed extensions: https://developer.chrome.com/extensions/management
(Previous Answer)
Unfortunately, there's not currently an API for Chrome extensions to access information about a user's downloads. It's a widely requested feature, though, and there's some discussion among Chrome developers here: http://code.google.com/p/chromium/issues/detail?id=12133
Star the issue if it's a feature that you'd like to see, and you'll receive email updates.
As this page shows, there is no API to override the downloads page... However, there is a way to make a file you have made replace the chrome://downloads/ page whenever it is loaded using javascript in your background page...
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status === "loading"){
if(tab.url === "chrome://downloads/"){
chrome.tabs.update(tab.id, {url: "REPLACEMENT.html"});
}
}
});
Essentially what this does is - As soon as the page chrome://downloads begins loading (using the tabs.onUpdated API), the page is redirected to REPLACEMENT.html (Using tabs.update API)... There is no visible delay in the tab update
as this script is run before the chrome://downloads page begins loading... You can use a similar code in your file by pressing CTRL + U on the downloads page to view and copy its source code