I'm making a Chrome Extension.
I want to use a image file on other servers as an icon of webkitnotifications(Desktop notifications)
in Content Script
window.webkitNotifications.createNotification(
"http://www.example.com/icon48.png", "title", "text"
).show();
in manifest.json
"permissions": [
"tabs", "notifications", "http://*/*", "https://*/*"
]
but I got the following error
Uncaught Error: SECURITY_ERR: DOM Exception 18
The URL of the icon changes in many ways. So I cannot add all of them to "web_accessible_resources" in manifest.json beforehand.
So, how can I do the above ??
Thank you very much in advance.
In my extension, with Chrome 23, I can point to external icon url like this without any problem
var notification = webkitNotifications.createNotification(
'http://placehold.it/48x48', // no need to add to "web_accessible_resources" beforehand
title, // notification title
textToDisplay // notification body text
);
Related
I'm migrating V2 to V3, but encountered some strange problems.
When extension has loaded, i fetching the resource, it will has a error: net::ERR_BLOCKED_BY_CLIENT. but it's no problem when i do it without loaded extension.
like this:
without loaded extension
with loaded extension
Extension launch up with a error:
GET chrome-extension://hbdmkhahfinoeomfcllpnpkcblpaofeh/css/style.css net::ERR_BLOCKED_BY_CLIENT
'web_accessible_resources' in content.js
var css1 = doc.createElement("link");
css1.href = chrome.runtime.getURL("css/style.css");
css1.type = "text/css";
css1.rel = "stylesheet";
doc.head.appendChild(css1);
code in manifest.json
"web_accessible_resources" : [{
"resources": [ "css/*", "content/*" ],
"matches": ["<all_urls>"]
}],
Converting the txt file to html is the main responsibility of this extension.
I have disabled Adblock Plus, and try to fix this problem pass a whole day, I really don't know what happened in this condition and how to fix it.
Building a Chrome Extension that adds a devtools panel. That part is working. The dev tools panel needs to be able to grab information from the current page.
The only way I see how to do it, is using a content script. Ideally I don't want to require the "tabs" or "" permissions. I'm fine with them being optional permissions".
My content scripts that I inject only appear to work on the pages that I have specified in my manifest file. I want them to work on any page the user inspects so my panel can display information.
User clicks a button in panel - I request optional permissions for "tabs" and "" in my panel.js
my devtools page .js checks for "tabs" and "" permission.
If permission is granted, I send background.js a message - load this content script.
Recieving the message doesn't seem to matter on Background.js's end as the content script loads automatically regardless on URL's specified in the manifest. It does not however appear on pages you inspect.
CODE
(in order of how it was explained above)
Button in panel.html
<button id="load">Load Dev Info</button>
https://github.com/williamspiro/HubSpot-Developer-Extension/blob/c23b8cad6f1787264bb3e8b3673c594a7db5fe7e/panel.html#L8
Permission request in Panel.js
document.querySelector('#load').addEventListener('click', function(event) {
// Permissions must be requested from inside a user gesture, like a button's
// click handler.
chrome.permissions.request({
permissions: ['tabs'],
origins:['<all_urls>']
}, function(granted) {
// The callback argument will be true if the user granted the permissions.
if (granted) {
console.log("Perm granted");
} else {
console.log("Perm denied");
}
});
});
https://github.com/williamspiro/HubSpot-Developer-Extension/blob/c23b8cad6f1787264bb3e8b3673c594a7db5fe7e/panel.js#L2-L18
permissions check if granted - sendMessage with content script name to background JS and devtools.js(loaded on devtools.html)
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Handle responses from the background page, if any
});
console.log("devtools.js ran");
chrome.permissions.contains({
permissions: ['tabs'],
origins: ['<all_urls>']
}, function(result) {
if (result) {
// The extension has the permissions.
// Relay the tab ID to the background page
chrome.runtime.sendMessage({
tabId: chrome.devtools.inspectedWindow.tabId,
scriptToInject: "hsInspector.js"
});
} else {
// The extension doesn't have the permissions.
}
});
https://github.com/williamspiro/HubSpot-Developer-Extension/blob/c23b8cad6f1787264bb3e8b3673c594a7db5fe7e/devtools.js#L7-L35
Receive message to background.js - inject content script
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
// assign the listener function to a variable so we can remove it later
var devToolsListener = function(message, sender, sendResponse) {
// Inject a content script into the identified tab
console.log("script:",message.scriptToInject);
chrome.tabs.executeScript(message.tabId,
{ file: message.scriptToInject });
}
// add the listener
devToolsConnection.onMessage.addListener(devToolsListener);
devToolsConnection.onDisconnect.addListener(function() {
devToolsConnection.onMessage.removeListener(devToolsListener);
});
});
https://github.com/williamspiro/HubSpot-Developer-Extension/blob/c23b8cad6f1787264bb3e8b3673c594a7db5fe7e/background.js#L38-L52
It appears the background JS part does not matter, because in manifest I have the content script mentioned in the manifest causing it to get injected on all URL's that match but not inspected pages.
Permissions and content scripts in manifest.json
"permissions": [
"storage",
"activeTab"
],
"optional_permissions": [
"https://app.hubspot.com/*",
"https://app.hubspotqa.com/*",
"tabs",
"<all_urls>"
],
"web_accessible_resources": [
"mac-text-cursor.svg",
"mac-text-cursor.png"
],
"content_scripts": [{
"run_at": "document_idle",
"js": ["jquery-3.2.1.min.js", "design-manager.js","hsInspector.js"],
"css": ["hsDarkIde.css"],
"document_idle": "document_start",
"matches": ["https://app.hubspot.com/*", "https://app.hubspotqa.com/*"]
}],
"content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'",
https://github.com/williamspiro/HubSpot-Developer-Extension/blob/66ee912d56b88be052182a91257af28a4e356558/manifest.json#L25-L46
The content script I am trying to inject from the devtools is hsInspector.js
I only care to have this file get loaded if the devtools injects it. It doesn't need to load on the "matches" pages at all.
EXPECTED AND ACTUAL RESULTS
Expected result is that when inspecting a page, if you go to the extension's dev tools tab, and have the permissions required, the content script will be injected into the page.
[if that were working my goal would be to then make the content script do this]
Content script will be used to grab data from the page, message background.js the required data, background.js messages panel.js the data, panel js would render what it needs to in the panel.
Actual result: content script is not loading into the inspected page, but is instead loading onto the "matches" URLs specified under content_scripts.
If you have questions please ask. I am not an expert at building chrome extensions, so maybe I'm making this way more complicated than it needs to be. Really appreciate any help. Thank you in advance.
I'm creating a Chrome extension for the first time.
I've used chrome.notifications.create in it, but it does not work! This is my code:
chrome.storage.sync.get('refresh_time',function(items){
status = $('td.c').next().html();
if (status.trim() == 'SomeText') {
alert('Works');
var opt = {
type: "basic",
title: "Project1",
message: "This is my first extension.",
iconUrl: "icons/icon-128.png"
};
chrome.notifications.create('statusChanged', opt, function(){});
}
})
I get the alarm after execution, but chrome notification does not work! May you tell me what is wrong in my code?
By the way, I used the code below in my manifest file.
"permissions" : [
"storage",
"notifications",
"tabs"
]
I think you need to make iconUrl a chrome extension path, something like this:
iconURL: chrome.runtime.getURL("icons/icon-128.png")
I think that the code is good. However, I guess that you need to confirm the iconUrl path. If the file specified by the path does not exist, the notification will not be displayed. At the time, you may see the following error message on the console tab of the DevTools:
Unchecked runtime.lastError while running notifications.create: Unable to download all specified images.
You need to specify the valid path for the iconUrl value.
For me, the notifications were disabled on windows. Make sure that "Get notifications from apps and other senders" is enabled.
Probably, you need to modify the image path as:
iconUrl: "../icons/icon-128.png"
UPDATE
From what I can tell, it is impossible to send a message from the background script to the content script using the "sendMessage" function. However there is a horrible workaround,
In your content script's window.onload, send a message to the background script:
chrome.runtime.sendMessage( { action: "messaging", window: "app" }, this.listenForFutureMessages );
Also in the content script, have the following function:
listenForFutureMessages: function(someAction)
{
//Take some action based on the message
//If we want the background script to be able to contact
//us again, we need to give them another callback. This
//is because Chrome only allows one use per callback
chrome.runtime.sendMessage( { action: "messaging", window: "app" }, this.listenForFutureMessages );
},
In the background script, have a listener that does something like this:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
{
if ( request.action === "messaging" )
{
//Save the callback for later
this.listeners[ request.window ] = sendResponse;
//Tell chrome we will be using the callback later
return true;
}
}
);
When your background script wants to send the content script a message, simply call it like this:
this.listeners[ "app" ]( { someProperty: "some value" } );
This is a stupid way to do this, but it makes this actually possible. Hope this helps anyone else who needs this functionality.
ORIGINAL
I'm unable to send a message from my background script to a content script. When I try to find the tab id, it tells me I don't have permissions even though my app has that permission. And when I receive a message from the content script, and print out the sender object, it shows tab.id = -1. The API to send a message to a content script requires a tab id!
chrome.tabs.sendMessage(integer tabId, any message, function responseCallback)
The error:
chrome.tabs is not available: You do not have permission to access this API. Ensure that the required permission or manifest property is included in your manifest.json.
Error in event handler for 'undefined': Cannot call method 'sendMessage' of undefined TypeError: Cannot call method 'sendMessage' of undefined
at chrome-extension://panoaieakcofaegcjfbmhndaekfgpijh/scripts/background.js:109:16
at Event.dispatchToListener (event_bindings:356:21)
at Event.dispatch_ (event_bindings:342:27)
at Event.dispatch (event_bindings:362:17)
at miscellaneous_bindings:167:33
at Event.dispatchToListener (event_bindings:356:21)
at Event.dispatch_ (event_bindings:342:27)
at Event.dispatch (event_bindings:362:17)
at Object.chromeHidden.Port.dispatchOnMessage (miscellaneous_bindings:253:22)
So how do I contact my content script? (I have multiple windows and need to be able to contact them individually)
My manifest:
{
"manifest_version": 2,
"name": "App",
"description": "App",
"version": "0.75",
"minimum_chrome_version": "27",
"offline_enabled": true,
"icons":
{
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
},
"app":
{
"background":
{
"scripts":
[
"scripts/background.js"
]
}
},
"permissions":
[
"unlimitedStorage",
"fullscreen",
{
"fileSystem":
[
"write"
]
},
"background",
"<all_urls>",
"tabs"
],
"update_url": "http://192.168.1.121/app.xml"
}
There's not such a thing called "Content scripts" in a Chrome app. Your manifest file looks like a mixture of a Chrome extension. Open chrome://extensions/, enable developer mode, and you would see a warning that the "background" and "tabs" permissions are invalid for a Chrome app.
If you're implementing a Chrome app, just use chrome.runtime.sendMessage and chrome.runtime.onMessage. These messages can be send from and to your event page and the main page. For example:
// event page (aka background page)
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('main.html');
});
// Later, when you want to notify the app window
chrome.runtime.sendMessage(" ... any message ... ");
<!-- main.html -->
<script src="main.js"></script>
// main.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
// Do something with the message
});
I do want to check the content written in Chrome omnibox and redirect to the proper page.
Still, I cannot use specific keywords because I do want to redirect things like BUG-1234 to http://bugs.example.com/BUG-1234
I do have a regexp for this (as the BUG part can have lots of values).
How can I do this?
A chrome extension can help you, with help of Omnibox.
If i understood correctly when you enter BUG-1234 and hit Enter in Omnibox, your webpage URL Should be http://bugs.example.com/BUG-1234
Demonstration
I have used keyword as
"keyword": "BUG"
BUG, you can change it as per functionality. So when you enter B+U+G in chrome Omnibox , the search provider adds a custom layer as shown here
Image 1)
and when you enter 1234 and hit Enter or Select the suggested URL Open Bug %s ? in Omnibox, as shown here
Image 2)
It opens a web page with URL as shown here, where i used http://bugs.example.com as a test URL, which can be extended further.
Image 3)
manifest.json
Registered background Page and Omnibox with Chrome Extension, and added related permissions.
{
"name": "Bug Tracker",
"description": "This integrates chrome omnibox with bug search",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": [
"background.js"
]
},
"omnibox": {
"keyword": "BUG"
},
"permissions": [
"<all_urls>"
]
}
background.js
Script for Custom Suggestions
//Set Text to show for custom suggested URL(s)
chrome.omnibox.setDefaultSuggestion({
"description": "Open Bug %s ?"
});
//Fired when Enter or a suggested Link is selected
chrome.omnibox.onInputEntered.addListener(function (bugId) {
//Use your custom URL
chrome.tabs.update({
"url": "http://bugs.example.com/BUG-" + bugId
}, function () {
console.log("Bug Page is open");
});
console.log("Input Entered is " + bugId);
});
References
Background Pages
Omnibox API
Manifest File