Search code examples
reactjsgoogle-chrome-extension

Load image from project in react chrome extension


I am trying to build a react chrome extension. I started off with the simple project found here. In its structure, the popup is contained in Modal.js and I would like to include an image in it which is contained in the project. However, to access that I must use chrome.runtime.getURL("image_file.png"), which I cannot access in Modal.js, but only in content.js. How should I get the image properly to Modal.js?

This is all activated when the browser action button is pressed, which calls this function within content.js:

function main() {
  const extensionOrigin = 'chrome-extension://' + chrome.runtime.id
  if (!location.ancestorOrigins.contains(extensionOrigin)) {
    fetch(chrome.runtime.getURL('index.html'))
      .then((response) => response.text())
      .then((html) => {
        const styleStashHTML = html.replace(
          /\/static\//g,
          `${extensionOrigin}/static/`
        )
        $(styleStashHTML).appendTo('body')
      })
      .catch((error) => {
        console.warn(error)
      })
  }
}

The content of index.html is:

<div id="modal-window"></div>

but when the html is returned from the fetch it has expanded in the build to:

<div id="modal-window"></div><script src="/static/js/runtime-main.0d1674f1.js"></script><script src="/static/js/2.021a85b4.chunk.js"></script><script src="/static/js/main.d80831e3.chunk.js"></script>

It is unclear to me how index.js is getting called but it is, which finds the div in index.html and replaces it with the modal object as follows:

import React from 'react'
import ReactDOM from 'react-dom'
import Modal from './Components/Modal'

ReactDOM.render(<Modal />, document.getElementById('modal-window'))

My current implementation of modal.js is as follows. Obviously the img src won't work as it is right now (needing to use chrome.runtime.getURL):

import React from 'react'

const Modal = () => {
  return <img src="icon48.png" alt="icon48"></img>
}

export default Modal

How would I actually be able to get the image src from chrome.runtime.getURL?


Solution

  • Figured this out. I don't know if this is the best solution, but it is working for me.

    Since I need to access chrome.runtime.getURL I need to do that from the content script. But I need the value of that in my component which doesn't have access to the chrome api. So I message between them through window events. Here is some example code:

    ExampleComponent.js

    import React, { Component } from 'react'
    
    let imgSrc = 'file.png'
    
    // Note that this listener is outside the Component
    window.addEventListener('ToComponent', (msg) => {
      imgSrc = msg.detail
    })
    
    class ExampleComponent extends Component {
      constructor(props) {
        super(props)
    
        // Note that this is occurring inside the Component constructor
        var event = new CustomEvent('FromComponent')
        window.dispatchEvent(event)
    
        this.state = {
          imgSrc: imgSrc,
          // etc.
        }
      }
      render() {
        return (
          <img src={this.state.imgSrc} alt=""></img>
        )
      }
    }
    

    content.js:

    window.addEventListener('FromComponent', () => {
      const imgSrc = chrome.runtime.getURL('file.png')
    
      // Send response
      var event = new CustomEvent('ToComponent', { detail: imgSrc })
      window.dispatchEvent(event)
    })