I'm currently developing a Chrome Extension and need to add/change a header value, but only on a specific page. Something like this:
chrome.onPageRequest(function(host) {
if(host == 'google.com') {
chrome.response.addHeader('X-Auth', 'abc123');
}
});
Any help would be greatly appreciated :)
You can use the chrome.webRequest API for that purpose. You'll need the following:
Declare the appropriate permissions in your manifest:
...
"permissions": [
...
"webRequest",
"*://*.google.com/*"
]
Register a listener for the chrome.webRequest.onHeadersReceived() event and modify the headers. In order to be able to modify the headers, you need to define the 'responseHeaders' extra info (see 3rd arguments of listener function):
chrome.webRequest.onHeadersReceived.addListener(function(details) {
console.log(details);
details.responseHeaders.push({
name: 'X-Auth',
value: 'abc123'
});
return { responseHeaders: details.responseHeaders };
}, {
urls: ['*://*.google.com/*']
}, [
"responseHeaders"
]);
Keep in mind that the webRequest permission only works if your background-page is persistent, so remove the corresponding line from your manifest (if it exists - which it should):
...
"background": {
"persistent": false, // <-- Remove this line or set it to `true`
"scripts": [...]
...
Also, keep in mind that pretty often Google redirects requests based on the user's country (e.g. redirecting www.google.com to www.google.gr), in which case the filter will not let them reach your onHeadersReceived listener.
Related
I've taken a look at other related SO posts and the solutions haven't helped solve my issue. This is my first chrome extension, so please bear with me!
I'm writing a simple chrome extension that searches for user provided keywords on a webpage. I can't get the content script that returns the DOM content to run. Some of the code, I've taken from an answer in another SO post, but I can't seem to get it to work for me.
I put a console.log("hello world") at the top of the file, and it doesn't show up, so I think it might be the structure of my project.
manifest.json
{
"name": "keyword search",
"version": "0.0.1",
"manifest_version": 2,
"permissions": [ "tabs" , "storage", "activeTab", "<all_urls>"],
"browser_action": {
"default_popup": "html/form.html"
},
"content_scripts": [{
"matches": [ "<all_urls>" ],
"js": [ "js/jquery.min.js", "content_scripts/content_script.js" ]
}],
"homepage_url": "http://google.com/"
}
js/popup.js
function run() {
running = true;
console.log('running');
var url = "https://www.stackoverflow.com/"
// Get KW & category for search
chrome.storage.local.get(["kw"],
function (data) {
kw = data.kw;
console.log("redirecting to find kw: " + kw);
// Send current tab to url
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.update(tabs[0].id, {url: url});
chrome.tabs.sendMessage(tabs[0].id, {type: 'DOM_request'}, searchDOM);
});
}
);
}
function searchDOM(domContent) {
console.log("beginning dom search \n" + domContent);
}
content_scripts/content_script.js
// Listen for messages
console.log("hello world")
chrome.runtime.onMessageExternal.addListener(function (msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.type === 'DOM_request') {
// Call the specified callback, passing
// the web-page's DOM content as argument
sendResponse(document.all[0].outerHTML);
}
});
console
running
redirecting to find kw: TestKeyword
beginning dom search
undefined
First, onMessageExternal is the wrong event (it's for external messaging):
you should use the standard onMessage.
Second, chrome extensions API is asynchronous so it only registers a job, returns immediately to continue to the next statement in your code without waiting for the job to complete:
chrome.tabs.update enqueues a navigation to a new URL
chrome.tabs.sendMessage enqueues a message sending job
the current page context in the tab gets destroyed along with the running content scripts
the tab starts loading the new URL
the message is delivered into the tab but there are no listeners,
but this step may instead run right after step 2 depending on various factors so the content script running in the old page will receive it which is not what you want
the tab loads the served HTML and emits a DOMContentLoaded event
your content scripts run shortly after that because of the default "run_at": "document_idle"
There are at least three methods to properly time it all:
make your content script emit a message and add an onMessage listener in the popup
use chrome.tabs.onUpdated to wait for the tab to load
use chrome.tabs.onUpdated + chrome.tabs.executeScript to simplify the entire thing
Let's take the executeScript approach.
remove "content_scripts" from manifest.json
instead of chrome.tabs.query (it's not needed) use the following:
chrome.tabs.update({url}, tab => {
chrome.tabs.onUpdated.addListener(function onUpdated(tabId, change, updatedTab) {
if (tabId === tab.id && change.status === 'complete') {
chrome.tabs.onUpdated.removeListener(onUpdated);
chrome.tabs.executeScript(tab.id, {
code: 'document.documentElement.innerHTML',
}, results => {
searchDOM(results[0]);
});
}
});
});
I currently have indexedDB on google.com domain. i want to be able to read it from google chrome extension. how can i accomplish this? do i need to add any specific permissions?
i currently have:
"permissions": [ "tabs", "bookmarks", "unlimitedStorage", "*://*/*", "identity", "https://*.google.com/*", "https://ssl.gstatic.com/", "https://www.googleapis.com/", "https://accounts.google.com/" ],
with what command i can do this? thank you!
Edit: i have readed i can access it from content script(aslong as the tab with domain is open - which is my case), but i dont know how to do that...
To access indexeddb of current tab add "activeTab" to "permissions" tag in manifest.json, Then create a content script, content script will be helpful in accessing the indexeddb as it runs in context of webpages, then add the content script created to the "content_scripts" tag in manifest.json file.
For Eg in manifest.json add the following:
"permissions": ["activeTab"],
"content_scripts": [
{
"matches": ["add the domains of the webpages where content script needs to run"],
"js": ["contentScript.js"]
}
]
For more info on matches check out here: https://developer.chrome.com/extensions/match_patterns
.
Inside content script add open the store and then perform transaction on the object store and perform queries on the object store.
For Eg in content script add following:
if (!('indexedDB' in window)) {
alert("This browser doesn't support IndexedDB");
} else {
let indexdb = window.indexedDB.open('firebaseLocalStorageDb', 1);
indexdb.onsuccess = function () {
let db = indexdb.result;
let transaction = db.transaction('firebaseLocalStorage', 'readwrite');
let storage = transaction.objectStore('firebaseLocalStorage');
console.log(storage.getAll());
};
}
Explanation of the above code:
It accesses the window object and opens the store "firebaseLocalStorageDb" with version "1", then after successfully accessing the object it looks for the result and performs transaction on the objectstore "firebaseLocalStorage" residing inside the store. Finally query the instance of objectstore "storage" to get all the key-value pairs.
For more info check: https://javascript.info/indexeddb
For anyone still interested, my solution to this problem -
this is placed in content script of extension -
chrome.extension.onConnect.addListener(function(port) {
if(port.name == "extension_request" ) {
port.onMessage.addListener(function(msg) {
if (msg.db) {
window.indexedDB.webkitGetDatabaseNames().onsuccess = function(sender,args)
{
var r = sender.target.result;
if(r.contains(msg.db)){
var openRequest = indexedDB.open(msg.db);
// your code
port.postMessage({foo: bar}); // your result which you want to send
}
}
}
}
}
and this is for background or popup script -
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var port = chrome.tabs.connect(tabs[0].id,{name: "extension_request"});
port.postMessage({db: "database_name_example"}); // send database name
port.onMessage.addListener(function(msg) {
if (msg.foo ) {
// do your stuff in extension
}
}
}
I'm trying to block some requests in a Chrome app.
I created a JavaScript listener that does this validation:
chrome.webRequest.onBeforeRequest.addListener(
{
urls: ["*://site.com/test/*"]
},
["blocking"]
);
But the requests are not blocking. Did I miss something in this code?
My manifest:
"background": {
"scripts": ["listener.js"],
"persistent": true
},
"permissions": ["tabs", "http://*/*"],
"manifest_version": 2,
It looks like you misunderstood the meaning of "blocking" here.
https://developer.chrome.com/extensions/webRequest.html#subscription
If the optional opt_extraInfoSpec array contains the string 'blocking'
(only allowed for specific events), the callback function is handled
synchronously. That means that the request is blocked until the
callback function returns. In this case, the callback can return a
BlockingResponse that determines the further life cycle of the
request.
To block a request (cancel it), return {cancel: true} in your event handler.
For example:
chrome.webRequest.onBeforeRequest.addListener(
function() {
return {cancel: true};
},
{
urls: ["*://site.com/test/*"]
},
["blocking"]
);
This will block all URLs matching *://site.com/test/*.
Also remember to declare both webRequest and webRequestBlocking permissions in your manifest.
From Chrome 59 you can block specific requests from Network tab of developer tools itself.
https://developers.google.com/web/updates/2017/04/devtools-release-notes#block-requests
Right-click on the request in the Network panel and select Block Request URL. A new Request blocking tab pops up in the Drawer, which lets you manage blocked requests.
I have figured out how to run a script on every page load when it is done explicitly by user but I want to run my script each time it makes a post or get request in its back end on its own to the database or ad server implicitly. [For example on gmail if we keep our eyes on requests (maybe firebug - console - all) we will see that after certain time a POST request is getting fired from the browser on its own. ]
Is there any way I can do that?
Actually I am writing my first extension so it clearly states I don't know much about it.
You should use webRequest module in your extension. After specifing proper permissions in the manifest, for example:
"permissions": [
"webRequest",
"*://*/*"
],
"background": {
"scripts": ["background.js"]
},
you can register in your background page ("background.js" in the example) any required handlers, such as onBeforeRequest, onBeforeSendHeaders, onHeadersReceived, onCompleted, and others. I think the names are self-explaining, but you can consult with abovementioned documentation.
Depending from your requirements, you can define event handlers which prevent requests, modify headers, just read and somehow analyse http-headers.
Example for reading http headers and possibly changing them:
chrome.webRequest.onBeforeSendHeaders.addListener(
function(details)
{
console.log(details.url);
if(details.method == 'POST')
{
// do some stuff
for(var i = 0; i < details.requestHeaders.length; ++i)
{
// log or change some headers
// details.requestHeaders[i].name
// details.requestHeaders[i].value
}
}
return {requestHeaders: details.requestHeaders};
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]);
I'm having fun with Google Chrome extension, and I just want to know how can I store the URL of the current tab in a variable?
Use chrome.tabs.query() like this:
chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
let url = tabs[0].url;
// use `url` here inside the callback because it's asynchronous!
});
This requires that you request access to the chrome.tabs API in your extension manifest:
"permissions": [ ...
"tabs"
]
It's important to note that the definition of your "current tab" may differ depending on your extension's needs.
Setting lastFocusedWindow: true in the query is appropriate when you want to access the current tab in the user's focused window (typically the topmost window).
Setting currentWindow: true allows you to get the current tab in the window where your extension's code is currently executing. For example, this might be useful if your extension creates a new window / popup (changing focus), but still wants to access tab information from the window where the extension was run.
I chose to use lastFocusedWindow: true in this example, because Google calls out cases in which currentWindow may not always be present.
You are free to further refine your tab query using any of the properties defined here: chrome.tabs.query
Warning! chrome.tabs.getSelected is deprecated. Please use chrome.tabs.query as shown in the other answers.
First, you've to set the permissions for the API in manifest.json:
"permissions": [
"tabs"
]
And to store the URL :
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
});
Other answers assume you want to know it from a popup or background script.
In case you want to know the current URL from a content script, the standard JS way applies:
window.location.toString()
You can use properties of window.location to access individual parts of the URL, such as host, protocol or path.
The problem is that chrome.tabs.getSelected is asynchronous. This code below will generally not work as expected. The value of 'tablink' will still be undefined when it is written to the console because getSelected has not yet invoked the callback that resets the value:
var tablink;
chrome.tabs.getSelected(null,function(tab) {
tablink = tab.url;
});
console.log(tablink);
The solution is to wrap the code where you will be using the value in a function and have that invoked by getSelected. In this way you are guaranteed to always have a value set, because your code will have to wait for the value to be provided before it is executed.
Try something like:
chrome.tabs.getSelected(null, function(tab) {
myFunction(tab.url);
});
function myFunction(tablink) {
// do stuff here
console.log(tablink);
}
This is a pretty simple way
window.location.toString();
You probaly have to do this is the content script because it has all the functions that a js file on a wepage can have and more.
Hi here is an Google Chrome Sample which emails the current Site to an friend. The Basic idea behind is what you want...first of all it fetches the content of the page (not interessting for you)...afterwards it gets the URL (<-- good part)
Additionally it is a nice working code example, which i prefer motstly over reading Documents.
Can be found here:
Email this page
This Solution is already TESTED.
set permissions for API in manifest.json
"permissions": [ ...
"tabs",
"activeTab",
"<all_urls>"
]
On first load call function. https://developer.chrome.com/extensions/tabs#event-onActivated
chrome.tabs.onActivated.addListener((activeInfo) => {
sendCurrentUrl()
})
On change call function. https://developer.chrome.com/extensions/tabs#event-onSelectionChanged
chrome.tabs.onSelectionChanged.addListener(() => {
sendCurrentUrl()
})
the function to get the URL
function sendCurrentUrl() {
chrome.tabs.getSelected(null, function(tab) {
var tablink = tab.url
console.log(tablink)
})
async function getCurrentTabUrl () {
const tabs = await chrome.tabs.query({ active: true })
return tabs[0].url
}
You'll need to add "permissions": ["tabs"] in your manifest.
For those using the context menu api, the docs are not immediately clear on how to obtain tab information.
chrome.contextMenus.onClicked.addListener(function(info, tab) {
console.log(info);
return console.log(tab);
});
https://developer.chrome.com/extensions/contextMenus
You have to check on this.
HTML
<button id="saveActionId"> Save </button>
manifest.json
"permissions": [
"activeTab",
"tabs"
]
JavaScript
The below code will save all the urls of active window into JSON object as part of button click.
var saveActionButton = document.getElementById('saveActionId');
saveActionButton.addEventListener('click', function() {
myArray = [];
chrome.tabs.query({"currentWindow": true}, //{"windowId": targetWindow.id, "index": tabPosition});
function (array_of_Tabs) { //Tab tab
arrayLength = array_of_Tabs.length;
//alert(arrayLength);
for (var i = 0; i < arrayLength; i++) {
myArray.push(array_of_Tabs[i].url);
}
obj = JSON.parse(JSON.stringify(myArray));
});
}, false);
If you want the full extension that store the URLs that opened or seen by the use via chrome extension:
use this option in your background:
openOptionsPage = function (hash) {
chrome.tabs.query({ url: options_url }, function (tabs) {
if (tabs.length > 0) {
chrome.tabs.update(
tabs[0].id,
{ active: true, highlighted: true, currentWindow: true },
function (current_tab) {
chrome.windows.update(current_tab.windowId, { focused: true });
}
);
} else {
window.addEventListener(hash, function () {
//url hash # has changed
console.log(" //url hash # has changed 3");
});
chrome.tabs.create({
url: hash !== undefined ? options_url + "#" + hash : options_url,
});
}
});
};
you need index.html file also. which you can find in the this Github
the manifest file should be like this:
{
"manifest_version": 2,
"name": "ind count the Open Tabs in browser ",
"version": "0.3.2",
"description": "Show open tabs",
"homepage_url": "https://github.com/sylouuu/chrome-open-tabs",
"browser_action": {},
"content_security_policy": "script-src 'self' https://ajax.googleapis.com https://www.google-analytics.com; object-src 'self'",
"options_page": "options.html",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"]
},
"web_accessible_resources": ["img/*.png"],
"permissions": ["tabs", "storage"]
}
The full version of simple app can be found here on this Github:
https://github.com/Farbod29/extract-and-find-the-new-tab-from-the-browser-with-chrome-extention