Capture link a user clicks on a page - google-chrome

I am playing around with making an extension. If a user has the extension installed, I would like to capture the link they clicked on a web page. Not quite sure how to do this, but it seems simple. I might add, I would like this to happen as long as the plugin is installed and enabled, but DON'T want the user to have to do anything in the toolbar to 'activate' it.
Not sure how to start. And I figure I have one too many JS files, but just trying to get one of them to log to the console. Neither do. My end goal is I would like to redirect them to an intranet page if they go to certain places.
background.js
var redirectedSites = ["https://www.facebook.com/profile.php?id=<SOMEPROFILEID>"];
// when the browser tries to get to a page, check it against a list
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
console.log('is this even getting hit?');
for(var i=0; i < redirectedSites.length; ++i) {
// if the attempt is to a listed site, redirect the request
if( details.url == redirectedSites[i] )
return {redirectUrl: "http://intranet/landing?from=" + details.url };
}
},
{urls: ["*://www.facebook.com/*"]},
["blocking"]
);
manifest.json
{
"name": "Capture Click",
"version": "0.1",
"description": "Simple tool that logs clicked links.",
"permissions": [
"tabs",
"webRequest",
"webRequestBlocking",
"https://*.facebook.com/*"
],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2
}

I've given some advice in the comments, but the best way to solve your actual larger problem is with a webRequest handler:
var redirectedSites = ["http://www.google.com/foobar", ...];
// when the browser tries to get to a page, check it against a list
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
for(var i=0; i < redirectedSites.length; ++i) {
// if the attempt is to a listed site, redirect the request
if( details.url == redirectedSites[i] )
return {redirectUrl: "http://intranet/landing?from=" + details.url };
}
},
{urls: ["*://www.google.com/*"]},
["blocking"]);
This is a really simple example, but I hope you get the idea. Here, details.url is the page the user is trying to get to, and the returned object has a redirectUrl property that redirects the attempt to visit the page. My example checks details.url against a list of target sites; you could use a regex or something else that's more robust.
Note that this will affect not only clicked links and typed-in URLs, but also resources (scrips, images) and Ajax requests.

Related

Content script code is not being executed

I've taken a look at other related SO posts and the solutions haven't helped solve my issue. This is my first chrome extension, so please bear with me!
I'm writing a simple chrome extension that searches for user provided keywords on a webpage. I can't get the content script that returns the DOM content to run. Some of the code, I've taken from an answer in another SO post, but I can't seem to get it to work for me.
I put a console.log("hello world") at the top of the file, and it doesn't show up, so I think it might be the structure of my project.
manifest.json
{
"name": "keyword search",
"version": "0.0.1",
"manifest_version": 2,
"permissions": [ "tabs" , "storage", "activeTab", "<all_urls>"],
"browser_action": {
"default_popup": "html/form.html"
},
"content_scripts": [{
"matches": [ "<all_urls>" ],
"js": [ "js/jquery.min.js", "content_scripts/content_script.js" ]
}],
"homepage_url": "http://google.com/"
}
js/popup.js
function run() {
running = true;
console.log('running');
var url = "https://www.stackoverflow.com/"
// Get KW & category for search
chrome.storage.local.get(["kw"],
function (data) {
kw = data.kw;
console.log("redirecting to find kw: " + kw);
// Send current tab to url
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.update(tabs[0].id, {url: url});
chrome.tabs.sendMessage(tabs[0].id, {type: 'DOM_request'}, searchDOM);
});
}
);
}
function searchDOM(domContent) {
console.log("beginning dom search \n" + domContent);
}
content_scripts/content_script.js
// Listen for messages
console.log("hello world")
chrome.runtime.onMessageExternal.addListener(function (msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.type === 'DOM_request') {
// Call the specified callback, passing
// the web-page's DOM content as argument
sendResponse(document.all[0].outerHTML);
}
});
console
running
redirecting to find kw: TestKeyword
beginning dom search
undefined
First, onMessageExternal is the wrong event (it's for external messaging):
you should use the standard onMessage.
Second, chrome extensions API is asynchronous so it only registers a job, returns immediately to continue to the next statement in your code without waiting for the job to complete:
chrome.tabs.update enqueues a navigation to a new URL
chrome.tabs.sendMessage enqueues a message sending job
the current page context in the tab gets destroyed along with the running content scripts
the tab starts loading the new URL
the message is delivered into the tab but there are no listeners,
but this step may instead run right after step 2 depending on various factors so the content script running in the old page will receive it which is not what you want
the tab loads the served HTML and emits a DOMContentLoaded event
your content scripts run shortly after that because of the default "run_at": "document_idle"
There are at least three methods to properly time it all:
make your content script emit a message and add an onMessage listener in the popup
use chrome.tabs.onUpdated to wait for the tab to load
use chrome.tabs.onUpdated + chrome.tabs.executeScript to simplify the entire thing
Let's take the executeScript approach.
remove "content_scripts" from manifest.json
instead of chrome.tabs.query (it's not needed) use the following:
chrome.tabs.update({url}, tab => {
chrome.tabs.onUpdated.addListener(function onUpdated(tabId, change, updatedTab) {
if (tabId === tab.id && change.status === 'complete') {
chrome.tabs.onUpdated.removeListener(onUpdated);
chrome.tabs.executeScript(tab.id, {
code: 'document.documentElement.innerHTML',
}, results => {
searchDOM(results[0]);
});
}
});
});

I am developing a Google Chrome Extension and I need to limit the usage of the extension. What's the best way to do that?

I do not want to use a service, and want to let the app locally figure out when it has been used for X hours (either continuously or in parts). After that, I want to terminate the functionalities and just show an error like "quote over" or something.
One basic idea would be calculating the duration between every browser start/close event, in the meanwhile start a timer everytime the browser starts with an interval equals with MAX_TIME - TIME_USED.
However, as per the description here, Event onBrowserClose for Google Chrome Extension? There is no onBrowserClose event and if using background permissions, chrome will run(invisibly) as soon as the user logs into the computer and it also makes chrome continue running until the user explicitly quits chrome. I believe it's not a good way.
I think the following could a workaround, though it is not that perfect.
You could start a timer with small interval (Depending on how many hours you would want users to use, I believe 1 minute may be a good choice). Code snippets would look like
manifest.json
{
"manifest_version": 2,
"name": "36683192",
"description": "36683192",
"version": "1.0",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"storage"
]
}
background.js
setInterval(function () {
chrome.storage.local.get("usageInMinutes", function (result) {
var usageInMinutes = result.usageInMinutes;
if (typeof usageInMinutes === "undefined") {
chrome.storage.local.set({ usageInMinutes: 1 });
} else {
usageInMinutes += 1;
if (usageInMinutes >= MAX_USAGE_IN_MINUTES) {
// Your usage has expired
} else {
chrome.storage.local.set({ usageInMinutes: usageInMinutes });
}
}
});
}, 1000 * 60);

Chrome extension run_at every post request it makes?

I have figured out how to run a script on every page load when it is done explicitly by user but I want to run my script each time it makes a post or get request in its back end on its own to the database or ad server implicitly. [For example on gmail if we keep our eyes on requests (maybe firebug - console - all) we will see that after certain time a POST request is getting fired from the browser on its own. ]
Is there any way I can do that?
Actually I am writing my first extension so it clearly states I don't know much about it.
You should use webRequest module in your extension. After specifing proper permissions in the manifest, for example:
"permissions": [
"webRequest",
"*://*/*"
],
"background": {
"scripts": ["background.js"]
},
you can register in your background page ("background.js" in the example) any required handlers, such as onBeforeRequest, onBeforeSendHeaders, onHeadersReceived, onCompleted, and others. I think the names are self-explaining, but you can consult with abovementioned documentation.
Depending from your requirements, you can define event handlers which prevent requests, modify headers, just read and somehow analyse http-headers.
Example for reading http headers and possibly changing them:
chrome.webRequest.onBeforeSendHeaders.addListener(
function(details)
{
console.log(details.url);
if(details.method == 'POST')
{
// do some stuff
for(var i = 0; i < details.requestHeaders.length; ++i)
{
// log or change some headers
// details.requestHeaders[i].name
// details.requestHeaders[i].value
}
}
return {requestHeaders: details.requestHeaders};
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]);

Chrome Tabs URL Redirecting

Good evening everyone ,
I am beginning a chrome extension and in a certain scenario I need to redirect (change URL) of a user's tab .
Here's my code
function changeTabURL(tabName,addr) {
var tabId=parseInt(localStorage.getItem(tabName)); //fetch tab ID
chrome.tabs.update(tabId,{"url":addr});
}
Now here's what's happening , The Chrome:// ... thing is being prepended to my URL !
Say I try to redirect the tab to 'http://www.google.com' , this is what happens :
"No webpage was found for the web address: chrome-extension://oihdngeahhchnacpilhnmaknneooabbc/http://www.google.com"
I can't shake this ! I've tried resetting the URL first
chrome.tabs.get(tabId,function(tab) {
tab.url='';
alert(tab.url);
});
chrome.tabs.update(tabId,{"url":addr});
}
nothing I do shakes this .
Any thoughts?
Since you are already using the chrome.tabs API, you may want to try using chrome.tabs.query to find the active tab and get it's id that way. Here's an example:
queryInfo = new Object();
queryInfo.active = true;
chrome.tabs.query(queryInfo, function(result) {
var activeTab = result[1].id;
updateProperties = new Object();
updateProperties.url = 'YOUR_URL_HERE';
chrome.tabs.update(activeTab, updateProperties, function() {
// Anything else you want to do after the tab has been updated.
});
});
have you set the permission in your manifest.json like this:
"permissions": [
"notifications",
"contextMenus",
"tabs",
"contentSettings",
"http://*/*",
"https://*/*"
]

Working with multiple HTML files in Chrome extension

I have the following question:
I am writing a chrome extension that works with context menu over text selection. one of the things that I want to do is to create a new tab that is based on one of my html files that I create dynamically using the data I received at the text selection.how do I communicate between my javascript file that is connected to my background.html and my other html file in order to get to its' DOM and alternate it's contents?
my manifest.json:
{
"name": "My flickr Extension",
"version": "1.0",
"description": "The first extension that I made.",
"icons": {
"16": "icon.png"},
"background_page":"background.html",
"permissions": ["tabs",
"http://api.flickr.com/","contextMenus","http://*/*","https://*/*"
]
}
my background.html:
<script src="ext.js"></script>
my ext.js main functions:
function searchSelection(info,tab){
var updated=makeNewString(info.selectionText);
var xhReq = new XMLHttpRequest();
xhReq.open(
"GET",
"http://api.flickr.com/services/rest/?method=flickr.photos.search&text="+updated+"&api_key=a0a60c4e0ed00af8d70800b0987cae70&content_type=1&sort=relevance",
true);
xhReq.onreadystatechange = function () {
if (xhReq.readyState == 4) {
if (xhReq.status == 200) {
var photos = xhReq.responseXML.getElementsByTagName("photo");
var urlOfNew=chrome.extension.getURL('results.html');//this is me getting the link of the other html page that i want to update
//here I want to manipulate the results.html DOM like adding images depending on the photos and other stuff
chrome.tabs.create({"selected":true,"url":urlOfNew});
}
};
};
xhReq.send(null);
}
var context="selection";
var id = chrome.contextMenus.create({"title": "search Flickr", "contexts":[context],"onclick":searchSelection});
Take a look at Message Passing, http://code.google.com/chrome/extensions/messaging.html, it has detailed examples on how to send messages from Content Script to Extension Page.
Since you are just communicating in the same page (background page), why are you having any trouble? You can just use normal JavaScript to pass variables around.