I am trying to write a chrome plugin for the first time and though I have basic javascript knowledge I do not know how to start my script.
My basic problem is that I do not want to use a popup or any other menu to start my script but I cannot figure out how to do this. My intention is that the extension runs commands on startup and then exits.
I am trying to fin out how I can start my Chrome extension can be started without doing it through any visual elements.
Here is what I have:
manifest.json
{
"manifest_version":2,
"name":"Audiotool control",
"version":"1",
"content_scripts":[
{
"matches":[
"http://www.audiotool.com/*"
],
"js":[
"jquery.js",
"content_script.js"
]
}
],
"offline_enabled":true,
"permissions":[
"tabs",
"http://www.audiotool.com/*"
]
}
main.js
chrome.tabs.query({url: "http://www.audiotool.com/*", }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
content_script.js (not really important but just in case)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?);
if (request.greeting == "hello")
alert("message received")
sendResponse({farewell: "function called"});
});
//var e = $.Event("keydown", { keyCode: 32});
//$("body").trigger(e);
To reiterate, I am trying to fin out how I can start my Chrome extension can be started without doing it through any visual elements.
Well, main.js never runs because you have not specified it in the manifest. You probably want something like this in your manifest:
"background": {
"scripts": ["main.js"],
"persistent": false
},
After that, you would only fire main.js when the extension started up. You need to add a listener and perform operations inside it. Such as:
chrome.tabs.onUpdated.addListener(function() {
//do stuff
});
Related
I'm creating a Pomodoro timer program, and I can't figure out how to keep the timer running in the background, after I unfocus the popup.
I've been working on this for a bit, but I currently have all the code for the actual timer in the background script. I was hoping to use the runtime API in popup.js to send a one-time message to start the timer in background.js, and then whenever the user opens the extension, to return what the timer is set to.
I'm also not entirely sure I'm approaching the question correctly.
The code wasn't working, so I simplified it down to just sending the message and trying to get a response, which I found is the problem.
Code:
popup.js:
chrome.runtime.sendMessage({greeting: 'hello'}, function(response) {
console.log(response.farewell)
});
background.js:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.greeting == 'hello') {
sendResponse({farewell: 'goodbye'})
toggleClock();
}
});
//working toggleClock() function
manifest.json:
"browser_action": {
"default_popup":"popup.html",
"default_title":"Flexidoro",
"default_icon":"flexidoro.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [ "storage", "alarms" ]
There aren't any errors in the extension error log, and there also isn't anything in the console.
Am I taking the right approach?
Thanks!
I am trying to pass data from my webpage to the chrome extension.
manifest.json (I am trying to do this in my local environment first)
"externally_connectable": {
"matches": ["*://localhost/*"]
}
In listen.js (a background script):
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
alert('test2');
alert(request.openUrlInEditor);
});
None of the alerts display above.
I got the extension ID of the unpacked chrome extension by viewing the ID when I navigate to chrome://extensions/. In my webpage in localhost environment
// DEVELOPMENT extension ID
var editorExtensionId = "fppgjikaoolnlcmdjalbfkmlcadcckmb";
var url = 'test';
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
When I run this. in the browser, I get an error saying:
Error in event handler for (unknown): TypeError: Cannot read property 'success' of undefined
I'm not sure where to begin debugging this.
After making a few changes in your code I am able achieve your goal.
See below the complete code.
manifest.json
{
"manifest_version": 2,
"name": "CS to Bg Communication",
"version": "0.1",
"background": {
"scripts": ["listen.js"]
},
"content_scripts": [
{
"all_frames" : true,
"matches": ["<all_urls>"],
"js": ["contentscript.js"]
}
],
"browser_action": {
"default_popup": "popup.html"
},
"externally_connectable": {
"matches": ["*://localhost/*"]
}
}
listen.js - the background script
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
blacklistedWebsite = 'http : / / yourdomain . com /';
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor) {
alert('test2 - ' + request.openUrlInEditor);
sendResponse({"success": true, "AckFromBG": "I have received your messgae. Thanks!"}); // sending back the acknowlege to the webpage
}
});
contentscript.js - the content script - actually does nothing
console.log("this is content script");
web-page.html - The local web page
<html>
<body>
This page will will send some message to BG script
<script type="text/javascript">
// DEVELOPMENT extension ID
var editorExtensionId = "fjaedjckfjgifecmgonfmpaoemochghb"; // replace with your extension ID
var url = 'test';
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url}, function(response) {
console.log(response);
if (!response.success)
handleError(url);
});
function handleError(url) {
console.log(url);
}
</script>
</body>
</html>
Summary of changes:
Defined blacklistedWebsite - this was undefined.
Added sendResponse({"success": true, "AckFromBG": "I have received
your messgae. Thanks!"}); to send back the acknowledgment to the
webpage.
Define function handleError(url) {
console.log(url);
} this was not defined.
That's it. Hope this will solve your issue.
The error you are getting indicates that chrome.runtime.sendMessage is executed. This means that external messaging is set up correctly: otherwise, chrome.runtime.sendMessage wouldn't be exposed to your page's code.
I think the problem is here:
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
I suspect the problem is blacklistedWebsite being undefined; the code fails with a ReferenceError and no meaningful response is being sent. Since the onMessage listener terminates (even with an error), the calling code gets an undefined response.
Check your background console to confirm if that's the case; if you copied this partial example code but aren't using this blacklisting functionality, delete this branch.
In future, please make sure you understand what every line of code you copy does!
I am trying to create a chrome extension, but for some reasons, sometimes, the chrome.runtime object seems incomplete, and a lot of methods are missing (including onMessage, which is the one I want).
It seems sometimes it works, sometimes not. I assumed it may be a time related issue, but I don't understand why I can't simply create a message listener on background?
My background script:
setTimeout(function () {
console.log("gogo!");
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.type == "tab") {
console.log("tab!");
sendResponse({status: "ok"});
}
}),
2
});
Where "chrome.runtime.onMessage" is undefined.
Thanks!
Edit2: I have built a much simpler prototype, and it's failing again. Now I am really confused. Here is what I have:
$tree
.
├── manifest.json
├── src
│ ├── background.html
│ ├── background.js
│ └── test.js
└── vendor
└── jquery.js
2 directories, 5 files
manifest.json file:
{
"manifest_version": 2,
"name": "test",
"description": "test",
"version": "1.0",
"author": "test",
"homepage_url": "http://www.test.com",
"content_scripts": [
{
"run_at" : "document_idle",
"matches": ["https://www.google*"],
"js": ["vendor/jquery.js", "src/test.js"]
}
],
"background": {
"page": "src/background.html",
"persistent": false
},
"permissions": [
"tabs",
"https://www.google*"
]
}
background.html file:
<script src="../vendor/jquery.js"></script>
<script src="background.js"></script>
background.js file:
function run () {
console.log("gogo!");
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.type == "tab") {
console.log("tab!");
sendResponse({status: "ok"});
}
});
}
run();
test.js file:
'use strict';
run();
function run() {
var url = window.location.href;
// Error if no URI
if (!url) {
return 1;
}
var uriRe = /https:\/\/www\.google.*/;
var reParse = uriRe.exec(url);
if (!reParse) {
return 2;
}
chrome.runtime.sendMessage({type: "tab"}, function(response) {
console.log(response);
});
}
I am using Chrome 49.0.2623.112 (64-bit) on OSX.
Edit: Here is a screenshot of what happens the times it fails:
I want to precise again that it doesn't fail all the time (maybe 50% of the time?), which makes it even more weird and makes me believe there is a kind of "race" condition somewhere I am not aware of.
Problem solved: I had to disable, then re-enable all my other extensions. Seems like a bug from Chrome.
click the top and set the console in extension environmint
enter image description here
the background just run once.you should run more to check the resutl
this is my code it wroks well:
chrome.tabs.onUpdated.addListener(
function(tabId,info,tab){
if(info.status=="complete")
console.log("complete")
chrome.tabs.sendMessage(tabId, {greeting: "inupdate"}, function(response) {
console.log(response);
});
}
)
I just encountered the same problem. Typing "chrome.runtime" on the console and expanding the resulting object by clicking on the little triangle showed that it had only 1 function instead of many. In particular, chrome.runtime.onMessage was undefined.
On the page chrome://extensions I clicked the "Remove" button on the extension I was working on. I then clicked "Load unpacked" near the top of the page and selected the directory with my extension. After that, chrome.runtime was fully populated, and my extension ran correctly. I have no idea why that worked.
I think it has to do with the timeout function you are using, Google already has something called alarms which helps to schedule code to run periodically or at a specified time.
https://developer.chrome.com/apps/alarms
Try that instead of timeout
I have created a Chrome extension that, as part of it's operation, opens a new tab with a specified url.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
(Full code available on GitHub)
This works fine on tabs with webpages, but I cannot get it to work on empty tabs, for example: chrome://apps/ To clarify, if I have a tab open and it is on stackoverflow.com, then when I click on my extension button it opens a new tab loading a generated url. When I am on a new tab, or a tab where the url begins with chrome:// then the extension does not work.
What permissions do I need to include to allow the extension to open in ANY tab? Including new tabs and any chrome:// tab?
Manifest.json:
{
"manifest_version": 2,
"name": "MyMiniCity Checker",
"short_name": "MyMiniCity Checker",
"description": "Checks what your city needs most and redirects the browser accordingly.",
"version": "0.2",
"author":"Richard Parnaby-King",
"homepage_url": "https://github.com/richard-parnaby-king/MyMiniCity-Checker/",
"icons": {
"128": "icon-big.png"
},
"options_page": "options/options.html",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": ["tabs","storage","http://*.myminicity.com/","http://*/*", "https://*/*"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [ {
"matches": [ "http://*/*", "https://*/*"],
"js": [ "jquery-1.11.3.min.js" ]
}]
}
Background.js:
//When user clicks on button, run script
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "jquery-1.11.3.min.js" }, function() {
chrome.tabs.executeScript(null, { file: "contentscript.js" });
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
It appears as though the background.js file is not being executed. I suspect this to be a permissions. What permissions do I need in order to run this extension in every tab?
Well, this message is supposed to come from a content script you're trying to inject into the current tab.
The widest permission you can request is "<all_urls>", however, there are still URLs that are excluded from access.
You can only normally access http:, https:, file: and ftp: schemes.
file: scheme requires the user to manually approve the access in chrome://extensions/:
Chrome Web Store URLs are specifically blacklisted from access for security reasons. There is no override.
chrome:// URLs (also called WebUI) are excluded for security reasons. There is a manual override in the flags: chrome://flags/#extensions-on-chrome-urls, but you can never expect it to be there.
There is an exception to the above, chrome://favicon/ URLs are accessible if you declare the exact permission.
All in all, even with the widest permissions you cannot be sure you have access. Check for chrome.runtime.lastError in the callback of executeScript and fail gracefully.
As I was wanting this to run on EVERY page it meant I could not have the code in the content script. I moved all the code into the background script:
chrome.browserAction.onClicked.addListener(function(tab) {
//...
chrome.tabs.create({"url": newTabUrl});
//...
});
So when I click on my button the above code is called, using the enclosed jquery script.
I am listening to some form events (mouse dbl clicking some elements), raise an event and catch that event in my content script. I do not need any direct interaction with my extension by user.
Here is my page.js (content script):
chrome.runtime.sendMessage( { method: e.data.methodName, cid: e.data.cbId, jparams: e.data.jsonParams, objectVersion: e.data.objectVersion, objectFile: e.data.objectFile }, function( response ) {
if( !response ){
//errCallback();
}
} );
Popup:
var host_name = "nativeclientapi";
var messageData = null;
var port = null;
// Listen for messages that come from the content script.
chrome.runtime.onMessage.addListener(
function( request, sender, sendResponse ) {
if( request) {
messageData = request;
alert ('hello');
sendResponse( { res: 'done!' } );
}
} );
Manifest:
{
"name": "MyChromeExt.Operarations",
"version": "1.0",
"manifest_version": 2,
"description": "This extension calls a Native API which that API calls some operations.",
"icons": {
"128": "icon.png"
},
"permissions": [
"nativeMessaging", "activeTab"
],
"content_scripts" : [{"matches": ["http://localhost/*","https://localhost/*"], "js": ["page.js"]}]
}
Why alert is not called? If I add browser_action to the manifest and set a popup page, then it works, but I do not need to have any interaction with the extension.
Thanks for your help.
Why alert is not called?
Because with that manifest popup.js is not referenced anywhere, and never gets loaded. Your extension can have lots of unused files and Chrome will not guess what goes where.
Browser / Page actions are, of course, UI elements. If you don't want a UI (or want a persistent script that's "always there") you need a background page (or better yet an event page, but make sure you understand the difference).
All in all, take a look at the Architecture Overview.
I fixed it. Simply added a background page to the manifest:
"background": {
"persistent": false,
"scripts": ["bg.js"]
},