Create an alert every page load with Chrome extension - google-chrome

This is my first time messing around with extensions and what I am trying to do is very simple yet I can't seem to get it to work.
I simply want an alert to be called every time a page on google is loaded.
In my manifest.json I have:
{
"name": "Bypass shib",
"version": "1.0",
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"js": ["secondScript.js"]
}
],
"manifest_version": 2
}
Okay now in my secondScript.js I have:
chrome.tabs.executeScript(null, {code: "alert('test')"});
Shouldn't this execute the alert whenever a page is loaded? If not can somebody explain why it's not?

The console reveals the following message:
Uncaught Error: "executeScript" can only be used in extension processes.
See the content scripts documentation for more details.
This post suggests "Chrome extension functions cannot be used in content scripts," which could be what you're running into.
For completeness, the secondScript.js that worked for me was as follows:
console.log("test");
//chrome.tabs.executeScript(null, {code: "alert('test')"});
alert("test");

Content scripts do not have access to any of the chrome.tabs.* API methods.
To display an alert on every page, remove the chrome.tabs.executeScript method, and let your secondScript.js just contain:
alert('Test');
In a Chrome extension, there are three different kinds of scopes in which JavaScript can run. The understanding of this separation is essential for writing Chrome extensions, see this answer.

Related

Why can't you create Custom Elements in content scripts?

I attempted to create a custom element in a Chrome extension content script but customElements.define is null.
customElements.define('customElement', class extends HTMLElement {
constructor() {
super();
}
...
});
So apparently Chrome doesn't want content scripts to create custom elements. But why? Is it a security risk?
I can't seem to find anything in Chrome's extension guide that says it's not allowed.
I found the solution reading this page but the information was so cumbersome I wanted to write this answer for future readers (I am using Manifest v3)
Firstly, install the polyfill :
npm install #webcomponents/webcomponentsjs -D
Then add the polyfill in your content_scripts block in your manifest file :
"content_scripts": [{
"matches": [ "..." ],
"js": [
"./node_modules/#webcomponents/webcomponentsjs/webcomponents-bundle.js",
"content.js"
]
}]
(important: you have to load it before your content script of course as the polyfill needs to load before you can use it)
Now it should works. Cheers
Note: the customElements feature is implemented in most modern browsers but for some reasons the interface is not available from a content script because the scripts are run in an isolated environment (not sharing the same window object space from the webpage the extension runs in).
As of now custom element can be used in chrome extensions UI. In Popup ui, option page ui and in the content script as well But it requires a polyfill which is this.
https://github.com/GoogleChromeLabs/ProjectVisBug - this is the one big custom element in the chrome extension.

Chrome extension can not access custom window properties

Im trying to write a Chrome extension that has a dev tools panel. This extension needs to call functions defined on a property on window in a webpage that I also have made. In other words, the extension is only for my own web page and I control both. Example:
// This script is added in my own webpage application when it loads
window.myTest = () => { /* do something */ }
I want to be able to call the function window.myTest from my Chrome extension. I need to make similar functionality like https://github.com/zalmoxisus/redux-devtools-extension.
It seems that I need to do this by inject script/code from my backend page. I have all working, extension with backend page that gets invoked and I can see that the code that I inject gets called in the page context (testing by console.log gets written to the console output of the page).
Here is my code:
manifest.json
{
"manifest_version": 2,
"name": "MyTest",
"description": "MyTest",
"version": "0.0.1",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
"background": {
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["testscript.js"]
}],
"permissions": [
"tabs",
"<all_urls>"
]
}
testscript.js
window.myTest(); // myTest is undefined in the context of the injected script
background.js
// empty, but here to be able to open background page
I also have a pannel that sends a message to the background page when a button is clicked. I know that the panel and sending the message also work. But window.myTest is still undefined.
Edit
Removed the injection from background.js, because I did not use it and have same issue as described.
Finally, I got the specs on this. Mozilla and Chrome follow the same specs for extensions.
Content scripts get a "clean" view of the DOM. This means:
Content scripts cannot see JavaScript variables defined by page
scripts.
If a page script redefines a built-in DOM property, the
content script sees the original version of the property, not the
redefined version.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts

Google Chrome extension that enables a specific website to trigger a function in the extension code

I'm new to extension development, maybe someone has a small example ready for my problem.
I plan a more complicate code (that will execute chromium API functions), but solving this task should help me get started:
I want to create an extension that triggers a popup or alert() (just anyything) based on a website javascript call.
So for example my website has a button, when clicked on the button a javascript with a few parameters is executed.
My extension picks those parameters up and executes APIs (for my example just any popup) based on the parameters.
In my basic example I'd like to trigger some sort of popup/notification with the text supplied by the website javascript.
Also only my website domain should be allowed to trigger that, anything else should be rejected.
I'd really appreciate help.
Here is my "empty" manifest
{
"name": "Special API",
"version": "1.0",
"description": "API demo extension.",
"browser_action":
{
"default_icon": "gears.ico",
"popup": "show_credits.htm"
},
"permissions": [
"http://www.mywebsite.com/"
]
}
Here the example button in my website.com/example
<html>
<body>
<button onClick="extension_do_exec('Hellow world','abcabc')">Execute extension function</button>
</body>
</html>
The approach you described is problematic, bacause javascripts of web-pages, and javascripts of extensions are isolated from each other (there is a concept of isolated world). So it is not possible to get a value "supplied by the website javascript" directly into the extension's javascript. I'd suggest another approach. You possibly could exchange with some values by assigning them as properties to DOM objects. These properties can be accessed from a content script, injected into the web-page. Of course, the content script can determine domain of the page and work as appropriate. As for popups, these are internal pages of an extension, and you should implement some kind of messaging between them and your content script.

Could I make a Google Chrome extension for chrome pages (downloads, extensions etc)?

I'd like to make a very simple extensions that slightly alters how the Downloads page looks. Changing the History page might be interesting too, but that's for later.
Is there a way to do that?
I tried making a Content Script extension, with "chrome://downloads" as match in manifest.json. Chrome won't allow that and responds with an error when packaging the extension.
Is there another simple way? It has to be simple, because changes would be simple, because all chrome:// pages are built with HTML, JS and CSS.
edit
After trying with background scripts a little...
I can't get chrome.tabs.executeScript to work! I added in background.html:
chrome.browserAction.onClicked.addListener(function(tab) {
alert(this.document.body.innerHTML);
alert(chrome.tabs.executeScript(null, {
code : "document.body.style.backgroundColor = 'red';"
}));
});
And I added this in manifest.json to add a (invisible) 'browser action button':
,"browser_action": {
/* "popup": "background.html",*/
"name": "Alter page"
}
The onClicked event fires both alerts (first is background.html's body, second is undefined). But the code (a string with document.body.style.backgroundColor = 'red';) doesn't execute! And ofcourse there's no debugging for extensions like this =)
Any tips anyone? I'm trying to get a hold of the tab's window.document (not background.html's window.document!). An injected script (that's what chrome.tabs.executeScript is supposed to do) should do that.
PS
I'm stealing from make_page_red/manifest and make_page_red/background.html
The 'extension' I have so far: http://hotblocks.nl/js/downloads.rar
EDIT
I found out what I want to achieve is possible with just CSS. I don't need to inject javascript. Does that make it easier? Does that make it possible? =)
According to this documentation, chrome:// URLs are an invalid scheme so they won't be matched:
A match pattern is essentially a URL that begins with a permitted scheme (http, https, file, or ftp), and that can contain '*' characters.
I would look into using override pages instead.
As requested, here's my extension that can at least load when chrome://downloads is loaded, although as I said, I don't think you can modify the page even if you know that's the page you're viewing.
manifest.json
{
"name": "Test",
"version": "0.0.1",
"background_page": "background.html",
"permissions": [
"tabs"
]
}
background.html
<script>
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
{
if (tab.status == "complete")
{
alert(tab.url);
// should alert 'chrome://downloads' on that page. You can
// check for this url here and then do whatever you want
}
});
</script>
Update: Since Chrome 31 there is an API for extensions that allows access to Chrome's downloads: https://developer.chrome.com/extensions/downloads
There's also an API that allows access to list and manage other installed extensions: https://developer.chrome.com/extensions/management
(Previous Answer)
Unfortunately, there's not currently an API for Chrome extensions to access information about a user's downloads. It's a widely requested feature, though, and there's some discussion among Chrome developers here: http://code.google.com/p/chromium/issues/detail?id=12133
Star the issue if it's a feature that you'd like to see, and you'll receive email updates.
As this page shows, there is no API to override the downloads page... However, there is a way to make a file you have made replace the chrome://downloads/ page whenever it is loaded using javascript in your background page...
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status === "loading"){
if(tab.url === "chrome://downloads/"){
chrome.tabs.update(tab.id, {url: "REPLACEMENT.html"});
}
}
});
Essentially what this does is - As soon as the page chrome://downloads begins loading (using the tabs.onUpdated API), the page is redirected to REPLACEMENT.html (Using tabs.update API)... There is no visible delay in the tab update
as this script is run before the chrome://downloads page begins loading... You can use a similar code in your file by pressing CTRL + U on the downloads page to view and copy its source code

How can i create a new tab via browserAction and then execute a script

I want to create a tab by clicking on the browser action button and then insert a content script or execute a script. So far, its not working well.
Background.html
chrome.browserAction.onClicked.addListener(function(tab)
{
chrome.tabs.create({url: "Dreamer.html"}, function(tab) //Dreamer.html is a file in my extension
{
//Add a script
chrome.tabs.executeScript(tab.id, {file:'Dreamer.js'});
});
});
Manifest.json
{
"name" : " Dreamer",
"version" : "0.1",
"description" : "My extensionr",
"browser_action" : {"default_icon" : "App/AppData/Images/icon.png", "default_title":"Start Dreamer" },
"background_page" : "App/AppData/background.html",
"content_scripts" :[{"matches":["http://*/*"],"js":["app/view/UIManager.js"]}],
"permissions": [ "cookies", "tabs", "http://*/*", "https://*/*" ]
}
i get this error in the background page
Error during tabs.executeScript: Cannot access contents of url "chrome-extension://femiindgnlfpdpajimkmldpgpccngfmd/Dreamer.html". Extension manifest must request permission to access this host.
I would really like to know how to create a tab(new tab) and run a script immediately
EDIT:
The kind of application i am creating requires the following actions:
-Allow user to create new tab by clicking the browserAction button
-On creation of the new tab, a file in my extension (Dreamer.html) is opened
-Add a content script or execute a script in the new tab
Thanks
Is there any particular reason you need to inject the script? Since both Dreamer.html and Dreamer.js seem to be hardcoded, you could just include <script type="text/javascript" src="Dreamer.js"></script> in the former, right?
As a side benefit, if you need it to send info to the background page, you can access it directly with chrome.extension.getBackgroundPage() instead of setting up complex listeners that usually come with content scripts, too.
Injecting content scripts is for injecting scripts outside the extension sandbox. Dreamer.html, however, is a part of the extension.
Edit
If you do want an (unwieldy) example of how to execute a script in an extension page, see here:
http://code.google.com/p/chromium/issues/detail?id=30756#c11
I don't think it applies to your case, however.