tl; dr: I'm implementing a runtime listener in a content script, where I do a sendMessage to it from background.js. The problem is that, when doing this way, the callback of the function in background.js is never executed.
I have this function, which is executed by my service worker (background.js) which does a chrome.tabs.sendMessage to the content script of an active tab. This is the content script.
The problem is that the callback for sendMessage is never executed, even though if I do a console.log inside the content script, it shows up. There is no runtime.LastError either.
I have tried to manually do chrome.tabs.sendMessage(37, {color: "FOO"}, resp=>console.log) in the console of my extension. But the console always terminates whenever I do this.
My content script function is synchronous, and so there is no need to do return true;. Even if I add return true;, the problem is still there.
Related
I am writing a chrome extension, using a content script to inject some javascript code. As follows:
let actualCode = 'My Injected JS Code';
let script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
For the injected script, I would like to use some value stored in chrome.storage.sync. However, I found that the API is unaccessible to the injected script (storage.sync is undefined). The API is only accessible within the content script, but not for the injected script. Any ideas how I could access chrome.storage API for the injected script too?
PS: I've registered the storage API in manifest.json
PS: When I open the developer's console on chrome and type "chrome.storage", it returns undefined too. I think this might be a permission problem?
The inject way you used for the script, made it work in the web page environment, which doesn't have access to most of Chrome Extensions API.
However, there is an option to use Messages API which allows sending requests from a webpage to the extension by ID.
In this case, you also need to implement a listener in your background page, to answer such requests.
P.S. chrome.storage API also shouldn't be available from page console. You may want to debug it from your background page console or select a content script environment (if the extension has such):
you can use window.postMessage({type : "MESSAGE_NAME"}) in injected script to send "message" event. then use windows.addEventListner("message", callback) in content_script to listen on "message" event.
You can specify the type of message to which you want to listen in the callback function. for instance
in content_script.js
function func_callback(){
if (event.data.type && event.data.type === "MESSAGE_NAME") {
# Your code
}`enter code here`
}
windows.addEventListner("message", func_callback)
in injected_script.js
<button onClick={()=>window.postMessage({type : "MESSAGE_NAME"})}></button>
It seems like the IE11 keeps executing JavaScript after load abort by user. I have a valid and working requireJS configuration with lots of modules.
When I open my Site and press the abort button (or click on the logout button) IE11 aborts all requireJS related async requests but keeps executing the requireJS Code (I figured it out with Debug and Network Panel). That shows an error like:
{description: "Script erro...",
message: "Script erro...",
name: "Error",
originalError: Event {...},
requireModules: Array[1],
requireType: "scripterror"}
(Because the async request for main.js was aborted)
All other browsers seem to stop JS execution if the user aborts loading the page (which is the right behaviour). Is there a way to handle that behaviour with requireJS?
It appears that a message from content to background only begins firing after backgroundAction has been run at least once.
In the below code example, a click on browserAction turns the page red, and a click on the page body turns the page blue (via a message sent by the content script).
If I click the page body first, nothing happens. It only begins working after I've clicked browserAction once.
Why is this happening and how can I make it so the message listener fires without having browserAction run first?
Any help would be greatly appreciated!
content.js
$(function(){
$('body').on('click', function() {
// Send a message to background.js
chrome.runtime.sendMessage(true, function(response){
console.log(response);
});
});
});
background.js
// Make background red when browserAction is cliked
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.executeScript( {
code: 'document.body.style.backgroundColor="red"'
});
});
// Make background blue when any message is received
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse){
chrome.tabs.executeScript( {
code: 'document.body.style.backgroundColor="blue"'
});
return true;
})
As always in such cases use the debugger. The error I'm seeing here in the extension's background page console which can be opened on chrome://extensions page:
Unchecked runtime.lastError while running tabs.executeScript: Cannot access contents of url "...". Extension manifest must request permission to access this host.
When runtime.onMessage is executed after a message from the content script Chrome doesn't know that executeScript was initiated by a user action so the code is blocked.
As for browserAction.onClicked, it is always invoked on user's interaction so "permissions": ["activeTab"] is sufficient for the code executed in the eventjob context of the issued click. And it creates temporary permission to modify the active tab, see the documentation:
The following user gestures enable activeTab:
Executing a browser action
Executing a page action
Executing a context menu item
Executing a keyboard shortcut from the commands API
Accepting a suggestion from the omnibox API
Solution #1 (the best) would be to avoid injecting any code from the background script and do everything in the content script based on messages from the background script.
Solution #2 would be to add the required permission to manifest.json:
"permissions": ["activeTab", "<all_urls>"]
I have created one extension to test my website, which will open page and do some activity like set text, get text etc etc.
I have created one C# application and via websocket I will communicate with extension.
In my extension I have added listener as below,
document.addEventListener('DOMContentLoaded', function() {
websocket.send(""); // Send signal to C# to execute next command
});
so when I will open any website e.g www.google.com, it will fire above event and my next action will come to execute, but issue is while I open any website which will have alert box at the first stage of loading page, will never execute above listener e.g If I will open http://www.crowderassoc.com/javascript/alertbox.html, it will give you an alert message, till your click on OK, the page will be busy and so It will get stuck.
I am created automated script, in which I will place one MSAA command to click on that "OK" button, but my it just got hanged.
Is there any option that I can make it work in this situation?
Move code of DOMContentLoaded Listener
document.addEventListener('DOMContentLoaded', function() {
websocket.send(""); // Send signal to C# to execute next command
});
in Content Scripts to listener of tabs.onUpdated or any of webRequest, webNavigation Appropriate Listeners in Background Page.
In a Google Chrome extension I want to pass messages between a content script and a popup page. I also want a function in the content script to be fired when a signal to do this is sent by the popup page to the content script.
The section in Google Chrome Extensions developer docs for messages, states that messages can be passed "from your content script to an extension page, or vice versa" (quoted from http://code.google.com/chrome/extensions/messaging.html )
Does this mean that I can send/receive messages between the content script and the popup page? Because the usage I have seen is for communication between background page and content script.
Or do I have to set up a 3 - way message passing route-- viz.
content script <--> background page <--> popup page. And if this is the case, how do I set up messaging between background page <--> popup page?
And how do I fire a function in the content script, after sending signal to content script from the popup page? Does this also require background script to be present?
Content scripts can only send a message to the background page. If you want to send a message from a content script to a popup, you have to:
Send the message from the Content script to the background page.
chrome.runtime.sendMessage( ...message... , function() { /*response*/ });
Receive the message at the background.
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { ... });
Pass the message to the popup. To get a reference to the global window object of the popup, use chrome.extension.getViews. Note: Unlike most of the other chrome APIs, this method is synchronous:
var popupWindows = chrome.extension.getViews({type:'popup'});
if (popupWindows.length) { // A popup has been found
// details is the object from the onMessage event (see 2)
popupWindows[0].whatever(message, sendResponse);
}
In the popup, define the whatever method.
function whatever(message, sendResponse) {
// Do something, for example, sending the message back
sendResponse(message);
}
When sendResponse (4) is called, details.sendResponse (see 3) is called. This, in turn, calls function() { /*response*/ } from 1.
Note: chrome.runtime.sendMessage/onMessage is only supported in Chrome 26+. Use chrome.extension.sendMessage if you want to support older browsers as well.