Chrome Extension Execute Script - javascript

I'm writing a chrome extension and trying to execute a script on my page.
My manifest.json includes:
"permissions": ["tabs"],
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["js/jquery.js", "js/content.js"]
}
]
And on my content.js page I have:
chrome.tabs.executeScript( null, {code:"document.write('hello world')"},
function(results){ console.log(results); } );
According to google's documentation, passing a null parameter has it refer to the active tab and I can then pass the javascript as a json object, which I am. However... no result? Any advice? Ideally, I'd like to to change document.write to a window command to get the the user's highlighted text.

You must have permissions for injecting script in a webpage...
for example
"permissions": [ "http://stackoverflow.com/"]
If you like to inject in all web pages you should specify:
"permissions": [
"<all_urls>", ].

Related

How to use background.html in manifest v3 in chrome extension

I'm trying to use the library of ffmpeg.wasm to download m3u8 videos in the background.js but it shows the error
ffmpeg.js:1 Uncaught (in promise) ReferenceError: document is not defined
at ffmpeg.js:1
at ffmpeg.js:1
at f (ffmpeg.js:1)
at Generator._invoke (ffmpeg.js:1)
at Generator.next (ffmpeg.js:1)
at n (ffmpeg.js:1)
at c (ffmpeg.js:1)
at ffmpeg.js:1
at new Promise (<anonymous>)
at ffmpeg.js:1
After I checked the document, it suggested me to use jsdom or create a new tab or window.
Service workers do not have access to windows or the DOM. If your
extension needs that, you can use libraries like jsdom or use
chrome.windows.create and chrome.tabs.create. It depends on your usage
and what fits your needs.
This is also needed if your background scripts record audio or video,
as that is not possible in service workers.
However, the document did not actually teach me how to do. I tried to use chrome.windows.create and chrome.tabs.create but it is not what I want because it actually create a new window or tab explicitly.
Then, I tried to use jsdom. I installed it with NPM. After I imported the library, it showed the error
service worker registration failed
Here is my manifest.json:
{
"name": "vDonwloader",
"description": "Download HLS videos.",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"],
"run_at": "document_start"
}
],
"permissions": [
"webRequest",
"tabs"
],
"host_permissions":[
"<all_urls>"
]
}
Here is my background.js:
importScripts('ffmpeg.js');
const { createFFmpeg, fetchFile } = FFmpeg;
const downloadHlsListener = async (msg, sender, sendResponse) => {
if(msg.action === 'DOWNLOAD_HLS'){
//...Do something
}
}
chrome.runtime.onMessage.addListener(downloadHlsListener);
How can I solve this problem? I want to make a chrome extension to download .m3u8 videos with ffempeg library.

Chrome's content script not allowed to add EventListeners by default?

Just to make it clear I read multiple similar questions
1 2 3 4 5 etc
none of them are relevant to mine.
As I understood, WebAPI content scripts even if run in isolated environment still can manipulate page's DOM and add EventListeners, at least this is what Developer.Chrome and MDN says. However, I'm having a situation where it does not seems to be true.
Here is a sample extension:
manifest.json
{
"manifest_version": 2,
"name": "Foo",
"version": "0",
"permissions":
[
"storage",
"https://steamcommunity.com/*"
],
"content_scripts":
[ {
"matches": ["*://steamcommunity.com/groups/*"],
"js": ["content.js"],
"run_at": "document_idle",
"all_frames": true
} ]
}
content.js
'use strict';
const butArea = document.querySelector(".grouppage_join_area");
function queueGroup()
{
alert('yay!');
}
if (butArea)
{
butArea.addEventListener("click", queueGroup, false);
}
Load unpacked and go to https://steamcommunity.com/groups/SteamClientBeta. Click he button and no alert. Add the eventListener manually through console and it just werks. I tried click/onclick properties too but same result.
Yes, I can inject my code into the page, no an issue here, but I dont really want to because it should work as it is, no? Otherwise - why not, what I'm missing?

Inject scripts error: Script returned non-structured-clonable data on Firefox extension

I want to inject script from firefox web extension to tabId thought browser.tabs.executeScript API.
I have a file Browser.js
MyFunc.Browser = (function() {
var self;
function Browser() {
self = this;
}
Browser.getExtensionURI = function() {
return "chrome-extension://";
};
return Browser;
})();
And execute script function:
var executing = browser.tabs.executeScript(tabId, {
file: "js/contentscripts/Browser.js"
});
executing.then(function(results) {
console.log("url: " + tabUrl + ", result", results);
}, function(error) {
return console.log("Inject scripts error: " + error);
});
But script cannot inject to tab and show error.
How I can fix it?
Manifest file:
{
"name": "abc",
"background": {
"page": "background.html"
},
"browser_action": {
"default_icon": "icons/icon_19.png",
"default_popup": "login.html",
},
"content_scripts": [
{
"web_accessible_resources": [
"js/contentscripts/Browser.js",
],
"js": [
"js/contentscripts/ContentScript.js"
],
"matches": [
"file://*/*",
"http://*/*",
"https://*/*"
],
"run_at": "document_end",
"all_frames": true
},
{
"js": [
"js/contentscripts/Browser.js",
],
"matches": [
"file://*/*",
"http://*/*",
"https://*/*"
],
"run_at": "document_start",
"all_frames": true
}
],
"icons": {
"16": "icons/icon_16.png",
"19": "icons/icon_19.png"
},
"incognito": "spanning",
"permissions": [
"activeTab",
"tabs",
"http://*/*",
"https://*/*",
"<all_urls>"
],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"version": "1.1.16"
}
in "js/contentscripts/Browser.js" file, add "undefined;" to last line.
the value will return to result of "executing.then" first callback argument
reference:https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/executeScript#Return_value
I think I understand your issue now.
The return data of your executeScript has to be structured clonable.
In order to be considered structured clonable the data has to match one of these data types:
All primitive types - However not symbols
Boolean object
String object
Date
RegExp - The lastIndex field is not preserved.
Blob
File
FileList
ArrayBuffer
ArrayBufferView - This basically means all typed arrays like Int32Array etc.
ImageData
Array
Object - This just includes plain objects (e.g. from object literals)
Map
Set
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types
In your case the problem is that you are returning an object that has functions in it's properties. Thus it is non-structured-clonable, which explains your error.
According to MDN
The result of the script is the last evaluated statement,...
(Similarly to how a script bash function uses the last calculated result as its return result.)
That result must be one of the list of types in #Forivin's answer above. However, that is not a usual constraint on the last command in a script, so it catches a lot of people out, as seen by the many results when searching for the OP's error message.
Adding the string
"Browser.js END OF FILE"
to the end of your file Browser.js would (if that line was actually reached) safely set results to that string.
(Note: various handler and living objects in the script will continue computation, but the interpreter will have finished parsing the script, sequentially executing commands, and returned with that finally parsed line.)
In my case I got the error after refactoring the script left
window.onhashchange=winHashHandler;
as the last line. Simply placing a string on the line after that removed the error.
I got same error trying to inject code that only made a dynamic import
import(...)
added a .then(x=>null) and solved it
import(...).then(x=>null)
I tried putting "" or undefined in last line, but I'm using the bundler rollup and it kept removing everything a put, since it thought it didn't affect anything

JQuery 3.1 failing to grab DOM when used inside chrome content scripts

I am new to developing chrome extensions, though I understand the concept of content scripts and isolated worlds. I just can't grasp the actual issue.
I am aware there is a lot of posts in StackOverflow for Jquery not working in Content Scripts ( Chrome Extension ). Most do not seem to address why.
My Code as follows
Manifest.json
{
"manifest_version": 2,
"name": "TestExtension",
"description": "Chrome Extension",
"version": "1.0",
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html",
"default_title": "MyExtension"
},
"content_scripts":[{
"js":["js/lib/jquery-3.1.1.min.js","js/app/content.js"],
"matches":["<all_urls>","http://*/*","https://*/*"],
"run_at":"document_start"
}],
"content_security_policy": "script-src https://*.google.com 'unsafe-eval'; object-src 'self'",
"minimum_chrome_version":"22",
"web_accessible_resources" : [
"js/lib/jquery-3.1.1.min.js"
],
"permissions": [
"activeTab",
"http://*/*",
"https://*/*",
"unlimitedStorage",
"contextMenus",
"cookies",
"tabs",
"notifications",
"identity",
"*://*.google.com/*"
],
}
I am trying to grab some DOM content from gmail.
I have used content script matches pattern to all urls for test purposes.
And so is Content Security Policy (unsafe-eval) and Web_Accessible_Resources ( Trial and error stuff )
I have provided almost all the permissions to check whats causing the issue.
Content.js
console.log('I am Content Script');
var jq = $.noConflict();
if (typeof jq == 'undefined') {
console.log('JQuery Not Loaded');
}else{
console.log('JQuery Loaded');
}
jq(document).ready(function(){
console.log(document.getElementsByClassName("editable"));
console.log(jq("body").className);
});
Output:
The Content Script gets injected to the Page.
The Jquery is loaded. And I have used noConflict() to make sure i am not running into any internal script conflicts.
The Vanilla JS grabs the DOM element.
But the Jquery fails not grab anything. No error messages shown.
Question:
I am aware of the "chrome.runtime.sendMessage" and "chrome.runtime.onMessage" and its neccessity during messaging. But do i have to wrap the logic inside this onMessage ?
Also, I have seen some solutions using the script injection ( chrome.tabs.executeScript ) , But is it the only solution. I feel like i am missing something in manifest.json could someone point out if i have missed something ?
Thanks in advance.

Add JS Library to Chrome Extension

I am building a Chrome Extension and I am having trouble adding a JavaScript library to use in my content script.
I am trying to add the Mutation Summary Library. I put the 'mutation_summary.js' file into the extension's directory and I tried to add it by adding 'mutation_summary.js' to the 'manifest.json' file as shown below:
"content_scripts": [
{
"matches": ["http://soundcloud.com/*", "https://soundcloud.com/*"],
"js": ["content_script.js", "mutation_summary.js"]
}
An extension error is thrown when I add it. The errors says "Could not load javascript 'mutation_summary.js' for content script.
Am I adding the javascript library incorrectly?
Thanks
It works perfectly for me. I created an extension with a file called mutation_summary.js which contains console.log('FILE LOADED!'); and it shows up as soon as I load soundcloud.com, maybe you had a typo with the file name?
manifest.json:
{
"name": "Extension",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["http://soundcloud.com/*", "https://soundcloud.com/*"],
"js":["mutation_summary.js"]
}
]
}

Categories