1

I'm trying my hand at a simple Chrome Extension, but I've hit a snag.
I'm trying to autofill a login form (username and password). (As backup in case the chrome autofill functionality is disabled)
I've managed to inject a script into the page and I can console.log the input I'm targeting. But it won't set the value.

Manifest.json

{
  "manifest_version": 2,
  "name": "Test Extension",
  "description": "Test Extension",
  "version": "1.0",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "index.html"
  },
  "content_scripts": [
    {
        "matches": [ "*://*.domain.net/*" ],
        "js": [ "autofill.js" ]
    }
  ],
  "permissions": [
    "tabs",
    "*://*.domain.net/*"
  ]
}

autofill.js

console.log( "Script properly injected into page" );

let usernameInput = document.querySelector( 'input[name="username"]' );
let passwordInput = document.querySelector( 'input[name="password"]' );

console.log( usernameInput );

usernameInput.value = "test";

What am I missing here?

Paul van den Dool
  • 2,498
  • 2
  • 16
  • 35

2 Answers2

1

Apparently, the issue was with the autofill functionality of Chrome. Setting the autocomplete attribute to off, false or new-password in case of the password didn't work for me. Chrome seems to ignore this.
Disabling Chrome Autofill

My solution was to add a small timeout before executing my code. It's far from ideal, but it works.

setTimeout( () => {
    usernameInput.value = "username";
    passwordInput.value = "password"
}, 500 );
Paul van den Dool
  • 2,498
  • 2
  • 16
  • 35
0

The problem is almost certainly that you need to wait for the document loaded event. As it is, your script has finished before the elements are loaded on the page.

Make your autofill.js

console.log( "Script properly injected into page" );
document.addEventListener('DOMContentLoaded', function () {
    let usernameInput = document.querySelector( 'input[name="username"]' );
    let passwordInput = document.querySelector( 'input[name="password"]' );

    console.log( usernameInput );

    usernameInput.value = "test";
});
Troy Wray
  • 810
  • 5
  • 15
  • Sounds logical. Tried it, but for some reason everything within the eventlistener doesn't fire. `document.addEventListener( 'DOMContentLoaded', () => { console.log( 'DOM fully loaded and parsed' ); } );` – Paul van den Dool Nov 07 '17 at 14:26
  • Apparently I don't have to wait for the DOM to be loaded: https://stackoverflow.com/questions/5113318/in-a-chrome-extension-content-script-must-i-wait-for-document-ready-before-proc I also tried adding `run_at: document_end` to my manifest.json, but to no avail. Another piece of evidence that the script runs after DOM is loaded, the console.log of the input element, would return undefined if it wasn't loaded yet. – Paul van den Dool Nov 07 '17 at 14:39
  • Fair enough, with small content scripts I usually use "run_at": "document_start" precisely so that I know the document ready listener is registered before it can fire. Maybe I've been missing a trick. – Troy Wray Nov 07 '17 at 15:15