Just started on a test chrome extension, basically I want to change the link on right click and send to clipboard, see:
background.js
var convert_buylink = function(event){
var parser = document.createElement('a');
parser.href = event.linkUrl;
parser.hostname = 'cart.local.co.nz';
parser.protocol = 'http';
var link = document.createElement('input');
//link.value = parse.href;
link.value = 'abc';
link.focus();
link.select();
document.execCommand('SelectAll');
document.execCommand("Copy")
}
chrome.contextMenus.create({title: "Copy Local BuyLink", contexts:["link"], onclick: convert_buylink});
manifest.json
{
"manifest_version": 2,
"name": "Local Buylink",
"description": "Changes buylink to local cart",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"permissions": [
"contextMenus",
"tabs",
"clipboardWrite"
]
}
I have read about some results from google about the copy not working, all of them saying it doesn't work on content page, but according to documentation:
A background page will be generated by the extension system that includes each of the files listed in the scripts property.
You're creating the input inside a document object of the background page, which fails because the user gesture (context menu click) required for the copy command to work was performed in another document object: the web page. Also the element you create doesn't belong to document yet, it's a detached node.
Solution: create a hidden input inside the web page.
background.js:
function convert_buylink(info, tab) {
var parser = new URL(info.linkUrl);
parser.hostname = 'cart.local.co.nz';
parser.protocol = 'http';
clipboardCopy(parser.href);
}
function clipboardCopy(text) {
chrome.tabs.executeScript({code: "\
var input = document.createElement('input');\
input.value = '" + text.replace(/'/g, "\\'") + "';\
input.style.cssText = 'opacity:0; position:fixed';\
document.body.appendChild(input);\
input.focus();\
input.select();\
document.execCommand('Copy');\
input.remove();\
"});
}
manifest.json:
"permissions": [
..............
"activeTab"
],
Related
i have a problem, i made a chrome extension and opéra, but for Firefox, it's no working at all, my extension just block a list of urls i added to my background.js.
Can someone help me with the chrome conversion to firefox?
more details:
Im trying to convert my chrome extension to fireox, my chrome extension blocks a list of urls who are inside the background.js, im really stuck with firefox, i have tried to use the chrome version of my extension under firefox, it load the icon, the infos of the manifest.json, but the background.js dont work, the urls are not blocked
here i give you first my manifest.json code:
{
"name":"blocker",
"description":"block bad urls",
"version":"1.0",
"manifest_version":2,
"permissions": [
"http://*/*",
"https://*/*",
"webRequest",
"webRequestBlocking",
"<all_urls>" ,
"unlimitedStorage"
]
,"icons":{"48":"icon.png"},
"background":{
"scripts": ["background.js"]
},
"browser_action":{
"default_popup":"popup.html",
"default_icon":"icon.png"},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["disablef12.js"]
}
]
}
and here its my background.js
var AUTHORIZED_DOMAINS= {
"www.url01.com": false,
"url01.com": false,
"www.url02.com": false,
etc..
};
function extract_domain(url) {
var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
return matches[1];
}
chrome.webRequest.onBeforeRequest.addListener(function(details) {
var domain = extract_domain(details.url);
return { cancel: AUTHORIZED_DOMAINS[domain ]===false };
}, {urls: ["<all_urls>"]},["blocking"]);
thanks a lot again for your time and help
block urls:
full working example of how to block urls, bootstrap method:
https://github.com/Noitidart/PortableTester/tree/block-urls
download the xpi and drag it onto firefox, it blocks google and bbc.
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/Services.jsm');
var urls_block = [ //if urls ontain any of these elements they will be blocked or redirected, your choice based on code in observer line 17
'www.google.com',
'www.bbc.com'
];
var observers = {
'http-on-modify-request': {
observe: function (aSubject, aTopic, aData) {
console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
var requestUrl = httpChannel.URI.spec;
for (var i=0; i<urls_block.length; i++) {
if (requestUrl.indexOf(urls_block[i]) > -1) {
//httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this aborts the load
httpChannel.redirectTo(Services.io.newURI('data:text,url_blocked', null, null)); //can redirect with this line, if dont want to redirect and just block, then uncomment this line and comment out line above (line 17)
}
}
},
reg: function () {
Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
},
unreg: function () {
Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
}
}
};
function install() {}
function uninstall() {}
function startup() {
for (var o in observers) {
observers[o].reg();
}
}
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
for (var o in observers) {
observers[o].unreg();
}
}
if you want an icon just add to the xpi file which is just a zip file renamed to xpi. add a file called icon.png
see this basic bootstrap template here: https://gist.github.com/Noitidart/9025999
I am trying out chrome.desktopCapture.chooseDesktopMedia in a chrome extension and I can get a desktop stream just fine.
I am using the following to turn the stream into an blob:-URL in the background script as follows:
var objectUrl = URL.createObjectURL(stream);
What I can't seem to work out is how to set this as the src attribute of a video element on the injected page.
I have tried the following, each of which do not work:
In Background.js:
var video = document.getElementById("video");
var objectUrl = URL.createObjectURL(stream);
video.src = objectUrl;
In Content.js
//objectUrl is a string received in a message from the background page by the content page
var video = document.getElementById("video");
video.src = objectUrl;
I get the following in the javascript console:
Not allowed to load local resource: blob:chrome-extension://panahgiakgfjeioddhenaabbacfmkclm/48ff3e53-ff6a-4bee-a1dd-1b8844591a91
I also get the same if I post the URL in a message all the way to the injected page. Should this work? I'd really appreciate any advice here.
In my manifest I also have
"web_accessible_resources": [ "*" ] but that was only to see if it resolved this issue (it did not).
In a content script, the DOM is shared with the page, so any DOM operations (such as setting the video src) is subject to the same-origin policy of the page, not the extension.
If you want to show the content of a tab, then you MUST pass a tab.Tab object to chrome.desktopCapture.chooseDesktopMedia. This object can be obtained in many ways, including the message passing and tabs APIs. Here is an example using the extension button:
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
// NOTE: If you want to use the media stream in an iframe on an origin
// different from the top-level frame (e.g. http://example.com), set
// tab.url = 'http://example.com'; before calling chooseDesktopMedia!
// (setting tab.url only works in Chrome 40+)
chrome.desktopCapture.chooseDesktopMedia([
'screen', 'window'//, 'tab'
], tab, function(streamId) {
if (chrome.runtime.lastError) {
alert('Failed to get desktop media: ' +
chrome.runtime.lastError.message);
return;
}
// I am using inline code just to have a self-contained example.
// You can put the following code in a separate file and pass
// the stream ID to the extension via message passing if wanted.
var code = '(' + function(streamId) {
navigator.webkitGetUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: streamId
}
}
}, function onSuccess(stream) {
var url = URL.createObjectURL(stream);
var vid = document.createElement('video');
vid.src = url;
document.body.appendChild(vid);
}, function onError() {
alert('Failed to get user media.');
});
} + ')(' + JSON.stringify(streamId) + ')';
chrome.tabs.executeScript(tab.id, {
code: code
}, function() {
if (chrome.runtime.lastError) {
alert('Failed to execute script: ' +
chrome.runtime.lastError.message);
}
});
});
});
manifest.json
{
"name": "desktopCapture.chooseDesktopMedia for a tab",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_title": "Show desktop capture request"
},
"permissions": [
"desktopCapture",
"activeTab"
]
}
ObjectURLs can't be shared cross-origin. A Data URL can be shared cross-origin if it works with your video stream (I'm not sure).
i am creating a chrome extension
i created a diretory with
1.background.js 2.icon.png 3.icon2.png 4.manifest.json 5.myscript.js
my manifest.json code is
{
"manifest_version": 2,
"name": "One-click Kittens",
"description": "This extension demonstrates a browser action with kittens.",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"permissions": [ "storage"],
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["myscript.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
}
}
code for myscript.js which is content script is
document.body.innerHTML=''+document.body.innerHTML+'' ;
var iframe = document.getElementById("frame1");
function addingevent(){
chrome.extension.sendMessage({change: "icon"}, function(response) {
console.log(response.resp);
});
}
iframe.onload = function(){
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
if(iframeDocument != null)
{var bb=iframeDocument.getElementById('mybutton');
if(bb != null)
{
bb.addEventListener("click",addingevent,false)
alert("Hello World");
}}
}
and the code for background.js is
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
console.log("from a content script:from the extension");
chrome.storage.local.get("icon",function(val){
if(val.icon == "icon1")
{chrome.browserAction.setIcon({"path" :"icon2.png"},function(){});
chrome.storage.local.set({"icon":"icon"},function(){});
}
else
{chrome.browserAction.setIcon({"path" :"icon.png"},function(){});
chrome.storage.local.set({"icon":"icon1"},function(){});
}
});
sendResponse({resp: "success"});
});
objective of this extension is when user click on the button which is in the frame loaded from url http://onemoredemo.appspot.com/ icon should be toggled between icon.png and icon2.png
this extension works perfectly when i load it in webpage with url http://onemoredemo.appspot.com/ there is frame created and when i click button it is changing icon but when i open url stackoverflow.com then frame is created and showing a button in it,but when i click on the button icon remains same i am expecting that icon will be changed irrespective of url why its not changing in other url??please specify the reason
There are multiple issues
Do you expect a DOM Element with id frame1 to exist on http://stackoverflow.com
document.getElementById("frame1");
What is significance of document.body.innerHTML=''+document.body.innerHTML+'';?
I want to create an addon for chrome. When clicked it should redirect the tab with a modified URL.
I am using this in a background page in a manifest:
<script type="text/javascript" language="JavaScript">
chrome.tabs.getCurrent(function (tab) {
var tabUrl = encodeURIComponent(tab.url);
var tabTitle = encodeURIComponent(tab.title);
chrome.tabs.update(tab.id, {url: "http://xyz.com/surf/browse.php?u=" + tabUrl});
});
</script>
And this is my manifest:
{
"name": "XYZ Surf",
"version": "1.0",
"description": "just info",
"background_page": "redirect.html",
"homepage_url":"http://www.xyz.com/surf",
"browser_action": {
"default_icon": "icon.png",
"default_title": "abc."
},
"permissions": ["tabs"]
}
All I want is that when the addon button is clicked then the user must be redirected to the modified URL. (Please explain completely and please do not refer to Google codes because it's going through my head.)
(I have been looking up for all answers and did find one but not getting it.)
Instead of doing that in the background page, you should listen on the browser action event [1]:
chrome.browserAction.onClicked.addListener(function(tab) {
var tabUrl = encodeURIComponent(tab.url);
var tabTitle = encodeURIComponent(tab.title);
chrome.tabs.update(tab.id, {url: "http://xyz.com/surf/browse.php?u=" + tabUrl});
});
For the Google Chrome extension, I need to capture selected text in a web page and send to a web service. I'm stuck!
First I tried a bookmarklet, but Chrome on Mac seems to have some bookmarklet bugs so I decided to write an extension.
I use this code in my ext:
function getSelText(){
var txt = 'nothing';
if (window.getSelection){
txt = "1" + window.getSelection();
} else if (document.getSelection) {
txt = "2" + document.getSelection();
} else if (document.selection) {
txt = "3" + document.selection.createRange().text;
} else txt = "wtf";
return txt;
}
var selection = getSelText();
alert("selection = " + selection);
When I click on my extension icon, I get a "1". So I think the act of selecting outside the browser window is causing the text to not be seen by the browser as "selected" any more.
Just a theory....
thoughts?
You can do this by using Extensions Messaging. Basically, your "background page" will send the request to your service. For example, lets say you have a "popup" and once you click on it, it will do a "Google search" which is your service.
content_script.js
In your content script, we need to listen for a request coming from your extension, so that we send it the selected text:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "getSelection")
sendResponse({data: window.getSelection().toString()});
else
sendResponse({}); // snub them.
});
background.html
Now in background page you can handle the popup onclick event so that we know we clicked on the popup. Once we clicked on it, the callback fires, and then we can send a request to the content script using "Messaging" to fetch the selected text.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "getSelection"}, function(response){
sendServiceRequest(response.data);
});
});
function sendServiceRequest(selectedText) {
var serviceCall = 'http://www.google.com/search?q=' + selectedText;
chrome.tabs.create({url: serviceCall});
}
As you have seen, I registered a listener in a content script to allow my extension to send and receive messages from it. Then once I received a message, I handle it by searching for Google.
Hopefully, you can use what I explained above and apply it to your scenario. I just have to warn you that the code written above is not tested, so their might be spelling, or syntax errors. But those can easily be found by looking at your Inspector :)
content script
document.addEventListener('mouseup',function(event)
{
var sel = window.getSelection().toString();
if(sel.length)
chrome.extension.sendRequest({'message':'setText','data': sel},function(response){})
})
Background Page
<script>
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
</script>
manifest.json
{
"name": "Word Reminder",
"version": "1.0",
"description": "Word Reminder.",
"browser_action": {
"default_icon": "images/stick-man1.gif",
"popup":"popup.html"
},
"background_page": "background.html",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/myscript.js"]
}
],
"permissions": [
"http://*/*",
"https://*/*",
"contextMenus",
"tabs"
]
}
and here is the link where i have all in one extension to download.
after reading this i tried of my own and have published.
and here is the complete source
http://vikku.info/programming/chrome-extension/get-selected-text-send-to-web-server-in-chrome-extension-communicate-between-content-script-and-background-page.htm
Enjoy
Using a content_scripts is not a great solution as it injection to all documents including iframe-ads etc. I get an empty text selection from other pages than the one I expect half the times on messy web sites.
A better solution is to inject code into the selected tab only, as this is where your selected text lives anyhow. Example of jquery doc ready section:
$(document).ready(function() {
// set up an event listener that triggers when chrome.extension.sendRequest is fired.
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
// text selection is stored in request.selection
$('#text').val( request.selection );
});
// inject javascript into DOM of selected window and tab.
// injected code send a message (with selected text) back to the plugin using chrome.extension.sendRequest
chrome.tabs.executeScript(null, {code: "chrome.extension.sendRequest({selection: window.getSelection().toString() });"});
});
It is not clear from your code where it is. What I mean, is that if this code is either in popup html or background html then the results you are seeing are correct, nothing in those windows will be selected.
You will need to place this code in a content script so that it has access to the DOM of the page, and then when you click your browser action, you will need to send a message to the content script to fetch the current document selection.
You don't need a Google API for something as simple as this...
I'll use the Bing online service as an example. Note that the URL is set up to accept a parameter:
var WebService='http://www.bing.com/translator/?text=';
frameID.contentWindow.document.body.addEventListener('contextmenu',function(e){
T=frameID.contentWindow.getSelection().toString();
if(T!==''){e.preventDefault(); Open_New_Tab(WebService+encodeURIComponent(T)); return false;}
},false);
NB: The function "Open_New_Tab()" used above is an imaginary one that accepts the webservice URL with the encoded selected text as a parameter.
That's the idea basically.