Listening to events on any Chrome html user tab - google-chrome-extension

I would like to write an extension that connects to all Chrome tabs that are html (critically, leaving out any tabs hosting non-html content such as chrome://extensions/ and other non-user tabs, as that would surely cause lots of internal errors if those special tabs aren't entirely excluded from handling by my business logic code). No need for a Chrome extension button.
I would then like to execute some code on any of those user html tabs:
When the user has clicked a hyperlink or button.
When navigation to a new url is about to begin (and get the target url)
After a new page has completed loading in any of the tabs (and get the url)
I am not sure which approach is currently best to use, for each of those above, and also am initially unable to get to the url. Currently, I'm trying a background tab (should I, really?). The trouble is I am unable to get to the url through the tab object with that approach ―
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.dir(tab);
});
It appears the tab object does not directly point at a url.
Regardless this pointwise issue, I wonder what might be the most robust approach for accomplishing the overall scenario described: getting notified of those events for all html user tabs, and getting the url in every case. In the official docs, a relevant sample is very much elusive to find.

Related

Chrome Extension overwrite existing webpage

I will try to make this as short as possible. I am making a Chrome extension and I wanted to have an integrated settings tab so users can customize their experience. Now, I want this settings tab to be somewhat of an "extension" to an existing settings tab in a website. Let me explain.
The website I am talking about is Roblox.com, a popular gaming platform. When logged in, you have the ability to visit your settings, which look something like this:
Now, in order to navigate the different setting "tabs," you simply click on a button and it takes you to another change. The URL corresponding to each page is https://www.roblox.com/my/account#!/TAB_NAME, with TAB_NAME being the name of the tab. What I want to do is make my own "tab" where once the player clicks, it will bring them to a settings tab where they can tweak the extension's settings. This would look something like this:
I am fully aware on how to this (inject a button into the list and customize said button), but what I don't know what to do is make it so that once the button is clicked, it will not redirect you to another website, but will simply "switch tabs" like it would with any other setting. There is an extension that already does that called "Roblox+", where it adds a button to the list, and once clicked, it takes you to a similar-looking page with the URL https://www.roblox.com/my/account?tab=rplus#!/info. From my understanding, since the tab name isn't a header, the URL does not change, which allows for a custom webpage. Now, if you were to paste that URL in a browser without the extension, then it would simply redirect you to the "Account Info" tab (although the URL remains). Here is how the Roblox+ extension settings page looks like:
Now, from what I can assume, what happens is that right after the normal account information page is loaded, it removes all the HTML elements that are related to the account information tab and re-creates the entire page using custom HTML elements. That is something similar to what I want to do. Regardless of this, I do have one question. Is it possible to somehow "overwrite" a certain domain so that, let's say, the URL https://www.roblox.com/my/account#!/my_plugin_settings led to my custom page (even if that means that the page is made from an HTML file) instead of where it was supposed to lead? If that isn't possible, would it be better to create a custom settings page outside of the Roblox website or somehow inject my own into the current settings?
This is the question that I have. Hopefully I explained it well. If someone could assist me on this, then that would be amazing. Thank you for your time and help, I truly appreciate it.

codeigniter secure opening of pdf file in new tab

There are many similar questions to this but none quite answers my problem. I have users who wish to be able to access certain pdf files via a password. I have set up a page, accessed via a password, and the page contains links to each pdf. I have added an .htaccess file into the folder with the code 'deny from all' which successfully defeats any attempt to type in the url directly. (Unfortunately the pdfs are of a nautical magazine called 'The Log', in a folder called 'log' with endless scope for confusion over logging in. Sigh.) At present, when users click on a link for one of the pdfs, a direct link wouldn't work because of the protecting .htaccess file. So they are taken to a controller method as below:
function loadlog($year='',$filename='')
{
$realpath = 'public/pdf/log/'.$year.'/'.$filename;
$tofile= realpath('public/pdf/log/'.$year.'/'.$filename);
header('Content-Type: application/pdf');
readfile($tofile);
}
This works fine except that the pdf opens in the same window. I would prefer not to do that as clicking the browser back button calls for more clicks to resend the page request. How can I get it to open in a new window ie the same effect as if I had been able to use a direct link with target=_blank?
Or have I tackled the entire problem the wrong way?

Can Chrome Extension’s new options_ui trigger a page action?

I’ve been placing a page action on the options page of my Chrome extension. options.js calls chrome.runtime.connect({"name":"someName"}), and background.js has
chrome.runtime.onConnect.addListener(function(port) {
chrome.pageAction.show(port.sender.tab.id);
});
Unfortunately, in the new options_ui with the recommended default (and someday mandatory) "open_in_tab":false, the Sender's tab won't be set. Is there a way to get the tab id in order to show the page action?
I could use tabs.query to get the chrome://extensions/ tab, but that requires the tabs permission, which I currently don’t need. Active tab seems like it would work, but it doesn’t provide the tab id and isn’t enabled by opening an option dialog (source).
(Why do I want the page action on my options page? The extension works with a website that is only available ~7-10 weeks per year. I’d like my users to be able to interact with the extension the rest of the time, so that they can get used to the process. But I don’t want to adjust the displayed extension permissions just to do so. I can accomplish this by having the options page pretend to be the website in question.)

What can you do in background scripts that you can't do in other js files?

*By other js files, I mean the files you include in popup.html.
The following code works, so why should I use a background script?
Content script
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
//Some code
}
);
Script included in popup.html
chrome.tabs.query({active:true,windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "someMethod"},
function(response){
//Some code
});
});
This
Background pages live as long as the Chrome browser is active (and even longer if the "background" permission is set). Popup pages are only active when the badge's popup is open. The popup can only be opened by the user.
The background page's document is never visible, whilst the popup page becomes visible on click of the badge's button.
Besides that, there's no difference between background pages and popup pages. They run in the same extension's process, and have access to the same set of APIs.
If your extension only needs to be active while the popup is active, you don't need a background page. To save the state of the popup, just use the synchronous localStorage or the asynchronous chrome.storage API. When the variables you use are too complex to be stored using either API, a background page may be useful.
One example where the use of a background page is beneficial:
Imagine an extension that downloads a huge text file from a server. The creation of the resource is very resource-intensive for the server. Technically, everything can be done from within the popup. However, offloading the task to the background page allows the user to do other tasks while the file is downloading (if you use a popup only, the download will stop when the user closes the popup).
Though you didn't ask, I'd like to make you aware of event pages. They are similar to background pages, with one difference: Event pages are automatically closed when the extension is idle. In other words, event pages are only active when needed! By doing this, your extension will profit from the advantages of background pages without needlessly wasting the user's memory.
My last example is also a perfect example of when an event page has to be used. Besides doing the http request on behalf of the popup, the background page does nothing. If you use an event page instead of a background page, you get the best of both worlds: the popup page can be closed without interrupting the download, and the extension will not waste memory.
Documentation
Learn more about Background pages and Event pages
"Popup" in this answer refers to the optional panel of the chrome.browserAction or chrome.pageAction API, set by declaring the "default_popup" key in the manifest file, or programatically using the setPopup method.

Ignoring local URLs when using chrome.tabs.onUpdated

I'm writing a Chrome extension that analyzes the websites a user visits. I've decided to use chrome.tabs.onUpdated to run my analysis script instead of content_scripts in manifest.json, because chrome.tabs.onUpdated does a better job picking up page refreshes on AJAX heavy sites.
I don't need to analyze updates to new, empty tabs or to chrome-extension:// (local) pages, and in fact an error will be thrown if I do try to inject a script into those tabs. Is there a more automatic way to ignore those pages, or do I have to do it the manual way with Try/Catch blocks or by analyzing the URL? I'm sure I can do it manually, but it seems there should be a more automatic way to accomplish this.
You can ignore all local or internal chrome extension URLs by filtering out ones that start with 'chrome':
// Listen for changes on tabs
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
log_console('tab', tab)
// If tab is not an internal chrome tab
if (!tab.url.startsWith('chrome')) {
console.log('Non-internal URL updated")
}
});
Note that you need the tabs permission in your manifest.json if you want to access the URL, otherwise tab.url will be undefined and this won't work. If you can't get the tabs permission, your best bet might be to just catch and handle the error when you try to inject.

Resources