I am building a Chrome extension. I am trying to get my app to communicate with each page in the extension and the page the user is viewing in the browser. I need to access the dom from the extension and then update it.
manifest.json popup.html popup.js background.js content.js
and the current page the user is viewing.
My goal is on page load modify the dom and show the user the new version of the page before they ever see it. in popup.js
users are allowed to enter keywords into the popup. The keywords are saved to localStorage
and while they view the web the keywords are censored out of their view by making the parent div of the keywords hidden if it is found on any pages they are viewing.
I need help getting each page to communicate and I think the way I am hiding the parent divs in popup.js won't work. I am confused on how to perform the action on the dom from the front.
Send the dom to the background.js Find keywords on the page and change their parent divs to hidden. push the dom back to the viewing page.
I think this line is saying if I match any url then run my app but I am not sure.
"matches": ["*://*/*"],
My manifest.json
{ "name": "Wuno Zensoring", "version" : "1.0", "permissions": [ "activeTab", "tabs", "storage" ], "description": "This extension will search the document file for keywords and hide their parent div.", "icons": { "19": "icon19.png", "38": "icon38.png", "48": "icon48.png", "128": "icon128.png" }, "background": { "persistent": false, "scripts": ["jquery-1.11.3.min.js","background.js"] }, "content_scripts": [{ "matches": ["*://*/*"], "js": ["content.js"], "run_at": "document_end", "all_frames": true }], "web_accessible_resources": [ "popup.js", "content.js" ], "browser_action": { "default_icon": "icon.png128", "default_popup": "popup.html", "default_icon": { "19": "icon19.png", "38": "icon38.png", "48": "icon48.png", "128": "icon128.png" } }, "manifest_version": 2 }
popup.html
<!doctype html> <html> <head> <title>Wuno Zensorship</title> <script src="jquery-1.11.3.min.js"></script> <script src="popup.js"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <img src="icon48.png"> <section> <form id="form" action="#" method="POST"> <input id="description" name="description" type="text" /> <input id="add" type="submit" value="Add" /> <button id="clearChecked">Clear Checked Items</button> <button id="clear">Clear All</button> </form> <div id="alert"></div> <ul id="keyWords"></ul> </body> </html>
popup.js
$(document).ready(function () { localArray = []; if (!localStorage.keyWords) { localStorage.setItem('keyWords', JSON.stringify(localArray)); } loadKeyWords(); function loadKeyWords() { $('#keyWords').html(''); localArray = JSON.parse(localStorage.getItem('keyWords')); for(var i = 0; i < localArray.length; i++) { $('#keyWords').prepend('<li><input class="check" name="check" type="checkbox">'+localArray[i]+'</li>'); } } $('#add').click( function() { var Description = $('#description').val(); if($("#description").val() === '') { $('#alert').html("<strong>Warning!</strong> You left the to-do empty"); $('#alert').fadeIn().delay(1000).fadeOut(); return false; } $('#form')[0].reset(); var keyWords = $('#keyWords').html(); localArray.push(Description); localStorage.setItem('keyWords', JSON.stringify(localArray)); loadKeyWords(); return false; }); $('#clear').click( function() { window.localStorage.clear(); location.reload(); return false; }); $('#clearChecked').click(function() { currentArray = []; $('.check').each(function() { var $curr = $(this); if (!$curr.is(':checked')) { var value = $curr.parent().text(); currentArray.push(value); localStorage.setItem('keyWords', JSON.stringify(currentArray)); loadKeyWords(); } else { $curr.parent().remove(); } }); }); // Update the relevant fields with the new data function setDOMInfo(info) { $("div p:contains(localStorage.getItem('keyWords')).parent('div').hide()"); } // Once the DOM is ready... window.addEventListener('DOMContentLoaded', function () { // ...query for the active tab... chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { // ...and send a request for the DOM info... chrome.tabs.sendMessage( tabs[0].id, {from: 'popup', subject: 'DOMInfo'}, // ...also specifying a callback to be called // from the receiving end (content script) setDOMInfo); }); }); }); // End of document ready function
background.js
chrome.runtime.onMessage.addListener(function (msg, sender) { // First, validate the message's structure if ((msg.from === 'content') && (msg.subject === 'showPageAction')) { // Enable the page-action for the requesting tab chrome.pageAction.show(sender.tab.id); } });
content.js
// Inform the background page that // this tab should have a page-action chrome.runtime.sendMessage({ from: 'content', subject: 'showPageAction' }); // Listen for messages from the popup chrome.runtime.onMessage.addListener(function (msg, sender, response) { // First, validate the message's structure if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) { // Collect the necessary data // (For your specific requirements `document.querySelectorAll(...)` // should be equivalent to jquery's `$(...)`) var domInfo = { total: document.querySelectorAll('*').length, inputs: document.querySelectorAll('input').length, buttons: document.querySelectorAll('button').length }; // Directly respond to the sender (popup), // through the specified callback */ response(domInfo); } });
Just put the DOM-manipulation logic in a content script and send the keywords to it (instead of sending the HTML, filtering it in the background or popup page and send it back to the content script).
The background script should be viewed as "running in the background of the Chrome browser". Your desired effect (running a script for every page) is actually a task for content scripts. To learn more, read https://developer.chrome.com/extensions/overview.html#arch. Follow this answer to receive notifications.
You need to use this query to send data to DOM from the current tab being viewed.
chrome.tabs.executeScript(null, { code: 'var config = ' + JSON.stringify(getKeywords) }, function() { chrome.tabs.executeScript(null, {file: 'custom.js'}); });
and in the custom.js
file you can write you function that you want to apply on the DOM element. like if you want to hide something than you need that query in custom.js
. So if you wanted to use that example you would need to modify it according to your requirements.
var all = document.getElementsByTagName("div"); var searchValue=config.toString().split(','); alert('Example:' + searchValue[0]); for(j=0; j < searchValue.length; j++) { for(i=0; i < all.length; i++) { if(all[i].innerHTML.indexOf(searchValue[j]) > -1){ all[i].innerHTML = "" } } }
You should send command from background.js or popup.js, receiving that and change the dom in content.js. The following code demonstrate a simple scenario: Click the browserAction and append a div to the current page. You can use the same logic to show/hide any elements.
manifest.json
{ "name": "Test", "version": "1.0", "permissions": [ "tabs" ], "description": "Test", "background": { "persistent": false, "scripts": [ "background.js" ] }, "content_scripts": [ { "matches": [ "*://*/*" ], "js": [ "content.js" ], "run_at": "document_end", "all_frames": true } ], "browser_action": { "title": "Test" }, "manifest_version": 2 }
background.js
chrome.browserAction.onClicked.addListener(function() { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, {command: "append"}, function(response) { console.log(response.result); }); }); });
content.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { console.log(request.command); var div = document.createElement('div'); var label = document.createElement('span'); label.textContent = "Hello, world"; div.appendChild(label); document.body.appendChild(div); sendResponse({result: "success"}); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With