How to share a unique tab ID between content and background scripts without an asynchronous delay?
up vote
0
down vote
favorite
I have built a chrome extension and I'm getting hit by a race condition that I need help with.
If you see the answer chrome extension: sharing an object between content scripts and background script it tells us that you cannot share a variable between content and background scripts.
My goal is to generate a unique ID per-browser tab and then share it in between the content.js
and the background.js
. Then I need to use this value in a content injected javascript as explained in this answer: In Chrome extensions, can you force some javascript to be injected before everything?
The only way I have been able to figure out how to do this is by doing the following async code then I just use the tab ID as the unique ID:
content.js
await pingBackground();
async function pingBackground() {
var info;
await new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({ type: 1 }, function (response) {
if (response !== undefined) {
info = response;
resolve();
}
else {
reject();
}
});
});
console.log("Id is " + info.id);
}
background.js
chrome.runtime.onMessage.addListener(messageHandler);
function messageHandler(message, sender, reply) {
switch (message.type) {
case 1:
reply({ 'id': sender['tab'].id, 'active': true });
break;
}
}
manifest.json
{
"name": "oogi",
"version": "0.1",
"manifest_version": 2,
"background": {
"scripts": [
"common.js",
"background.js"
],
"persistent": true
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_start"
}
],
"permissions": [
"contentSettings",
"webRequest",
"webRequestBlocking",
"*://*/*"
]
}
But the problem with this is by the time I get the tab ID from background js, the script's content has already been loaded.
Is there some way to make it so this variable can be asynchronously shared between background.js
and content.js
? Or is this simply impossible?
Can I switch it around and have background.js
load a variable from content.js
asynchronously?
UPDATE:
A terrible hack which works is to do this in the foreground of the content.js
:
var sleepScript = document.createElement('script');
var sleepCode = `function sleep (ms) {
var start = new Date().getTime();
while (new Date() < start + ms) {}
return 0;
}
sleep(500);`;
sleepScript.textContent = sleepCode;
(document.head || document.documentElement).appendChild(sleepScript);
This will force the page to wait for a bit giving the time to query the background before running the inline dom.
It works but that's awful.
javascript google-chrome-extension
|
show 10 more comments
up vote
0
down vote
favorite
I have built a chrome extension and I'm getting hit by a race condition that I need help with.
If you see the answer chrome extension: sharing an object between content scripts and background script it tells us that you cannot share a variable between content and background scripts.
My goal is to generate a unique ID per-browser tab and then share it in between the content.js
and the background.js
. Then I need to use this value in a content injected javascript as explained in this answer: In Chrome extensions, can you force some javascript to be injected before everything?
The only way I have been able to figure out how to do this is by doing the following async code then I just use the tab ID as the unique ID:
content.js
await pingBackground();
async function pingBackground() {
var info;
await new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({ type: 1 }, function (response) {
if (response !== undefined) {
info = response;
resolve();
}
else {
reject();
}
});
});
console.log("Id is " + info.id);
}
background.js
chrome.runtime.onMessage.addListener(messageHandler);
function messageHandler(message, sender, reply) {
switch (message.type) {
case 1:
reply({ 'id': sender['tab'].id, 'active': true });
break;
}
}
manifest.json
{
"name": "oogi",
"version": "0.1",
"manifest_version": 2,
"background": {
"scripts": [
"common.js",
"background.js"
],
"persistent": true
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_start"
}
],
"permissions": [
"contentSettings",
"webRequest",
"webRequestBlocking",
"*://*/*"
]
}
But the problem with this is by the time I get the tab ID from background js, the script's content has already been loaded.
Is there some way to make it so this variable can be asynchronously shared between background.js
and content.js
? Or is this simply impossible?
Can I switch it around and have background.js
load a variable from content.js
asynchronously?
UPDATE:
A terrible hack which works is to do this in the foreground of the content.js
:
var sleepScript = document.createElement('script');
var sleepCode = `function sleep (ms) {
var start = new Date().getTime();
while (new Date() < start + ms) {}
return 0;
}
sleep(500);`;
sleepScript.textContent = sleepCode;
(document.head || document.documentElement).appendChild(sleepScript);
This will force the page to wait for a bit giving the time to query the background before running the inline dom.
It works but that's awful.
javascript google-chrome-extension
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
The problem is the seed value that it creates is created in thebackground.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in thecontent.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.
– Nicholas DiPiazza
Nov 6 at 6:03
|
show 10 more comments
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have built a chrome extension and I'm getting hit by a race condition that I need help with.
If you see the answer chrome extension: sharing an object between content scripts and background script it tells us that you cannot share a variable between content and background scripts.
My goal is to generate a unique ID per-browser tab and then share it in between the content.js
and the background.js
. Then I need to use this value in a content injected javascript as explained in this answer: In Chrome extensions, can you force some javascript to be injected before everything?
The only way I have been able to figure out how to do this is by doing the following async code then I just use the tab ID as the unique ID:
content.js
await pingBackground();
async function pingBackground() {
var info;
await new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({ type: 1 }, function (response) {
if (response !== undefined) {
info = response;
resolve();
}
else {
reject();
}
});
});
console.log("Id is " + info.id);
}
background.js
chrome.runtime.onMessage.addListener(messageHandler);
function messageHandler(message, sender, reply) {
switch (message.type) {
case 1:
reply({ 'id': sender['tab'].id, 'active': true });
break;
}
}
manifest.json
{
"name": "oogi",
"version": "0.1",
"manifest_version": 2,
"background": {
"scripts": [
"common.js",
"background.js"
],
"persistent": true
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_start"
}
],
"permissions": [
"contentSettings",
"webRequest",
"webRequestBlocking",
"*://*/*"
]
}
But the problem with this is by the time I get the tab ID from background js, the script's content has already been loaded.
Is there some way to make it so this variable can be asynchronously shared between background.js
and content.js
? Or is this simply impossible?
Can I switch it around and have background.js
load a variable from content.js
asynchronously?
UPDATE:
A terrible hack which works is to do this in the foreground of the content.js
:
var sleepScript = document.createElement('script');
var sleepCode = `function sleep (ms) {
var start = new Date().getTime();
while (new Date() < start + ms) {}
return 0;
}
sleep(500);`;
sleepScript.textContent = sleepCode;
(document.head || document.documentElement).appendChild(sleepScript);
This will force the page to wait for a bit giving the time to query the background before running the inline dom.
It works but that's awful.
javascript google-chrome-extension
I have built a chrome extension and I'm getting hit by a race condition that I need help with.
If you see the answer chrome extension: sharing an object between content scripts and background script it tells us that you cannot share a variable between content and background scripts.
My goal is to generate a unique ID per-browser tab and then share it in between the content.js
and the background.js
. Then I need to use this value in a content injected javascript as explained in this answer: In Chrome extensions, can you force some javascript to be injected before everything?
The only way I have been able to figure out how to do this is by doing the following async code then I just use the tab ID as the unique ID:
content.js
await pingBackground();
async function pingBackground() {
var info;
await new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({ type: 1 }, function (response) {
if (response !== undefined) {
info = response;
resolve();
}
else {
reject();
}
});
});
console.log("Id is " + info.id);
}
background.js
chrome.runtime.onMessage.addListener(messageHandler);
function messageHandler(message, sender, reply) {
switch (message.type) {
case 1:
reply({ 'id': sender['tab'].id, 'active': true });
break;
}
}
manifest.json
{
"name": "oogi",
"version": "0.1",
"manifest_version": 2,
"background": {
"scripts": [
"common.js",
"background.js"
],
"persistent": true
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_start"
}
],
"permissions": [
"contentSettings",
"webRequest",
"webRequestBlocking",
"*://*/*"
]
}
But the problem with this is by the time I get the tab ID from background js, the script's content has already been loaded.
Is there some way to make it so this variable can be asynchronously shared between background.js
and content.js
? Or is this simply impossible?
Can I switch it around and have background.js
load a variable from content.js
asynchronously?
UPDATE:
A terrible hack which works is to do this in the foreground of the content.js
:
var sleepScript = document.createElement('script');
var sleepCode = `function sleep (ms) {
var start = new Date().getTime();
while (new Date() < start + ms) {}
return 0;
}
sleep(500);`;
sleepScript.textContent = sleepCode;
(document.head || document.documentElement).appendChild(sleepScript);
This will force the page to wait for a bit giving the time to query the background before running the inline dom.
It works but that's awful.
javascript google-chrome-extension
javascript google-chrome-extension
edited Nov 5 at 21:58
asked Nov 5 at 19:38
Nicholas DiPiazza
3,37853472
3,37853472
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
The problem is the seed value that it creates is created in thebackground.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in thecontent.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.
– Nicholas DiPiazza
Nov 6 at 6:03
|
show 10 more comments
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
The problem is the seed value that it creates is created in thebackground.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in thecontent.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.
– Nicholas DiPiazza
Nov 6 at 6:03
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
The problem is the seed value that it creates is created in the
background.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in the content.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.– Nicholas DiPiazza
Nov 6 at 6:03
The problem is the seed value that it creates is created in the
background.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in the content.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.– Nicholas DiPiazza
Nov 6 at 6:03
|
show 10 more comments
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
This question was already answered previously, although it is hard to tell that this is the same issue at first glance.
https://stackoverflow.com/a/45105934
The answer is pretty descriptive so give it a read.
Here is the script changes that make it work:
// background.js
function addSeedCookie(details) {
details.responseHeaders.push({
name: "Set-Cookie",
value: `tab_id=${details.tabId}; Max-Age=2`
});
return {
responseHeaders: details.responseHeaders
};
}
chrome.webRequest.onHeadersReceived.addListener(
addSeedCookie, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]
);
// inject.js
function getCookie(cookie) { // https://stackoverflow.com/a/19971550/934239
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
var tabId = getCookie("tab_id");
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
This question was already answered previously, although it is hard to tell that this is the same issue at first glance.
https://stackoverflow.com/a/45105934
The answer is pretty descriptive so give it a read.
Here is the script changes that make it work:
// background.js
function addSeedCookie(details) {
details.responseHeaders.push({
name: "Set-Cookie",
value: `tab_id=${details.tabId}; Max-Age=2`
});
return {
responseHeaders: details.responseHeaders
};
}
chrome.webRequest.onHeadersReceived.addListener(
addSeedCookie, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]
);
// inject.js
function getCookie(cookie) { // https://stackoverflow.com/a/19971550/934239
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
var tabId = getCookie("tab_id");
add a comment |
up vote
0
down vote
accepted
This question was already answered previously, although it is hard to tell that this is the same issue at first glance.
https://stackoverflow.com/a/45105934
The answer is pretty descriptive so give it a read.
Here is the script changes that make it work:
// background.js
function addSeedCookie(details) {
details.responseHeaders.push({
name: "Set-Cookie",
value: `tab_id=${details.tabId}; Max-Age=2`
});
return {
responseHeaders: details.responseHeaders
};
}
chrome.webRequest.onHeadersReceived.addListener(
addSeedCookie, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]
);
// inject.js
function getCookie(cookie) { // https://stackoverflow.com/a/19971550/934239
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
var tabId = getCookie("tab_id");
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
This question was already answered previously, although it is hard to tell that this is the same issue at first glance.
https://stackoverflow.com/a/45105934
The answer is pretty descriptive so give it a read.
Here is the script changes that make it work:
// background.js
function addSeedCookie(details) {
details.responseHeaders.push({
name: "Set-Cookie",
value: `tab_id=${details.tabId}; Max-Age=2`
});
return {
responseHeaders: details.responseHeaders
};
}
chrome.webRequest.onHeadersReceived.addListener(
addSeedCookie, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]
);
// inject.js
function getCookie(cookie) { // https://stackoverflow.com/a/19971550/934239
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
var tabId = getCookie("tab_id");
This question was already answered previously, although it is hard to tell that this is the same issue at first glance.
https://stackoverflow.com/a/45105934
The answer is pretty descriptive so give it a read.
Here is the script changes that make it work:
// background.js
function addSeedCookie(details) {
details.responseHeaders.push({
name: "Set-Cookie",
value: `tab_id=${details.tabId}; Max-Age=2`
});
return {
responseHeaders: details.responseHeaders
};
}
chrome.webRequest.onHeadersReceived.addListener(
addSeedCookie, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]
);
// inject.js
function getCookie(cookie) { // https://stackoverflow.com/a/19971550/934239
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
var tabId = getCookie("tab_id");
edited Nov 6 at 14:21
answered Nov 6 at 13:53
Nicholas DiPiazza
3,37853472
3,37853472
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53161083%2fhow-to-share-a-unique-tab-id-between-content-and-background-scripts-without-an-a%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
You can share it by setting an http cookie header in your background script using webRequest API in blocking mode. The cookie will be available via document.cookie in your content script. I believe I saw an answer for that by Xan. If the value is big you can additionally use blob + synchronous XHR (Tampermonkey does that).
– wOxxOm
Nov 6 at 4:36
Found it: Injecting javascript variable before content script
– wOxxOm
Nov 6 at 5:06
You are definitely my favorite person. I would have never figured this out. It worked like a charm.
– Nicholas DiPiazza
Nov 6 at 5:38
Darn. Show-stopper on this one for me is that I need it to work in multiple tabs. As soon as one of my tabs opens this up, bam I'm stuck with it.
– Nicholas DiPiazza
Nov 6 at 5:52
The problem is the seed value that it creates is created in the
background.js
foreground which is once per browser window. So now every page is using that same seed value. What I really need is the Tab ID in thecontent.js
page of the tab that it belongs to, or some seed value set per tab to achieve the same thing.– Nicholas DiPiazza
Nov 6 at 6:03