adambullmer / vue-cli-plugin-browser-extension

Browser extension development plugin for vue-cli 3.0
GNU Lesser General Public License v3.0
427 stars 76 forks source link

How to communicate from background.js to popup #92

Open doutatsu opened 4 years ago

doutatsu commented 4 years ago

I am trying to figure out how to communicate between background script and the popup. I want to send a message from the background to popup, so that it can then write into a persisted store. I can't do it on the background, as it would be a different store to the one on the popup.

I've tried a simple communication on the background:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, _tab) => {
  if (changeInfo.url) {
    chrome.runtime.sendMessage({
      msg: 'url_changed',
      data: {
        newURL: changeInfo.url,
        newHost: (new URL(changeInfo.url)).hostname,
      },
    });
  }
});

And then I tried adding a message listener in both App.vue mounted as well as main.js, with no luck:

<script>
  import { mapGetters } from 'vuex';

  import Navbar from '@/components/NavBar.vue';

  export default {
    components: {
      Navbar,
    },
    data() {
      return {};
    },
    mounted() {
      chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        alert('hi')
        if (request.msg === 'url_changed') {
          alert('Hello');
          //  To do something
          // console.log(request.data.subject);
          // console.log(request.data.content);
        }
      });
    },
    computed: {
      ...mapGetters('user', [
        'signedIn',
      ]),
    },
  };
</script>
import Vue from 'vue';
import router from '@/router';
import store from '@/store';
import '@/components/_globals.js';

import App from './App.vue';

Vue.config.productionTip = false;

chrome.runtime.onMessage.addListener(
  (request, sender, sendResponse) => {
    console.log(sender.tab
      ? `from a content script:${sender.tab.url}`
      : 'from the extension');
    if (request.greeting == 'hello') sendResponse({ farewell: 'goodbye' });
  },
);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  render: (h) => h(App),
});

I do see an error on the extension: Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist., so I presume none of these listeners are being registered... 

I've been on this problem for the second day now, would really appreciate some help

adambullmer commented 4 years ago

So one problem with the popup receiving messages is that the popup doesn't exist when it is closed to receive that message. You'll probably need to use the background script to do most of your heavy lifting to track and store state, or potentially look into opening a new tab instead of leveraging the popup. Hope this helps.

I think in general you will send a message to the background script, and then receive a message back when done for the popup to update state. There are also other things you can do like updating the browser action icon so you can reflect state like logged out, or disabling the button on certain pages.

doutatsu commented 4 years ago

@adambullmer Thanks, I didn't realise that was the case and that makes total sense, why my messages don't get received. I guess I'll have to re-think the architecture then, to make this work. Thanks for explaining