Chrome Commands API to make default popup visible - javascript

I was looking at the chrome.commands API for adding some functionality to m y extension.
Basically what I want to do is to listen for specific key combinations, say CTRLALTS, to display the default popup of my extension.
I understood how that could be included in the manifest. Reading further, I found this:
In your background page, you can bind a handler to each of the
commands defined in the manifest (except for '_execute_browser_action'
and '_execute_page_action') via onCommand.addListener.
What I understand is that I need to have a background page that listens for these key combinations and takes actions appropriately. All good.
and there is this paragraph, too:
The '_execute_browser_action' and '_execute_page_action' commands are
reserved for the action of opening your extension's popups. They won't
normally generate events that you can handle. If you need to take
action based on your popup opening, consider listening for an
'onDomReady' event inside your popup's code.
The difficulty that remains is :
How do I make the default popup visible? :)

Basically, that remark says "you don't need to (and can't) handle these actions yourself".
They will open the popup regardless, and listeners don't get fired.
So, for a minimal example a background page is not needed at all.
In the manifest:
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Alt+S",
}
}
}
And then Ctrl+Alt+S will mimic clicking your browser action.
If a popup is set, it will open it.
If not, chrome.browserAction.onClicked will fire.
The chrome.commands.onCommand even will not fire in either case.

Related

How To Use 'beforeunload' to Capture Iframe Click?

I am trying to build a code that does a request when a cross-origin iframe is clicked and it directs the main window to a new page.
Since it's impossible to directly tap into Iframe click events, I thought of the following conditions as necessary:
page unload event occurs
the window is out of focus
Page unload (As far as I know) happens only when the current url is directed to some other url.
Now, this unload could happen by clicking any link. To restrict it to Iframes, I added the condition of window being out of focus.
addEventListener('beforeunload',(event) =>{
if(!(document.hasFocus())){
// Do Something
}
});
My question is, are their any limitations to this approach? If yes, then please suggest some more conditions to make it as close to reality.
For those of you, who are curious: I want to track clicks on Google AdSense Iframes on my website.

How to run popup.html without using default_popup? (CHROME EXTENSION)

So, I've got a situation where I want a background and content script to be run everytime the browser extension icon is clicked. The ideal behaviour is that extension icon is clicked, the script runs, and the popup will open, displaying the data that was grabbed by the script (but this should happen quickly, the script runs and gets the data very fast). Since chrome.pageAction.onClicked will not work if there is a default_popup defined in manifest.json, I think this leaves me with two options:
Use default_popup and figure out that the extension icon has been clicked some other way. I found this solution in another stack overflow post, but the workaround is to use default_popup: "popup.html", and then the popup.js that is defined in popup.html will send a message saying that the icon has been clicked, then when background.js receives this message, it executes the script. I implemented this idea and it worked... kinda. The trouble is, the popup will always come up before the script is fully executed, so you can't actually display the data grabbed by the script in the popup until the next click. I'm not sure there's any way to get the behaviour I desire using this method, so on to the next:
The other solution I can possible think of is to use onClicked, and then make the popup come up some other way, besides using default_popup in manifest.json. I'm also not sure if this is possible, I have looked on stackoverflow and haven't found anything similar.
Is the second method possible? Can the first method work somehow?
Your option #1 is correct, I think all that is needed is a loading screen when the user first sees the popup, and add some code that updates the popup as soon as it hears from the backend. Might need to see some code to better help there.
Option #2 will not really work, unless you opened the popup in a new tab (or just made it a whole new HTML page). I say this because there is a note here from the Chrome Dev team they will not support opening a popup unless it is from a user gesture -- https://stackoverflow.com/a/10484764/4875295.
If you wanted to go that route it would probably look something like:
Delete from your manifest.json browser_action.default_popup
In your background script add something like:
chrome.browserAction.onClicked.addListener(() => {
const data = dataMaker();
chrome.tabs.create({
url: `${chrome.runtime.getURL("app.html")}?data=${data}`
});
});
Then in your html file have some JS that reads the query string and updates the page accordingly.
Though, that's a different approach than you asked for and I think your original route may still be the best bet (with some added JS around loading).

How to stop my chrome extension after opening it?

I'm currently developing a chrome extension, that contains background.js and content_scripts.js. In content_scripts, I've added some "event.preventDefault"
in all elements and also added some elements on the page. But when user clicks my extension for the second time, I'd like to "close" my extension and cancel all changes my extensions have done.
Is there a easy way to do that or do I have to treat all changes that I've made individually?
No, without reloading the page, there is no easy way to generically undo all your changes. Yes, if you want all your changes undone, then you have to undo them yourself. There is no magic recording being made of your changes which will back them out for you if your extension is disabled, or you call a particular API.
There are some obvious strategies for doing so:
Remember the changes you made and undo them one by one (undo changes, remove event listeners, etc). What is required depends on what your extension did and the state you desire to leave it in. You can easily send a message to your content script with chrome.tabs.sendMessage() which indicates that it should disable itself and/or back out any changes.
Reload the page
Store the initial state of at least portions of the page and restore it. This may difficult to do, and could be impossible on generic pages. You would have to know all of the event listeners and potentially other state information which has been set by JavaScript in the page.
Try this.
if(localStorage.getItem('firstClick')==='true'){
localStorage.setItem('firstClick', 'false');
chrome.tabs.executeScript(null, {file: "contentscript.js"});
}
else {
localStorage.removeItem('firstClick');
localStorage.set('firstClick', 'true')
}

Click on page from chrome extension

How can a chrome extension click on a button on active page?
There is banal page on the Web. There is simple element of button type with specific ID on the page. Also there is Chrome extension with a button. I'd like to click to extension button and the button in turn clicks to page button.
var someElement = document.getElementById('someElement');
someElement.addEventListener('click', function () {
// here I'd like to click on a button with specific ID.
});
The very first thing you want to do is to read the Overview page, especially the Architecture part. Read it thoroughly, and it will answer many questions you have.
Your problem can be split into two parts.
How to trigger something with a click on your extension.
How to click something inside the active tab.
Before I proceed, I'll reiterate what wOxxOm said: there's a great small example in the docs that does nearly what you want. But if you want to be someone taught to fish, not given a fish, read on.
How to trigger something with a click on your extension
It depends on what kind of UI you're using; the simplest is a Browser Action button.
Simplest button:
If you add a browser action to the manifest without specifying a popup:
"browser_action": {
"default_icon": { "38": "icon38.png" }
},
then clicking on it will raise chrome.browserAction.onClicked event to your extension's pages. The only page open at any time you need it is a background page, the role of which is usually the central dispatch for extension events. So, you need a background page that listens to that event:
"background": {
"scripts": ["background.js"]
},
and
// background.js
chrome.browserAction.onClicked.addListener(function(tab) {
// Okay, the actual action should go here
// And look, we already have the required Tab object for free!
});
Variations (exercises for the reader):
If you do specify a "default_popup" in your manifest, then chrome.browserAction.onClicked will not trigger. Instead, a small popup page will open with the HTML file you specify; you can add UI/logic there as you wish, the principle will be the same as normal webpages but with Chrome API access, except:
You'll need to query for the current tab yourself.
You'll need to be mindful of Chrome's extension CSP.
In case you run into problems, you need to know how to debug them.
If your extension targets only a few specific pages, consider using Page Actions instead of Browser Actions.
As noted in the documentation, Event pages are preferable to Background pages. In this case, you can use an Event page easily without any side effects, but in general this may require some thinking.
You could inject your own UI into the page itself with Content scripts; this is an advanced topic and will not be covered here.
How to click something inside the active tab
Since you've read the Architecture overview, you already know that the only part of the extension that can interact with the DOM of an open page is a Content script.
Content scripts can either be specified in the manifest (and then they will automatically be injected and ready for you when a matching page is opened), or they can be manually injected into the page.
In your case, you want to do something simple, and only when clicked. This is a perfect job for programmatic injection, so we'll stick with that.
Assuming the solution from the previous section, you are in a context of a background page and already have the current tab as the tab variable:
// background.js
chrome.browserAction.onClicked.addListener(function(tab) {
// Do something with tab
});
Programmatic injection is done with chrome.tabs.executeScript method. At a minimum, you need to specify the tab you want to inject to, and the code that will be run:
// background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.id, {
code: "document.getElementById('#specificId').click()"
});
});
That's not all yet though. The extension must have permissions to execute code in an open tab.
You could use "host permissions" that are defined by a match pattern to give access to specific pages, but remember that we are only triggering it when the user clicks the extension.
For that specific case, there's a special permission "activeTab". It is sufficient to do a lot of things with the currently active tab when the extension is explicitly invoked, and clicking its button is explicit enough.
So, add to manifest:
"permissions": ["activeTab"],
And that should be all you need for this to work.
Extra credit:
While not necessary for this simple purpose, you may want more complicated code than a single line to be executed in the tab. Then it makes sense to use a separate file and invoke executeScript with "file" instead of "code".
Just triggering a click on a button does not require you to directly interact with JavaScript running in the page itself, as DOM events are shared. However, it's important to understand that normally, content scripts can't interact with the page's own scripts, which is called "isolated world". There are ways to bypass it if you really need it, but it's an advanced topic better explained elsewhere.
Sometimes you need the content script to persist, answer some commands and maybe send its own queries to the extension's pages. In that case, it's probably better to auto-inject through the manifest and use Messaging instead of executeScript.

Capture link clickthrough events from JavaScript

In order to track the overall user clickstream, I'd like to fire a JavaScript event, if the user right-clicks, and select "Open in new Tab" (or middle-clicks in most browsers) on a link. Most of these links are linking outside of my site, and I'd like to interfere with overall browser experience (such as: status bar, etc) as little as possible. What options are there to solve this?
If you're looking at ways to see outbound link hits, you could try the following:
Use a script, example link.php?src=http://www.example.com that increments a counter per IP & User Agent combo when clicked. This however doesn't look very good in the status bar. It could also be saved by web crawlers.
Use unobtrusive JavaScript to attach event handlers on links that are external. You could determine if they are external if the hostname is present and doesn't match the one you are on. You could then use this event handler to save the href, prevent default of click event, to increment a number much like the first script and then send the window.location to the actual href. This of course fails without JavaScript enabled/supported.
There are many ways that a user can create a new tab in a browser:
Middle click
Context menu
Mouse gesture
"New tab" button on the toolbar
"File" > "New tab"
Unfortunately there is no way to handle all these and potentially more user actions that could create a new tab.
You could do a simple server redirect and log the hits that it gets
Or does it have to be js?
Middle click capturing does work.
You
have to check the browsers version (ie6 doesn't open anything on middle click),
have to use mousedown and mouseup to check if these two events happen on the same element,
have to check which button was pressed. (jQuery "which" function, for example)
If mousedown and mouseup happen on the same element, a new window opens, so you'll know that your link was clicked.

Categories

Resources