Obtain the tabId of new created tab - google-chrome-extension

How do I get the tabId of a new created tab? My tabId I want to send in sendMessage is undefinded.
How do I get the tabId?
Later I need the tabId to update the tabs....
popup.js
$(document).ready(function () {
"use strict";
$('button').on('click', function () {
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlDe'});
window.close();
});
chrome.tabs.create({
url: "http://google.com"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlCom'});
window.close();
});
});
background.js
chrome.runtime.onMessage.addListener(function(request) {
if (request.type === 'urlDe') {
alert(request.type + request.content);
} else if (request.type === 'urlCom') {
alert(request.type + request.content);
}
});

You need to access to the tabId via tab.id in your callback function, because chrome.tabs.create is async function:
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
chrome.runtime.sendMessage({content: tab.id, type:'urlDe'});
});
});
More information are in documentation or in this question.

Related

chrome.runtime.sendMessage not working with Asynchronous calls from Multiple Tabs

I have a popup with a button like shown below
I am having a click function like below in popup.js
$('#fetch_article').on('click',()=>{
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
const url=tabs[0].url;
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles || [];
if(articles.length<=0 && Object.keys(articles).length === 0){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}else{
// Check if URL already exists
const linkFound = articles.find(link=>link.url===url);
if(linkFound===undefined){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}
}
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
});
});
})
function fetcArticles(url){
chrome.runtime.sendMessage({type: "fetch_article",url:url},(response)=>{
if(response.type==='success'){
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles;
const linkIndex = articles.findIndex(link=>link.url===response.data.url);
if(linkIndex!==-1){
articles[linkIndex].state='Done';
articles[linkIndex].data={summary:response.data.summary,title:response.data.title};
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
}else{
console.error("Error in Fetching articles from session");
}
});
}else{
console.error("Could not Fetch article, So deleting it from storage");
removerArticleFromStorage(url);
}
});
}
In Backgroun.js
chrome.runtime.onMessage.addListener( (request, sender, sendResponse) => {
switch (request.type) {
case "fetch_article":
$.ajax({
type: "POST",
url: "http://someajaxurl.com/method",
data: JSON.stringify({url:request.url}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(response){
if(response.type==='error'){
sendResponse({type:'error',msg:response.msg});
}else{
response.data.url=request.url;
sendResponse({type:'success',data:response.data});
}
}
});
return true;
break;
default:
sendResponse({type:'error',msg:'Nothing Found Here...'});
break;
}
});
This works all good if I click the fetch article button and stays in that tab, but if I click the fetch article button in Tab1 and Move to Tab2 The fetcArticles callback is not working expectedly. What I am doing wrong here.

Is it possible to POST from the same URL without refreshing the page?

I'm using ajax to do so and am responding with res.end on the backend but so far, I can only POST once. Here is my code:
Server
app.post("/awesome", passwordless.restricted({ failureRedirect: "/" }), (req, res, next) => {
// ...do a bunch of stuff
res.end();
});
Client
$("[data-new-save]").on("click", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This sounds like a case for event-delegation. The best guess I have is that your refreshContent() function is removing the original [data-new-save] elements and creating new ones. This will cause the bound click event to be removed as well as it is a property of the DOM nodes that existed when it was originally called. You can get around this by delegating the event to a DOM node that does not get "refreshed", I'm assuming that the <body> tag does not get redrawn, only some set of children, so if you target <body> and look for selectors that match "[data-new-save]" it should function properly:
$('body').on('click', "[data-new-save]", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This is what i used for something similar:
$(document).ready(function () {
$('#myform').on('submit', function(e) {
e.preventDefault();
$.ajax({
url : $(this).attr('action') || window.location.pathname,
type: "GET",
data: $(this).serialize(),
success: function (data) {
$("#form_output").html(data);
},
error: function (jXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});

Infinite redirect using Mocha, Veloctiy, and Meteor

I'm trying to use mocha paired with PhantomJS to run some integration tests without needing to open a new window. My code looks something like:
var waitForAccounts = function(callback) {
if (Accounts.loginServicesConfigured()) {
callback();
} else {
setTimeout(function() {
waitForAccounts(callback);
}, 10);
}
}
var waitForLogin = function(callback) {
if (!!Meteor.user()) {
callback();
} else {
setTimeout(function() {
waitForLogin(callback)
}, 10);
}
}
if (!(typeof MochaWeb === 'undefined')){
MochaWeb.testOnly(function(){
describe("Menu bar", function(){
it("should have the correct title", function() {
expect($('.navbar-brand').html()).to.equal('Lynx');
});
describe('when logged in', function() {
beforeEach(function(done) {
waitForAccounts(function() {
if (!Meteor.user()) {
Meteor.loginWithFacebook({
loginStyle: 'redirect'
});
waitForLogin(function() {
console.log('User:', Meteor.user());
done();
});
} else {
done();
}
});
});
it('should have a logout link', function() {
expect($('#logout').html()).to.exist;
expect($('#login').html()).to.be.undefined;
});
});
});
});
});
I'm guessing this has something to do with the code reloading on every page load, which happens when the account logs in (currently there's a proxy that fakes and auto accepts for the fb oauth.) I'm just not sure how to solve it at this point.
The UI is written using ReactJS and the backend/reactivity is written using Meteor.

passing massage from injected js to background.js in chrome extesion

I have a problem with passing data from injected js to background.js
injected js name "getDOM.js" and injected with this code in background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
i want to pass data from getDOM.js to background.js, so in background.js there is a function that will be ran when context menu clicked
this is the function in background.js :
function SetLinks(info, tab) {
chrome.extension.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
alert(tabURL);
});
}
as you can see i tried to send a massage and want to get tabURL (this is just for test)
in getDOM.js file i've wrote this code :
chrome.extension.onMessage.addListener(function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
sendResponse( {navURL:'test'} );
}
});
so the navURL must be returned. but it not working
it works reverse, i mean if i was trying for sending request "from" getDOM.js it will work. it seams the request function should be in getDOM.js otherwise it will not work. please help me
I also tried it this way :
background.js
function SetLinks(info, tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
chrome.contextMenus.onClicked.addListener(SetLinks);
// Set up context menu tree at install time.
chrome.runtime.onInstalled.addListener(function() {
// Create one test item for each context type.
var contexts = ["page","selection","link","editable","image","video",
"audio"];
var context = contexts[1];
var title = "test";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
but still not working
Sending a request from the extension/background.js to a content script that you need to specify which tab to send it to. https://developer.chrome.com/extensions/messaging.
I created the sample code and tested it works with me as below:
Background.js:
chrome.contextMenus.create({"title": "sample text", "contexts":["page"],
"id": "ViewAlert"
});
function contextClicked(info, tab) {
if (info.menuItemId == "ViewAlert" ) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
};
chrome.contextMenus.onClicked.addListener(contextClicked);
Content.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
Also keep in mind to add "permissions": ["contextMenus"...] in your manifest.
i have found the solution
background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});

Node js + PhantomJs: send data to page.evaluate

How can I send variable from server to page.evaluate ?
var test = 'Lorem Ipsum';
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(){
$('body').html(test);
});
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Thank you in advance for your help.
Edit1
Now it look like
var message = function(){
return {message: 'Hello Word'};
};
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(content){
$('body').html(content);
}, message);
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Now I haven't any error, but I don't know how can I handle this object to use it in page.evaluate
try with
page.evaluate(function (...) {...}, function (err, data){...}, arg1, arg2, ...);
example:
var message = 'hello world';
page.evaluate(function(content){
$('body').html(content);
return 'any data'
}, function (err, anydata) {}, message);
Adding jquery to page
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function(err) {
//jQuery Loaded.
//Wait for a bit if site have AJAX
setTimeout(function() {
return page.evaluate(function() {
// USE JQUERY HERE
//
//
return
}, function(err, result) {
console.log(result);
ph.exit();
});
}, 3000);
});
see readme at:
https://github.com/alexscheelmeyer/node-phantom

Resources