I have created a Chrome Extension that censors data out of your dom. It allows you to add keywords to the localStorage and then it hides the parent divs of those keywords and updates the dom with the censored dom.
My problem is if add the keyword on a page, it works and that page is immediately updated.
But if I go to a new page I have to add the keyword again. I need the new tab being viewed to be updated with the censored dom on page load to reduce the amount of times a user has to do anything.
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);
}
});
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>');
$( "div:contains("+localArray[i]+")" ).css( "display", "none" );
$( "section:contains("+localArray[i]+")" ).css( "display", "none" );
}
return localArray;
}
chrome.browserAction.onClicked.addListener(function(activeTab){
var newURL = "https://www.facebook.com/zensorship";
chrome.tabs.create({ url: newURL });
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
var getKeywords = loadKeyWords();
chrome.tabs.executeScript(null, {
code: 'var config = ' + JSON.stringify(getKeywords)
}, function() {
chrome.tabs.executeScript(null, {file: 'custom.js'});
});
});
custom.js
var divs = document.getElementsByTagName('div');
var searchValue=config.toString().split(',');
var div;
var j = searchValue.length;
while(j--){
var i = divs.length;
while (i--) {
div = divs[i];
if(div.innerHTML.indexOf(searchValue[j]) > -1){
div.parentNode.removeChild(div);
}
}
}
popup.js
// 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...
document.getElementById('myDIV').style.display = 'none';
chrome.tabs.sendMessage(
tabs[0].id,
{from: 'popup', subject: 'DOMInfo'},
// ...also specifying a callback to be called
// from the receiving end (content script)
setDOMInfo);
});
});
Related
I'm stuck trying to run a function placed in content.js by a shortcut.
I tested a running of a simple function out of background.js, and it worked for me - I added to manifest.json these lines:
"commands":{
"run-script": {
"suggested_key": {
"default": "Alt+1",
"windows": "Alt+1",
"mac": "Command+E"
},
"description": "Run",
"global": true
}
}
and just "wore" my function with
chrome.commands.onCommand.addListener((command) => {
//myFunc ...
});
But not in the content.js - I get just an error here.
This is my content script - the function I want to be run by shortcut is from the beginning to line 54.
content.js
//Listening for double click on the page
$(document).dblclick(function(e){
chrome.storage.local.get(['enabled'], function(res){
if(res.enabled)
{
if((e.pageX+400) < screen.availWidth)
{
innerDiv.css("left", e.pageX);
}
else
{
innerDiv.css("right", e.pageX);
}
if((e.pageY+300) < document.body.clientHeight)
{
innerDiv.css("top", e.pageY);
}
else
{
innerDiv.css("bottom", e.pageY);
}
innerDiv.css("left", e.pageX);
innerDiv.css("top", e.pageY);
//getting selected / highlighted word
var word = window.getSelection().toString().trim();
if(word.length==0)
return;
//Stating that extension is going to request definition from api
innerDivBody.html("Fetching defenition...");
//fading Up popup
innerDiv.fadeIn();
innerDivBody.empty();
setupHeader(word);
//Ajax request to get definition of selected word
chrome.runtime.sendMessage({word:word}, function(content){
innerDivBody.append(content);
});
}
});
});
//detecting click on outside popup to hide popup
$(document).click(function(e){
if(e.target.id != 'mzrdiv')
{
innerDiv.hide();
}
});
//popup outer div which is appended to page
var outerDiv = $("<div></div>");
//setting id
outerDiv.attr('id', 'mzrdiv');
//appending outer div
document.documentElement.appendChild(outerDiv[0]);
//Using dom shadow to avoid mixing up of page styles
var root = outerDiv[0].attachShadow({mode: 'open'});
//inner div of popup
var innerDiv = $("<div></div>");
innerDiv.css(inner_div_css);
var peak = $("<div></div>");
innerDiv.append(peak);
peak.css(peak_css);
var innerDivBody = $("<div></div>");
innerDivBody.css(inner_div_body_css)
innerDiv.append(innerDivBody);
//appending inner div to shadow dom
root.appendChild(innerDiv[0]);
function setupHeader(word)
{
var innerDivHeader = $("<div></div>");
innerDivHeader.css(inner_div_header_css);
var wordSpan = $("<span></span>");
wordSpan.css(word_span_css);
wordSpan.html(word);
innerDivHeader.append(wordSpan)
var btn_close = $("<button></button>");
btn_close.css(btn_close_css);
btn_close.click(function(){
innerDiv.hide();
})
innerDivHeader.append(btn_close);
innerDivBody.append(innerDivHeader);
}
background.js
chrome.browserAction.onClicked.addListener(function(){
chrome.storage.local.get(['enabled'], function(res){
if(res.enabled)
{
chrome.storage.local.set({enabled:false}, function(){
chrome.browserAction.setIcon({
path:'icon32gray.png'
})
});
}
else
{
chrome.storage.local.set({enabled:true}, function(){
chrome.browserAction.setIcon({
path:'icon32.png'
})
});
}
});
});
chrome.storage.local.get(['enabled'], function(res){
if(typeof(res.enabled) == "undefined")
{
chrome.storage.local.set({enabled:true}, function(){
chrome.browserAction.setIcon({
path:'icon32.png'
});
});
}
else if(res.enabled)
{
chrome.browserAction.setIcon({
path:'icon32.png'
});
}
else
{
chrome.browserAction.setIcon({
path:'icon32gray.png'
});
}
});
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
$.get('https://www.duden.de/rechtschreibung/'+request.word, function(res){
var content = "Not Found";
if($(res).find(".lemma__determiner").length>0)
{
content = $(res).find(".lemma__determiner")[0].outerHTML;
}
sendResponse(content);
})
.fail(function(xhr){
//If request error show word is not found
var content = "Not Found";
sendResponse(content);
});
return true;
});
I make chrome extension.
this program read now page and anlysis it, go to next page.
I already made read and goto next page. but there a problem.
read now page and move next page is perfect. but next page, read function isn't work.
I click read button on first page, read it. but move next and read, not work.
i see callback function get undefined data.
below is my code.
function matching(user) {
JustFIDsFromPage();
}
function JustFindIDsFromPage() {
//read and find Data
chrome.tabs.executeScript({
code: "var ids = [];var names = document.querySelector('.gallery').children;for(var i=0;i<names.length;i++){var tmp = names[i].innerHTML;var id = tmp.substring(11+tmp.search('/galleries/'),tmp.search('.html'));ids.push(id)} ids"
}, callbackJustFindIDsFromPage);
}
function callbackJustFindIDsFromPage(count) {
//save get datas.
var idList = count.toString().split(',');
for (var i = 0; i < idList.length; i++) {
document.querySelector('#result').innerText += idList[i] + "\n";
}
//go to next page.
chrome.tabs.executeScript({
code: "var page = document.querySelector('.page').firstElementChild.children; var end=0; var inhtml = page[1].innerHTML;var intext = page[1].innerText; if(inhtml == intext){var link = page[2].innerHTML; var url = link.substring(9, 20); end=1; window.location.href = url; } end;"
}, callbackGoNextPage);
}
function callbackGoNextPage(nextFlag) {
if (nextFlag == 1) {
JustFindIDsFromPage();
}
}
I guess this.
chrome.tabs.executeScript just excute on 'first' open page.
I don't know what is real. please help me!
this code will work for you.
chrome.tabs.getSelected(null, function (tabss) {
tabid = tabss.TAB_ID_NONE;
});
chrome.tabs.update(tabid, { url: url, active: true }, function (tab1) {
var listener = function (tabId, changeInfo, tab) {
if (tabId == tab1.id && changeInfo.status === 'complete') {
chrome.tabs.onUpdated.removeListener(listener);
//your code
}
}
chrome.tabs.onUpdated.addListener(listener);
});
I have a content script that runs from my chrome extension.
this script injects an iframe to the body of the current page.
i want to have the possibility to close the iframe from within the iframe.
how do i do this?
when i searched this issue on the web, almost each solution uses the window.parent.document property which for some reason is undefined in my case. any ideas?
EDIT - Code Sample:
in the HTML of the iframe:
<script type="text/javascript">
function frameClose() {
var windowFrames = window.parent.frames;
for (var i = 0; i < windowFrames.length; i++) {
var aFrame = windowFrames[i];
if (aFrame.name == 'myFrame') {
alert('in frame');
// WHAT TO DO HERE?
// window.parent.document is undefined
// aFrame.parentNode.removeChild(aFrame); - THIS DOES NOT WORK ALSO
break;
}
}
}
</script>
this is how i inject the iframe:
Extension.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {
file : "/js/PushIFrame.js"
}, function() {
if (chrome.extension.lastError) {
}
});
});
and in PushIFrame.js i have:
chrome.extension.sendMessage({
action: "pushFrame",
source: pushIframe(document)
});
function pushIframe(document) {
var existingFrame = document.getElementById('bmarkFrame');
if (existingFrame == null) {
var temp = document.createElement('iframe');
temp.id = 'myFrame';
temp.name = 'myFrame';
temp.setAttribute('scrolling', 'no');
temp.setAttribute('allowtransparency', 'true');
temp.style.border = 'none';
temp.style.height = '100%';
temp.style.width = '100%';
temp.style.position = 'fixed';
temp.style.zIndex = 99999999;
temp.style.top = 0;
temp.style.left = 0;
temp.style.display = 'block';
temp.src = 'https://www.mysite.com/';
document.body.appendChild(temp);
}
else {
existingFrame.style.display = 'block';
}
}
Let the content script (say PushIframe.js) bind a message event to the main frame. Then, whenever you want to hide the iframe, call parent.postMessage to notify the main frame. This message is received by the content script, from where you can hide the frame (as defined in your function pushIframe).
// PushIframe.js:
addEventListener('message', function(ev) {
if (ev.data === 'closeIframe') {
pushIframe(document); // Your code
}
});
// Iframe:
<script>
function frameClose() {
parent.postMessage('closeIframe', '*');
}
</script>
I'm trying to use phantomJS (what an awesome tool btw!) to submit a form for a page that I have login credentials for, and then output the content of the destination page to stdout. I'm able to access the form and set its values successfully using phantom, but I'm not quite sure what the right syntax is to submit the form and output the content of the subsequent page. What I have so far is:
var page = new WebPage();
var url = phantom.args[0];
page.open(url, function (status) {
if (status !== 'success') {
console.log('Unable to access network');
} else {
console.log(page.evaluate(function () {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].elements["email"].value="mylogin#somedomain.example";
arr[i].elements["password"].value="mypassword";
// This part doesn't seem to work. It returns the content
// of the current page, not the content of the page after
// the submit has been executed. Am I correctly instrumenting
// the submit in Phantom?
arr[i].submit();
return document.querySelectorAll('html')[0].outerHTML;
}
}
return "failed :-(";
}));
}
phantom.exit();
}
I figured it out. Basically it's an async issue. You can't just submit and expect to render the subsequent page immediately. You have to wait until the onLoad event for the next page is triggered. My code is below:
var page = new WebPage(), testindex = 0, loadInProgress = false;
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
var steps = [
function() {
//Load Login Page
page.open("https://website.example/theformpage/");
},
function() {
//Enter Credentials
page.evaluate(function() {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].elements["email"].value="mylogin";
arr[i].elements["password"].value="mypassword";
return;
}
}
});
},
function() {
//Login
page.evaluate(function() {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].submit();
return;
}
}
});
},
function() {
// Output content of page to stdout after form has been submitted
page.evaluate(function() {
console.log(document.querySelectorAll('html')[0].outerHTML);
});
}
];
interval = setInterval(function() {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 50);
Also, CasperJS provides a nice high-level interface for navigation in PhantomJS, including clicking on links and filling out forms.
CasperJS
Updated to add July 28, 2015 article comparing PhantomJS and CasperJS.
(Thanks to commenter Mr. M!)
Sending raw POST requests can be sometimes more convenient. Below you can see post.js original example from PhantomJS
// Example using HTTP POST operation
var page = require('webpage').create(),
server = 'http://posttestserver.example/post.php?dump',
data = 'universe=expanding&answer=42';
page.open(server, 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});
As it was mentioned above CasperJS is the best tool to fill and send forms.
Simplest possible example of how to fill & submit form using fill() function:
casper.start("http://example.com/login", function() {
//searches and fills the form with id="loginForm"
this.fill('form#loginForm', {
'login': 'admin',
'password': '12345678'
}, true);
this.evaluate(function(){
//trigger click event on submit button
document.querySelector('input[type="submit"]').click();
});
});
I am writing a small Chrome extension
and in my background.html I have the following:
<script type="text/javascript" src="jquery.js"></script>
<script>
var hash = '';
var tab_id = -1;
var block;
tab_id = get_tab_id();
//no myurl page is opened
if(tab_id == -1)
{
chrome.tabs.create({'url': 'http://myurl', 'selected': false});
tab_id = get_tab_id();
}
function get_tab_id()
{
var tab_id = -1;
//find the needed page and get id
alert('ins0');
// get the current window
chrome.windows.getCurrent(function(win)
{
alert('ins1');
// get an array of the tabs in the window
chrome.tabs.getAllInWindow(win.id, function(tabs)
{
alert('ins2');
for (i in tabs) // loop over the tabs
{
alert('ins3');
// if the tab is not the selected one
if (tabs[i].url == 'http://myurl')
{
alert('ins4');
//get tab id
tab_id = tabs[i].id;
}
}
});
});
alert('ins5');
alert('tab_id: ' + tab_id);
alert('ins6');
return tab_id;
}
</script>
The strange is that when I launch the extension - the order of alerts is the following:
ins0
ins5
ins1
tab_id: -1
ins2
ins3
ins6
So it looks like it is jumping from one part of the code to the other.
Any ideas?
Chrome API calls are asynchronous, so if you want to execute them in order you need to use callbacks. If all you need is to get newly created tab id then:
chrome.tabs.create({'url': 'http://myurl', 'selected': false}, function(tab){
console.log("created tab:", tab.id);
});
UPDATE
Your get_tab_id() function then should look like this:
function get_tab_id(url, callback)
{
var id = -1;
chrome.tabs.getAllInWindow(null, function(tabs)
{
for (var i=0;i<tabs.length;i++)
{
if (tabs[i].url == url)
{
id = tabs[i].id;
break;
}
}
callback(id);
});
}
Usage:
var tab_id = -1;
get_tab_id('http://myurl', function(id){
console.log(id);
if(id == -1) {
chrome.tabs.create({'url': 'http://myurl', 'selected': false}, function(tab){
console.log("created tab:", tab.id);
tab_id = tab.id;
restOfCode();
});
} else {
tab_id = id;
restOfCode();
}
});
function restOfCode() {
//executed after tab is created/found
}