I am using this library for messaging.
I have my background script like this
import { sendUrlInfo, waitForUrl } from 'utils/messaging';
import URL from 'url-parse';
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
});
chrome.webNavigation.onCompleted.addListener((details) => {
if (details.url !== 'about:blank') {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
}
});
And according to documentation i have message.js as shown below
import { getMessage } from '@extend-chrome/messages';
import URL from 'url-parse';
const messageTypes = {
URL_INFO: 'URL_INFO',
};
export const [sendUrlInfo, urlStream, waitForUrl] = getMessage<URL>(
messageTypes.URL_INFO,
);
and now content script I have written in react So i am trying to subscribe to stream when the component is mounted
import React, { useState, useEffect, useRef } from 'react';
import Editor from 'content/components/Editor';
import Opener from 'content/components/Opener';
import { urlStream, waitForUrl } from 'utils/messaging';
const Main: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);
const [showContent, setShowContent] = useState(false);
const editorRef = useRef<HTMLTextAreaElement | null>(null);
useEffect(() => {
console.log('MOunted');
urlStream.subscribe(([url]) => {
console.log('Received', url.hostname, url.pathname);
if (url.hostname === 'www.youtube.com' && url.pathname === '/watch') {
if (!showContent) setShowContent(true);
} else {
if (showContent) setShowContent(false);
}
});
}, []);
useEffect(() => {
document.addEventListener('keydown', onKeyPress);
return () => {
document.removeEventListener('keydown', onKeyPress);
};
});
const onKeyPress = (e: KeyboardEvent) => {
if (e.ctrlKey && e.which === 192) {
e.preventDefault();
setIsOpen(!isOpen);
}
};
if (!showContent) return <></>;
return (
<>
<div>test</div>
<Opener isOpen={isOpen} onClick={() => setIsOpen(true)} />
<Editor
isOpen={isOpen}
ref={editorRef}
onClose={() => setIsOpen(false)}
/>
</>
);
};
export default Main;
The error I am getting in background script console is
Could not establish connection. Receiving end does not exist
I think as much as i understand the background script is trying to send msg but the content script observable is not subscribed yet. As content script run after the page is loaded. If this is the issue is there any way to use this library properly.
BTW this works if we use normal chrome api like this
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(
tabs[0].id,
message,
function () {
console.log("msg sent")
}
);
});
and use onMessage to receive the msg.
The background page needs to know that we're sending a message to a tab. Unless options.tabId
is defined, sendUrlInfo
sends a message using chrome.runtime.sendMessage
.
Add the options argument to sendUrlInfo
in the background script:
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
const options = { tabId: details.tabId }; // Add options.tabId here
sendUrlInfo(new URL(details.url), options);
});