unable to share my screen with my chrome extension - javascript

im trying to share my screen and record it but the problem its that when i choose the source of the stream, it doesnt start streaming, it only shows the window with the screen and window options to share but after selecting one, i checked that i get the ChromeMediaSource and the ChromeMediaSourceID but as i said, the dialog that says sharing wont appear and because of this i cant record anything.
This is an error i found debugging that is not logged into the console:
" at chrome-extension://mnoggiilghljimfhpghalhngdciecafi/background.js:16:31"
which is in "chrome.desktopCapture.chooseDesktopMedia" in the background file
this is my background file
background.js
chrome.runtime.onConnect.addListener( function( port ){
// listen for messages from the port
port.onMessage.addListener( function( message ){
// send back a "pending" answer on the port
port.postMessage( {
"answer": 1,
"state": "pending",
"requestId": message.requestId
} );
chrome.desktopCapture.chooseDesktopMedia(["screen", "window"], port.sender.tab, function( id ){
var response = {
"answer": 1,
"state": "completed",
"requestId": message.requestId,
"streamId": id || undefined
};
// send back a "completed" answer on the port
port.postMessage( response );
} );
} );
} );
this is the file that its loaded to the website using the extension
bridge.js
// open a port to communicate with background
var port = chrome.runtime.connect();
// create node
var node = document.createElement( 'div' );
// listen for messages from webpage and forward them to the background, through the previously opened port
window.addEventListener( 'message', function ( event ){
if ( event.source != window || !event.data ){
return;
}
// prevent to return answer to the background
if( event.data.answer ){
return;
}
port.postMessage( event.data );
} );
// listen for messages from background and forward them to the webpage
port.onMessage.addListener( function( data ){
window.postMessage( data, '*' );
} );
// insert tag into parent page
node.id = 'extension-screensharing-installed';
document.body.appendChild( node );
manifest.js
{
"name": "extension name",
"description": "This extension allows you to share your screen",
"version": "0.1",
"manifest_version": 2,
"minimum_chrome_version": "34",
"icons": {
"16": "img16.png",
"48": "img48.png",
"128": "img128.png"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [ {
"js": [ "bridge.js" ],
"matches": [
"https://*/tester"
]
} ],
"permissions": [
"desktopCapture",
"https://*/tester"
]
}
could it be something wrong in my code?
i dont fully understand the error found by debuging
thanks!
edit: added manifest.json file!

Developing a Chrome screen-sharing extension includes instructions and sample code on developing the extension wherein values for apiKey, sessionId and token were entered and OT.registerScreenSharingExtension() method was also used to register the screen-sharing extension.
// API key and generate a test session ID and token:
var apiKey = "<YOUR_API_KEY>";
var sessionId = "<YOUR_SESSION_ID>";
var token = "<YOUR_TOKEN>";
var session = OT.initSession(apiKey, sessionId);
session.connect(token, function(error) {
var publisher = OT.initPublisher('camera');
session.publish(publisher, function() {
screenshare();
});
});
session.on('streamCreated', function(event) {
session.subscribe(event.stream);
});
OT.registerScreenSharingExtension('chrome', '<YOUR_CHROME_EXTENSION_ID>', 2);
And for the recording part, you may check how they did it in Screensharing with WebRTC. Hope it helps!

Related

Chrome Extension: How to assign global value from onMessage local scope function

Basically what I am trying to do is send a message from the popup.js by grabbing values from the input fields, and onMessage in the content_script to assign those values from that local scope to the global scope. I can't manage to do it! I can close the whole code in the onMessage function, but then to get to next function of the code I have to keep clicking save on the chrome extension. If someone knows this way better than I do with chrome extensions and what not please review my code and guide me to progress. I have been on this for like a week and my head is about to expload!
I have tried enclosing all the code in the onMessage function in the content_script. I have tried flipping which .js files are sending the message and trying to send the input fields from the extension as a response. I have tried to exclude the sendMessage out of the .click DOM function. Reviewed Messaging API on Google Chrome Extension and im puzzled.
content.js file
chrome.runtime.onMessage.addListener (
function(request) {
item_name = request.name;
item_color = request.color;
item_category = request.category;
item_size = request.size;
console.log(item_name);
console.log(item_color);
console.log(item_category);
console.log(item_size);
});
var url = window.location.href;
var i;
var item_category;
var item_name;
var item_color;
var item_size;
console.log(item_name);
console.log(item_color);
console.log(item_category);
console.log(item_size);
popup.js file
document.getElementById("save_input").onclick = function() {
var item_name_save = document.getElementById("item_name_save").value;
var item_color_save = document.getElementById("item_color_save").value;
var item_category_save = document.getElementById("item_category_save").value;
var item_size_save = document.getElementById("item_size_save").value;
chrome.storage.sync.set({'item_name_save' : item_name_save}, function() {
console.log('Value is set to ' + item_name_save);
});
chrome.storage.sync.set({'item_color_save' : item_color_save}, function() {
console.log('Value is set to ' + item_color_save);
});
chrome.storage.sync.set({'item_category_save' : item_category_save}, function() {
console.log('Value is set to ' + item_category_save);
});
chrome.storage.sync.set({'item_size_save' : item_size_save}, function() {
console.log('Value is set to ' + item_size_save);
});
const msg = { name: item_name_save,
color: item_color_save,
category: item_category_save,
size: item_size_save
};
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, msg, function() {
});
});
location.reload();
// window.close();
}
manifest.json
{
"manifest_version": 2,
"name": "Supreme bot",
"description": "A bot for Supreme",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Supreme bot"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["bot-functionallity.js"]
}
],
"permissions": [
"activeTab",
"tabs",
"storage",
"tabs"
]
}
(When all code is in the onMessage function, works but not as intended)
The Incorrect Functionality
I basically want the content.js to NOT be all inside of the onMessage function because that doesn't work properly, and have it assign values in the global scope from the onMessage function. I just want that info to be sent 1 time from the popup.js to the content.js.
I just set the value with chrome.storage.sync.set and use chrome.storage.sync.get in the other file...

Autofilling input from chrome extension doesn't work

I'm trying my hand at a simple Chrome Extension, but I've hit a snag.
I'm trying to autofill a login form (username and password). (As backup in case the chrome autofill functionality is disabled)
I've managed to inject a script into the page and I can console.log the input I'm targeting. But it won't set the value.
Manifest.json
{
"manifest_version": 2,
"name": "Test Extension",
"description": "Test Extension",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "index.html"
},
"content_scripts": [
{
"matches": [ "*://*.domain.net/*" ],
"js": [ "autofill.js" ]
}
],
"permissions": [
"tabs",
"*://*.domain.net/*"
]
}
autofill.js
console.log( "Script properly injected into page" );
let usernameInput = document.querySelector( 'input[name="username"]' );
let passwordInput = document.querySelector( 'input[name="password"]' );
console.log( usernameInput );
usernameInput.value = "test";
What am I missing here?
Apparently, the issue was with the autofill functionality of Chrome. Setting the autocomplete attribute to off, false or new-password in case of the password didn't work for me. Chrome seems to ignore this.
Disabling Chrome Autofill
My solution was to add a small timeout before executing my code. It's far from ideal, but it works.
setTimeout( () => {
usernameInput.value = "username";
passwordInput.value = "password"
}, 500 );
The problem is almost certainly that you need to wait for the document loaded event. As it is, your script has finished before the elements are loaded on the page.
Make your autofill.js
console.log( "Script properly injected into page" );
document.addEventListener('DOMContentLoaded', function () {
let usernameInput = document.querySelector( 'input[name="username"]' );
let passwordInput = document.querySelector( 'input[name="password"]' );
console.log( usernameInput );
usernameInput.value = "test";
});

"Attempting to use a disconnected port object" while sending message from content to popup in Chrome extension

So, I need to pass messages from popup to content and vice versa. Currently here is what I am doing now, but this does not work how it's supposed to work:
manifest.json:
{
// Required
"manifest_version": 2,
"name": "Extension name",
"version": "0.1",
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"]
}
],
"browser_action" : {
"default_title" : "Extension name",
"default_popup" : "popup.html"
},
"permissions": [
"tabs",
"*://*/*",
"contextMenus"
]
}
popup.js
var port = "";
window.onload = function()
{
document.getElementById("captureImage").onclick = captureImage;
}
function captureImage(isBig = true)
{
chrome.tabs.query({'active': true}, function (tabs) {
port = chrome.tabs.connect(tabs[0].id, {name: "Besada"});
port.onMessage.addListener(function(msg) {
alert(msg.message);
});
port.postMessage({message: "getCoords"});
});
}
and content.js
chrome.runtime.onConnect.addListener(function(port){
port.onMessage.addListener(function(msg) {
});
port.postMessage({message: "hello!"}); // this message I receive
document.onmouseup = function(e) {
port.postMessage({message: "hello!"}); // this message produces an error
};
});
What I need is message to be sent when user releases the left mouse button. Here is what happens: when I am clicking a button in my popup.html, the alert with the text "Hello" shows, but when I am clicking anywhere in the page after that, I am getting an error: Uncaught Error: Attempting to use a disconnected port object
What am I doing wrong and how can I fix this?
My guess the port is disconnecting when popup closes when I click on page, but I'm not really sure about this.
The popup ceases to exist as a document when you click elsewhere. It's like a tab that has closed. As such, there's no longer anything to communicate to.
The proper way to fix it is to communicate with the background page instead, or use the non-volatile chrome.storage. Then, when the popup is opened, you can use either information source to show content.

Chrome App Popup On Notification

I'm new to Chrome Apps, however I did successfully get my app to work with GCM. I'm so happy! What I would like the app to do however, is open a popup window when the user gets a notification. I'm making it a video chat app. Please Any Help at all would be greatly appreciated! This code that I have is currently not working for popups, tabs or anything of the sort... :(
background.js
// Returns a new notification ID used in the notification.
function getNotificationId() {
var id = Math.floor(Math.random() * 9007199254740992) + 1;
return id.toString();
}
function messageReceived(message) {
// A message is an object with a data property that
// consists of key-value pairs.
// Concatenate all key-value pairs to form a display string.
var messageString = "";
for (var key in message.data) {
if (messageString != "")
messageString += ", "
messageString += key + ":" + message.data[key];
}
console.log("Message received: " + messageString);
// Pop up a notification to show the GCM message.
chrome.notifications.create(getNotificationId(), {
title: 'GCM Message',
iconUrl: 'gcm_128.png',
type: 'basic',
message: messageString
}, function() {});
chrome.tabs.create({url:"http://www.google.com"});
}
var registerWindowCreated = false;
function firstTimeRegistration() {
chrome.storage.local.get("registered", function(result) {
// If already registered, bail out.
if (result["registered"])
return;
registerWindowCreated = true;
chrome.app.window.create(
"register.html",
{ width: 500,
height: 400,
frame: 'chrome'
},
function(appWin) {}
);
});
}
// Set up a listener for GCM message event.
chrome.gcm.onMessage.addListener(messageReceived);
// Set up listeners to trigger the first time registration.
chrome.runtime.onInstalled.addListener(firstTimeRegistration);
chrome.runtime.onStartup.addListener(firstTimeRegistration);
Manifest.json
{
"name": "GCM Notifications",
"description": "Chrome platform app.",
"manifest_version": 2,
"version": "0.3",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": ["gcm", "storage", "notifications", "tabs", "<all_urls>"],
"icons": { "128": "gcm_128.png" }
}
chrome.notifications.create should appear outside the browser. I can't see anything wrong with the call you made, though. We need to determine if you're not breaking the Content Security Policy
In Chrome Apps, due to a strict Content Security Policy these URLs must point to a local resource or use a blob or data URL. Use a 3:2 ratio for your image; otherwise a black border frames the image.
Additional references you can look at is the official notification sample repo as well as how to integrate notification with GCM.

Google Chrome - Screen capture failing when iframe is used, same script works without iframe

When i use this following script it works with normal browser. But when iframe is used then its showing me this error:
Does anyone know what is causing this and can be resolved?
ERROR:
channel message Object {type: "getScreenPending", id: 24504, request: 6} content.js:4
channel message Object {type: "gotScreen", id: 24504, request: 6} content.js:4
>>> ShareScreen: if any err NavigatorUserMediaError {constraintName: "", message: "", name: "InvalidStateError"} test.js:1616
manifest.json:
{
"name": "Screen sharing",
"description": "Screensharing utility",
"version": "0.0.2",
"manifest_version": 2,
"minimum_chrome_version": "34",
"icons": {
"48" : "icon.png"
},
"permissions": [
"desktopCapture"
],
"background": {
"scripts": ["background.js"]
},
"content_scripts": [ {
"js": [ "content.js" ],
"all_frames": true,
"run_at": "document_start",
"matches": ["*://*.a.com/*", "*://*.b.com/*"]
}],
"web_accessible_resources": [
"icon.png"
]
}
background.js:
/* background page, responsible for actually choosing media */
chrome.runtime.onConnect.addListener(function (channel) {
channel.onMessage.addListener(function (message) {
switch(message.type) {
case 'getScreen':
var pending = chrome.desktopCapture.chooseDesktopMedia(message.options || ['screen', 'window'],
channel.sender.tab, function (streamid) {
// communicate this string to the app so it can call getUserMedia with it
message.type = 'gotScreen';
message.sourceId = streamid;
channel.postMessage(message);
});
// let the app know that it can cancel the timeout
message.type = 'getScreenPending';
message.request = pending;
channel.postMessage(message);
break;
case 'cancelGetScreen':
chrome.desktopCapture.cancelChooseDesktopMedia(message.request);
message.type = 'canceledGetScreen';
channel.postMessage(message);
break;
}
});
});
content.js:
/* the chrome content script which can listen to the page dom events */
var channel = chrome.runtime.connect();
channel.onMessage.addListener(function (message) {
console.log('channel message', message);
window.postMessage(message, '*');
});
window.addEventListener('message', function (event) {
if (event.source != window)
return;
if (!event.data && (event.data.type == 'getScreen' || event.data.type == 'cancelGetScreen'))
return;
channel.postMessage(event.data);
});
This is caused by the fact that the a stream can only be used by frames whose URL match the origin of the tab. Starting with Chrome 40, you can use the stream in frames as well if you set tab.url to a URL whose origin matches the frame (crbug.com/425344).
The stream is only valid for ten seconds, so you have to follow the following flow:
Load the iframe that contains the page that should handle the stream. This page must be served from a secure scheme, e.g. https: or chrome-extension:.
Send the frame's origin (location.origin) to the background page.
Request the desktop stream using the tab info, with tab.url set to the frame's URL or origin.
Send the streamId back to the frame and use it (within ten seconds).
Example (based on the code in the question):
var tab = channel.sender.tab;
// NEW (Chrome 40+)
tab.url = message.url; // Your custom message, e.g. {url: location.origin}
chrome.desktopCapture.chooseDesktopMedia(['screen', 'window'], tab,
function (streamid) {
// ... see question for the rest of the code
});
1 - this is not a code problem, browser problem
2 - this is not working because i am launching the extension from HTTP (http://www.maindomain.com) using iframe a HTTPS (https://subdomain.maindomain.com) link which is using the browser extension
So to fix it. I needed to use HTTPS (https://www.maindomain.com) opening HTTPS iframe links (https://subdomain.maindomain.com) . Since then it works now.
Hope this help others.
NOTE: problem occurred: when i run the iframe from same subdomain subdomain.maindomain.com/test.php (iframe src=subdomain.maindomain.com/core.php) then it works. But when i am running it as maindomain.com/otherpages (iframe src=subdomain.maindomain.com/core.php) then this is not working. Was very confusing.
EDIT: This still did not resolved the problem. screen share dialog box opens but when i press share screen then it gives same error and fails.

Categories

Resources