XMLHttpRequest status 0 in click event handler - javascript

I'm writing a Google Chrome extension to take advantage of an API we have written. The problem I'm having is that the popup.html has a login form, and when the submit button is pressed it calls the necessary authentication code, which involves making a couple of XMLHttpRequests to the API server.
The code is as follows:
authenticate.js
function authenticate(username, password)
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "<api-server>/challenge?username=dummyusername", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
alert(xhr.status);
}
};
xhr.send();
}
/*Gets the username and password textboxes from popup.html and passes their values on to authenticate()*/
function getCredentials()
{
authenticate("test", "test");
}
document.addEventListener("DOMContentLoaded", function() {
var submitBtn = document.getElementById("submitBtn");
if (submitBtn != null) {
submitBtn.onclick = getCredentials;
}
});
popup.html
<!doctype html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<form>
<label for="username">Username:</label>
<input type="text" id="usernameTxt"><br>
<label for="password">Password:</label>
<input type="password" id="passwordTxt"><br><br>
<input type="submit" id="submitBtn" value="Submit">
</form>
<script src="authenticate.js"></script>
</body>
</html>
manifest.json
{
"manifest_version": 2,
"name": "Chrome Extension",
"description": "Chrome Extension",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"<all_urls>",
"activeTab",
"https://ajax.googleapis.com/",
"<api-server>"
]
}
If, however, I replace:
document.addEventListener("DOMContentLoaded", function() {
var submitBtn = document.getElementById("submitBtn");
if (submitBtn != null) {
submitBtn.onclick = getCredentials;
}
});
with:
document.addEventListener('DOMContentLoaded', function() {
getCredentials();
});
it does the right thing, which leads me to believe it's to do with the fact that it's being called from a click event handler and perhaps somehow the permissions haven't been extended to the button.
I saw this post (Chrome Extension: XMLHttpRequest canceled (status == 0)) and added "<all_urls>" to permissions and that has made no difference.

Cancel the click so the form does not submit.
document.getElementById("submitBtn").addEventListener('click', function(evt){
evt.preventDefault();
getCredentials();
});

Related

Change of variables via popup chrome extension

I am doing a Chrome extension and I have a problem. It is supposed to click button on the page.
I want to use a variable that I can change via the popup because I don't want to go to the script all the time and change the variable. How do I do that?
I want to change the variable sku via popup.
Manifest:
{
"name": "Clicker",
"manifest_version": 2,
"version": "0.0.1",
"browser_action": {
"default_popup": "popup.html",
"default_title": "popup",
"default_icon": "icon.png"
},
"description": "Clicker",
"content_scripts": [
{
"matches": ["https://www.zalando.pl/*"],
"js": ["content.js"]
}
],
"permissions": [
"tabs", "storage" ,"activeTab", "http://*/*", "https://*/*",
"<all_urls>",
"*://*/*",
"tabs",
"storage",
"webRequest",
"webRequestBlocking",
"webNavigation",
"alarms",
"cookies"
]
}
popup.html
<html>
<body>
<h1>Esensial Scripts</h1>
<input type="text" id="sku" placeholder="Enter Sku Here"/>
<input type="submit" id="Save" value="Save"/>
</body>
</html>
content.js
var spicker = "size-picker-";
var sku = "NI112O0J9-A110075000";
//example var sku = "XXXXXXXXX-XXXXXXXXXX";
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
window.addEventListener('load', function () {
sleep(1).then(() => {
document.getElementById(spicker + sku).click();
})
})
Save the name of the button to chrome storage (You'll need to add new javascript code for popup html):
window.onload = function(){
document.getElementById('Save').onclick = function(){
var value = document.getElementById('sku').value;
chrome.storage.sync.set({'myLine': value}), function() {
console.log("you saved me!!");
});
}
Add new script to popup.html:
<script src="popup.js"></script>
And check chrome storage in content.js:
var spicker = "size-picker-";
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
window.addEventListener('load', function () {
chrome.storage.sync.get('myLine', function(result){
sleep(1).then(() => {
document.getElementById(spicker + result.myLine).click();
})
});
})

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');

jQuery only working in certain areas of Chrome App

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

Chrome extension browse file (Chrome v33)

I had browsing for files working in chrome extensions but suddenly it stopped working (im guessing because of a chrome upgrade (to v33?))
i have looked around and all answers seem outdated...
here are my files (i got it from this: Upload File as a Form Data through chrome extension)
manifest.json:
{
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"name": "yoyo",
"manifest_version": 2,
"version": "1.0.0",
"browser_action": {
"default_title": "Test Extension",
"default_popup": "popup.html"
},
"permissions": [
"https://www.example.com/uploads"
]
}
popup.html:
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<input type="button" id="button" value="Browse and Upload" />
</body>
</html>
popup.js:
document.addEventListener('DOMContentLoaded', function () {
document.getElementsByTagName('input')[0].addEventListener('click', function () {
chrome.runtime.sendMessage({ action: 'browseAndUpload' }, function(response){});
window.close();
});
});
background.js:
var uploadURL = 'https://www.example.com/uploads';
/* Creates an `input[type="file]` */
var fileChooser = document.createElement('input');
fileChooser.type = 'file';
fileChooser.addEventListener('change', function () {
var file = fileChooser.files[0];
var formData = new FormData();
formData.append(file.name, file);
var xhr = new XMLHttpRequest();
xhr.open('POST', uploadURL, true);
xhr.addEventListener('readystatechange', function (evt) {
console.log('ReadyState: ' + xhr.readyState,
'Status: ' + xhr.status);
});
xhr.send(formData);
form.reset(); // <-- Resets the input so we do get a `change` event,
// even if the user chooses the same file
});
/* Wrap it in a form for resetting */
var form = document.createElement('form');
form.appendChild(fileChooser);
/* Listen for messages from popup */
chrome.runtime.onMessage.addListener(function (msg) {
if (msg.action === 'browseAndUpload') {
fileChooser.click();
}
});

Categories

Resources