Firefox Addon won't open new tab with url - javascript

I tried this code:
var contextMenu = require("context-menu");
var menuItem = contextMenu.Item({
label: "Test name",
contentScript: 'self.on("click", function () {' +
' window.open("options.html", "_blank");' +
'});'
});
But when I click on the new Context menu item, I get the following error:
Security Error: Content at "le Site" may not load or link to chrome://browser/content/options.html.
Which permissions do I have to give of get?

It seems that the relative address is resolved incorrectly in case of a content script - as a result you are attempting to open chrome://browser/content/options.html in a window which is correctly forbidden. Simply specify the full address and things should work:
' window.open("http://example.com/options.html", "_blank");' +

Related

Firefox extension: Open window and write dynamic content

I have developed a Chrome Extension and it's mostly compatible to firefox web-extensions API. Just one problem:
In Chrome Extension i have popup.js and background.js. User click's a button, popup.js does chrome.sendMessage to background.js where data is received and afterwards (popup.html may be closed meanwhile) i just call in background.js:
newWin = window.open("about:blank", "Document Query", "width=800,height=500");
newWin.document.open();
newWin.document.write('<html><body><pre>' + documentJson + '</pre></body></html>');
// newWin.document.close();
so that works fine in Chrome extension but not in firefox. I read here (https://javascript.info/popup-windows) that for safety reasons firefox will only open with a "button click event". And if i move above code to popup.js, inside button-click-evenListener, it will open this way (but i dont have the data prepared yet, thats really not what i want)
So i tried everything i found but i dont get the chrome.tabs.executeScript running. Here is my code with comments:
popup.js
// working in firefox and chrome (popup.js)
const newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
// not working firefox: id's match, he enters function (newWindow) but document.write doing nothing (but no error in log)
// not working chrome: doesnt even enter "function (newWindow)""
chrome.windows.create({
type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.tabs[0].id, {
code: 'document.write("hello world");'
});
});
background.js
(created local output.html and gave several permissions in Manifest.json - tabs, activeTab, output.html, , about:blank)
// opening but executeScript not working in firefox: Unchecked lastError value: Error: The operation is insecure.
// opening but executeScript not working in chrome: Unchecked runtime.lastError: Cannot access contents of url "chrome-extension://plhphckppghaijagdmghdnjpilpdidkh/output.html". Extension manifest must request permission to access this host
chrome.tabs.create({
// type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.id, {
code: 'document.write("hello world");'
});
});
How can I get the data into the new window/popup from background.js - i can open an empty page from there, so it's only about getting executeScript() running
Thanks to #wOxxOm for pointing me to a data URI to transport the json document into the browser from background.js.
While searching for a javascript method to build a data URI i found this thread, with the suggestion to create a Blob :
https://stackoverflow.com/a/57243399/13292573
So my solution is this:
background.js
var documentJson = JSON.stringify(documents, null, 2)
let a = URL.createObjectURL(new Blob([documentJson]))
chrome.windows.create({
type: 'popup',
url: a
});

firefox extension works through sdk but not when installed in browser - compatibility issue?

---Update----
After experimenting more with this, I've determined that the contentScript I have written is not the problem here. For example, if I reduce the extension to merely:
var buttons = require('sdk/ui/button/action');
var data = require("sdk/self").data;
var self = require("sdk/self");
var button = buttons.ActionButton({
id: "library-link",
label: "External Resource Locator",
icon: self.data.url("icon-16.png"),
});
The button will still appear when I run the extension through the SDK, but will not appear when I install the xpi in a current firefox browser (version 38, on some platforms). This problem seems to be occurring at a very basic level in their design process.
I am trying to write a simple extension for firefox which appends a form to the current page and posts data to another site. It can be called by an action button or through a context menu item.
I have been developing with the add-on sdk and it is working perfectly when I use cfx run to test it. However, after doing cfx xpi and installing the extension into my firefox browser, it does not work at all. The action button and context menu item do not appear, and although the extension shows up under add-ons -> extensions as installed and enabled, none of the images packaged with the xpi will display.
I am not sure what could be causing this, and my code is fairly brief, so I will add my entire main.js:
var buttons = require('sdk/ui/button/action');
var data = require("sdk/self").data;
var contextMenu = require("sdk/context-menu");
var self = require("sdk/self");
var menuItem = contextMenu.Item({
label: "Look for selected text in the Library of Babel",
context: contextMenu.SelectionContext(),
contentScript: 'self.on("click", function () {' +
'var text = window.getSelection().toString();' +
'var formext = document.createElement("form");' +
'formext.setAttribute("method", "POST");' +
'formext.setAttribute("action", "https://libraryofbabel.info/resourcelocator.cgi");' +
'var hiddenField = document.createElement("input");' +
' hiddenField.setAttribute("type", "hidden");' +
'hiddenField.setAttribute("name", "extension");' +
' hiddenField.setAttribute("value", window.getSelection().toString());' +
' formext.appendChild(hiddenField);' +
' document.body.appendChild(formext);' +
' formext.submit();' +
'});',
image: self.data.url("icon-16.png")
});
var button = buttons.ActionButton({
id: "library-link",
label: "External Resource Locator",
icon: {
"16": "./icon-16.png",
"32": "./icon-32.png",
"64": "./icon-64.png"
},
onClick: function() {
require("sdk/tabs").activeTab.attach({
contentScriptFile: data.url("form.js")
});
}
});
I've noticed that when I run cfx xpi the automatically generated install.rdf file says the maximum version for compatibility is 30.0. However, I have also found that on some computers running versions of firefox up to and including 38 it will work perfectly. Is there anything in this code which would prevent compatibility with newer versions of firefox? I will add the ContentScriptFile in case that may be responsible:
function getSelectedText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
var bodytext = document.getElementsByTagName("BODY")[0];
var formext = document.createElement("form");
formext.setAttribute("method", "POST");
formext.setAttribute("action", "https://libraryofbabel.info/resourcelocator.cgi");
//formext.setAttribute("target","_blank");
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", "extension");
hiddenField.setAttribute("value", getSelectedText() || document.body.innerHTML); // take selected text OR bodytext
formext.appendChild(hiddenField);
document.body.appendChild(formext);
formext.submit();
Open context menu on the toolbar where your icon would be, select Customize.... In the opened window, can you see your icon in "Additional tools and features"? If yes, then it means firefox remembered the icon's absence while you were developing the addon. You can put the icon to the toolbar manually. I believe regular users will not face this problem.
Change your em:maxVersion manually in install.rdf
Configure your firefox as described in Setting up an extension development environment, namely, at least these:
javascript.options.showInConsole = true to have addon errors shown in F12 console
javascript.options.strict = true to have even more warnings in the console
extensions.logging.enabled = true to have installation/update problems in the console.
After that, restart firefox and see if you can get anything useful from console. Disable other addons to remove the noise.
Try to backup and remove the entire firefox's profile folder, to have firefox 100% clean. Does it help? If yes, that narrow the problem to something in profile.
Try to change all identifiers of your addon (including addon name, ID, description, button id and description, etc), thus making a new duplicate addon. Does that help? If yes, that most likely means firefox has remembered some settings for your addon while you played with it.

Chrome extension: get current site name

I just get started building my first Chrome extension. One functionality in my app is to get the name of the current site. For example, if the current url matches "*://*.facebook.com/", I would interpret this url and know the site name as Facebook.
How should I go about doing this?
It's not clear wheter you want to get the host name or the title of the page, but you can get both of them if you want.
Inside a content script you can do:
var site = location.hostname,
title = document.title;
alert("Site: " + site + " - Title: " + title);
If you want to do this from the background page and you don't want to use content scripts nor inject code in the tab then you can only get the host name:
var site;
chrome.tabs.query({/* some query */}, function(tabs) {
site = tabs[0].url.split("/")[2];
alert("Site: " + site);
});
If you also want to get the page title from the background page you'll need to use executeScript(). NOTE: since January 2021, use Manifest V3 with chrome.scripting.executeScript() instead of chrome.tabs.executeScript().
var title;
chrome.runtime.onMessage.addListener(function(message, sender, sensResponse) {
if (message.title) {
title = message.title;
alert("Title: " + title);
}
});
chrome.tabs.query({/* some query */}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {code: "chrome.runtime.sendMessage({title: document.title});"});
});
For more informations about the methods I used in the above snippets you can see these documentation links:
chrome.tabs API
chrome.tabs.query method
chrome.tabs.executeScript method (deprecated, manifest v2)
chrome.scripting.executeScript method (manifes v3)
Message passing
chrome.runtime.onMessage event
chrome.runtime.sendMessage method
Since the content script is injected into the page, you could use window.location.host in the content script itself and get the name of your site.

Firefox Add-on SDK's selection module (sdk/selection) triggering more than once when going back and forward in webpages

I'm using the Firefox Add-on SDK to create an add-on that triggers when the user selects text on a page. I use the high level module sdk/selection for this, but I found a problem.
This is a working test example, where my main.js is completely defined as follows:
var self = require("sdk/self");
var pageMod = require("sdk/page-mod");
var selection = require("sdk/selection");
var activeWorker = null;
var workerID = 0;
pageMod.PageMod({
include: "*",
contentScriptFile: self.data.url("some-empty-file.js"),
onAttach: function(worker)
{
worker.id = workerID++;
worker.onSelection = function() {
console.log("selected text: " + selection.text + " (from worker " + worker.id + ")");
}
worker.activate = function() {
if (activeWorker != null) {
activeWorker.deactivate();
}
console.log("activate worker " + worker.id);
selection.on('select', worker.onSelection);
activeWorker = worker;
}
worker.deactivate = function() {
console.log("deactivate worker " + worker.id);
selection.removeListener('select', worker.onSelection);
activeWorker = null;
}
worker.on('pageshow', function() {
console.log("pageshow " + worker.tab.title);
worker.activate();
});
}
});
Essentially, it tries to attach a worker to a page everytime that page is shown, by disabling the active worker if it exists and then setting the new one. As you can see, every time I register a worker with the selection.on('select', ...) event, I do the respective selection.removeListener('select', ...) on the previous active worker. This should keep a single registration with the selection module at all times: the one made by the active worker.
But now please see the following console.logs, with associated steps:
Open mozilla.org and wait for page load.
log: pageshow Home of the Mozilla Project — Mozilla
log: activate worker 0
Select some text on the page (in this case, "volunteers"). It works fine.
log: selected text: volunteers (from worker 0)
Now open mozilla.org/firefox (on the same page).
log: pageshow Download Firefox — Free Web Browser — Mozilla
log: deactivate worker 0
log: activate worker 1
Select some text on the page (in this case, "Firefox"). It works fine.
log: selected text: Firefox (from worker 1)
Now press the back button to go to the last page.
log: pageshow Home of the Mozilla Project — Mozilla
log: deactivate worker 1
log: activate worker 0
We're back at Mozilla's main page. Select some text on the page again (in this case, "supporters").
log: selected text: supporters (from worker 0)
log: selected text: supporters (from worker 0)
It triggers twice.
I can't find a problem with my code, and the issue only appears when going back or forward in pages. If you keep opening pages and going back and forward in some ways, it'll start triggering more than twice.
Could this be a bug in the SDK or am I just doing something very wrong? Thanks!

ContextMenu.add shows a warning whenever initiated

I'm trying to follow sample for appAPI.contextMenu in Crossrider API
http://docs.crossrider.com/#!/api/appAPI.contextMenu-method-add
background.js
appAPI.ready(function() {
// Adds a command to all context menus that displays the data object
appAPI.contextMenu.add("key1", "Display data object", function (data) {
console.log('pageUrl: ' + data.pageUrl + '\n' +
'linkUrl: ' + data.linkUrl + '\n' +
'selectedText:' + data.selectedText + '\n' +
'srcUrl:' + data.srcUrl);
}, ["all"]);
// Adds a command to "link" context menus that displays 'Hello World'
// Note: Since both commands display on links, they are grouped in a sub menu
appAPI.contextMenu.add("key2", "Hello World", function (data) {
console.log('Changed onClick to Alert Hello World');
}, ["link"]);
});
extension.js
appAPI.ready(function($) {
});
the following warn is thrown in console log of background page.
Warning: Parameter context value is not supported. Function-name:
appAPI.contextMenu.add
PS, if you are a Crossrider Staff willing to help, a sample can be reproduced by extension id: 62139
The message is a mere warning and does not affect the operation of the extension; hence, it can be safely ignored.
I took the additional precaution of installing the extension on Chrome and Firefox and the context menu works correctly as defined in your code. If you have a specific issue with the extension not working correctly, please feel free to email support#crossrider.com.
[Disclaimer: I am a Crossrider employee]

Categories

Resources