I want to run console app by clicking button on webpage
Console app will get Information and put in clipboard, and then I will get that information on webpage.
I am following this blog
I did this 3-4 times, all other things looks fine, but console app is not being called/executed.
I am getting these errors.
on webpage console
Unchecked runtime.lastError: The message port closed before a response was received.
on background file
Unchecked runtime.lastError: Specified native messaging host not found.
Unchecked runtime.lastError: The message port closed before a response was received.
my codes are
manifest.json
{
"name": "EID Reader",
"version": "1.0",
"manifest_version": 2,
"description": "Read Emirates ID",
"permissions": [ "contextMenus", "activeTab", "clipboardRead", "nativeMessaging" ],
"icons": {
"16": "eid16.png",
"48": "eid48.png",
"128": "eid128.png"
},
"background": {
"scripts": [ "eid.js" ]
},
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*", "file://*/*"],
"js": [ "content_script.js", "jquery-3.3.1.js" ],
"all_frames": true,
"run_at": "document_start"
}
]
}
content_script.js
// Listener to catch the event raised by the webpage button
document.addEventListener("EID_EVENT", function (data) {
// send message to background process to read emirates ID and send back the data
chrome.runtime.sendMessage("ifligfijbkpijeafdfbpljjibfbppmeb", function (response) {
});
});
// Listener to catch the data coming from the background process
chrome.extension.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.action == 'EID_DATA') {
//Parse the data and fill the form accordingly
try {
var json = $.parseJSON(msg.response);
$(json).each(function (i, val) {
$.each(val, function (key, value) {
if (key == 'EIDNumber')
$("#txtNumber").val(value);
if (key == 'Name')
$("#txtName").val(value);
if (key == 'Email')
$("#txtEmail").val(value);
if (key == 'PassportNumber')
$("#txtPassport").val(value);
});
});
}
catch (e) {
var error = "error" + e;
}
}
});
eid.js (background)
var port = null;
var tabId = null;
/* listener for messages coming from the content_scrip */
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
tabId=sender.tab.id;
var hostName = "ae.eid.chrome";
port = chrome.runtime.connectNative(hostName);
port.onDisconnect.addListener(onDisconnected);
});
/* THIS WILL BE CALLED ONCE EXE FINISH */
function onDisconnected() {
port = null;
SendResponse();
}
function SendResponse() {
//create a textarea, focus on it, and make a "paste" command to get the clipboard, then send the pasted value back to the content_script
bg = chrome.extension.getBackgroundPage();
bg.document.body.innerHTML = ""; // clear the background page
var helper = null;
if (helper == null) {
helper = bg.document.createElement("textarea");
helper.style.position = "absolute";
helper.style.border = "none";
document.body.appendChild(helper);
}
//Focus the textarea
helper.select();
// perform a Paste in the selected control, here the textarea
bg.document.execCommand("Paste");
// Send data back to content_script
chrome.tabs.sendMessage(tabId, { action: "EID_DATA", response: helper.value }, function (response) { });
}
ae.eid.chrome.json
{
"name": "ae.eid.chrome",
"description": "chrome extension to read EID",
"path": "EIDSampleConsole.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://ifligfijbkpijeafdfbpljjibfbppmeb/"
]
}
install_host.bat
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\ae.eid.chrome" /ve /t REG_SZ /d "%~dp0ae.eid.chrome.json" /f
I spent 2 days didnot get anything helpful.
Am I doing some error or Google Chrome prevented or changed the way to register host.
I have solved all the issues and posted all the steps at
http://www.codingsips.com/emirates-id-reader-and-google-chrome-via-extension-and-console-app/
Also I have published chrome extension, it you follow above steps the same extension will also work for you
chrome extension
https://chrome.google.com/webstore/detail/adcs-eid-reader/ipcncgpbppgjclagpdlodiiapmggolkf
Related
I am working on building a Javascript (in-browser) Instagram bot. However, I ran into a problem.
If you run this script, the first function will be called and the page will be redirected to "https://www.instagram.com/explore/tags/samplehashtag/" and the second function will be called immediately after (on the previous URL before the page changes to the new URL). Is there a way to make the second function be called after this second URL has been loaded completely?
I have tried setting it to a Window setInterval() Method for an extended time period, window.onload and a couple of other methods. However, I can't seem to get anything to work. Any chance someone has a solution?
This is my first chrome extension and my first real project, so I may be missing something simple..
manifest.json
{
"name": "Inject Me",
"version": "1.0",
"manifest_version": 2,
"description": "Injecting stuff",
"homepage_url": "http://danharper.me",
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"browser_action": {
"default_title": "Inject!"
},
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
inject.js
(function() {
let findUrl = () => {
let hashtag = "explore/tags/samplehashtag/";
location.replace("https://www.instagram.com/" + hashtag);
}
findUrl();
})();
background.js
// this is the background code...
// listen for our browerAction to be clicked
chrome.browserAction.onClicked.addListener(function(tab) {
// for the current tab, inject the "inject.js" file & execute it
chrome.tabs.executeScript(tab.ib, {
file: 'inject.js'
});
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
chrome.tabs.executeScript(tab.ib, {
file: 'inject2.js'
});
});
inject2.js
(function() {
if (window.location.href.indexOf("https://www.instagram.com/explore/tags/samplehashtag/") != -1){
let likeAndRepeat = () => {
let counter = 0;
let grabPhoto = document.querySelector('._9AhH0');
grabPhoto.click();
let likeAndSkip = function() {
let heart = document.querySelector('.glyphsSpriteHeart__outline__24__grey_9.u-__7');
let arrow = document.querySelector('a.coreSpriteRightPaginationArrow');
if (heart) {
heart.click();
counter++;
console.log(`You have liked ${counter} photographs`)
}
arrow.click();
}
setInterval(likeAndSkip, 3000);
//alert('likeAndRepeat Inserted');
};
likeAndRepeat();
}
})();
It is not clear from the question and the example, when you want to run your function. But in chrome extension there is something called Message Passing
https://developer.chrome.com/extensions/messaging
With message passing you can pass messages from one file to another, and similarly listen for messages.
So as it looks from your use case, you can listen for a particular message and then fire your method.
For example
background.js
chrome.runtime.sendMessage({message: "FIRE_SOME_METHOD"})
popup.js
chrome.runtime.onMessage.addListener(
function(request) {
if (request.message == "FIRE_SOME_METHOD")
someMethod();
});
EDIT
Also if you want to listen for the URL changes, you can simply put a listener provided as in the documentation.
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.log('updated tab');
});
I'm well aware that there are older questions regarding this issue, but I havent't found a solution from them.
My extension is supposed to detect a copy event in contentScript.js and pass the information, that event has been detected to oncopy.js. After that oncopy.js is supposed to copy users clipboard contents and pass them to popup.js, where the content is stored using Googles storage API, and set to the input fields value in popup.html.
The copy detection works perfectly, but I don't know what to do after that. This is my first extension, so I'm still trying to get hang of things.
Here are my manifest.jsons relevant parts:
"permissions": [
"activeTab",
"storage",
"clipboardRead"
],
"background": {
"scripts": ["oncopy.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentScript.js"]
}
]
contentScript.js:
// Fires when copy event is detected
document.addEventListener("copy", () => {
chrome.runtime.sendMessage({event: "copy"}, msg => console.log(msg))
})
oncopy.js e.g. the background script:
console.log("oncopy.js background scipt is running...");
// When copy event is detected and message of it is received, this starts to run
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
chrome.runtime.sendMessage({ event: "new clipboard" }, () => {
// This is supposed to get the clipboard contents from user
bg = chrome.extension.getBackgroundPage();
bg.document.body.innerHTML = "";
var helperdiv = bg.document.createElement("div");
document.body.appendChild(helperdiv);
helperdiv.contentEditable = true;
var range = document.createRange();
range.selectNode(helperdiv);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
helperdiv.focus();
bg.document.execCommand("Paste");
var clipboardContents = helperdiv.innerHTML;
});
sendResponse("Message has been processed by background page");
});
popup.js:
// This is supposed to set all of the clipboards to input fields values
document.body.onload = () => {
chrome.storage.sync.get("clipboards", (clipboards) => {
if (!chrome.runtime.error) {
document.getElementById("clipboard1").value = clipboards[0];
}
});
};
// The function that gets clipboard contents in oncopy.js is supposed to pass the contents here
// addClipboard is supposed to handle multiple clipboards, but for the sake of simplicity I'm using one as an example
function addClipboard(clipboard) {
chrome.storage.get("clipboards", (clipboards) => {
clipboards[0] = clipboard;
chrome.storage.sync.set({'clipboards': clipboards}, () => {
message('Clipboard saved');
});
document.getElementById("clipboard1").value = clipboards[0];
});
}
and finally the popup.html:
<h2>Clipboards</h2>
<form>
<input type="text" id="clipboard1" value="Empty" readonly>
</form>
I have a Google Chrome extension which contains the following two files...
manifest.json
{
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
"name": "Native Messaging Example",
"version": "1.0",
"manifest_version": 2,
"description": "Send a message to a native application.",
"app": {
"launch": {
"local_path": "index.html"
}
},
"icons": {
"128": "icon-128.png"
},
"permissions": [
"nativeMessaging"
],
"externally_connectable": {
"matches": ["*://*.chrome-extension.com/*"]
},
"background": {
"scripts": ["background.js"]
}
}
background.js
var sendResponseCallBack;
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
sendResponseCallBack = sendResponse;
var message = {"comment": '*** ' + request['comment'] + ' ***'};
var useNative = false;
if (useNative) {
connect();
sendNativeMessage(message);
}
else {
sendResponseCallBack(message);
}
}
);
function connect() {
var hostName = "com.google.chrome.example.echo";
port = chrome.runtime.connectNative(hostName);
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
}
function sendNativeMessage(message) {
port.postMessage(message);
}
function onNativeMessage(message) {
port.disconnect();
sendResponseCallBack(message);
}
I also configured the virtual host: chrome-extension.com to access to the url from a local server:
http://www.chrome-extension.com/
With the Chrome extension installed and enabled, if I access to:
http://www.chrome-extension.com/
and the variable useNative = false then I get a response from the plugin through: sendResponseCallBack(message);, but if useNative = true then I don't get any response from the plugin, I get: undefined and also the native operation which should take about 5 seconds, doesn't go thru because the undefined response is returned in 0 seconds.
I also have enabled another html page I access thru the extension url:
chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/calc-with-os.html
Inside that page I include the calc-with-os.js file which contains the above functions: connect() sendNativeMessage(message) onNativeMessage(message) and the function: chrome.runtime.connectNative works properly performing the native process in all its phases.
Any idea on how can I connect to a native process from an external url?
[EDIT: TRY NUMBER 2]
Based on the comment of: #wOxxOm I did the following modification to the code with the purpose of don't send the message to fast and wait for the native process to start, but it is not still working.
Any other suggestions?
var port = null;
var sendResponseCallBack;
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
sendResponseCallBack = sendResponse;
connect(request);
}
);
function connect(request) {
chrome.runtime.onConnect.addListener(function(p){
port = p;
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
var message = {"comment": '*** ' + request['comment'] + ' ***'};
sendNativeMessage(message);
});
var hostName = "com.google.chrome.example.echo";
chrome.runtime.connectNative(hostName);
}
function sendNativeMessage(message) {
port.postMessage(message);
}
function onNativeMessage(message) {
port.disconnect();
sendResponseCallBack(message);
}
Work algorithm of extension
For example, I am on site C, I see pageAction, click on it, script parsing needed information, then opens site A, script add all that information in textarea.
backround.js ---> c.js (signal to start parsing)
c.js ----> backround.js (message with information)
backround.js ----> a.js (that message, add in textarea) [Here I have problem]
manifest.json
{
"name": "test",
"version": "0.0.1",
"manifest_version": 2,
"description": "test",
"icons": { "16": "16.png",
"48": "48.png",
"128": "128.png"
},
"page_action" :
{
"default_icon" : "icon19.png",
"default_title" : "TEST"
},
"background": {
"page": "html/background.html"
},
"content_scripts": [
{
"matches": ["http://A_SITE"],
"js": ["js/jquery.js", "js/a.js"]
},
{
"matches": ["http://C_SITE"],
"js": ["js/jquery.js", "js/c.js"]
},
],
"minimum_chrome_version":"31.0",
"offline_enabled": true,
"permissions": ["tabs", "http://C_SITE/*", "http://A_SITE/*"]
}
c.js
$(document).ready(function(){
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.c_go == "go"){
//parsing here
chrome.runtime.sendMessage({ some obj }); // HERE I SEND MESSAGE TO BACKGROUND
}
});
});
a.js
$(document).ready(function(){
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request){
console.log(request); // NOTHING IN CONSOLE
}
});
});
background.js
function checkForValidUrl(tabId, changeInfo, tab) {
if(changeInfo.status === "loading") {
if (tab.url.indexOf('C_SITE') > -1) {
chrome.pageAction.show(tabId);
}
}
};
chrome.tabs.onUpdated.addListener(checkForValidUrl);
chrome.pageAction.onClicked.addListener(function(tab){
if (tab.url.indexOf('C_SITE') > -1){
// HERE I SEND MESSAGE TO c.js TO PARSING
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tab.id, {c_go: "go"});
});
// OPENS SITE_A
chrome.tabs.create({url: "SITE_A", "active":true}, function(tab){
// REQUEST FROM c.js
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
// SEND REQUEST TO TAB WITH SITE_A
chrome.tabs.query({active: true, currentWindow: true}, function(tab) {
chrome.tabs.sendMessage(tab[0].id, request);
});
});
});
}
});
So, in console on SITE_A I see nothing in console. Its very strange, because I use the same code in c.js chrome.runtime.onMessage.addListener.
How to fix it? Thanks.
chrome.runtime.onMessage is an event listener so it needs to be defined before said event occurs in order to listen for it. Right now you have it sending a message background -> c.js then send a new message c.js -> background.js. This turns it into a race condition as your background page opens up the new tab and creates the event handler at the same time that c.js is trying to send a message. Instead, try to make it all one flow.
c.js
chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){
if(request.c_go == "go"){
//parsing here
sendResponse({ some obj }); // HERE I SEND MESSAGE TO BACKGROUND
}
});
This changes the message c -> background to a response to the first message.
background.js
chrome.pageAction.onClicked.addListener(function(tab){
chrome.tabs.sendMessage(tab.id,{c_go:"go"},function(response){
chrome.tabs.create({url: "SITE_A", "active":true}, function(newTab){
chrome.tabs.executeScript(newTab.id, {file:"a.js"},function(){
chrome.tabs.sendMessage(newTab.id, response);
});
});
});
});
This makes is so that Site A isn't opened until you get the info from Site C.
This is what happens on page-action click:
You send message to C_SITE.
You create new tab with A_SITE.
You register an onMessage listener to receive messages from C_SITE.
You forward any messages from C_SITE to A_SITE.
Unfortunately, somewhere between 1 and 3 (before the listener is registered), C_SITE sends its message (which goes unnoticed).
You should always make sure your events are fired after the corresponding listeners are properly set-up.
See my comment above:
* You use chrome.tabs.query() unnecessarily and risk breaking your extension's behaviour (e.g. if another widnow happens to become unexpectedly active).
* You unnecessarily use $(document).ready().
I am trying to create a channel to my Google App Engine (Python) server, and there seems to be a problem but I am unsure why. When the user toggles the extension, it authenticates the user. If successful, the server replies with a channel token which I use to create the channel. When I authenticate the user, alert("a") appears, but alert("b") does not which makes me believe there is a problem with the line var channel = new goog.appengine.Channel(msg.token);, but the console does not report an error.
I have also copied the javascript code from here and placed it in my manifest as oppose to putting <script type="text/javascript" src="/_ah/channel/jsapi"></script> in background.html.
//script.js
function authenticate(callback) {
var url = "https://r-notes.appspot.com/init/api/authenticate.json?username=" + username + "&password=" + password;
$.post(url, function(data) {
if (data.status == "200") {
channelToken = data.channeltoken;
if (callback) {
callback();
}
var port = chrome.extension.connect({name: "myChannel"});
port.postMessage({token: channelToken});
port.onMessage.addListener(function(msg) {
console.log(msg.question);
});
}
});
}
//background.html
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
alert("a"); //pops up
var channel = new goog.appengine.Channel(msg.token);
alert("b"); //does not pop up
console.log(channel); //display error ' Error in event handler for 'undefined': ReferenceError: goog is not defined '
var socket = channel.open()
socket.onopen = function() {
// Do stuff right after opening a channel
console.log('socket opened');
}
socket.onmessage = function(evt) {
// Do more cool stuff when a channel message comes in
console.log('message recieved');
console.log(evt);
}
});
});
//manifest.json
{
"name": "moot",
"description": "Clicking on the moot button will display a sidebar!",
"version": "0.2.69",
"background_page": "html/background.html",
"browser_action": {
"default_icon": "img/icon_64.png",
"default_title": "moot"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/channelApi.js",
"js/script.js", "js/mootsOnSidebar.js", "js/mootsOnPage.js", "js/authenticate.js", "js/otherFunctions.js",
"js/jquery/jquery-1.7.1.js", "js/jquery/jquery.mCustomScrollbar.js", "js/jquery/jquery-ui.min.js",
"js/jquery/jquery.autosize.js", "js/jquery/jquery.mousewheel.min.js", "js/jquery/jquery.easing.1.3.js",
"js/channel.js"],
"css": ["css/cssReset.css", "css/sidebar.css", "css/onPageCreate.css", "css/onPageExists.css", "css/scrollbar.css", "css/authenticate.css"]
}
],
"permissions": [
"tabs", "contextMenus", "http://*/*", "https://*/"
],
"icons": {
"16": "img/icon_16.png",
"64": "img/icon_64.png"
}
}
EDIT - After doing console.log(channel), I discovered the error ' Error in event handler for 'undefined': ReferenceError: goog is not defined '. I am unsure why I receive this error as I did include the required javascript file as I followed this post.
So the solution is that you need to include the file <script type="text/javascript" src="https://talkgadget.google.com/talkgadget/channel.js"></script> in a HTML page. I placed this on the first row of background.html.
My mistake was saving a local copy of channel.js, and refer to it in manifest.json.
I'm now going to place a copy of channel.js on my server, and refer to my server's copy. I don't think there will be any issues with that.
Make a console log for the value of msg direct between alert("a") and var channel = ...
and inspect the value.