The onMessage listener in Chrome consistently returns an 'undefined' response

My latest project involves creating a simple chrome extension that utilizes message passing. The goal of the extension is to listen for messages from a specific website (in this case, localhost:8080/*) and respond with a simple "Bye". To test this functionality, Selenium opens a locally served page in Chrome, attempts to send a message to the extension, and then displays the response in the console:

$ tree -I node_modules
.
├── extension
│   ├── background.js
│   └── manifest.json
├── package.json
└── test
    ├── index.html
    └── selenium-test.js

2 directories, 5 files

background.js

chrome.runtime.onMessage.addListener(
    function (req, sender, sendResp) {
        sendResp('Bye');
    });

manifest.json

{
    "name": "chrome-test",
    "version": "0.1",
    "manifest_version": 2,
    "key": "pcoogjpilcclcmejpkmbifdbihomlgec",
    "description": "Test extension.",
    "app": {
    "background": {
        "scripts": ["background.js"],
        "persistent": true
    }
    },
    "externally_connectable": {
    "matches": [
        "http://localhost:8080/*"
    ],
    "accepts_tls_channel_id": false
    },
    "permissions": [
    "http://localhost:8080/*"
    ]
}

package.json

{
    "name": "chrome-test",
    "version": "0.0.5",
    "description": "Chrome API sucks.",
    "keywords": [ "" ],
    "author": "Chris Perivolaropoulos",
    "contributors": [],
    "dependencies": {
    "selenium-webdriver": "*",
    "mocha": "*",
    "chai": "*"
    },
    "scripts": {
    "test": "mocha test/selenium-test.js"
    }
}

index.html

<html>
  <head>
    <title>Test page</title>
  </head>
  <body>
    <h1>Test page</h1>
    <div id="echo"></div>
    <script type="text/javascript">
      chrome.runtime.sendMessage('pcoogjpilcclcmejpkmbifdbihomlgec', 'hello',
      function (msg) {
      console.log("Received! " + msg);
      });
    </script>
  </body>
</html>

selenium-test.js

var assert = require('chai').assert,
    test = require('selenium-webdriver/testing'),
    webdriver = require('selenium-webdriver'),
    chromedriver = require('selenium-webdriver/chrome');

// @param extensions: string of unpacked extension path to install.
function chrome_driver(extension) {
    var logperfs = new webdriver.logging.Preferences(),
            opts = new chromedriver.Options().
                addArguments("--load-extension=" + extension ||
                                         '../extension');

    logperfs.setLevel(webdriver.logging.Type.BROWSER,
                                        webdriver.logging.Level.ALL);

    var chrome = new webdriver.Builder().
                withCapabilities(webdriver.Capabilities.chrome()).
                setChromeOptions(opts).
                setLoggingPrefs(logperfs).
                build();

    chrome.manage().timeouts().pageLoadTimeout(5000);
    return chrome;
}

function browser_logs(driver, callback) {
    driver.manage().logs().
        get(webdriver.logging.Type.BROWSER).then(callback);
}

test.describe('Test', function() {
    var chrome;
    this.timeout(10000);

    test.before(function() {
        chrome = chrome_driver("extension");
    });

    test.it("Test messages", function () {
        chrome.get("http://localhost:8080/test/index.html").then(function () {
            browser_logs(chrome, function (entries) {
                entries.forEach(function (e) {console.log("BrowserLog: " + e.message);});
                assert.equal(entries.pop().message,
                                         "hello", "Bus not echoing.");
            });
        });
    });

    test.after(function() {
        chrome.quit();
    });
});

To run a test first run a local http server

$ python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...

and from another console run the tests

$ npm test

> <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="27444f55484a420a53425453671709170912">[email protected]</a> test /path/to/project
> mocha test/selenium-test.js



  Test
BrowserLog: http://localhost:8080/test/index.html 11:15 Received! undefined
[2K[0G    1) Test messages


  0 passing (1s)
  1 failing

  1) Test Test messages:

      Bus not echoing.
      + expected - actual

      +hello
      -http://localhost:8080/test/index.html 11:15 Receviced! undefined

      at /path/to/project/test/selenium-test.js:43:12
      at /path/to/project/node_modules/selenium-webdriver/lib/goog/base.js:1582:15
      at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:1640:20)
      at notify (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:444:12)
      at notifyAll (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:422:7)
      at resolve (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:400:7)
      at fulfill (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:512:5)
      at Object.webdriver.promise.asap (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:758:5)
      at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:1651:25)
      at notify (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:444:12)
      at notifyAll (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:422:7)
      at resolve (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:400:7)
      at fulfill (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:512:5)
      at Object.webdriver.promise.asap (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:758:5)
      at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/prompt...
      

npm ERR! Test failed.  See above for more details.

The extension always responds undefined instead of 'Bye' as instructed in background.js.

Answer №1

Incorrect Event.

When messages are sent from webpages using externally_connectable, they are categorized as external messages. Therefore, your background script should be configured like this:

chrome.runtime.onMessageExternal.addListener(
  function (req, sender, sendResp) {
    sendResp('Bye');
  }
);

The issue you are facing is due to the listener sending an undefined response. This happens when the callback of sendMessage is triggered by one of two scenarios:

  • A listener actually utilizes sendResponse. In this case, the argument will contain that response.
  • If there was an error sending the message, the argument will be undefined, and chrome.runtime.lastError will be set.

In your situation, you are encountering the second scenario - where there is no listener for the specific event.

It raises the question of whether the webpage context has access to chrome.runtime.lastError.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to use Python to translate the webpage that was loaded with Selenium Webdriver into English?

Here is the code I have worked on: username_input = "username" password_input = "password" url='myurl' browser = webdriver.Chrome(r'chromedriver.exe') browser.get(url) browser.maximize_window() username = browser.find_element_by_id("j_ ...

Create a unique shader in Three.js that remains unaffected by the fog effect

I have implemented a custom shader to add glow to a sphere on my scene. However, I noticed that the fog in the scene affects the sphere but not the glow. When I zoom out, the sphere disappears but the glow remains visible. Is there a way to make the fog ...

Node - ensure that each API call finishes before initiating the next one

Currently, I am encountering an issue with my POST request within the 'add-users' route. I have initialized an array named success and aim to trigger the next API call once a response is received. It seems that the problem lies in sending too ma ...

The functionality to input text using 'sendKeys' method in Selenium WebDriver is not functioning properly

Struggling to input any value into my application via WebDriver due to the presence of frames. It's peculiar that I can successfully clear the textbox using driver.findElement(By.name("name")).clear();, however, attempts to input a value wit ...

Is there any method to determine whether a floated element has been pushed down?

Imagine a dynamic menu with floating elements, each set at a width of 150px. As the menu's width decreases, the elements progressively move to the next row. You are contemplating how to detect when an element has been moved down. One approach could b ...

Tips for rendering the stencil as invisible and disabled while still allowing other features (such as rotating and flipping) to remain enabled within the react-advanced-cropper

I am facing a challenge where I need to hide and disable the stencil and overlay in react-advanced-cropper, while keeping all other features like rotation and flipping enabled. Is there a specific property in this library that allows me to disable the st ...

What is the method for attaching a div to another div using javascript?

function displayContent(a) { var content = $("#" + a).html().trim(); alert(content); $('#temstoredivid').append( "<div class='maincover' id='maincov1'>" + " <div class='subcover' id='sub ...

What is the alternative method for reading an HTML text file in JavaScript without utilizing the input type file?

Within the assets folder, there is a text file containing HTML that needs to be displayed within a specific component's div. Is it possible to retrieve the contents of this file and assign them to a string variable during the ngOnInit lifecycle hook ...

Tips for Customizing the Appearance of Material UI Select Popups

My React select component is functioning properly, but I am struggling to apply different background colors and fonts to the select options. https://i.stack.imgur.com/kAJDe.png Select Code <TextField fullWidth select size="small" nam ...

Denied from being displayed in a frame due to a violation of the Content Security Policy directive by a parent element

I'm in the process of developing a Salesforce app that is displayed within an iframe on a Salesforce page. I am using a node express server to render this page. In order to ensure security compliance, I want the app to only display within the Salesfor ...

Exploring document in Node.js

Is there a way to read the data of a file (for example, read.txt) in Node.js without buffering the data? I want to access the content of the file directly rather than as buffered data. Also, how can I delete a folder in Node.js? ...

Encountering difficulty establishing a new remote session - Selenium browser automation framework

I encountered an exception while running my Selenium script in a remote web driver. Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: Unable to create new remote session. The desired capabilities were: {marionette=true, br ...

Tips for managing dynamic elements in a Selenium automation framework designed with the page object model

When working with the page object model in Selenium, you create classes that represent different pages. These classes include locator objects and functions specific to each page. Consider the following example: public class LoginPage(){ @FindBy(id=&q ...

When a URL is triggered via a browser notification in Angular 2, the target component ceases to function properly

Whenever I access a URL by clicking on a browser notification, the functionality of the page seems to stop working. To demonstrate this issue, I have a small project available here: https://github.com/bdwbdv/quickstart Expected behavior: after starting t ...

Operating multiple windows using C# Selenium

I attempted to create a selenium script that would open multiple windows or tabs in IE. The challenge lies in not knowing how many tabs will be opened. Here is the current script I have: private void button1_Click(object sender, EventArgs e) { ilosc = ...

Having a hard time finding the perfect styling solution for Material UI

Is there a way for me to customize the styling of Material UI's components in addition to their default rules by injecting my own CSS? I'm unsure how I would go about setting these parameters using the styled-components API. Is this even doable? ...

Issues encountered with integrating external jQuery/JavaScript functions with Wordpress child theme template

After creating a custom template in my WordPress child theme, I added a link to the Bootstrap v3.0.3 .js file stored on my site. While the popup modal is functioning properly, the jQuery tabs seem to be having some issues. Although they are being display ...

No matter what I do, I can't seem to stop refreshing the page. I've attempted to prevent default, stop propagation, and even tried using

Below is the code I have written for a login page: import { useState } from "react"; import IsEmail from "isemail"; import { useRouter } from "next/router"; import m from "../library/magic-client"; import { useEffect ...

Manipulating the "placeholder" attribute with Knockout.js and JSON data

Is it possible to use the placeholder attribute with data-bind? I am encountering an error message ([object object]). Can someone help me figure out how to properly utilize it? html: input id="comments" class="form-control" data-bind="attr: { placeholde ...

What are the best practices for utilizing the "this" keyword with fetch?

After extensively studying ES6 documentation and the changes it brings, I am eager to incorporate the new oop syntax along with modern libraries such as fetch. Below is the code snippet I have been working on: apiCall(url, thisAlias=this){ fetch(url). ...