Change user-agent headers only in incognito mode with a Chrome extension - google-chrome-extension

I'm trying to have my extension only work while in incognito mode. I can't seem to get it to work by adding "incognito": "split" to my manifest.json, and adding an if statement in the background.js looking for chrome.extension.inIncognitoContext.
Edit:
Okay, so what I'm trying to do is change my user-agent headers while only in incognito. I'm doing this based off this: http://elaineou.com/2016/02/19/how-to-use-chrome-extensions-to-bypass-paywalls/
It works for the said link above, but I can't seem to get it to work for all website while in incognito mode. This also won't be released, and I do have the allowed in incognito button checked.
manifest.json
{
"name": "Incognito Chrome Extension",
"version": "0.1",
"description": "This is an incognito chrome extension.",
"incognito": "split",
"permissions": ["webRequest", "webRequestBlocking",
"http://localhost:3000/",
"http://*/*",
"https://*/*"
],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2
}
Background.js
var ALLOW_COOKIES = [""];
if(chrome.extension.inIncognitoContext){
function changeRefer(details) {
foundReferer = false;
foundUA = false;
var reqHeaders = details.requestHeaders.filter(function(header) {
// block cookies by default
if (header.name !== "Cookie") {
return header;
}
allowHeader = ALLOW_COOKIES.map(function(url) {
if (details.url.includes(url)) {
return true;
}
return false;
});
if (allowHeader.reduce(function(a, b) { return a || b}, false)) { return header; }
}).map(function(header) {
if (header.name === "Referer") {
header.value = "https://www.google.com/";
foundReferer = true;
}
if (header.name === "User-Agent") {
header.value = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";
foundUA = true;
}
return header;
});
// append referer
if (!foundReferer) {
reqHeaders.push({
"name": "Referer",
"value": "https://www.google.com/"
});
}
if (!foundUA) {
reqHeaders.push({
"name": "User-Agent",
"value": "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
});
}
console.log(reqHeaders);
return {requestHeaders: reqHeaders};
}
function blockCookies(details) {
for (var i = 0; i < details.responseHeaders.length; ++i) {
if (details.responseHeaders[i].name === "Set-Cookie") {
details.responseHeaders.splice(i, 1);
}
}
return {responseHeaders: details.responseHeaders};
}
chrome.webRequest.onBeforeSendHeaders.addListener(changeRefer, {
urls: ["<all_urls>"],
types: ["main_frame"],
}, ["requestHeaders", "blocking"]);
chrome.webRequest.onHeadersReceived.addListener(blockCookies, {
urls: ["<all_urls>"],
types: ["main_frame"],
}, ["responseHeaders", "blocking"]);
}

I guess that your concern is the extra redundant background page process?
Add "incognito": "split" in the manifest file and close the extension's background page in non-incognito mode:
// background page or event page:
if (!chrome.extension.inIncognitoContext) {
window.close();
}
Content scripts will still be run in non-incognito pages. To counter that, just exit your code after checking whether your extension is running in incognito mode (similar to the above check).
Note: If the extension is going to be published and only useful in incognito mode, consider checking whether incognito mode is enabled and offer instructions if it's disabled. See e.g. How can I enable my chrome extension in incognito mode?

Related

how to make gtag to work in chrome extension?

I've added gtag.js to my chrome extension but I don't see anything on the nework, please tell me what I did wrong.
This is my CSP in manifest.json
{
"content_security_policy": "script-src 'self' https://www.googletagmanager.com https://ssl.google-analytics.com https://www.google-analytics.com https://mustsee-earth.firebaseio.com; object-src 'self'"
}
This is my index.html used by my extension (which replaces the user's default tab)
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>mustsee.earth</title>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX-X"></script>
</head>
Here's how I trigger views and events
gtag('config', GATID, {
page_title: place.name,
page_path: path
})
gtag('event', binding_value.action, {
event_category: binding_value.category,
event_label: binding_value.label,
value: binding_value.value
})
Although I followed every step, here's what I have on the network : nothing.
Here's the dataLayer var which proves my events are added to the queue but not triggered
[
{
"0": "js",
"1": "2018-04-24T21:02:54.881Z"
},
{
"0": "config",
"1": "UA-XXXXXXXXX-X",
"2": {
"checkProtocolTask": null,
"custom_map": {
"dimension5": "under 1.5 or failed"
}
}
},
{
"0": "config",
"1": "UA-XXXXXXXXX-X",
"2": {
"page_title": "Mesquite Flat Sand Dunes",
"page_path": "/mesquite-flat-oleksandr-mokrohuz-small.jpg"
}
},
{
"0": "event",
"1": "click on reload",
"2": {
"event_category": "Image View"
}
}
]
What can the issue be here ?
Adding gtm in the Chrome Extension is a bit tricky job. I had faced the same issues you are facing now. However, this is possible to implement gtm in CE.
Your manifest looks fine. You need to do some configuration changes in https://tagmanager.google.com/
You must add checkProtocolTask : false to each gtm tag in order to track them from Google Chrome Extension.
Add checkProtocolTask : false to Fields to Set
Scroll down to Fields to Set, and add a new field:
Field Name: checkProtocolTask
Value: false
See this SO post for more details.
gtag('config', GATID, {
page_title: place.name,
page_path: path
})
gtag = (function (old_gtag) {
var inited = false;
return function gtag() {
if (!inited && window.ga && window.ga.getAll) {
window.ga.getAll().forEach(function (tracker) {
tracker.set("checkProtocolTask", null);
inited = true;
});
}
if (inited) return old_gtag.apply(this, arguments);
var args = arguments;
setTimeout(function () {
gtag.apply(this, args);
}, 300);
};
})(gtag);
gtag('event', binding_value.action, {
event_category: binding_value.category,
event_label: binding_value.label,
value: binding_value.value
})

Why does my Chrome extension's Action Icon shown on all pages in omnibox?

I have following manifest
"page_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "Helper for soiduplaan.tallinn.ee"
},
"content_scripts": [
{
"matches": [
"http://soiduplaan.tallinn.ee/*"
],
But I see icon of my app in all pages I visit:
What do I do wrong? =\
Your current code is:
chrome.tabs.onUpdated.addListener(function(a) {
chrome.pageAction.show(a);
});
This causes the page action to be shown whenever a page is loaded, ie for every tab.
If you want to restrict the page action to certain pages only, check the tab.url property:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (tab.url && tab.url.indexOf('http://soiduplaan.tallinn.ee/') === 0) {
chrome.pageAction.show(tabId);
}
});
For more info, read the docs for chrome.tabs.onUpdated.

How can I work around Access-Control-Allow-Origin in extensions

My requests fail because of the same origin policy, but is there anyway I can work around this in extensions using the webRequest api to modify the headers?
Add this to your background.js file:
/**
* Force Access-Control-Allow-Origin
*
* Ideally, we'll want to remove this for production,
* and actually set the header server side instead.
*/
chrome.webRequest.onHeadersReceived.addListener(function onHeadersReceived(resp) {
var len = resp.responseHeaders.length;
while(--len) {
if(resp.responseHeaders[len].name.toLowerCase() === "access-control-allow-origin") {
resp.responseHeaders[len].value = "*";
break;
}
}
if (len === 0) { //if we didn't find it len will be zero
resp.responseHeaders.push({
'name': 'Access-Control-Allow-Origin',
'value': '*'
});
}
return {responseHeaders: resp.responseHeaders};
}, {
urls: ['*://*.YOU-API-DOMAIN.com/*', '*://localhost/*'],
/*TYPES: "main_frame", "sub_frame", "stylesheet", "script",
"image", "object", "xmlhttprequest", "other" */
types: ['xmlhttprequest']
}, ['blocking', 'responseHeaders']);
And also add these to your manifest.json permissions:
"webRequest",
"webRequestBlocking"
Reload extension and you should be good to go!

Why does "waiting" or "waitFor" dissapear in my code?

OK Ive updated the code to be as small as possible and still get the error...although now the question isnt quite right...it should now be "Why does waitFor jump out of the sandbox?" (but Ive been told not to change questions for a post, sorry if this is bad form). If you install this extension and follow the below instructions youll see waitFor get transferred to out side the content scripts sandbox.
To see this error.....
Go to....
https://www.facebook.com/groups/382415791793391/
..wait for the page to fully load.
Then click on the tab "Testy Testy" to cause the page to refresh.
Have a look in the console and youll see "You shouldnt be able to see this".
The console output for me looks like this....
chekcpage
waitFor
(19)waitFor
pop
attach contentNodeRemoved
chekcpage
waitFor
removing
added
attach contentNodeRemoved
chekcpage
waitFor
(156+)You shouldnt be able to see this
myscript.js
script = function(old) {
window.variableInUnsafeWindow = "You shouldnt be able to see this";
}
function exec(fn) {
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.textContent = '(' + fn + ')();';
document.documentElement.appendChild(script); // run the script
document.documentElement.removeChild(script); // clean up
}
exec(script);
window.onpopstate = function(event) {
console.debug('pop');
checkPage();
};
function waitFor(query, delay) {
if (typeof(variableInUnsafeWindow) == "undefined") {
console.debug('waitFor');
found = document.documentElement.querySelector(query);
if (!found) {
window.setTimeout("(" + waitFor + ")('" + query + "'," + delay + ");", delay);
}
} else {
console.debug(variableInUnsafeWindow);
window.setTimeout("(" + waitFor + ")('" + query + "'," + delay + ");", delay);
}
}
function contentNodeRemoved() {
console.debug('removing');
document.querySelector('div#contentCol').removeEventListener('DOMNodeRemoved', contentNodeRemoved, false);
document.querySelector('div#contentCol').addEventListener('DOMNodeInserted', contentNodeAdded, false);
}
function contentNodeAdded() {
console.debug('added');
document.querySelector('div#contentCol').removeEventListener('DOMNodeInserted', contentNodeAdded, false);
checkPage();
}
function checkPage() {
if (document.querySelector('div#contentCol')) {
console.debug('attach contentNodeRemoved');
var node = document.querySelector('div#contentCol');
node.addEventListener('DOMNodeRemoved', contentNodeRemoved, false);
}
console.debug('chekcpage');
waitFor('ul#group_mall_382415791793391', 300);
}
checkPage();
manifest.json
{
"name": "Facebook - Group member ban icon",
"description": "Puts an X after a users name on the groups page for banning. Unfortunately the X show on groups your not an Admin of still.",
"content_scripts": [{
"matches": ["*://*.facebook.com/*"],
"js": ["myscript.js"],
"run_at": "document_start"
}],
"permissions": ["tabs"],
"icons": {
"16": "icon.png",
"48": "icon48.png",
"128": "icon128.png"
},
"version": "1.0"
}

Render context menu depending on selection

I want to display a different menu option depending on whether a number or text is selected.
I've tried playing with content scripts but I can't get them to work in gmail which is where I need it to work. Here is what I have, it works on sites other than gmail (is it a https thing?)
Background.html
<script src="driver.js"></script>
content_script.js
document.addEventListener("mousedown", function(event){
if(event.button == 2) {
var selection = window.getSelection().toString();
chrome.extension.sendRequest({cmd: selection});
}
}, true);
driver.js
chrome.extension.onRequest.addListener(function(request) {
alert(request.cmd);
});
manifest.json
{
"name": "Context Menu Search",
"description": "Opens the selected text as keyword in a new window",
"version": "0.1",
"permissions": ["contextMenus"],
"content_scripts": [
{
"matches": ["http://*/*","https://*/*"],
"js": ["content_script.js"]
}
],
"background_page": "background.html"
}
Selection type changes context menu using chrome extension
You will have to set a listener for mouse down. There is no other way to get the selected text before the menu is created.
See this SO question:
chrome extension context menus, how to display a menu item only when there is no selection?
Here is part of the code the rest is at the link.
document.addEventListener("mousedown", function(event){
//right click
if(event.button == 2) {
if(window.getSelection().toString()) {
chrome.extension.sendRequest({cmd: "createSelectionMenu"});
} else {
chrome.extension.sendRequest({cmd: "createRegularMenu"});
}
}
}, true);

Resources