I am working to create a Web Extension for both google chrome and Firefox.
Ultimately my goal is to open a file dialogue when I click on the context menu item added by my extension. However, there are two major problems when trying to do this.
The file dialogue must be opened by user action that activates an input element with type=file.
Context menu events are added and called from the background script of the extension.
Is there a silver bullet solution I am missing?
Failed Solutions
Background input element: Input elements will not function when used in the background script.
Message Passing (works on Chrome but not Firefox): Sending a message from the background to the content script keeps its user triggered status on chrome, but loses it in Firefox.
For those interested: this is the code that works in Chrome but not Firefox.
Background.js:
chrome.contextMenus.create({
title: "Clickme",
contexts:["image"], // ContextType
onclick: function(){sendMsg("openDialog")} // Called when clicked in menu
});
Content.js:
var fInput= document.createElement("input"); //hidden input to open filedialog
fInput.setAttribute("type", "file"); //opens files
fInput.setAttribute("id", "fileopeninput"); ////only useful for inspector debugging
///TAKE MESSAGE FROM Background
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request.msg === "openDialog"){
fInput.click(); //triggers open file dialogue
}
});
Related
I'd like to understand how can I make changes to the HTML of popup.html in a Chrome extension that reloads a given URL every x seconds and looks for a certain text in the webpage.
More precisely: the extension's UI has two buttons "Run" and "Stop", respectively running and stopping the reload-and-search function above.
I also wanted to include in the UI a "loading" gif to display when the user clicks on the "Run" button and the extension is searching for the text. The loading gif should disappear either when the user clicks on the "Stop" button (and the extension stops searching) or when the the text is found on the target website.
The loading gif is inside an invisible with id="searching" in popup.html:
<div id="searching" style="display: none;" align="center"><img src="loading.gif" style="width: auto; height: 30%"/></div>
and I tried to reach the desired outcome by adding in app.js two functions that change its attributes, as well as chrome.runtime.onMessage.addListener (in addition to backround.js):
function showSrc() {
document.getElementById('searching').style.display ='block';
}
function hideSrc() {
document.getElementById('searching').style.display ='none';
}
document.querySelector('.button-run').addEventListener('click', () => {chrome.runtime.sendMessage('start'); showSrc();});
document.querySelector('.button-stop').addEventListener('click', () => {chrome.runtime.sendMessage('stop'); hideSrc();});
chrome.runtime.onMessage.addListener(function(message, callback){
if(message === 'stop') {
hideSrc();
} else if(message === 'run') {
showSrc();
}
});
As you can see from app.js, when the user clicks on "Run" or "Stop", the script not only sends the respective messages to background.js for the extension to perform/stop its reload-and-search function, but also changes the attribute of the with id="searching" so that the loading gif is visible/invisible in the UI accordingly by calling showSrc() or hideSrc(), respectively.
However, this works fine only when I stay with the UI open in the tab where I launch the script. If I switch the tab while the extension is running, then the UI (popup.html) closes and when I reopen it by clicking on the extension's icon, loading.gif is gone although the extension is still running.
How can I fix this?
I am developing an Edge extension, I need to send a message from frame document(not the top document, top document works fine) to content script.
As following:
`contentscript.js
window.addEventListener("message", function(event) {
console.log("window top message...event:");
console.log(event);
});`
Send a message from the frame document, with:
window.top.postMessage("Hi, I am from frame", "*").
In the console panel, I can see window top message...event: and then the browser reload the page. It seems the message was blocked.
The extension can be got from github.
steps to reproduce:
Load the extension, open Google, open console panel, switch to Frame, and type
window.top.postMessage("Hi, I am from frame", "*").
Could anybody help?
If you have a background page, and your contentscript.js has access to browser. object, the cheap'n'easy way might be to bounce message to extension and back like so:
contentscript.js
browser.runtime.sendMessage({name: 'bounce', payload: {name: hello}});
background.js
browser.runtime.onMessage.addListener(function (request, sender) {
if (request.name === 'bounce') {
browser.tabs.sendMessage(sender.tab.id, request.payload);
}
});
and just listen for {name: hello} on your contentscript. All frames, including top should get this message.
So I'm just trying to get a response every time the extension button is clicked. So like with AdBlock how this comes down
But instead I'm just trying to do a console.log() every time the button is clicked without any visible popups.
I've tried this so far
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case "popup-click":
// execute the content script
chrome.tabs.executeScript(null, { // defaults to the current tab
file: "real.js", // script to inject into page and run in sandbox
allFrames: true // This injects script into iframes in the page and doesn't work before 4.0.266.0.
});
sendResponse({}); // sending back empty response to sender
break;
default:
// helps debug when request directive doesn't match
alert("Unmatched request of '" + request + "' from script to background.js from " + sender);
}
}
);
Then my real.js
console.log("Yo");
But sadly I only get a Yo when it launches. Any ideas?
If you don't have a popup (nothing shows when you click the button), then there is an event that will fire when the button is clicked:
chrome.browserAction.onClicked
Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup.
To use:
// In your background script
chrome.browserAction.onClicked.addListener( function() {
// Do stuff
});
If, however, you do have a popup, then, as the docs mention, this event will not fire. Then your code is more appropriate: you just need to send a message from the popup and catch it in the background script whenever it is opened. See a full example in this answer.
I am new to writing extensions for Chrome. I am trying to write a simple extension that will open a new tab with the specified url, on a click of the extension icon and need to pass a value to it so that this value is filled in the input area (ex: input for search) of the specified url.
I am successful in opening the new tab with the given url on clicking the icon. I used background script to listen for the event on the icon and open a tab, the script is as follows:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.create({'url': 'www.google.com'}, function(tab1) {
// Tab opened.
});
});
Now I am confused about what method will allow me to send some values to the new tab and use the value and perform some operation there like, if I pass "java api" I have to put this in the search area of the google page. I tried looking the Chrome extension docs but it is confusing as to what to use?
You should use chrome.tabs.executeScript() to run a content script in this tab:
chrome.tabs.create(..., function(tab1) {
chrome.tabs.executeScript(tab1.id, {file: ...});
});
This content script will then be able to do something with the tab contents. If it needs some data from your extension it will have to send a message.
I got this problem during development of my own addon, but I get the same with the reddit example, so I'll use that for simplicity.
Using the exact code from the example found here, this is what happens.
Reddit Example
This example add-on creates a panel containing the mobile version of Reddit. When the user clicks on the title of a story in the panel, the add-on opens the linked story in a new tab in the main browser window.
To accomplish this the add-on needs to run a content script in the context of the Reddit page which intercepts mouse clicks on each title link and fetches the link's target URL. The content script then needs to send the URL to the add-on script.
main.js:
var data = require("self").data;
var reddit_panel = require("panel").Panel({
width: 240,
height: 320,
contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
contentScriptFile: [data.url("jquery-1.4.4.min.js"),
data.url("panel.js")]
});
reddit_panel.port.on("click", function(url) {
require("tabs").open(url);
});
require("widget").Widget({
id: "open-reddit-btn",
label: "Reddit",
contentURL: "http://www.reddit.com/static/favicon.ico",
panel: reddit_panel
});
panel.js:
$(window).click(function (event) {
var t = event.target;
// Don't intercept the click if it isn't on a link.
if (t.nodeName != "A")
return;
// Don't intercept the click if it was on one of the links in the header
// or next/previous footer, since those links should load in the panel itself.
if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
return;
// Intercept the click, passing it to the addon, which will load it in a tab.
event.stopPropagation();
event.preventDefault();
self.port.emit('click', t.toString());
});
The icon is displayed in the bar, and clicking it launches the panel. Clicking a link within the panel opens it in a new tab - just as described and expected.
Clicking the "next page" link within the tab successfully fetches the next page, within the panel - as expected.
Clicking a link on the 2nd page does NOT open it in a tab, it opens it WITHIN the panel.
Here's my guess: When the page reloads within the panel, it does not reload the script specified in the contentScriptFile. Does anyone else experience this? And is there a workaround?
I'm using SDK 1.0 and FF 5.0
Question cross-posted on the Addon forum here
Recieved this answer at the Mozilla forum, and will post here as well for future reference.
Perhaps you are seeing Bug 667664 - Panel content scripts don't work after reloading or changing location. I think the workaround is to load the content in an iframe.
Which I believe might be the case, I'll try this during the day and report back.
EDIT: iframe seems to do the trick