I am creating a chrome extension that autofills forms on a webpage. Similar to this post I am running into the following error:
Error handling response: Error: Blocked a frame with origin "<URL_OF_WEBSITE>" from accessing a cross-origin frame.
at chrome-extension://lmhbdbgimlffldbbijpmbinppkeopclf/content.js:56:45
I have tried the suggested answer of using "all_frames": true as well as "match_origin_as_fallback": true but I still receive the same error message.
Any ideas of what may be going on would be appreciated as I know there are plenty of extensions that do perform these steps perfectly.
manifest.json
{
"name": "Extension Autofill",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "ext/popup.html",
"default_title": "Extension Autofill"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"all_frames": true,
"match_origin_as_fallback": true,
"js": ["content.js"]
}
],
"permissions": ["storage", "tabs", "activeTab", "declarativeContent"]
}
content.js - Attempt 1
let ifr = document.getElementsByTagName("iframe")[1];
if(ifr){
ifr.contentWindow.document.getElementById('name').value = "John Doe";
}
content.js - Attempt 2
function imitateKeyInput(el, keyChar) {
const keyboardEventInit = {
bubbles:false,
cancelable:false,
composed:false,
key:'',
code:'',
location:0
};
let keyDownEvent = new KeyboardEvent("keydown", keyboardEventInit);
el.dispatchEvent(keyDownEvent);
el.value = keyChar;
let keyUpEvent = new KeyboardEvent("keyup", keyboardEventInit);
el.dispatchEvent(keyUpEvent);
let inputChangeEvent = new Event('change', { bubbles: true });
el.dispatchEvent(inputChangeEvent);
}
const el = document.querySelector('#name');
if(el) {
el.focus();
imitateKeyInput(el, 'John Doe');
} else {
console.log("element NOT FOUND);
}
Javascript Context
Content script verified to be in target iFrame.
Tested on: Edge Version 109.0.1518.70 & Chrome Version 109.0.5414.120
Related
Answer Found
This extension is for google meet. What I have written in manifest.json is wrong, line "matches": ["*://*.meet.google.com/*"], should be "matches": ["*://meet.google.com/*"],
Original Question
I have this chrome extension, I want to let my contentScript.js to search for an element (tag) in a webpage when I press a button in popup.html. I set the sending message part in popup.js and the sending seems to work fine. But when I tried to receive it on the contentScript.js, console.log gives me Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
May someone please help me, any suggestions are welcome.
Code snippets:
popup.js
retrieveTabId();
function retrieveTabId() {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs) {
var activeTab = tabs[0];
console.log("tabID", activeTab.id);
tabId = activeTab.id;
});
}
document.getElementById("btn").addEventListener('click', function (){
chrome.tabs.sendMessage(tabId, {type: "listener"}, function(response) {
console.log((response.success));
});
console.log("tabID", tabId);
})
content-script.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.type == 'listener') {
try {
let textarea = document.getElementsByTagName('textarea');
if (textarea.length == 0) {
sendResponse({success: false});
}
else {
console.log('find node -- textarea' + textarea);
sendResponse({success: true});
}
}
catch (e){
console.log(e);
sendResponse({success: false});
}
}
}
);
manifest.json
{
"name": "name",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"permissions": ["storage", "activeTab", "scripting", "downloads", "notifications", "<all_urls>", "tabs"],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["*://*.meet.google.com/*"],
"js": ["contentScript.js"]
}]
}
I'm developing chrome extension for my coworkers and myself. The goal is to download single image by clicking a button at behance.net.
The problem is that some of my coworkers using "Ask where to save each file before downloading" option, so the code doesn't work for them. I don't use this option, so download is successfull for me.
I've tried to set different options for chrome.downloads.download(), but I got nothing. Save As dialog not showing.
Manifest
{
"name": "Begrab",
"description": "Download pics right from Behance",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"permissions": ["activeTab", "downloads","tabs", "background"],
"content_scripts": [
{
"matches": ["https://*.behance.net/*"],
"run_at": "document_end",
"css": ["content.css"],
"js": ["content.js"]
}
]}
content.js
window.setTimeout(()=> {
codeRun();
}, 1000)
let projectLinks = document.querySelectorAll('.ProjectCoverNeue-coverLink-102')
Array.from(projectLinks).forEach(projectLink => {
projectLink.addEventListener('click', function(){
window.setTimeout(()=> {
codeRun();
}, 4000)
})
})
function codeRun() {
let imageParents = document.querySelectorAll('.js-project-lightbox-link');
Array.from(imageParents).forEach(imageParent => {
let button = document.createElement('a'),
buttonCopy = document.createElement('a'),
buttonsWrap = document.createElement('div'),
img = imageParent.querySelector('img'),
controls = imageParent.querySelector('.project-module__actions');
if(img) {
button.innerText = "Download";
button.className = "begrab__btn";
buttonsWrap.className = "begrab__wrap";
buttonsWrap.appendChild(button);
imageParent.appendChild(buttonsWrap)
button.addEventListener('click', (e) => {
let param = {src: img.src,
fileName: window.location.href};
e.stopPropagation()
chrome.runtime.sendMessage(param);
});
}
});
}
background.js
chrome.runtime.onMessage.addListener(
function(arg, sender, sendResponse) {
if(arg.src){
chrome.downloads.download({
url: arg.src,
conflictAction: "prompt"
}, function (downloadId) {
console.log(downloadId);
});
}
});
Did anyone face the same problem? Hope that somebody would help me. Thanks!
After some debugging i found out that the user is canceling the download for some reason.
The onChanged event outputs the following:
{
"error": {
"current": "USER_CANCELED"
},
"id": 1,
"state": {
"current": "interrupted",
"previous": "in_progress"
}
}
The only way i was able to get it work was downgrading the manifest to v2:
{
"manifest_version": 2,
"background": {
"persistent": true,
"scripts": [
"background.js"
]
}
}
I don't know if this is an option for you.
I've been trying to make Firefox Extension which needs to have an ability for user to record a voice message.
I've made a web page which does work, but when I put the same code in the extension (with all the proper manifest.json changes), it doesn't work. It simply doesn't ask user for access to microphone.
I went through extension examples on Firefox site but I can't find the solution.
How can the extension, if it can, access users microphone?
Code:
window.addEventListener('load', initAudio);
And the initAudio function:
function initAudio() {
console.log("initAudio");
if (!navigator.getUserMedia)
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mediaDevices.mozGetUserMedia;
if (!navigator.cancelAnimationFrame)
navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
if (!navigator.requestAnimationFrame)
navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;
console.log("initAudio");
navigator.mediaDevices.getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}, gotStream, function (e) {
console.log('Error getting audio');
$("#controls").css("background", "red");
console.log(e);
});
}
I don't get console output
Error getting audio
But I also don't get the console output from gotStream function.
Later, I have an HTML object which triggers the recording process:
<img id="record" src="./res/icons/mic.png" class="">
with it's accompanying Javascript code:
$(document).ready(function () {
$("#record").click(function () {
console.log("trigerred", this);
toggleRecording(this);
});
});
function toggleRecording does get trigerred properly, but it can't work since Recorder object is not initalized (it gets initalized in gotStream function).
Here is the manifest.json file:
{
"manifest_version": 2,
"name": "Speech",
"version": "1.1",
"description": "blank desript",
"icons": {
"16": "popup/res/icons/icon16.png",
"32": "popup/res/icons/icon32.png",
"48": "popup/res/icons/icon48.png",
"128": "popup/res/icons/icon128.png"
},
"permissions": [
"storage"
],
"browser_action": {
"default_icon": {
"32": "popup/res/icons/icon.png"
},
"default_title": "Speech",
"default_popup": "popup/popup.html"
},
"content_scripts": [
{
"js": [
"popup/res/script/jquery-3.2.1.js",
"popup/res/script/audiodisplay.js",
"popup/res/script/recorder.js",
"popup/res/script/recorderWorker.js",
"popup/res/script/resampler.js",
"popup/res/script/main.js"
],
"matches": [ "<all_urls>" ],
"match_about_blank": true,
"all_frames": true
}
],
"content_security_policy": [
"script-src 'unsafe-inline'"
]
}
How can I access a Xively Feed through chrome extension. I am building a simple extension which will block websites depending on the value that is currently displayed on my Xively Feed. However I unsure on how to access the Xively feed without Html, I've looked at the XivelyJS library which I have used before but in a HTML page. However my extension needs to be independent of HTML.
Code Below is my attempt at using XivelyJS however I would be appreciative of an easier or better method.
Background.js:
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
return {cancel: true};
},
{urls: ["*://www.facebook.com/*", "*://www.twitter.com/*"]},
["blocking"]);
// Set your API key first
// Get feed content
xively.setKey( "APIKEY" );
function ReadData(){
var reading = xively.datastream.get ("832936337", "Reading", callback (data));
console.log(reading);
console.log(data);
setTimeout(ReadData,3000);
}
ReadData();
Manifest.json:
{
"manifest_version": 2,
"name": "SiteBlockerFyp",
"description": "Block Respective Sites",
"version": "1",
"permissions": [
"webRequest",
"webRequestBlocking",
"*://www.facebook.com/*","*://www.twitter.com/*"
],
"content_scripts": [
{
"matches": ["*://www.facebook.com/*"],
"js": ["jquery.min.js", "xivelyjs.min.js"]
}
],
"background": {"scripts": ["background.js"]}
}
Found that I could access the values like so :
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
return {cancel: true};
console.log(details.url);
},
{urls: ["*://www.twitter.com/*"]},
["blocking"]);
// Set your API key first
// Get feed content
xively.setKey( "APIKEY" );
console.log("XIVELY LOADED");
var feedID = 832936337, // Feed ID
datastreamID = "Reading"; // Datastream ID
data = "null"; // Your element on the page
dataUpdated= "null";
console.log("READ ");
xively.datastream.get (feedID, datastreamID, function ( datastream ) {
data = datastream["current_value"];
console.log(data);
xively.datastream.subscribe( feedID, datastreamID, function ( event , datastream_updated ) {
dataUpdated = datastream_updated["current_value"] ;
console.log(dataUpdated);
});
});
chrome.tabs.query({'active': true, 'windowId': chrome.windows.WINDOW_ID_CURRENT},
function(tabs){
console.log(tabs[0].url);
if (tabs[0].url == "*www.twitter.com*") {
alert("Twitter");
}
}
);
subscribing also gave me updates as they occurred. However using background.js as a background script in the manifest means it wont run across all pages so I still trying to figure this one out, Content-scripts is apparently the way to go.
{
"manifest_version": 2,
"name": "SiteBlockerFyp",
"description": "Block Respective Sites",
"version": "1",
"permissions": [
"webRequest",
"webRequestBlocking",
"*://www.twitter.com/*",
"tabs"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery.min.js", "xivelyjs.min.js", "background.js"]
}
]
}
I'd like to make a website that is not part of the chrome plugin but rather just uses some API that the plugin exposes to it. Is this possible and if so, how do I do it? I googled this question and was unable to find anything.
I'm trying to use content scripts but nothing happens. Can someone explain what's wrong here?
manifest.json
{
"manifest_version": 2,
"name": "Hello World Extension",
"description": "This extension prints hello world.",
"version": "1.0",
"background": {
"page": "background.html"
},
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://locahost:8888/*"],
"js": ["EmotivAPI.js"]
}
]
}
EmotivAPI.js
var port = chrome.runtime.connect();
console.log("Hello?");
window.addEventListener("message", function (event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
alert("recieved!");
}
}, false);
js in the webpage
window.sayHello = function () {
window.postMessage({ type: "FROM_PAGE", text: "Hello from webpage!" }, "*");
}
console.log('Emotiv extension loaded.');
}
I'm calling window.sayHello() from the console
Content Scripts can help you in this case.
The content script will be injected into a page:
"content_scripts": [
{
"matches": ["http://www.google.com/*"], // try with "http://localhost:*/*" or "http://localhost:*"
"css": ["mystyles.css"],
"js": ["content_script.js"]
}
]
If you want to inject the code only sometimes, use the permissions field instead
/* in manifest.json */
"permissions": [
"tabs", "http://*/*"
],
In you extension html file, you can then execute the script by:
chrome.tabs.executeScript(null, {file: "content_script.js"});