chrome extension notification with tabs - google-chrome-extension

I try make deskotp notification used chrome extension.
I would it can work like this - when user visit recomended page it will be show.
background.js
function show() {
var notification = window.webkitNotifications.createNotification(
'48.png',
'YOUR VISIT PAGE http://stackoverflow.com/!'
);
notification.show();
}
// Conditionally initialize the options.
if (!localStorage.isInitialized) {
localStorage.isActivated = true; // The display activation.
localStorage.frequency = 1; // The display frequency, in minutes.
localStorage.isInitialized = true; // The option initialization.
}
function checkForValidUrl(tabId, changeInfo, tab) {
if (tab.url.indexOf('stackoverflow') > -1) {
if (window.webkitNotifications) {
if (JSON.parse(localStorage.isActivated)) {
show();
}
}
}
}
chrome.tabs.onUpdated.addListener(checkForValidUrl);
manifest.json
{
"name": "YouVisit",
"version": "0.1",
"description":
"Show desktop notification when user visit page",
"icons": {"48": "48.png"},
"permissions": [
"notifications",
"tabs"
],
"background": { "scripts": ["background.js"] },
"manifest_version": 2,
"web_accessible_resources": [
"48.png"
]
}
any ideas why this code doesn't work? can someone give me some literature to make it proper?

You failed to provide the proper arguments for the createNotification() function:
According to the docs:
// Create a simple text notification:
var notification = webkitNotifications.createNotification(
'48.png', // icon url - can be relative
'Hello!', // notification title
'Lorem ipsum...' // notification body text
);

Related

Change the color of Send button of Gmail Compose dialog using chrome extension

I am making a chrome extension in which I want to change the color of the "Send" button of Compose dialog.
What is the best way to do it?
Thanks in advance!
Update-
Here is the function of content.js I am currently using to change the color-
function modifySendButton(check, form) {
var send_button = $(form).siblings('table').find('div[role="button"][aria-label="Send ‪(Ctrl-Enter)‬"]');
if (0 === send_button.length) {
send_button = $(this).siblings('table').find('div[role="button"][aria-label="Send ‪(⌘Enter)‬"]');
}
if (true === check) {
send_button.addClass("active-send-button");
} else {
send_button.removeClass("active-send-button");
}
}
It is changing the Send button color, but I want to know is it the right way to do so?
You can try to use mutation observer inside the content-script.
Complete example:
manifest.json
{
"manifest_version": 2,
"name": "Btn Color",
"description": "",
"version": "1.0.0",
"content_scripts": [{
"js": ["content-script.js"],
"matches": [
"https://mail.google.com/*"
],
"run_at": "document_end"
}],
"permissions": [
"tabs"
]
}
content-script.js
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.addedNodes && mutation.addedNodes.length) {
// look for the button
const sendBtn = document.querySelector('.dw [aria-label*="Send"]');
if(sendBtn) {
sendBtn.style.background = 'red'; // set your styles
}
}
});
});
var targetNode = document.body;
observer.observe(targetNode, {childList: true});

chrome.browserAction.onClicked cannot be triggered

I am working on some experiments that requires to auto generate IDs for elements, I have decided to go with chrome extension.
However, the content script only got triggered when I land on the homepage of the site (e.g. https://secure.checkout.visa.com/). Once I navigate to other pages (e.g. tap on "Create Account"), the script didn't get triggered, I tried to set a break point on the content script but it only got hit on the home page, but not on create account page.
Any idea what went wrong here? Below is the code:
// manifest.json
{
"manifest_version": 2,
"name": "Chrome Auto Gen ID",
"description": "Generate IDs",
"version": "1.0",
"permissions": ["activeTab"],
"background": {
"scripts": ["event_page.js"],
"persistent": false
},
"browser_action": {
"default_title": "Auto generate ID"
},
"content_scripts": [
{
"matches": ["https://secure.checkout.visa.com/*"],
"js": ["jquery-3.2.1.min.js", "auto_gen_id.js"],
"all_frames": true,
"run_at": "document_idle"
}
]
}
The content script:
// auto_gen_id.js
var divs = document.getElementsByTagName("div");
var inputs = document.getElementsByTagName("input");
var sections = document.getElementsByTagName("section");
var count = 0;
function genId(list) {
for (var i = 0; i < list.length; ++i) {
var element = list[i];
if (element.hasAttribute("id")) {
continue;
}
element.id = "gen-id-" + count++;
}
}
genId(divs);
genId(inputs);
The background script:
// event_page.js
chrome.browserAction.onClicked.addListener(function(tab) {
console.log('Generating IDs on ' + tab.url);
chrome.tabs.executeScript(null, {file: "auto_gen_id.js"});
});
Thanks #makyen and #wOxxOm, followed the suggestions below to solve the problem:
Is there a JavaScript/jQuery DOM change listener

Chrome extension : Is it possible to keep extension open on reload?

I'm building an google extension that inserts html in page and shows a menu on browser action icon click and I don't find way to keep my extension open when I reload the page. So on every reload, we have to active it again from Browser Action icon.
Below the manifest file
{
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "img/icone.png",
"default_title": "show menu"
},
"icons" : {
"128" : "img/icone_128.png",
"48" : "img/icone_48.png",
"32" : "img/icone_32.png",
"24" : "img/icone_24.png",
"16" : "img/icone_16.png"
},
"manifest_version": 2,
"name": "p|layer",
"version": "1.0.4",
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css":["css/grid.css", "css/font-awesome.min.css"],
"js":["js/jquery-1.11.1.min.js","js/jquery-ui.js", "js/jquery.nicefileinput.min.js"]
}
],
"web_accessible_resources": [
"fonts/fontawesome-webfont.woff"
],
"permissions": [ "activeTab"]
}
script (background.js) injecting contentscript
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
chrome.tabs.executeScript(tab.id,
{"file": "js/contentscript.js"},
function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
chrome.tabs.insertCSS(tab.id, {file: "css/grid.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/font-awesome.min.css"});
chrome.tabs.insertCSS(tab.id, {file: "css/slider.css"});
});
any help will be appreciated
So, from the comments the problem was inferred: your button click activates your content script, but a page reload clears it. Assuming you want the button click to act as a toggle:
1) Always inject the content script / CSS, but don't show the UI immediately:
"content_scripts": [
{
"matches": [ "<all_urls>"],
"css": ["css/grid.css", "css/font-awesome.min.css", "css/slider.css"],
"js": [
"js/jquery-1.11.1.min.js", "js/jquery-ui.js",
"js/jquery.nicefileinput.min.js", "js/contentscript.js"
]
}
],
2) Keep track of "activated" tabs:
var activeTabs = {};
chrome.browserAction.onClicked.addListener( function(tab){
var active;
if(activeTabs[tab.id]){
delete activeTabs[tab.id];
active = false;
} else {
activeTabs[tab.id] = true;
active = true;
}
/* (part 3) */
});
chrome.tabs.onRemoved.addListener( function(tabId){
delete activeTabs[tabId];
});
chrome.tabs.onReplaced.addListener( function(newTabId, oldTabId){
if(activeTabs[oldTabId]) activeTabs[newTabId] = true;
delete activeTabs[oldTabId];
});
3) Use messaging to show/hide UI:
Content script:
chrome.runtime.onMessage.addListener( function(message. sender, sendResponse){
if(message.showUI) showUI();
if(message.hideUI) hideUI();
});
Background script:
chrome.browserAction.onClicked.addListener( function (tab) {
var active;
/* (part 2) */
if(active) {
chrome.tabs.sendMessage(tab.id, {showUI: true});
} else {
chrome.tabs.sendMessage(tab.id, {hideUI: true});
}
});
Additional robustness can be added for the cases of extension reload, but that's the gist of it.

Inserting code into a Confluence page programmatically using a Chrome content script

I am trying to develop a Chrome extension to open Office documents stored in Confluence in a new tab using the IE Tab extension.
In the 'View Page Attachment' screen, there is an 'Edit in Office' link for Office file attachments. The link has a click event that creates a new instance of a URLLauncher, which is used to open the document. This feature is not supported in Chrome, so I want to add my own URLLauncher prototype into the web page to make it work.
In short, this is my idea:
Create a Chrome extension with a content script that injects a URLLauncher prototype into the 'View Page Attachment' page (I don't know if this is the right approach, so I am open to suggestions).
When the user clicks on the 'Edit in Office' link, the URLLauncher.open method opens the file attachment in a new tab by calling the IE Tab extension.
I can see the 'Hi there!' alert every time I load a web page, and that confirms that content.js is being injected. Nevertheless, the URLLauncher is not available in the web page. I think this is because the global window object of the content script is distinct from the page/extension's global namespace (i.e., window.URLLauncher is undefined). How could I reorganize my code to overcome this obstacle?
These are my files:
manifest.json
{
"manifest_version": 2,
"background": {
"scripts": [
"background.js"
]
},
"content_scripts": [ {
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
} ],
"description": "This is a test extension",
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"name": "Test extension",
"version": "1.0.0"
}
background.js
chrome.tabs.executeScript(null, {
code: "document.body.appendChild(document.createElement('script')).src='" +
chrome.extension.getURL("content.js") + "';"
}, null);
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.id == "doUrlLaunch") {
chrome.tabs.create({ url: request.nUrl, selected: true });
sendResponse({result: "goodbye"});
}
}
);
content.js
var prefixUrl = 'chrome-extension://hehijbfgiekmjfkfjpbkbammjbdenadd/iecontainer.html#url=';
alert('Hi there!');
function URLLauncher() {
}
URLLauncher.prototype = {
open : function(urlStr) {
var newUrl = prefixUrl + 'https://host.com' + encodeURI(urlStr);
chrome.runtime.sendMessage({id: "doUrlLaunch", nUrl: newUrl}, function(response) {
});
}
}
Thanks in advance.
UPDATE 1
I edited the files following the instructions given by Rob W and this page ('Message Passing'); now the code is injected in the page itself, but a major problem still remains. The actual JS code sends a message to the content script, but the message is not caught by the listener, so the new tab is not created and the callback function does not receive a response; the error message I got: Error in event handler for (unknown): TypeError: Cannot read property 'success' of undefined.
These are the updated files:
manifest.json
{
"manifest_version": 2,
"content_scripts": [ {
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
} ],
"web_accessible_resources": [ "script.js" ],
"description": "This is a test extension",
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"name": "Test extension",
"version": "1.0.0",
"externally_connectable": {
"ids": ["*"],
"matches": ["*://*.hostname.com/*"]
}
}
content.js
var s = document.createElement('script');
s.src = chrome.extension.getURL("script.js");
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
chrome.runtime.onMessage.addListener(
//Unreachable code!
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.id == "doUrlLaunch") {
chrome.tabs.create({ url: request.nUrl, selected: true });
sendResponse({result: "goodbye"});
}
}
);
script.js
var prefixUrl = 'chrome-extension://hehijbfgiekmjfkfjpbkbammjbdenadd/iecontainer.html#url=';
function URLLauncher() {
}
URLLauncher.prototype = {
open : function(urlStr) {
var newUrl = prefixUrl + 'https://hostname.com' + encodeURI(urlStr);
chrome.runtime.sendMessage({id: "doUrlLaunch", nUrl: newUrl}, function(response) {
if (!response.success)
console.log('Something went wrong...');
});
}
}
Not sure if you're still interested in an answer, but in your edited files your problem is where your listener sits.
chrome.runtime.sendMessage does not reach content scripts; it is intended for extension pages. Message passing to content scripts works through chrome.tabs.sendMessage, but this is irrelevant for this task.
Content scripts can't call chrome.tabs as they do not have the required API access.
A solution would be to call a background script, that can receive those messages and can call the required API.
Therefore, you need a third script, taking out this code from content.js:
// background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.id == "doUrlLaunch") {
chrome.tabs.create({ url: request.nUrl, selected: true });
sendResponse({result: "goodbye"});
}
}
);
And modify your manifest:
"background": { "scripts": [ "background.js" ] },

How to allow an extension for two domains only?

I've written a google chrome extension. It's okay and works now but I want the extension to be usebale only on two domains because it's written for these two websites only and is useless for others. There is a context menu only. For now it hasn't even popup, or action button in the top right corner (hidden by default). How can achieve this?
My current manifest.json:
{
"manifest_version": 2,
"background": {
"scripts": ["scripts/jquery.min.js", "scripts/background.js"]
},
"name": "Export Entries",
"description": "some descriptions here",
"version": "1.0",
"icons": {
"16": "images/logo.png",
"48": "images/logo.png",
"128": "images/logo.png"
},
"permissions": ["downloads", "tabs", "contextMenus", "http://my-own-domain-accessed-via-ajax-for-creating-some-files-there.com/*"],
"content_scripts": [{
"matches": ["*://allowed-domain1.com/*", "*://allowed-domain2.com/*"],
"css": ["styles/style.css"],
"js": ["scripts/jquery.min.js", "scripts/popup.js", "scripts/background.js"],
"run_at": "document_end"
}],
"web_accessible_resources": [
"images/logo.png"
]
}
As I understand the extension cannot be disabled absolutely, its process will run in background again. But it's not a problem. I just want to not display the context menu item on other websites.
background.js creates the context menu item and handles its click event:
function exportEntries(info, tab) {
if (info['linkUrl'].indexOf('domain1.com/user/') > -1) {
var user = info['linkUrl'].substr('27');
} else {
var user = null; // export all entries from this topic
}
$.ajax({
url: 'http://my-own-domain-which-creates-the-file.eu/exportEntries/create.php',
method: 'POST',
data: {
topic: tab.url,
user: user
}
}).done(function(url) {
forceDownload(url);
});
}
function forceDownload(url) {
var filename = url.replace(/^.*\/|\.[^.]*$/g, '');
chrome.downloads.download({
url: url,
saveAs: true
}, // options array
function(id) {
// callback function
}
);
};
document.addEventListener('DOMContentLoaded', function() {
chrome.contextMenus.create({
'title': 'Export Entries',
'contexts': ['link'],
'onclick': function(info, tab) {
exportEntries(info, tab);
}
});
});
create.php is on my own domain. It just gets the current page's URL and the user's nickname. Then export all entries from the given topic (i.e. page URL) for the given user, creates a file (.txt, .pdf etc.) and sends back url for downloading the file.
popup.html, popup.js, css file and other stuff is not used for now.
Remove all of your content scripts, they're useless, because the chrome.contextMenus API can only be used on the background page.
To limit the context menu entry to certain domains, pecify the documentUrlPatterns key when you create the context menu using the chrome.contextMenus.create:
chrome.contextMenus.create({
'title': 'Export Entries',
'contexts': ['link'],
'onclick': function(info, tab) {
exportEntries(info, tab);
},
'documentUrlPatterns': [
'*://allowed-domain1.com/*',
'*://allowed-domain2.com/*'
]
});
According to the content scripts documentation:
"If you want to inject the code only sometimes, use the permissions field instead, as described in Programmatic injection."
So instead of
"content_scripts": [
{
"matches": [ "http://allowed-domain.com" ]
}
],
use
permissions: [
"tabs", "http://allowed-domain.com"
],

Resources