jQuery only working in certain areas of Chrome App - javascript

I am trying to create a simple serial port reader for Chrome. Nothing major, just receive the input so I can parse it. I am having some problems where jQuery is working at one point but then two lines down it is "$ undefined".
Manifest:
{
"name": "Serial Reader",
"description": "Read Serial barcode scanners with Google Chrome.",
"version": "0.1",
"manifest_version": 2,
"app": {
"background": {
"scripts": ["background.js", "script.js", "jquery.js"],
"transient": true
}
},
"permissions": [
"serial"
],
"icons": { "16": "icon-16.png", "128": "icon-128.png" }
}
Script.js:
var onGetDevices = function(ports) {
for (var i=0; iNo ports were found.");
} else {
//Works
$("#portList").append("" + ports[i].path + "");
}
}
};
chrome.serial.getDevices(onGetDevices);
var connectionId = -1;
var portSelected = $("#portList").val(); //Returns undefined $
var connectCallback = function() { console.log("Connected") };
chrome.serial.connect(portSelected, null , connectCallback);
var stringReceived = '';
var onReceiveCallback = function(info) {
if (info.connectionId == expectedConnectionId && info.data) {
var str = convertArrayBufferToString(info.data);
if (str.charAt(str.length-1) === '\n') {
stringReceived += str.substring(0, str.length-1);
$('#member').val(onLineReceived(stringReceived));
stringReceived = '';
} else {
stringReceived += str;
}
}
};
chrome.serial.onReceive.addListener(onReceiveCallback);
Background.js:
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('window.html', {
'bounds': {
'width': 1024,
'height': 768
},
"resizable": false
});
});
Window.html:
<!DOCTYPE html>
<html>
<head>
<title>Serial Reader</title>
<script type="text/JavaScript" src="jquery.js"></script>
<style>
body {
background-image: url(/images/checkin_green.png);
}
</style>
</head>
<body>
<center><strong style="font-size: 16px;">Account Number:</strong> <input id="member" /></center>
<br /><br /><br />
<center><strong style="font-size: 16px;">Avaliable Ports:</strong> <select id="portList"></select></center>
<br />
<center><span id="notFound"></span></center>
<script type="text/JavaScript" src="script.js"></script>
</body>
</html>
I have been playing around with this for quite some time and cannot come up with a solution. I don't understand how it can populate the list of ports but then three lines down say that it is undefined. Any help would be greatly appreciated! Thanks!

I believe the issue is that the DOM is not completely ready when you query for #portList, so it returns an empty list and you are trying to set the value of elements that don't exist yet.
I would suspect that the onGetDevices gets called after the DOM is ready, so there is no issue. Consider wrapping DOM dependent code within $(document).ready(function(){ ... })
Another issue could be that you are not querying the DOM of your extension, but rather the DOM of whatever page that triggered the extension.

Problem was the actual manifest loading of the scripts. The manifest should look like this:
{
"name": "Serial Reader",
"description": "Read Serial barcode scanners with Google Chrome.",
"version": "0.1",
"manifest_version": 2,
"app": {
"background": {
"scripts": ["jquery.js", "background.js", "script.js"],
"transient": true
}
},
"permissions": [
"serial"
],
"icons": { "16": "icon-16.png", "128": "icon-128.png" }
}
With that being said I put this here just for reference sake. Thanks for the help #Wio

Related

Chrome Extension execute script doesn't render browser content value

All I am trying to do change the value of popup.html on the basis of Specific URL. So I am sending message to background.js when user click on change ID of H2 from popup.html render the content by using specific JavaScript file
manifest.json
{
"manifest_version": 2,
"name": "Helpfullio",
"version": "0.1",
"content_scripts": [{
"matches": [
"*://google.com/*/*",
],
"js": ["jquery-3.2.1.js"]
}],
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"permissions": ["tabs","http://*/*", "https://*/*"]
}
popup.html
<html>
<head>
</head>
<body>
<h2 id="change">Change ___________</h2>
<script src="popup.js"></script>
</body>
</html>
popup.js
function clickHandler(e) {
chrome.runtime.sendMessage({directive: "popup-click"}, function(response) {
// this.close(); finishes processing request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('change').addEventListener('click', clickHandler);
})
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case "popup-click":
chrome.tabs.query({
'active': true, 'lastFocusedWindow': true
}, function (tabs) {
var url = tabs[0].url;
var result = url.split('/');
var hostname = result[2];
if("bitlock" == hostname){
chrome.tabs.executeScript(null, {
file: "render.js",
// allFrames: true
});
}else{
hrome.tabs.executeScript(null, {
file: "secondrender.js",
// allFrames: true
});
}
sendResponse({});
});
break;
default:
alert("Unmatched request of '" + request + "' from script to background.js from " + sender);
}
}
);;
JavaScript doesn't render the content of popup.html as it is not finding the elementID "change" . SO here how can I give reference of popup.html file in render.js file
render.js
document.getElementById("change").textContent = 'new text';

chrome.runtime.onMessage.addListener is undefined in content script

Im trying to send message to Background, and as well receive back to content script.
This is my content_script.js
init();
function init() {
function notifyBackgroundPage(event) {
chrome.runtime.sendMessage(chromeExtID, {
greeting: "Greeting from the content script"
});
}
window.addEventListener("click", notifyBackgroundPage);
// accept messages from background
// below line addListener is undefined
chrome.runtime.onMessage.addListener(function backgroundListener(request, sender, sendResponse) {
console.log("BgExt.js says: " + request);
});
}
BgExt.js
define([], function GmailExt() {
return {
start: function () {
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
console.log('inside response');
// to send back your response to the current tab
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {farewell: response}, function (response) {
});
});
return true;
}
);
}
};
});
This GmailExt file is loaded inside all.js (while all.js is inserted in index.html)
require([
"base_host/chrome/Server",
"kernel/Kernel",
"hydra/version",
"base_host/chrome/StartupConfig",
"hydra/apps",
"dojo/_base/Deferred",
"talkto_util/common",
"dojo/i18n!base_host/nls/CommonStrings",
"base_host/chrome/BgExt",
"dojo/domReady!"
], function (Server, Kernel, version, StartupConfig, apps, Deferred, talktoUtil, nls, BgExt) {
document.getElementById("logoMessage").innerText = nls.simple_secure_text;
var host = new Server();
//if app and not extension
chrome.browserAction && chrome.browserAction.onClicked.addListener(function() {
Deferred.when(kernel.onInit(), function () {
host.appManager.showShell();
});
return true;
});
BgExt.start();
});
client_base/host/chrome/index.html
<!DOCTYPE HTML>
<html>
<head>
<!-- Background Page for Extension/app -->
<title>Flock</title>
<meta charset="UTF-8">
<!--BUILD_REPLACE_BLOCK_START-->
<!-- This block will be remove by build.
All the files from libs/common/files.txt would be prepended to dojo.js -->
<script type="text/javascript" src="../../../hydra/src/libs/common/dojoConfig.js"></script>
<script type="text/javascript" src="../../../hydra/src/libs/common/underscore.js"></script>
<script type="text/javascript" src="../../../hydra/src/libs/common/underscore-ext.js"></script>
<!--BUILD_REPLACE_BLOCK_END-->
<script type="text/javascript" src="../../../hydra/src/libs/dojotoolkit/dojo/dojo.js"></script>
<script type="text/javascript" src="all.js"></script>
</head>
<body>
</body>
</html>
Manifest.json
{
"manifest_version": 2,
"content_security_policy": "script-src 'self' 'unsafe-eval' https://j.maxmind.com https://ssl.google-analytics.com https://flock-apps.flock.co https://flock-apps.flock-staging.co https://flock-apps.flock.com https://flock-apps.flock-staging.com; object-src 'self'",
"minimum_chrome_version": "22",
"options_page": "client_base/host/chrome/static/crx_browser_actions/index.html?app=preferences",
"name": "__MSG_extName__",
"description": "__MSG_extDescription__",
"background": {
"page": "client_base/host/chrome/index.html",
"persistent": true
},
"browser_action": {
"default_popup": "/gmail_ext/popup.html"
},
"web_accessible_resources": [
"client_base/host/chrome/static/blank.gif",
"gmail_ext/icons.png",
"gmail_ext/jquery-3.2.1.min.js",
"gmail_ext/gmail.js",
"gmail_ext/content_script.js"
],
"permissions": [
"<all_urls>",
"unlimitedStorage",
"notifications",
"idle",
"background",
"tabs",
"activeTab"
],
"optional_permissions": [
"clipboardWrite"
],
"externally_connectable": {
"matches": [
"https://*.google.com/*",
"http://localhost/*",
]
},
"content_scripts": [
{
"matches": [
"*://mail.google.com/*"
],
"css": [
"/gmail_ext/content_script.css"
],
"js": [
"/gmail_ext/loader.js"
],
"run_at": "document_end"
}
],
"version": "1.0"
}
I fixed it. The Solution was since I was using loader.js to load my content script and jquery via chrome.extension.getURL('/gmail_ext/content_script.js');
And was using "content_script.js" as a web_accessible_resources only loader.js had access to chrome object.
And yes, its a Dojo project, you can see the Working Extension here : https://chrome.google.com/webstore/detail/flock-chat-for-teams-and/enfaahabcinohafeakbliimmoholjeip?hl=en
I'm using page events now as showed here : https://developer.chrome.com/extensions/content_scripts#host-page-communication
At the top of loader.js I added below:
function initPort() {
var contentScriptPort,
chromeExtID = "lddaepjihbpbfpegjhjnkffjmmoigphe";
contentScriptPort = chrome.runtime.connect(chromeExtID);
contentScriptPort.onMessage.addListener(function (message) {
// Send data back to content script received from Background.
window.postMessage({type: "FROM_BACKGROUND", emails: message}, "*");
});
window.addEventListener("message", function _postMessage(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
// console.log("Content script received: " + event.data.emails);
contentScriptPort.postMessage(event.data);
}
}, false);
}
initPort();

Logon to a remote system via a Chrome extension

This is my first extension and I suspect the way I've gone about structuring the order of calling code is not completely right. I would appreciate pointers please - hopefully I'm fairly close as it has taken weeks of study, trial and error to get this far :-) XMLHttpRequest does not seem to call the system and the extension crashes a lot.
In the popup.html, there's a SignIn button which opens the 'popup' form signin.html via a listener in background.js. The signin page contains a form with a username & password inputs, and a signin button. Clicking this button calls signin.js to pickup the data from the form, and calls a routine in background.js to connect to the system (could this be the issue - since this was all kicked off from the background.js in the first place???)
In the code,e I'm connecting to Google so I know I have a website that works - I'll deal with the logon part later. Thanks.
manifest.json:
{
"name": "logon test",
"description": "logon test",
"version": "1.0",
"manifest_version": 2,
"icons": { "128": "images/logon.png" },
"browser_action": {
"default_icon": "images/logon.png",
"default_title": "logon test",
"default_popup": "popup.html" },
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"background",
"storage",
"activeTab",
"nativeMessaging",
"http://www.google.com/*",
"https://www.google.com/*"
]
}
popup.html:
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<button id = "signin">Sign In</button>
</body>
</html>
popup.js:
function onSignIn() {
chrome.extension.sendMessage({'action' : 'signin', 'url' :
'/signin.html'});
} //onSignIn
document.getElementById('signin').addEventListener('click', onSignIn);
**signin.html:**
<html>
<body>
<form>
<input name="userid" type="text" id="userid" value="User ID">
<input name="password" type="password" id="password">
<input type="submit" name="submit" id="submit" value="Login">
</form>
<script src="signin.js"></script>
</body>
</html>
signin.js:
document.forms[0].onsubmit = function(e) {
e.preventDefault(); // Prevent submission
var password = document.getElementById('password').value;
var userid = document.getElementById('userid').value;
chrome.runtime.getBackgroundPage(function(bgWindow) {
bgWindow.signIn(password, userid); //background page
window.close(); // Close dialog
});
};
background.js:
function signIn(inPass, inUserid) { //called from signin.html popup
var xhr = new XMLHttpRequest();
if (xhr === null){
alert("Unable to create request");
} else {
xhr.open('GET', 'http://www.google.com/search?q=helloworld',
true);
xhr.onreadystatechange = function() {
var resp = JSON.parse(this.responseText);
alert("result here" + resp);
} //readystate
};
}
xhr.send(null);
} //signin
// button functionality - called from popup.html
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
if (request.action === 'signin') {
chrome.tabs.create({
url: chrome.extension.getURL(request.url),
active: false
}, function(tab) {
chrome.windows.create({
tabId: tab.id,
type: 'popup',
focused: true,
left: 500,
top: 20,
width: 450,
height: 200});
}); //tab
} //if
return true;
});

Chrome plugin - How to modify dynamically added content on a webpage from a content script

I've literally been stuck on this for 2 full days so any help would be greatly appreciated.
I'm trying to build a chrome plugin that will modify the text of an element that has id ='MTG_INSTR$2'. The issue appears to be that this element only loads after some javascript is executed. Even if I wait for this element to load, when my plugin executes this line,
var els = document.getElementById('MTG_INSTR$2')
els is null. I've attached the full code below.
PS: when debugging in chrome I can see that it has the correct document and that the MTG_INSTR$2 id is within the document
manifest.json
{
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"manifest_version": 2,
"name": "extensiontest",
"version": "0.2",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery-3.2.1.min.js","content.js"]
}
],
"browser_action": {
"default_icon": "icon.png",
"default_popup":"popup.html"
},
"permissions": [
"tabs"
]
}
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "start" ) {
start();
}
}
);
function start(){
var els = document.getElementById('#MTG_INSTR$2'); //first sign of the issue, els is always left null
console.log(els);
alert("started");
}
popup.js
$(document).ready(function(){
$('body').on('click', '#button1', function(){
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "start"});
});
});
});
popup.html
<!DOCTYPE html>
<html>
<head>
<script src = "jquery-3.2.1.min.js"></script>
<script src="popup.js"></script>
</head>
<body>
<input id="button1" type=button value=clickme></input>
</body>
</html>
You need to remove the hash in :
var els = document.getElementById('#MTG_INSTR$2');
Good way would be :
var els = document.getElementById('MTG_INSTR$2');

chrome extension sendMessages more than one

Hello i'm trying to send message to popedup window, but when i close popup window end call it(from context menu) again.. it shows all last masseges..
How can i send only one message only to new opened window?
Manifest.json
{
"manifest_version": 2,
"name": "1tst",
"description": "sm txt",
"version": "0.1",
"author": "smwn",
"permissions": [
"activeTab",
"tabs",
"contextMenus"
],
"background": {
"scripts": ["sample.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["1.js"]
}]
}
sample.js
function genericOnClick(info, tab,selT) {
var vid;
var nw_tb;
chrome.tabs.create({
url: chrome.extension.getURL('1.html'),
active: false
}, function(tab) {
vid = tab.id;
// After the tab has been created, open a window to inject the tab
chrome.windows.create({
tabId: tab.id,
type: 'popup',
focused: true
// incognito, top, left, ...
},function(chromeWindow) {
//vid = chromeWindow.id;
}
);
});
chrome.windows.onCreated.addListener(function(tabb){
nw_tb = tabb.id;
alert("vid: "+vid+" nw_tb: "+nw_tb);
chrome.runtime.sendMessage(vid, {statn: selT});
return;
});
}
var title = "Test '%s' menu item";
var id = chrome.contextMenus.create({"title": title, "contexts":["selection"],
"onclick": function(info,tab){ genericOnClick(info,tab, info.selectionText);}
});
1.html
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="1.js"></script>
</head>
<body>
</body>
</html>
1.js
window.onload=function(){
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
sendResponse({metroSTAT: "OK"});
alert(request.statn);
});
}
The problem
Every time genericOnClick() is called, it registers a new listener for the windows.onCreated event. Once registered, the listeners will trigger every time.
The solution
One of the many possible solutions is to "un-register" the listener once it is triggered for the first time (using removeListener()):
// Replace the following block:
chrome.windows.onCreated.addListener(function(tabb){
...
});
// With this:
chrome.windows.onCreated.addListener(function tmpListener(tabb) {
chrome.windows.onCreated.removeListener(tmpListener);
...
});

Categories

Resources