Inject HTML signature into Gmail from hosted page - google-chrome

I have the basic shell of a Chrome extension done and have come to the point where I am trying to inject an HTML signature into Gmail using code hosted on an unindexed page on my site. The reason I want to do this is to be able to include web fonts, something that for the life me I can't figure out why Gmail hasn't allowed you to do from their font library.
In any regard, as I said, I have a right-click context menu option ready to trigger a script from my js function page and the extension loads without errors. I need to figure out the best way to inject the HTML into the email and without losing any of the formatting that has been done on the page.
I have created the extension manifest, set the permissions on the context menu and created a function to call back to the js page that will inject the signature.
var contextMenus = {};
contextMenus.createSignature =
chrome.contextMenus.create(
{"title": "Inject Signature",
"contexts": ["editable"]},
function (){
if(chrome.runtime.lastError){
console.error(chrome.runtime.lastError.message);
}
}
);
chrome.contextMenus.onClicked.addListener(contextMenuHandler);
function contextMenuHandler(info, tab){
if(info.menuItemId===contextMenus.createSignature){
chrome.tabs.executeScript({
file: 'js/signature.js'
});
}
}
The end result is nothing enters the page and get massive errors related to cross-site because the domain is not the same obviously. This has obviously been solved as there are numerous signature extensions out there. I would probably use one of theirs but a) I want to build it on my own, b) they all want you to use their templates, none of them that I have seen will let you just use your own code.
So, any ideas?

Related

How to hide HTML and other Content in EJS and Node

Having a tough time doing a simple web site in EJS.
I have this set up in my server file:
//Use the .html extension instead of having to name the views as *.ejs
server.engine('.html', require('ejs').__express);
// This avoids having to provide the extension to res.render()
server.set('view engine', 'html');
//set up directory to serve css and javascript files
server.use(Express.static(__dirname, '/views'));
This works great. I have HTML files, I have graphics, I have CSS. I am serving it up with a simple controller that renders the page. Nothing dynamic in these pages. But I do want them protected with an id/password system, and only served up through Express.
The access works fine, I have an end point set up to serve them. I'm forcing log in in that end point. But the problem is, that if someone knows the actual path to those files, they can get at them. So, the access is localhost:8081/admin/documentation/. However, the files are at /views/app_documents. And by entering in localhost:8081/views/app_documents/file_name.html, they can download/view the content, without going through my controls. I moved the content out of views, and grab it in my code, and serve it up, but that doesn't work for images or CSS.
Any suggestions for how to get around this?
Well, the things you find out after the fact.
This:
server.use(Express.static(__dirname, '/views'));
Is very bad. It should be:
server.use(Express.static('./views'));
The way it was, you could download our code, also. So, server.js was available for download. Yikes.
Live and learn.
Still can download the content without going through my authentication, though.
In case anyone else wants to do this, took a while. There are a few problems, as you still need to be able to directly access JS libraries, images and CSS. I found my answer in enter link description here.
The following modifications to that code does the trick. UserIsAllowed checks my permissions system to see if they can access that folder. If they can, no harm, off you go. Otherwise, kill the attempt. They get ACCESS_DENIED back as a string. I can't just kill anyone not going through my code, because then the CSS and images would not work. But this functions nicely. I now am able to serve up content based on my custom permissions system, which is part of a bunch of other administration functions. I can also have multiple different areas based on the URL that are protected by different privileges.
// This function returns a middleware function. It checks to see if the user has access
var protectPath = function(regex)
{
return function(request, response, next)
{
if (!regex.test(request.url)) { return next(); }
userIsAllowed(regex,function(allowed)
{
if (allowed)
{
next(); // send the request to the next handler, which is express.static
}
else
{
response.end('ACCESS_DENIED');
}
});
function userIsAllowed(regex,callback) {
if (regex.test('documentation_website') && request.session.admin_me && _.contains(request.session.admin_me["privileges"],"view_server_documentation")) callback(true);
else callback(false);
}
};
};
server.use(protectPath(/^\/documentation_website\/.*$/));

Checking tab status in a chrome extension with a popup without the tabs permission

I'm currently trying to build my first chrome extension and I only need it to interact with pages of a few domains, so I want to avoid using the "tabs" permission since I understand it would have me request access to all information and all domains.
Instead I want to restrict myself to using the aciveTab permission and, if need be, a content script.
In short, what I want to do is display a "Subscribe button" in my extension's popup if the currently selected tab's url is of the domain(s) I'm interested in.
I can get the url of the page when it's created using a content script but I don't know how to make sure the user is still on that page when my extension is clicked.
I haven't managed to get anything done with activeTab.
Thanks in advance for any piece of advice you can give, I'll check on the answers (if any) after work.
A working example with the activeTab permisison:
In your popup.js
chrome.tabs.query({lastFocusedWindow: true, active: true}, function(tabs) {
if (tabs && tabs[0] && tabs[0].url) {
var match = tabs[0].url.match(/^[^:]+:\/\/([^\/]+)/);
if (match) {
var domain = match[1];
if (domain == 'stackoverflow.com')
alert('test');
}
}
});
Note:
You have to declare the "activeTab" permission in your manifest (of course).
JavaScript code must be in a standalone file and included in popup.html with <script src="..."></script>. Inline JavaScript is not allowed due to CSP.

Is it possible to get access to my chrome extension localStorage from my website?

I built a chrome extension that saves data to localStorage from the background page (using the chrome.storage.sync.set).
Now, say that I want to build a website and access to the extension's data on the localStorage from the website, is it possible to access this data from the website domain? maybe I can add something to the manifest file to allow that?
You would have to inject a content script into your web site and then have your background script pass the localStorage to your content script. As for communication between your content script and the script on your web site, you'll have to get creative.
I am assuming here that you are aware of the message passing procedures between the content script and background script.
Now, I don't think your website can make a request to the extension and "pull" data from it, but you can certainly have your extension "push" data to your website.
This is how you can do it:
Content Script
The content script should check if the site open in the website is your website, say www.yourwebsite.com
if (currentUrl == "www.yourwebsite.com")
{
....
}
If it is indeed your website, pull the required data from the background script
if (currentUrl == "www.yourwebsite.com")
{
chrome.extension.sendRequest({ "getLocalStorageData": true, "dataFieldName": "favouriteColor" }, handleLocalStorageResult);
}
function handleLocalStorageResult(dataValue)
{
.....
}
On receiving the data in method handleLocalStorageResult, inject the data into the page's html so that your website's javascript can read it
if (currentUrl == "www.yourwebsite.com")
{
chrome.extension.sendRequest({ "getLocalStorageData": true, "dataFieldName": "favouriteColor" }, handleLocalStorageResult);
}
function handleLocalStorageResult(dataValue)
{
var localStorageDataDiv = $('<div>').appendTo('body');
localStorageDataDiv.attr('id', 'extensionData');
localStorageDataDiv.html(dataValue);
}
Your WebSite's Javascript
Now your website's javascript can read the data
var data = $('#extensionData').html();
alert('My Extension's LocalStorage Data is ' + data);
Answers to date do not mention that content scripts and the webpage share their localStorage object. If your content script writes to localStorage, the webpage will be later able to read it, and vice versa.

Chrome Extension Content Script on https://chrome.google.com/webstore/

Is Chrome blocking access to the webstore url?
I would like to make an extension that displays a like button beside the +1 button, but it looks like that content scripts are not working on https://chrome.google.com/webstore/*
Is that true?
TL;DR The webstore cannot be scripted by extensions, and the flag that previously allowed you to do that (--allow-scripting-gallery) has been removed in Chrome 35.
Chrome extensions cannot execute Content scripts / insert CSS the Chrome Web Store. This is explicitly defined in the source code, at function IsScriptableURL (click on the previous link to see the full logic).
// The gallery is special-cased as a restricted URL for scripting to prevent
// access to special JS bindings we expose to the gallery (and avoid things
// like extensions removing the "report abuse" link).
// TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
// against the store app extent?
GURL store_url(extension_urls::GetWebstoreLaunchURL());
if (url.host() == store_url.host()) {
if (error)
*error = manifest_errors::kCannotScriptGallery;
return false;
}
manifest_errors::kCannotScriptGallery is defined here:
const char kCannotScriptGallery[] =
"The extensions gallery cannot be scripted.";
The error can be viewed in the background page's console when you use chrome.tabs.executeScript to inject a script in a Web Store tab. For instance, open https://chrome.google.com/webstore/, then execute the following script in the background page of an extension (via the console, for live debugging):
chrome.tabs.query({url:'https://chrome.google.com/webstore/*'}, function(result) {
if (result.length) chrome.tabs.executeScript(result[0].id, {code:'alert(0)'});
});

Could I make a Google Chrome extension for chrome pages (downloads, extensions etc)?

I'd like to make a very simple extensions that slightly alters how the Downloads page looks. Changing the History page might be interesting too, but that's for later.
Is there a way to do that?
I tried making a Content Script extension, with "chrome://downloads" as match in manifest.json. Chrome won't allow that and responds with an error when packaging the extension.
Is there another simple way? It has to be simple, because changes would be simple, because all chrome:// pages are built with HTML, JS and CSS.
edit
After trying with background scripts a little...
I can't get chrome.tabs.executeScript to work! I added in background.html:
chrome.browserAction.onClicked.addListener(function(tab) {
alert(this.document.body.innerHTML);
alert(chrome.tabs.executeScript(null, {
code : "document.body.style.backgroundColor = 'red';"
}));
});
And I added this in manifest.json to add a (invisible) 'browser action button':
,"browser_action": {
/* "popup": "background.html",*/
"name": "Alter page"
}
The onClicked event fires both alerts (first is background.html's body, second is undefined). But the code (a string with document.body.style.backgroundColor = 'red';) doesn't execute! And ofcourse there's no debugging for extensions like this =)
Any tips anyone? I'm trying to get a hold of the tab's window.document (not background.html's window.document!). An injected script (that's what chrome.tabs.executeScript is supposed to do) should do that.
PS
I'm stealing from make_page_red/manifest and make_page_red/background.html
The 'extension' I have so far: http://hotblocks.nl/js/downloads.rar
EDIT
I found out what I want to achieve is possible with just CSS. I don't need to inject javascript. Does that make it easier? Does that make it possible? =)
According to this documentation, chrome:// URLs are an invalid scheme so they won't be matched:
A match pattern is essentially a URL that begins with a permitted scheme (http, https, file, or ftp), and that can contain '*' characters.
I would look into using override pages instead.
As requested, here's my extension that can at least load when chrome://downloads is loaded, although as I said, I don't think you can modify the page even if you know that's the page you're viewing.
manifest.json
{
"name": "Test",
"version": "0.0.1",
"background_page": "background.html",
"permissions": [
"tabs"
]
}
background.html
<script>
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
{
if (tab.status == "complete")
{
alert(tab.url);
// should alert 'chrome://downloads' on that page. You can
// check for this url here and then do whatever you want
}
});
</script>
Update: Since Chrome 31 there is an API for extensions that allows access to Chrome's downloads: https://developer.chrome.com/extensions/downloads
There's also an API that allows access to list and manage other installed extensions: https://developer.chrome.com/extensions/management
(Previous Answer)
Unfortunately, there's not currently an API for Chrome extensions to access information about a user's downloads. It's a widely requested feature, though, and there's some discussion among Chrome developers here: http://code.google.com/p/chromium/issues/detail?id=12133
Star the issue if it's a feature that you'd like to see, and you'll receive email updates.
As this page shows, there is no API to override the downloads page... However, there is a way to make a file you have made replace the chrome://downloads/ page whenever it is loaded using javascript in your background page...
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status === "loading"){
if(tab.url === "chrome://downloads/"){
chrome.tabs.update(tab.id, {url: "REPLACEMENT.html"});
}
}
});
Essentially what this does is - As soon as the page chrome://downloads begins loading (using the tabs.onUpdated API), the page is redirected to REPLACEMENT.html (Using tabs.update API)... There is no visible delay in the tab update
as this script is run before the chrome://downloads page begins loading... You can use a similar code in your file by pressing CTRL + U on the downloads page to view and copy its source code