chrome storage sync input value - javascript

I try to get the input value in my main.js (content script) but I struggle to finialize it somehow. I managed to save the value with the windows.onload approach as you can see below in my popup.js. But I can't get it over to the content script.
I want to use the value as a variable "userInput" in my content script.
popup.js:
function registerButtonAction(tabId, button, action) {
// clicking button will send a message to
// content script in the same tab as the popup
button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}
function setupButtons(tabId) {
// add click actions to each 3 buttons
registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
registerButtonAction(tabId, document.getElementById('stop-btn'), 'stopSearch');
}
function injectStartSearchScript() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
// Injects JavaScript code into a page
// chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });
// add click handlers for buttons
setupButtons(tabs[0].id);
});
}
injectStartSearchScript();
window.onload = function () {
document.getElementById('save-btn').onclick = function () {
let valueInput = document.getElementById('deal-ipt').value;
chrome.storage.sync.set({ 'maxBidDeal': valueInput }, function () {
alert('Saved!');
});
};
};
manifest.json:
{
"manifest_version": 2,
"name": "test app",
"description": "test desc",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "<all_urls>", "storage"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["main.js"]
}
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}
main.js:
// highlight deals
async function deals() {
// let userInputBidPrice = prompt('Set max Bid Price to show deals:');
chrome.storage.sync.get('MaxBidDeal', function (data) {
let userinput = data.MaxBigDeal;
deals(userinput);
});
let cardCurrentBidValuesString = document.querySelectorAll('.auction > .auctionValue:nth-child(2) > .currency-coins.value');
let cardStartBidValueString = document.querySelectorAll('.auction > .auctionStartPrice.auctionValue > .currency-coins.value');
let cardBg = document.querySelectorAll('.rowContent.has-tap-callback');
for (let i = 0; i < cardCurrentBidValuesString.length; i++) {
cardsCurrentBidPrice = cardCurrentBidValuesString[i].textContent.toString().split(',').join('');
cardsStartBidPrice = cardStartBidValueString[i].textContent.toString().split(',').join('');
if (cardsCurrentBidPrice === '---') {
cardsCurrentBidPrice = 0;
}
if (cardsStartBidPrice === '---') {
cardsStartBidPrice = 0;
}
parsedCardsCurrentBidPrice = parseInt(cardsCurrentBidPrice);
parsedCardsStartBidPrice = parseInt(cardsStartBidPrice);
if (parsedCardsCurrentBidPrice < parseInt(userinput) && parsedCardsStartBidPrice < parseInt(userinput)) {
cardBg[i].style['background-color'] = '#0311c3';
}
}
}
chrome.runtime.onMessage.addListener((message) => {
// choose action based on received message:
if (message.startSearch) {
startSearch();
} else if (message.startDeals) {
deals();
}
});
// sanity check: content has loaded in the tab
console.log('content loaded');
So I am sure that I have to use chrome.storage.get somehow but I cant figure it out exactly.

Your code is calling deals recursively forever without actually passing the value because you didn't declare a parameter and then you're trying to use userinput beyond the variable's scope.
You can promisify chrome.storage and use await like this:
async function deals() {
// Note that chrome.storage is already promisified in ManifestV3 since Chrome 95
let { MaxBidDeal } = await new Promise(resolve =>
chrome.storage.sync.get('MaxBidDeal', resolve));
// use MaxBidDeal right here
console.log('MaxBidDeal', MaxBidDeal);
}

Related

Unable to persist state of my chrome extension between tab reloads and tab changes

I am trying to create a pretty simple chrome extension that enables me to navigate the browser back and forward using horizontal scrolling. I want to be able to enable and disable the extension; however I want the state to persist when the tab changes (whether the active tab is a new url or a new tab is launched).
Here is my current code that partially works for only the active tab:
manifest.json:
{
"name": "SwipeNav",
"action": {},
"manifest_version": 3,
"version": "0.1",
"description": "Navigates browser forward and back with 2 finger swiping",
"permissions": [
"activeTab",
"scripting",
"tabs",
"alarms"
],
"background": {
"service_worker": "background.js"
}
}
background.js
function twoFingerBack() {
console.log("Enabling 2 finger scrolling");
let timer;
window.addEventListener("wheel", function(event) {
clearTimeout(timer);
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
timer = setTimeout(function() {
if (event.deltaX > 0) {
history.back();
} else if (event.deltaX < 0) {
history.forward();
}
}, 200);
}
});
}
function removeExt() {
console.log("Disabling 2 finger scrolling");
window.removeEventListener("wheel", removeExt)
}
let enabled = true;
chrome.action.onClicked.addListener((tab) => {
enabled = !enabled;
if (enabled) {
if (!tab.url.includes("chrome://")) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: twoFingerBack
});
}
} else {
if (!tab.url.includes("chrome://")) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: removeExt
});
}
}
});
I have read that I can use chrome.tabs.onActivated however I could not get this to work at all. Not sure if that is the right path.
Any help is appreciated...thanks!
Save the state in storage. Since localStorage is not available in a service worker you can use chrome.storage.local.
Register/unregister the content script, so it runs automatically next time the tab is loaded.
Process all tabs using executeScript to apply the changes to the currently loaded pages.
Use a global function for the wheel listener and use its name in removeEventListener.
// manifest.json
Add "storage" inside "permissions"
Add "host_permissions": ["<all_urls>"]
// background.js
chrome.action.onClicked.addListener(async (tab) => {
let {enabled} = await chrome.storage.local.get('enabled');
enabled = !enabled;
chrome.storage.local.set({enabled});
await chrome.scripting.unregisterContentScripts({ids: ['foo']}).catch(() => {});
if (enabled) {
chrome.scripting.registerContentScripts([{
id: 'foo',
js: ['content.js'],
matches: ['<all_urls>'],
runAt: 'document_start',
}]);
}
const execOpts = enabled ? {files: ['content.js']} : {func: removeExt};
const tabs = (await chrome.tabs.query({}))
.sort(t => t.active ? -1 : 0); // processing the active tab(s) first
for (const {id} of tabs) {
chrome.scripting.executeScript({target: {tabId: id}, ...execOpts})
.catch(() => {});
}
});
function removeExt() {
console.log('Disabling');
// onWheel is the name of the global function used in content.js
if (typeof onWheel === 'function') removeEventListener('wheel', onWheel);
}
// content.js
console.log('Enabling');
if (typeof onWheel !== 'function') (() => {
let timer;
window.onWheel = e => {
clearTimeout(timer);
const x = e.deltaX;
if (x && Math.abs(x) > Math.abs(e.deltaY)) {
timer = setTimeout(() => x > 0 ? history.back() : history.forward(), 200);
}
};
addEventListener('wheel', onWheel);
})();

How to use ExecuteScript and MutationObserver for a Chrome extension Manifest V3?

The Manifest V3 JavaScript Chrome extension only has one button. When the button is clicked the browser should go to multiple pages and perform an action on each page before going to the next one.
What's currently happening, is the browser jumping to the last page and not performing any action.
How to fix my code, so that the extension visits each page one by one (in the same tab), then waits on the page until a button is detected, clicks the button, checks if the button is clicked, and then goes to the next page?
Manifest.json:
{
"name": "Twitch Follower",
"version": "0.1",
"manifest_version": 3,
"description": "Automatically follows Twitch users.",
"action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"tabs",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"https://www.twitch.tv/*"
]
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css#2/out/water.css">
</head>
<body>
<button id="start">Start</button>
<script src="popup.js"></script>
</body>
</html>
popup.js:
start.addEventListener("click", async () => {
chrome.runtime.sendMessage({ start: true });
});
background.js:
const list = ["https://www.twitch.tv/hello1", "https://www.twitch.tv/hello2"];
function clickFollow() {
document.querySelector("button[data-a-target='follow-button']").click();
}
function handleFollowButton(followButton) {
setTimeout(clickFollow, 1000);
}
// Check for a button
async function checkButton() {
const findButton = new Promise((resolve, reject) => {
const observerConfig = { attributes: true, attributeOldValue: true };
const observer = new MutationObserver((mutations) => {
const followButton = document.querySelector("button[data-a-target='follow-button']");
const unfollowButton = document.querySelector("button[data-a-target='unfollow-button']");
// If follow button is found, click it
if (followButton) {
handleFollowButton(followButton);
}
// If unfollow button is found, end observing and continue
if (unfollowButton) {
unfollowButtonFound = True;
observer.disconnect();
resolve;
}
});
window.setTimeout(() => {
if (!unfollowButtonFound) {
reject;
}
}, 5000);
observer.observe(document, {
childList: true,
subtree: true,
});
});
await findButton;
return true;
}
// When the start button is clicked
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.start === true) {
// Loop through every link
for (const link of list) {
console.log(link);
// Open the link and inject the script
chrome.tabs.update({ url: link }, (tab) => {
chrome.scripting.executeScript(
{
target: { tabId: tab.id },
func: checkButton,
},
(result) => {
console.log(results);
}
);
});
}
}
});

Chrome Extension gives two errors: Uncaught TypeError and Unchecked runtime.lastError

I am facing two errors on Chrome extension that I am building:
Error 1:
Uncaught TypeError: Cannot set properties of null (setting 'onclick')
Context
_generated_background_page.html
Stack Trace
popup.js:3 (anonymous function)
Error 2:
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
Context
_generated_background_page.html
Stack Trace
_generated_background_page.html:0 (anonymous function)
I have already checked the questions on this site that address these two errors and I tried the solutions provided in them, but I am still facing the two errors.
My original code:-
popup.js (tried changing from onclick to onClicked for error 1, tried putting this code in window.onload for error 2)
let populateBtn = document.getElementById('populateBtn');
let textArea = document.getElementById('productList');
populateBtn.onclick = function(element) {
let color = element.target.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(!textArea.value)
{
chrome.tabs.executeScript(
tabs[0].id,
{code: 'alert("Please, populate the order list!");'});
return;
}
chrome.tabs.sendMessage(tabs[0].id, {data: textArea.value.replace(/\t/g,'').split("\n")}, function(response) {
});
});
};
background.html (tried putting <script> after </body> tag for error 1)
<body>
<p>Gina's Bakery Bulk Order</p>
<textarea id="productList"></textarea>
<button id="populateBtn">Create Order</button>
<script src="popup.js"></script>
</body>
app.js (tried chrome.runtime.connect for error 2)
chrome.runtime.onInstalled.addListener(function() {
});
inject.js (tried chrome.runtime.onConnect.addListener for error 2)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
let failed = [];
request.data.forEach(element => { // itterate over all products
if(element.includes('-')){
let data = element.split('-');
let quantity = data[0].toLowerCase().replace("gb", "").trim();
let ID = data[1].trim();
let elementName = 'pid_' + ID.replace(".", "_");
if(document.getElementsByName(elementName).length > 0)
document.getElementsByName(elementName)[0].value = quantity;
else
failed.push("<td>GB-"+ ID +"</td><td>" + quantity + "</td>");
}
});
if(failed.length > 0){
//alert("Order unsuccessful! One or more products are not ordered: " + failed.join(", "));
let modal = document.createElement("div");
modal.setAttribute("id", "failedOrderModal");
modal.setAttribute("style", "position:fixed;width:250px;left:50%;top:100px;background-color:#fff;border-radius:10px;padding:10px;z-index:10000;color:#000;border: 1px solid red;text-align:center;");
let head = document.createElement("h2");
head.innerText = "Order unsuccessful! One or more products were not found!";
modal.appendChild(head);
let table = document.createElement("table");
let tbody = document.createElement("tbody");
table.appendChild(tbody);
let tr = document.createElement("tr");
tr.innerHTML = "<td>ITEM</td><td>QTY</td>";
tbody.appendChild(tr);
failed.forEach(failedItem => {
tr = document.createElement("tr");
tr.innerHTML = failedItem;
tbody.appendChild(tr);
});
modal.appendChild(table);
let closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.innerText = "Close";
closeBtn.onclick = function(){
document.getElementById("failedOrderModal").remove();
}
modal.appendChild(closeBtn);
document.body.appendChild(modal);
}
else
{
alert("All products were successfuly populated!");
}
sendResponse({result: "ok"})
return true;
});
manifest.json
{
"name": "Gina's Bakery Order",
"version": "1.0",
"description": "Helps automate orders from ginas-bakery.com.au",
"permissions": ["activeTab", "declarativeContent", "storage"],
"background": {
"scripts": ["app.js", "popup.js"],
"persistent": false
},
"icons": {
"16": "images/ginas-bakery_16.png",
"32": "images/ginas-bakery_32.png",
"48": "images/ginas-bakery_48.png",
"128": "images/ginas-bakery_128.png"
},
"browser_action": {
"default_popup": "background.html"
},
"content_scripts": [
{
"matches": ["*://www.ginas-bakery.com.au/order/"],
"js": ["inject.js"]
}
],
"manifest_version": 2
}
None of the above mentioned solutions worked.
The background script page is an invisible hidden page, so running visible scripts like app.js or popup.js there is meaningless. Remove background section from manifest.json and rename your background.html to popup.html both on the disk and in manifest.json.
manifest.json:
{
"name": "Gina's Bakery Order",
"version": "1.0",
"permissions": ["activeTab", "declarativeContent", "storage"],
"browser_action": {"default_popup": "popup.html"},
"manifest_version": 2
}
Content scripts run only when the page loads, so if you just reloaded or installed/updated the extension without reloading the tab, the content scripts won't run there.
Although you can inject them explicitly, it's much better to switch to programmatic injection on demand (use executeScript instead of content_scripts) because you can do it without requiring any host permissions when installing the extension.
popup.js:
const textArea = document.getElementById('productList');
const btn = document.getElementById('populateBtn');
btn.onclick = () => {
const data = textArea.value.replace(/\t/g, '').split('\n');
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {data}, () => {
if (chrome.runtime.lastError) {
chrome.tabs.executeScript({file: 'inject.js'}, () => {
chrome.tabs.sendMessage(tab.id, {data});
});
}
});
});
};
Since you're not using the response in sendMessage, don't send it in the first place, i.e. remove sendResponse({result: "ok"}); return true; from inject.js.

chrome extension command passing to content script

I would like to implement a hotkey that triggers a function in my content script.
The content script (main.js) is executed on page laod from my popup.js file.
i have added the command into my manifest.json and when I add the onCommand listener to my popup.js I can console log that it gets triggered when I press my hotkey (Ctrl+Shift+K)
However I can not get it passed to my content script.
manifest.json
{
"manifest_version": 2,
"name": "Ccghjj",
"description": "hdjdjdjsjs",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "*storage", "activeTab"],
"content_scripts": [
{
"matches": ["*://"],
"css": ["style.css"],
"js": ["jquery.js", "main.js"]
}
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",
"web_accessible_resources": ["toolbar.html", "style.css"],
"commands": {
"show_deals": {
"suggested_key": {
"default": "Ctrl+Shift+K"
},
"description": "Highlight Deals"
}
}
}
popup.js
function registerButtonAction(tabId, button, action) {
// clicking button will send a message to
// content script in the same tab as the popup
button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}
function setupButtons(tabId) {
// add click actions to each 3 buttons
registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
registerButtonAction(tabId, document.getElementById('stop-btn'), 'stopSearch');
}
function injectStartSearchScript() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
// Injects JavaScript code into a page
// chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });
// add click handlers for buttons
setupButtons(tabs[0].id);
});
}
injectStartSearchScript();
// hotkey command listener
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
// how can I get to main.js to call deals()
});
main.js (content script)
async function deals() {
// should be fired when I press my hotkey Ctrl+Shift+K
Use messages like below
popup.js
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tab.id, { msg: "deals"})
})
});
and in your content script
if (!window.firstTimeExecuted) {
window.firstTimeExecuted = true;
chrome.runtime.onMessage.addListener((data, sender, sendResponse) => {
if (data.msg == 'deals') {
deals()
}
});
}

Same messages being passed more that once while switching tabs fast : Chrome extension issue

I am currently new to building the chrome extension. However I have started to build a chrome extension that scrapes a webpage and stores the data in the google spreadsheet.
Here is my manifest.json:
"manifest_version": 2,
"version": "0.0.1",
"name": "A listener check",
"description": "Understanding the working of listeners in the application",
"content_scripts": [
{
"matches": [
"https://some.website.com/projects/*",
"http://some.website.com/projects/*"
],
"js": [
"content.js"
],
"all_frames": true,
"run_at": "document_end"
},
{
"matches": [
"https://embedded_website.net/*",
"https://embedded_website_2.net/*"
],
"js": [
"demeter.js"
],
"all_frames": true,
"run_at": "document_end"
}
],
"background":{
"scripts": [
"background.js"
]
},
"browser_action": {
"default_popup": "popup/popup.html"
},
"permissions": [
"tabs",
"background",
"management",
"storage"
]
}
Here is my background.js file
const loadedTabs = [];
const switchedTabs = [];
function updatedCallbackFunction(tabId, changeInfo, tab) {
const message = {
action: "load_page",
changeInfo: changeInfo,
tab: tab,
allowLoad: 1,
state: "loaded"
}
if (!loadedTabs.includes(tab.id))
loadedTabs.push(tab.id);
if (changeInfo.status === 'complete') {
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tab.id, message);
});
}
}
function tabActivatedCallbackFunction(activeInfo) {
const message = {
action: "load_page",
activeInfo: activeInfo,
state: "switched",
allowLoad: 1
}
console.log(`Switched Tabs : ${switchedTabs}`)
if (!switchedTabs.includes(activeInfo.tabId) ) {
switchedTabs.push(activeInfo.tabId);
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(activeInfo.tabId, message);
});
}
}
async function backgroundRuntimeCallbackFunction(message, sender, sendResponse) {
switch (message.action) {
case "unload":
console.log('Wrong page loaded');
break;
case "listen":
console.log('Investigating current page');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {action: "load_page"});
})
break;
case "demeter_page_direct":
console.log('Going to demeter page');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {...message, action: 'demeter_page_load'});
});
break;
case "wait_for_page_load":
console.log('Waiting for demeter page load');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {...message, action: 'demeter_page_load'});
});
break;
case "upload_google_sheet":
console.log('Updating to google sheet');
const {action, allowLoad, QApresent, ...googleSheetData} = message;
console.log(googleSheetData);
googleSheetData.hitlink = googleSheetData.hitlink.substring(0, googleSheetData.hitlink.lastIndexOf('&'));
const options = {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(googleSheetData)
}
const response = await fetch('my_backend_app.com/url_to_fetch', options);
const responseBody = await response.json();
console.log(responseBody);
const boxUpdateMessage = {
...message,
action: "load_page",
allowLoad: 0
};
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, boxUpdateMessage);
});
break;
}
}
// creating the functions to get the listeners
function tabUpdateFunction() {
if (chrome.tabs.onUpdated.hasListener(updatedCallbackFunction)) {
console.log('The onupdated listener is already there so removing it!');
chrome.tabs.onUpdated.removeListener(updatedCallbackFunction);
}
// adding the onupdated listener again
console.log('No overhead update function');
chrome.tabs.onUpdated.addListener(updatedCallbackFunction);
}
function tabSwitchFunction() {
if (chrome.tabs.onActivated.hasListener(tabActivatedCallbackFunction)) {
console.log('The tab switch function already there so removing it');
chrome.tabs.onActivated.removeListener(tabActivatedCallbackFunction);
}
console.log('No overhead switch function');
chrome.tabs.onActivated.addListener(tabActivatedCallbackFunction);
}
function backgroundRuntimeFunction() {
console.log(`backgroundRuntimeFunction : ${chrome.runtime.onMessage.hasListener(backgroundRuntimeCallbackFunction)}`);
chrome.runtime.onMessage.removeListener(backgroundRuntimeCallbackFunction);
if (chrome.runtime.onMessage.hasListener(backgroundRuntimeCallbackFunction)) {
chrome.runtime.onMessage.removeListener(backgroundRuntimeCallbackFunction);
}
chrome.runtime.onMessage.addListener(backgroundRuntimeCallbackFunction);
}
// calling the functions
tabUpdateFunction();
tabSwitchFunction();
backgroundRuntimeFunction();
Here is content.js
function getDetails(msg) {
// extract info
return {
action: 'demeter_page_direct',
// more info
};
}
function contentRuntimeCallback(message, sender, sendResponse) {
switch (message.action) {
case "load_page":
const delimiterMessage = getDetails(message);
if (delimiterMessage.title) {
const returnBtnForms = document.getElementsByClassName('force-inline');
for (let returnBtnForm of returnBtnForms) {
returnBtnForm.addEventListener('submit', (e) => {
console.log('Return btn was clicked!');
e.preventDefault();
delimiterMessage.return = 1;
delimiterMessage.allowLoad = 0;
chrome.runtime.sendMessage(delimiterMessage);
})
}
chrome.runtime.sendMessage(delimiterMessage);
}
else {
chrome.runtime.sendMessage({...delimiterMessage, action: 'unload'});
}
break;
}
}
function contentRuntimeCheck() {
if (chrome.runtime.onMessage.hasListener(contentRuntimeCallback))
chrome.runtime.onMessage.removeListener(contentRuntimeCallback);
chrome.runtime.onMessage.addListener(contentRuntimeCallback);
}
contentRuntimeCheck();
and demeter.js
function demeterRuntimeCallbackFunction(message, sender, sendResponse) {
switch (message.action) {
case "demeter_page_load":
if (message.hittitle.includes("specifictitle")) {
const svgParentContainer = document.getElementById('SVG_PARENT_CONTAINER');
if (!svgParentContainer) {
console.log('svg container loading!');
chrome.runtime.sendMessage({...message, action: 'wait_for_page_load'});
break;
} else {
// counting the total number of boxes
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
// when page loads for the first time
if (message.allowLoad === 1) {
if (message.changeInfo)
console.log('Updated info done');
else if (message.currentTabInfo)
console.log('In port 1');
console.log(`still allowing to load`);
message.allowLoad = 0;
const finalSheetUploadMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes
}
chrome.runtime.sendMessage(finalSheetUploadMessage);
break;
} else if (message.return === 1) {
console.log('In port 2');
const finalSheetUploadMessage = {
...message,
hitqueue: message.hitqueue - 1,
action: 'upload_google_sheet',
boxcount: totalBoxes
}
chrome.runtime.sendMessage(finalSheetUploadMessage);
break;
} else {
console.log('In port 3');
const saveBtn = document.querySelector("[aria-label='save']");
const submitBtn = document.querySelector('[aria-label="submit"]');
console.log(submitBtn);
if (saveBtn) {
saveBtn.addEventListener('click', function (e) {
console.log('Save button clicked');
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
const finalSheetUploadMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes
};
chrome.runtime.sendMessage(finalSheetUploadMessage);
});
}
if (submitBtn) {
console.log(submitBtn);
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
submitBtn.addEventListener('click', (e) => {
const sheetUpdateMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes,
submit: 1,
return: 0
}
console.log('Submit btn was clicked');
chrome.runtime.sendMessage(sheetUpdateMessage);
});
break;
}
break;
}
}
}
}
}
if (chrome.runtime.onMessage.hasListener(demeterRuntimeCallbackFunction))
chrome.runtime.onMessage.removeListener(demeterRuntimeCallbackFunction);
chrome.runtime.onMessage.addListener(demeterRuntimeCallbackFunction);
Working
The website i am scraping has an embedded website inside it as an iframe, so I created another content script for it. What i did was scraped details on the original webpage, then sent those details to the embedded webpage to extract further information there and then I am clustering those information and uploading to my google sheet
here is my workflow
content.js -> background.js -> demeter.js -> upload_google_sheet
I have kept allowload = 1 for automatically update the google sheet once all the page loads. Since several instances of the webpage can be open so I tried to implement tab switch event. So that the extension starts firing messages again from scratch once tab switch happens.
Problem
I open let say 3 tabs of the website and rapidly switch tabs among them. I get quite a large number of duplicate rows. I did a lot in tracking and removing listeners. But I really can't find the exact solution or approach to solving this. I want that after rapid switching of tabs. I get the information on the current tab only and no information from other tabs.
Since I am very new to stack overflow. Pardon my long question.

Categories

Resources