Chrome extension and history.onVisited event - google-chrome-extension

I'm new to the Chrome extensions development, and i have the following questions:
My extension should work in background, with no UI, and show an alert dialog every time the user visits a specific web page. So it should work always, in backround, when the browser is executed.
I was trying with the following code without results:
manifest.json
{
"name": "My First Extension",
"version": "1.0",
"description": "The first extension that I made.",
"background_page": "background.html",
"permissions": [
"history"
]
}
background.html
<html>
<head>
<script>
chrome.history.onVisited.addListener(function(HistoryItem result) {
if (result.url == "http://my.url.com") {
alert("My message");
}
});
</script>
</head>
</html>
What's wrong with this code?
Thanks

Take HistoryItem out of the function and you are fine:
<html>
<head>
<script>
chrome.history.onVisited.addListener(function(result) {
if (result.url == "http://my.url.com/") {
alert("My message");
}
});
</script>
</head>
</html>
Also note that I added the slash at the end of "http://my.url.com/" since that is what will be returned in result.url.

Test this:
<script>
chrome.history.onVisited.addListener(function(e) { console.log(e)})
</script>
it's clearly

Related

Chrome extension: Receiving error while making extension

I'm developing a chrome extension. It will make it possible to press a button, and it will capture a screenshot of your screen, then you will be able to save it to your computer.
However after attempting to load my extension at chrome://extensions/
I'm getting either of 2 messages:
"Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."
"Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem:". Either the 'unsafe-inline' keyword, a hash ('sha256-0xoq3Fm+45tEb3FQIwY9RYnpdCuDu/FcIzz/s1HPTAM='), or a nonce ('nonce-...') is required to enable inline execution."
I've been at this for a long time now and can't seem to find the problem. I have inserted the codes below, can anyone help me fix this?
Might be even the smallest oversight from my part, but would be super grateful for any help.
See code below:
manifest.json
{
"manifest_version": 2,
"name": "MySnap",
"description": "Take a screenshot of a selected portion of the screen",
"version": "1.0",
"permissions": [
"tabs",
"activeTab"
],
"browser_action": {
"default_icon": "icon.png",
"default_title": "MySnap",
"default_popup": "popup.html"
},
"content_security_policy": "script-src 'self' 'sha256-Ws4H0eytNaM/o8NllzTlOPZFeyohSxu1N5dQ7JOcjMI='"
}
popup.html
<!DOCTYPE html>
<html>
<head>
<title>MySnap</title>
</head>
<body>
<h1>MySnap</h1>
<button id="screenshot-button">Take Screenshot</button>
<div id="screenshot-container"></div>
<script src="screenshot.js"></script>
<script>
document.getElementById("screenshot-button").addEventListener("click", function() {
chrome.runtime.sendMessage({message: "take_screenshot"}, function(response) {
// Do something with the response
});
});
</script>
<script>
function takeScreenshot() {
chrome.runtime.sendMessage({message: "take_screenshot"}, function(response) {
if (response && response.screenshotUrl) {
// Create a link element and set its href to the screenshot URL
var link = document.createElement("a");
link.href = response.screenshotUrl;
// Set the download attribute of the link element
link.download = "screenshot.png";
// Append the link element to the DOM
document.body.appendChild(link);
// Click the link to initiate the download
link.click();
// Remove the link element from the DOM
document.body.removeChild(link);
}
});
}
</script>
</body>
</html>
screenshot.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.message === "take_screenshot") {
chrome.tabs.captureVisibleTab(null, {}, function(screenshotUrl) {
sendResponse({screenshotUrl: screenshotUrl});
});
}
return true;
});
background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.message === "take_screenshot") {
chrome.tabs.captureVisibleTab(null, {}, function(screenshotUrl) {
sendResponse({screenshotUrl: screenshotUrl});
});
}
});
You can make the screenshot in the popup script, no need for messaging.
remove content_security_policy from manifest.json
remove all <script> elements from popup.html except <script src="screenshot.js">
remove background.js
// popup.html:
<!DOCTYPE html>
<h1>MySnap</h1>
<button id="screenshot-button">Take Screenshot</button>
<div id="screenshot-container"></div>
<script src="screenshot.js"></script>
// screenshot.js:
document.getElementById('screenshot-button').onclick = () => {
chrome.tabs.captureVisibleTab(url => {
const el = document.createElement('a');
el.href = url;
el.download = 'screenshot.png';
document.body.appendChild(el);
el.click();
el.remove();
});
};

Performing browser action on two different pages

I have below files with me
manifest.json
{
"name": "Get Response URL",
"version": "1.0",
"manifest_version": 2,
"name": "Test" ,
"browser_action": {
"icon":"icon.png"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icon.png"
},
"permissions":["https://myblog.com/*"] ,//Put All your URL here
"manifest_version": 2
}
background.js
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
if (tab.url.indexOf("https://myblog.com/page1.html")==0) { // Inspect whether the place where user clicked matches with our list of URL
chrome.tabs.executeScript(tab.id, {
"file": "page2.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
else if (tab.url.indexOf("https://myblog.com/page2.html")==0) { // Inspect whether the place where user clicked matches with our list of URL
chrome.tabs.executeScript(tab.id, {
"file": "page1.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
});
Page1.html
<html>
<head>
<title>Page1</title>
</head>
<body>
<input type='button' name='submit' id='myBtn' value='click here to move to next page' onclick="document.location.href='page2.html';" />
</body>
</html>
page2.html
<html>
<head>
<title>Page2</title>
</head>
<body>
<input type="text" name="textBox" id="myText" />
</body>
</html>
And to two JavaScript files page1.js and page2.
page1.js
var button=document.getElementById("myBtn");
button.click();
Page2.js
document.getElementById("myText").value="Text Box";
I have developed a Chrome extension. On first page when I click the Chrome extension icon the functionality is working good as per JavaScript file(page1.js) for https://myblog.com/page1 page.
And what I am doing on https://myblog.com/page1 page with the help of page1.js is to just click a button to move to second page that is https://myblog.com/page2. Now I want that page2.js should wrok on page https://myblog.com/page2 as scripted(page2.js) but its not working.
Script is working good when I click the extension icon on page1 and then again click the extension icon on page2.
But I want to extension icon should be clicked on page1 not repetitively.
Edited the Question
Added page1.html and page2.html
page1.js and page2.js
Is it possible to doing the same.
If yes where I am doing the mistake?
here's what you need to do.
Your code block chrome.browserAction.onClicked.addListener(function (tab) { makes the JS functions to execute only when you click the icon. That's why your Page 1 works whereas the Page 2 doesn't.
You want the page2.js to run as soon as the Page2.html is opened right? Hence change the coding of your Page2.html. Add the below code in the page2.html itself.
document.addEventListener("DOMContentLoaded", function(event) {
//Do work
});
What this will do is, as soon as the Page2.html is loaded, it will execute the Javascript. Eventhough it works in most of the browsers, but for IE 8 and below it won't.
If you need for IE 8 and below too, then try using the following code:
<script type="text/JavaScript">
function funtionToBeCalled(){
// code that will be exected after dom ready
}
window.onload=funtionToBeCalled;
</script>

Chrome extension: managing multiple html pages in an extension

I want to have several html files in my extension so I can open each of them according to some conditions or events. Say I want a.html to be opened when the user chooses an option on the context menu.
I tried the following:
manifest.json:
{
"name": "My extension",
"version": "1.1",
"background": { "page": ["background.html"] },
"incognito": "split",
"permissions": ["tabs", "<all_urls>", "contextMenus"],
"icons": { "16": "images/16.png" },
"manifest_version": 2
}
background.html:
<!DOCTYPE html>
<html>
<head>
<script src="background.js"></script>
<script src='someWindow.js'></script>
</head>
<body>
</body>
</html>
background.js:
var winID;
chrome.contextMenus.onClicked.addListener(function proccess_interested(info, tab){
chrome.tabs.create({active: false}, function(newTab) {
// After the tab has been created, open a window to inject the tab into it.
chrome.windows.create(
{
tabId: newTab.id,
type: "popup",
url: chrome.extension.getURL('a.html'),
focused: true
},function(window){
winID = newWindow.id;
});
});
})
chrome.extension.onMessage.addListener(function(Msg, sender, sendResponse) {
if(Msg.close_comment_win){
chrome.windows.remove(winID, function(){});
}
});
someWindow.js:
function hide_win()
{
chrome.extension.sendMessage({close_win: close}, function(response) {});
}
a.html:
<!DOCTYPE html>
<html>
<head>
<script src='someWindow.js'></script>
head //with tags, can't show it here
body
<input type='button' value=' Cancel ' onclick="hide_win()"></input>
</body>
</html>
The window is opened when context menu is clicked, but when hitting cancel, it's not closed. console.log says: Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". I guess the reason is that a.html is not part of the extension, even though someWindow.js which triggers sendMessage is part of the extension.
Including a.html in the extension through manifest isn't an option as no more than one background html page can be included.
Of course I get the same when putting chrome.windows.remove(winID, function(){}); directly in hide_win() without using sendMessage.
Any ideas how to get this job done?
Just as the error says, it is against v2's content security policy to have any inline code in extension html pages. Simply move that handler to your js file and it should work fine.

How to make a extension/script/program that will refresh a browser until a certain phrase/keyword is found or is not found?

Is there any program/extension that I can use with browser that will refresh a webpage and search for a certain phrase or text and then stop once the phrase is found or is not found.
For example say I made a site that cycles using a randomizer through the words "One," "Two," and "Three."
This program would refresh the page until the word "Three" is found, If I set it to find that word, and then stop once it is found.
OR
This program would refresh the page until the word "Three" is not found, If I set it to find that word, and then stop once it is not found.
I know that we can use curl and grep to do that, but the page is not loaded on webbrowser. This is not what I want. see if there is solution that we can load on browser as well
If there no such things exists, any idea on how to write this kind of program? use what tool to do that?
You could very easily write an extension to do this. I would suggest instead of refreshing the page every time, you poll the data until you get the desired result then refresh the page once you find it. A short example using jQuery because I am familiar with it:
Manifest.json
{
"name": "Find Text",
"version": "0.1",
"description": "Find Text",
"manifest_version": 2,
"browser_action": {
"default_icon": "on.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs","http://*/*","https://*/*"
],
"background": {
"scripts": ["bgp.js","jquery-1.8.3.min.js"],
"persistent": true
}
}
Popup.html
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 300px; }
</style>
<script src="jquery-1.8.3.min.js"></script>
<script src="popup.js"></script>
</head>
<body>
<div>Desired Search Url</div>
<input type="text" id="searchUrl">
<div>Desired Search Text</div>
<input type="text" id="searchText">
<button id="searchButton">Search</button>
</body>
</html>
Popup.js
$(function(){
var tabId;
chrome.tabs.query({active:true,currentWindow:true}, function(tab) {
$('#searchUrl').val(tab[0].url);
tabId = tab[0].id;
});
$('#searchButton').click(function(){
chrome.extension.sendMessage({
url:$('#searchUrl').val(),
text:$('#searchText').val(),
tab:tabId
});
});
});
bgp.js
chrome.extension.onMessage.addListener(function(message,sender,sendResponse){
checkUrlForText(message.url,message.text,message.tab);
});
function checkUrlForText(url,text,tab){
var contains;
$.ajax({
url:url,
async:false,
success: function(data){
contains = $(':contains('+text+')',data);
while(contains.length == 0){
$.ajax({
url:url,
async:false,
success: function(dat){
contains = $(':contains('+text+')',dat);
}
});
}
}
});
chrome.tabs.reload(tab);
}
If having it refresh the tab every time is a requirement (the content would change between the time it found what you were looking for and when it refreshes the page) then you should use content scripts to test for the desired value and send a message to the background page if the desired text is not there to refresh the page and start again. Like this:
bgp.js
var contains;
chrome.extension.onMessage.addListener(function(message,sender,sendResponse){
checkTabForText(message.text,message.tab);
contains = false;
});
function checkTabForText(text,tab){
chrome.tabs.executeScript(tab,{file:"jquery-1.8.3.min.js"});
chrome.tabs.executeScript(tab,{file:"checkText.js"},function(){
chrome.tabs.sendMessage(tab, {text:text}, function(response){
contains = response.contains;
if(!contains){
chrome.tabs.reload(tab,function(){
checkTabForText(text,tab);
});
}
});
});
}
checkText.js
chrome.extension.onMessage.addListener(function(message,sender,sendResponse){
var contains = $(':contains('+message.text+')');
if(contains.length > 0)
sendResponse({contains:true});
else
sendResponse({contains:false});
});

Trivial Chrome pageAction extension not working

I'm trying to write a trivial Chrome pageAction extension to change all anchors on a page from one domain to another... but I can't quite seem to get it to work, and I'm having trouble debugging it.
Am I misunderstanding how this kind of extension needs to be built? Or am I just misusing the API?
manifest.json:
{
"name": "theirs2ours",
"version": "1.0",
"description": "Changes all 'their' URLs to 'our' URLs.",
"background_page": "background.html",
"permissions": [
"tabs"
],
"page_action": {
"default_icon": "cookie.png",
"default_title": "theirs2ours"
},
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["content.js"]
}
]
}
background.html:
<html>
<head>
<script type='text/javascript'>
chrome.tabs.onSelectionChanged.addListener(function(tabId) {
chrome.pageAction.show(tabId);
});
chrome.tabs.getSelected(null, function(tab) {
chrome.pageAction.show(tab.id);
});
chrome.pageAction.onClicked.addListener(function(tab) {
chrome.tabs.sendRequest(tab.id, {}, null);
});
</script>
</head>
<body>
</body>
</html>
content.js:
var transform = function() {
var theirs = 'http://www.yourdomain.com';
var ours = 'http://sf.ourdomain.com';
var anchors = document.getElementsByTagName('a');
for (var a in anchors) {
var link = anchors[a];
var href = link.href;
if (href.indexOf('/') == 0) link.href = ours + href;
else if (href.indexOf(theirs) == 0) link.href = href.replace(theirs, ours);
}
};
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
transform();
});
I think this is not the way to do the extension you want.
First of all, I assume you want to replace the anchors when you click the page action button.
The manifest you have injects content.js on every page, no matter if you click or not the page action button.
I suggest you remove the content_scripts field from your manifest, and inject content.js manually, with
chrome.tabs.executeScript(tabId, {file:'content.js'})
You should do this in the page action's click listener.
By the way, in that listener you are sending a request to the content script, but it hasn't a listener to listen to such request message. In this extension you won't need to use senRequest.
You're not requesting permission to run content scripts on these pages. The matches for content scripts determines what pages they are executed in but you still need to request permission to inject scripts in to these pages.
"permissions": [
"tabs",
"http://*/*"
]

Resources