JS Userscript: accessing DOM of new tab - google-chrome

I'm writing a Chrome userscript to open a new tab, then click on some DOM elements. But how can I access the DOM of the new tab?
/* background script */
chrome.browserAction.onClicked.addListener(() => {
chrome.tabs.create({"url": MY_URL, (tab) => {
// What ought I to do?
});
});

You will need to have at least one content script file loaded in your tab (with the right permissions to allow the content script to be loaded).
In the content script, you will have to leverage the Messaging API to communicate with the background page.
If your logic is simple enough, you could even run all logic directly inside content script, as they have access to be same set of chrome API as the background page.

Related

Google Chrome - add to homescreen - force refresh

I have a website with "add to homescreen" enabled - i.e. I have got a manifest.json file with "display": "standalone".
The problem I'm having is when I open the website via the homescreen shortcut, it will resume from when I last accessed it. I have to pull to refresh to make it fetch the latest content.
My question is, is it possible to make it do a refresh every time it is accessed?
If you'd like to take specific action inside of your web app whenever it moves from the "background" to the "foreground" again, you could listen for the appropriate events using the Page Lifecycle API.
The most straightforward way of doing this would probably be to listen for visibilitychange events, and programmatically refresh your data source when you detect that the current visibilityState has transitioned to 'visible'.
This could look like:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
// Your refresh logic goes here.
}
});

Background scripts vs Content Scripts

I am trying to develop a chrome extension which saves the url of webpages opened in all tabs and then load them whenever needed. Now I know content scripts, background scripts and popup.js. Content scripts mainly deal with the content of the loaded webpage and they have less chrome api interactions, background scripts are executed in an isolated environment and we can use all chrome api methods, popup.js is simply javascript that runs in context of popup.html.
Now here is my problem, I have a button in popup.html named "save" and on click of that button I want to save all the webpage urls opened in multiple tabs under one window. How can I do that?
Should I write a content or a background script?
Sorry for my noobish question. I am new to chrome api. Any help/suggestions?
Neither content script or background page is needed. You could do that just in popup.js, since popup page actually runs in the same context with extension.
In your popup.js, just call chrome.tabs.query to get tab info, including url (you would need to declare tabs permissions in manifest.json). If you want to specify window id, either use WINDOW_ID_CURRENT or retrieve it through other ways (depends on your logic)
chrome.tabs.query({ windowId: YOUR_WINDOW_ID }, (tabs) => {
tabs.forEach((tab) => console.log(tab.url));
});

Chrome extension - Collect elements from active tab

I am learning to create a chrome extension. To start, I am trying to just gather all links on the page and display them in the popup window of the extension when the button is clicked. I can't seem to get it right. I am able to use messages and send a message from my chrome tab to the extension. But when I try to pass the array of a tags, then it breaks.
My content script:
window.addEventListener('DOMContentLoaded', function () {
chrome.tabs.executeScript(null, {file: "content.js"});
});
My extension script:
window.addEventListener('message', function(e) {
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
console.log(event.data.links);
}
}, false);
if I dont do the links, it works fine and sends the messages. So I can't find another way to send all the links to the extension so I can process them. I have this in a github repo here https://github.com/skiftio/chrome-linkman
Your understanding of the architecture is a bit off. Please read through the Overview page, especially the Architecture part.
I'll even include a helpful picture here:
The popup is counted as "other pages" on this picture. It's an HTML page on its own domain (chrome-extension://yourextensionidhere), which is created when you open the popup and destroyed when you close it.
A content script is a script attached to a real Chrome tab; it gets access to its DOM, but is isolated from the page's own scripts. It also has very limited access to Chrome APIs.
More importantly, there are 2 ways of telling Chrome to add a content script to the page: you can declare it in the manifest so that Chrome automatically injects it upon navigation, or you can programmatically inject it from somewhere in your extension pages. You are mixing up those two.
Your manifest entry refers to scripts.js which is NOT a content script and you should not call it such. For instance, chrome.tabs.executeScript is not allowed to be called from a content script, and it will just throw an error. Since you're also injecting the script from the popup, you should just remove the section from the manifest, you don't need it.
As for messaging, you're trying to use window.postMessage, but this is not standard in Chrome extensions.
Take a look at the full Messaging docs, and I recently gave a short overview here.
In your situation, you could add a listener to chrome.runtime.onMessage to the popup and send a message with chrome.runtime.sendMessage from the content script:
/* --- Popup code (scripts.js) --- */
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message.links) {
/* do work */
}
});
chrome.tabs.executeScript({file: "content.js"});
/* --- Content script code (content.js) --- */
var links = document.getElementsByTagName("a");
chrome.runtime.sendMessage({links: links});

How can I open my extension's pop-up with JavaScript?

I am trying to write a JavaScript function that will open my extension like when the extension icon is clicked. I know how to open my extension in a new tab:
var url = "chrome-extension://kelodmiboakdjlbcdfoceeiafckgojel/login.html";
window.open(url);
But I want to open a pop-up in the upper right corner of the browser, like when the extension icon is clicked.
The Chromium dev team has explicitly said they will not enable this functionality. See Feature request: open extension popup bubble programmatically :
The philosophy for browser and page action popups is that they must be triggered by user action. Our suggestion is to use the new html notifications feature...
Desktop notifications can be used progammatically to present the user with a small HTML page much like your popup. It's not a perfect substitution, but it might provide the type of functionality you need.
Chrome team did create a method to open the popup programmatically, but it's only enabled as a private API, and plans to make it generally available have stalled due to security concerns.
So, as of March 2018 as of now, you still can't do it.
Short answer is that you cannot open browserAction programmatically. But you can create a dialog with your content script which emulates your browserAction and display that isntead (programmatically). However you won't be able to access your extension's background page from this popup directly as you can from your popup.html. You will have to pass message instead to your extension.
As mentioned there is no public API for this.
One workaround I have come up with is launching the extension as an iframe inside a content script with a button click. Whereby the background script emits the extension URL to the content script to be set as the iframe's src, something like below.
background.js
browser.runtime.onMessage.addListener((request) => {
if (request.open) {
return new Promise(resolve => {
chrome.browserAction.getPopup({}, (popup) => {
return resolve(popup)
})
})
}
})
content-scipt.js
const i = document.createElement('iframe')
const b = document.createElement('button')
const p = document.getElementById('some-id')
b.innerHTML = 'Open'
b.addEventListener('click', (evt) => {
evt.preventDefault()
chrome.runtime.sendMessage({ open: true }, (response) => {
i.src = response
p.appendChild(i)
})
})
p.appendChild(b)
This opens the extension in the DOM of the page the script is running on. You will also need to add the below to the manifest.
manifest.json
....
"web_accessible_resources": [
"popup.html"
]
....
You could emulate the popup by displaying a fixed html element on the page in the same location the popup would be and style it to look like the popup.
I had the same requirement: When the user clicks on the extension icon a small popup should open. In my case, I was writing an extension which will give updates on selective stocks whenever the icon is clicked. This is how my popup looked.
If you were having the same requirement then please read the answer below.
This is how my manifest.json file looked.
All the heavy lifting was handled by manifest.json file only. There is a section browser_action inside which there is a key called default_popup, just put the name of the HTML file that you want the popup to display.
I wanted my extension to work on all the pages that's why I added the attribute matches under content_scripts. I really didn't need to put the jquery file jquery-3.2.1.js inside the js array but the extension manager was not allowing me to keep that array empty.
Hope this helps, do comment if you have any doubt regarding the answer.

Working with current tab from Popup chrome extention

I'm trying to make an extension that will collect some data from currently opened tab on Google chrome.
I also use a popup in my extension to provide a control interface (buttons and stuff).
I need to be able to do the following:
1) Read source code of currently opened tab.
2) To be able to scroll down window content (using the code of course) .
If I could only get access to a javascript "window" object of currently opened tab , that would be enough.
But I'm open for another suggestions .
Can anyone help ?
You can simple use document in a content_script. Content scripts are defined in the manifest.json. In your case you should set "run_at": "document_end", so the dom is fully loaded when your script is called.
For more informations about content scripts and chrome extension development you find an easy to use guide from google - http://code.google.com/chrome/extensions/content_scripts.html
Code from popup won't be able to access directly to window objects from displayed tabs. You have to use a content script which will be able to send the source code of opened tab to the background page. This content script will also be able to scroll the window of opened tab.