Chrome Extension with injected Javascript – Cannot read properties of undefined (reading ‘sendMessage’)

I have a script that I inject in the DOM and I want to send messages to my service worker in the background. I am getting an error and I don’t understand why.

Here is my background.js file:

chrome.runtime.onMessage.addListener((req, sender, sendRes) => {
  console.log('this has worked', req, sender, sendRes('this worked'));
  return true;
});

Here is my inject.js file that injects the injected.js (see below) code:

const s = document.createElement('script');
s.src = chrome.runtime.getURL('injected.js');
s.onload = function () {
  this.remove();
};
(document.head || document.documentElement).appendChild(s);

injected.js:

console.log('fetch interceptor started');
const { fetch: origFetch } = window;
chrome.runtime.sendMessage({ works: 'This worked at least' }, (res) => console.log(res)); // Error is thrown immediately
window.fetch = async (...args) => {
  const response = await origFetch(...args);

  const url = new URL(args[0].url);
  //   sendMessageToBackground({ pathname, ...url.searchParams }); // not in use because it throws error at the top already
  response
    .clone()
    .json()
    .then(async (body) => await sendMessageToBackground({ pathname, body }))
    .catch((err) => console.error(err));

  return response;
};

async function sendMessageToBackground(msg) {
  const res = await chrome.runtime.sendMessage(msg);
  console.log('result message', res);
  console.log('msg', msg);
}

manifest.json in case required:

{
...
"permissions": ["storage", "activeTab", "scripting", "webRequest"],
  "host_permissions": ["https://REDACTED.com/*"],
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["https://REDACTED.com/*"],
      "run_at": "document_start",
      "js": ["inject.js"]
    }
  ],
  "web_accessible_resources": [{ "resources": ["injected.js"], "matches": ["https://REDACTED.com/*"] }],
...
}

How to set number of tag dynamically where number of tag is fixed?

I have a table looks like below:

<table border="1">
<tr bgcolor=#0D9381>
<th rowspan=2><center>Characteristics</center></th>
<th rowspan=2><center>Spec.</center></th>
<th colspan=<%=gcaqa.getX2() %>><center>Observed<br>Value</center></th>
<th rowspan=2><center>Date of<br>Analysis</center></th>
</tr>
<%
if(vaqm!=null && vaqm.size()>0){
    for(class_div h11:vaqm){
%>
<tr bgcolor=#02321D>
<td><center><%=h11.getCharacteristics() %></center></td>
<td><center><%=h11.getSpec() %></center></td>
<td><center><%=h11.getObservedValue1() %></center></td>
<td><center><%=h11.getObservedValue2() %></center></td>
<td><center><%=h11.getObservedValue3() %></center></td>
<td><center><%=h11.getDateofAnalysis() %></center></td>
</tr>
<%
    }
}
%>
</table>

But here I want to show only <%=gcaqa.getX2() %> number of Observed Value out of <%=h11.getObservedValue1() %>, <%=h11.getObservedValue2() %> and <%=h11.getObservedValue3() %>
that is out of 3rd, 4th and 5th td tag I want to display only <%=gcaqa.getX2() %> number of td tag.

I made it sure that number of observed value is less than or equals to <%=gcaqa.getX2() %>.

Please someone give any clue. Because there is no clue in the internet. In my case <%=gcaqa.getX2() %> is 2. So, to be very clear. I want to show only two td tag containing observed value out of 3.

Why history listen is not updating my component’s state?

TLDR: I am building a React router app, I trying to update the state of my component through a history listener, this listener works fine I put a console.log and I can see it, but the state of my component is not changing, I can see this with the React chrome extension and my component is not updating.

`

import React from "react";
import { withRouter } from "react-router-dom";
import { styles } from './Styles';
import { url } from './App';


class Searchresults extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            searchResults : []
        }

    }

    async fetchResults(endpoint) {
        try {
            const response = await fetch(endpoint);
            if (response.ok) {
                const rJson = await response.json();
                return rJson;
            }
        } catch (err) {
            console.log(err);
        }
    }

    componentDidMount() {
        this.searchUpdate();
        this.unlisten = this.props.history.listen((location, action) => {
            console.log("it works!");
            this.searchUpdate();
        })
    }

    searchUpdate = () => {
        const { location } = this.props;
        const params = new URLSearchParams(location);
        const query = params.get("search");
        const name = query.replace("?name", "s");
        const endpoint = url + "&" + name;
        this.fetchResults(endpoint).then(response => {
            return  response['Search'].map(item => {
                return { title: item['Title'], poster: item['Poster'], id: item['imdbID'] }
            })
        }).then(response => {
            this.setState({
                searchResults : response
            })
        });
    }
    render() {
        return (
            <div style={styles.movieList}>
                <ul>
                    {
                       !this.state.searchResults? 'Loading' : this.state.searchResults.map((item, index) => {
                            return (<li key={index}>
                                <a href={'/moviepage?id=' + item.id}>{item.title}</a><br />
                                <img src={item.poster} alt="Movie poster"
                                    style={{ width: "6rem", height: "auto" }} />
                            </li>)
                        })
                    }
                </ul>
            </div>
        );
    }
}

export default withRouter(Searchresults);

`

I am trying to update the state with a method searchUpdate, then this method is called in componentDidMount, here works fine, then when the URL changes, the history.listen triggers and searchUpdate is fired again, and everything seems to work except the change of the state of my component.

Translating code from JS to C#. I don’t understand what this function does

`

    const yandexRequests = (function() {
      var protoRequest = new protobuf.Type("VideoTranslationRequest").add(new protobuf.Field("url", 3, "string")).add(new protobuf.Field("deviceId", 4, "string")).add(new protobuf.Field("unknown0", 5, "int32")).add(new protobuf.Field("unknown1", 6, "fixed64")).add(new protobuf.Field("unknown2", 7, "int32")).add(new protobuf.Field("language", 8, "string")).add(new protobuf.Field("unknown3", 9, "int32")).add(new protobuf.Field("unknown4", 10, "int32"));
      var protoResponse = new protobuf.Type("VideoTranslationResponse").add(new protobuf.Field("url", 1, "string")).add(new protobuf.Field("status", 4, "int32"));
      new protobuf.Root().define("yandex").add(protoRequest).add(protoResponse);
      return {
          encodeRequest: function(url, deviceId, unknown1) {
              return protoRequest.encode({url: url, deviceId: deviceId, unknown0: 1, unknown1: unknown1, unknown2: 1, language: "en", unknown3: 0, unknown4: 0}).finish();
          },
          decodeResponse: function(response) {
              return protoResponse.decode(new Uint8Array(response));
          }
      };
  })();

var body = yandexRequests.encodeRequest(url, deviceId, unknown1);
`

I don’t understand what this function does.

Transition property not working in this senario , here i am given max-height 0 to main-div and dropdown max-height 150px some transition

this is a css part here i am applying the transition to main-div class but it’s not working properly

ul {
  list-style: none;
}

.main-div {
  max-height: 0;
  overflow-y: hidden;
  background-color: skyblue;
  transition: height 0.1s linear;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}

.dropdown-open {
  max-height: 150px;
  border: 1px solid red;
}
import { useState } from "react";
import "./styles.css";

export default function App() {
  const [show, setShow] = useState(false);
  return (
    <div className="App">
      <button onClick={() => setshow(!show)}>dropdown</button>
      {show ? (
        <div className={`main-div ${show && "dropdown-open"}`}>
          <div>static data</div>
          <ul>
            <li>list 1</li>
            <li>list 2</li>
            <li>list 3</li>
            <li>list 4</li>
            <li>list 5</li>
          </ul>
        </div>
      ) : (
        ""
      )}
    </div>
  );
}

Here i am trying to apply transition to the main-div whenever use click on the button main-div takes max height so in my case transition not taking

interaction of a chrome extension based on React TSX UI chrome API

I’m attempting to build some extension which contains a form and an option to capture screen with desktopCapture, which looks like this:

enter image description here

The form is written in React TypeScript and the code for capturing the screen (taken from here) is the following:

chrome.runtime.onMessage.addListener(
  (message, sender, senderResponse) => {
    if (message.name === "stream" && message.streamId) {
      let track, canvas;
      navigator.mediaDevices
        .getUserMedia({
          video: {
            mandatory: {
              chromeMediaSource: "desktop",
              chromeMediaSourceId: message.streamId,
            },
          },
        })
        .then((stream) => {
          track = stream.getVideoTracks()[0];
          const imageCapture = new ImageCapture(track);
          return imageCapture.grabFrame();
        })
        .then((bitmap) => {
          track.stop();
          canvas = document.createElement("canvas");
          canvas.width = bitmap.width;
          canvas.height = bitmap.height;
          let context = canvas.getContext("2d");
          context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
          return canvas
            .toDataURL()
            .then((url) => {
              //TODO download the image from the URL
              chrome.runtime.sendMessage(
                { name: "download", url },
                (response) => {
                  if (response.success) {
                    alert("Screenshot saved");
                  } else {
                    alert("Could not save screenshot");
                  }
                  canvas.remove();
                  senderResponse({ success: true });
                }
              );
            })
            .catch((err) => {
              alert("Could not take screenshot");
              senderResponse({ success: false, message: err });
            });
        });
    }
    return true;
  }
);

My intention is that when the user will click on “take screen shot”, the code above will run, and then, on save, the image will be presented in that box.

I was able to ‘grab’ the two elements, both the box where I wish the image to appear after screenshooting, and the “TAKE SCREEN SHOT” button.

as far as I’m aware of, content_script only injects into web-pages (browser), and has no access to extension, therefor, that’s not the way to add the code inside..

What am I missing? How could I add an eventListener, that if the button is clicked, the screenCapturing code will run, and I’ll be able to set the box to be the captured image?

Best regards!

Make elements visible based on radio check value not working

I’m creating an RSVP form where if a user selects that they are attending, only then would the dietary options be presented.

I’m creating these options dynamically via php. For example, if there are 4 invites sent out in an RSVP, 4 options will exist for each user, i.e

Name 1

 - Are you attending the wedding? Yes / No
 - Dietary requirements Veg / Non veg

Name 2 

 - Are you attending the wedding? Yes / No
 - Dietary requirements Veg / Non veg

etc ...

The dietary options are hidden by default (as I only want them appearing if they select yes to attendance). As such, if a user clicks “yes”, then I’m trying to make that element visible.

With my approach below, the dietary options do not show if “yes” is checked. I thought this may be because my fields are being generated dynamically, so I also experimented with a on change function, but it yielded the same results.

(function ($) {

  // loop through elements with same class and check if checked
  $(".member__attendance-input").each(function(i, obj) {
    var $this = $(this);
    console.log(obj);
    if( $this.is(':checked')) {
      console.log("it's checked");
      // make .member__dietary visible for that member
      $this.parent(".member").addClass("show-dietary-options");
    }
  });

}) (jQuery);


// $("document").on("change", ".member__attendance-input", function(){
//   if($(this).checked){
//     console.log("it's checked");
//   }
// });
.rsvp{
  padding: 60px 0;
}

form{
  padding: 40px;
  border: 1px solid #000000;
}

.input-label{
  margin: 0 20px 0 0;
}

.member{
  margin-bottom: 30px;
}

.member__name{
  display: block;
  margin-bottom: 15px;
}

.member__options{
  margin-bottom: 20px;
}

.member__dietary{
  opacity: 0;
  height: 0;
}

.show-dietary-options .member__dietary{
  opacity:1;
  height: auto;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div class="rsvp">
  <div class="container">
    <div class="row">
      <div class="col-12">
        <form>

          <!-- member 1 -->
          <div class="member d-flex flex-column">
            <span class="member__name">Name 1</span>
            <div class="member__attendance member__options d-flex">
              <div class="member__attendance-option">
                <input class="member__attendance-input" id="attending-yes-0" type="radio" name="attending-0" value="yes" required />
                <label class="input-label" for="attending-yes-0">Yes</label>
              </div>
              <div class="member__attendance-option">
                <input class="member__attendance-input" id="attending-no-0" type="radio" name="attending-0" value="no" required />
                <label class="input-label" for="attending-no-0">No</label>
              </div>
            </div>
            <div class="member__dietary member__dietary--0 member__options d-flex">
              <div class="member__dietary-option">
                <input id="diet-veg-0" type="radio" name="diet-0" value="veg" required />
                <label for="diet-veg-0" class="input-label">Vegetarian / Vegan</label>
              </div>
              <div class="member__dietary-option">
                <input id="diet-nonveg-0" type="radio" name="diet-0" value="nonveg" required />
                <label for="diet-nonveg-0" class="input-label">Non-vegetarian</label>
              </div>
            </div>
          </div>

          <!-- member 2 -->
          <div class="member d-flex flex-column">
            <span class="member__name">Name 2</span>
            <div class="member__attendance member__options d-flex">
              <div class="member__attendance-option">
                <input class="member__attendance-input" id="attending-yes-1" type="radio" name="attending-1" value="yes" required />
                <label class="input-label" for="attending-yes-1">Yes</label>
              </div>
              <div class="member__attendance-option">
                <input class="member__attendance-input" id="attending-no-1" type="radio" name="attending-1" value="no" required />
                <label class="input-label" for="attending-no-1">No</label>
              </div>
            </div>
            <div class="member__dietary member__dietary--1 member__options d-flex">
              <div class="member__dietary-option">
                <input id="diet-veg-1" type="radio" name="diet-1" value="veg" required />
                <label for="diet-veg-1" class="input-label">Vegetarian / Vegan</label>
              </div>
              <div class="member__dietary-option">
                <input id="diet-nonveg-1" type="radio" name="diet-1" value="nonveg" required />
                <label for="diet-nonveg-1" class="input-label">Non-vegetarian</label>
              </div>
            </div>
          </div>

        </form>
      </div>
    </div>
  </div>
</div>

If it helps, here is the PHP snippet in which these fields are generated dynamically based on the number of people in the database.

<?php foreach ($party_members as $index=>$member){ ?>

<div class="member d-flex flex-column">
  <span class="member__name"><?php echo $member; ?></span>

  <div class="member__attendance member__options d-flex">
    <div class="member__attendance-option">
      <input class="member__attendance-input" id="attending-yes-<?php echo $index; ?>" type="radio" name="attending-<?php echo $index; ?>" value="yes" required/>
      <label class="input-label side-label" for="attending-yes-<?php echo $index; ?>">Yes</label>
    </div>
    <div class="member__attendance-option">
      <input class="member__attendance-input" id="attending-no-<?php echo $index; ?>" type="radio" name="attending-<?php echo $index; ?>" value="no" required/>
      <label class="input-label side-label" for="attending-no-<?php echo $index; ?>">No</label>
    </div>
  </div>

  <div class="member__dietary member__dietary--<?php echo $index; ?> member__options d-flex">
    <div class="member__dietary-option">
      <input id="diet-veg-<?php echo $index; ?>" type="radio" name="diet-<?php echo $index; ?>" value="veg" required/>
      <label for="diet-veg-<?php echo $index; ?>" class="input-label side-label">Vegetarian / Vegan</label>
    </div>
    <div class="member__dietary-option">
      <input id="diet-nonveg-<?php echo $index; ?>" type="radio" name="diet-<?php echo $index; ?>" value="nonveg" required/>
      <label for="diet-nonveg-<?php echo $index; ?>" class="input-label side-label">Non-vegetarian</label>
    </div>
  </div>

</div>

<?php }

How can I show the dietary options only when that user selects “yes” to attendance?

Using Generators with TypeScript and ES5

I’m trying to write a small package which I will publish in NPM. I wrote it in JS and now I’m trying to convert it to TypeScript. I’m really new to publishing packages in NPM (this will be my first package) so I’m not sure what would be the right way – should I support ES5/ES6? How the configuration file should look like?

My current tsconfig.json looks like:

{
  "compilerOptions": {
    "target": "ES5",
    "moduleResolution": "node",
    "experimentalDecorators": true ,
    "emitDecoratorMetadata": true,
    "types": [
      "node"
    ]
  }
}

In my JS code I have:

for (const [index, node] of this.get_nodes()) {
  if (!(callbackFn(node.value, index, this))) {
    return false;
  }
}

Which I get the following error:

src/List.ts:105:33 - error TS2802: Type 'Generator<any[], void, unknown>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.                                                                                                 
105     for (const [index, node] of this.get_nodes()) {

The get_nodes method returns a generator:

* get_nodes() {
  var node = this.head;
  var counter = 0;
  while (node) {
    yield [counter, node];
    node = node.next_node;
    counter = counter + 1;
  }
}

I believe that generators are not supported in ES5. But then I see that Babel and TypeScript do provide an option to compile it to that.

So a few questions:

  • Due to my lack in experience with TypeScript, which configurations should I use to support most of the NPM users? What’s the default?
  • I guess I have a configuration problem – how should I solve the problem with the generators?

How can i arrange this 2D array diagonally while decrease numbers vertically?

The goal is to get something like this

[1, 3, 6, 0, 0, 0, 0, 0, 0, 0]
[0, 2, 5, 9, 0, 0, 0, 0, 0, 0]
[0, 0, 4, 8, 12, 0, 0, 0, 0, 0]
[0, 0, 0, 7, 11, 15, 0, 0, 0, 0]
[0, 0, 0, 0, 10, 14, 18, 0, 0, 0]
[0, 0, 0, 0, 0, 13, 17, 21, 0, 0]
[0, 0, 0, 0, 0, 0, 16, 20, 24, 0]
[0, 0, 0, 0, 0, 0, 0, 19, 23, 27]
[0, 0, 0, 0, 0, 0, 0, 0, 22, 26]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 25]




import java.util.*;

public class Main {
    public static void main(String[] args) {
        int values[][] = new int [10][10];
        for (int[] row : values) {
            for (int col : row) {
                row[col] = 0;
            }
        }
       
        int n = 0;
        int k = 27;
        for (int j=9; j<=0; j--) {
            for (int i=7-n; i<=9-n; i++){
                n++;
                if (i >=0){
                    values[j][i] = k--;

                }
            }
        }
            for (int[] row : values) {
            System.out.println(Arrays.toString(row));
        }
    }
}

The code i worked out so far: just a bunch of zeros
i believe that am very close and that i am missing something small, would appreciate help!

console shows “cannot read properties of null (setting innerHTML)” error

I’m trying to create a quiz and console throws the “cannot read properties of null (setting innerHTML)” error and underlines userScoreTemplate on the last line. I’m not sure what to do because it worked perfectly fine before. Any help would be appreciated.

document.querySelector(".check").onclick = function () {
        /* Hide unneeded sections and showing scores */
        quiz.classList.add("hidden");
        correctAnswer.classList.remove("hidden");

        /*Showing all previous scores */
        const lastScore = localStorage.getItem("latestScore") || "";

        const scoreDetail = lastScore.split(',');

        scoreDetail.push(score);

        localStorage.setItem("latestScore", scoreDetail);

        let userScoreTemplate = `<h2>This Round's Score: ${score}</h2>`;

        scoreDetail.map((items, index) => {
            userScoreTemplate += `<h3>Score ${index}: ${items}</h3>`
        });

        let userScoreBoard = document.getElementById("user-score");

        userScoreBoard.innerHTML = userScoreTemplate;
    };

How to hash CSS module class names in Nextjs 13?

How can I edit/minify/hash/hide/obfuscate css class names in Next JS?

I tried many ways including this thread

Getting the following errors when trying this solution.

yarn build
yarn run v1.22.19
$ next build
warn  - You have enabled experimental feature (appDir) in next.config.js.
warn  - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
info  - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback

warn  - The @next/font/google font Inter has no selected subsets. Please specify subsets in the function call or in your next.config.js, otherwise no fonts will be preloaded. Read more: https://nextjs.org/docs/messages/google-fonts-missing-subsets
info  - Creating an optimized production build
Failed to compile.

HookWebpackError: Unexpected '/'. Escaping special characters with  may help.
    at makeWebpackError (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledwebpackbundle5.js:28:308185)   
    at C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledwebpackbundle5.js:28:105236
    at eval (eval at create (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledwebpackbundle5.js:13:28771), <anonymous>:44:1)
-- inner error --
Error: Unexpected '/'. Escaping special characters with  may help.
    at C:kvercelstaticcss9db6a345a2f242fe.css:1:817
    at Root._error (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:78465)   
    at Root.error (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:124360)   
    at Parser.error (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:86811)  
    at Parser.unexpected (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:87297)
    at Parser.combinator (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:85544)
    at new Parser (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:78322)    
    at Processor._root (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:95242)
    at Processor._runSync (C:[email protected]_m5sxuueb27gk6ddc5gums6vtgqnode_modulesnextdistcompiledcssnano-simpleindex.js:190:95749)


> Build failed because of webpack errors
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.