Archive for the ‘Google Products’ Category

Google Chrome Extension and Loading/Embeding the Flash Files

Monday, September 24th, 2012

If you are Google Chrome Extension developer, then you may have used the “chrome-extension://” protocol to refer to the locally stored files under the extension (could be images, JS, html, etc).

However, I have been trying to use the “.swf” files in the page, and it had kept failing. For some reason, you can’t use the embed tag source with file protocol like “chrome-extension://”. Now this might be some security check at Adobe Flash plug-in or it could be a bug in the Chrome. As a workaround, I have shared the resources on a website, and using them from the extension.

FYI, I have been using this in the Basecamp Extension product to show the animated and active graphs which are developed in the Falsh. I know there are other, may be even better, workarounds available in the JavaScript only, but I started with the flash, and its code is complex enough to stop me from porting this to another language until I have lot of free time.

So, back to the problem, with increased security policies from the Google with Chrome Extensions, I have to look back into this because now youc an’t load the remote resoruces from the “http” only remote (though you can access remote resources over the https).

Fortunatley, the new version of the Chrome on Windows allow accessing the flash files in the extension folder (or may be it was a Adobe Flash fix). But this works on the Windows only, and other Google Chrome version for platforms like Mac OS-X or Linux still have this issue.

After, doing some research, I was able to make all this work and thought to share with you too.

The trick is that though you can’t seem to load the local (placed in extension bundle) swf files using the embed tags, this work well if you add the flash file using the iFrame tag. This solves one problem, but what if you also have to pass the data (as used the FlashVars). The asnwer is simple, and that’s you can pass all these variables using query string parameter.

So, here is my fix for all this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Get the full path of the locally stored graph file
graphUrl = chrome.extension.getURL ("FusionCharts/" + graphFile);
 
// Setup the width and height
graphWidth = 500;
graphHeight = 300;
 
// So far only the Windows Chrome seems to load the local flash/swf files correctly
// For all others, we need to use the iFrame to load the local swf file
if (!(window.navigator.userAgent && window.navigator.userAgent.indexOf("(Windows") > 0) )
{
	// Add the flash varaibles/defaults
	graphUrl += "?chartWidth="+graphWidth+"&chartHeight="+graphHeight;
	graphUrl += "&debugMode=0&DOMId=bceTimeChart&registerWithJS=0&scaleMode=noScale&lang=EN";
 
	// Make an IFRAME and set this flash object as its source
	iFrameHtml = "<iframe src='"+graphUrl+"' style='border:none; width:100%; height:"+graphHeight+"px'>"
	$('#bceGraphDiv').html(iFrameHtml);
}
else
{
	// Render the flash file using the EMBED tag
	// Better use swfobject for rendering:
	// http://code.google.com/p/swfobject/
}

The solution is not very elegant, but at least it works

Content Security Policy and Remote Scripts

Saturday, September 15th, 2012

Google Chrome is targeting toward more secure web, and one of the major step in this is by also enforcing Content Security Policy at the Chrome Extensions level. This is enabled in all the manifest version 2 Extension, and the manifest version 1 is slowly being phased out (you get warning about it being deprecated soon when installing it).

This new policy applies two of the following main limitations on the content scripts:
- Inline JavaScript will not be executed
- Only local script and and object resources are loaded

For more details on this, please check:
http://developer.chrome.com/trunk/contentSecurityPolicy.html

I was working on upgrading my Dynamic Language Tools extension, and though applying first rule of using the Inline scripts was comparatively easy (for tips and pitfalls on this, please check JavaScript eval function and Content Security Policy). But I found the other policy “Only local script and and object resources are loaded” was quite limiting and confusing. I was using the Google AJAX APIs in my extension, and since these are just the JavaScript files, I can download them and integrate most of them directly in the extension, but then this would mean that I will have to update my extension with every update of Google API. This is something which I hate most.

I was using the following code in my extension background page:

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
 
<script type="text/javascript">
// Load the Necessary APIs
googleElementsLoaded = false;
googleLanguageLoaded = false;
 
// Load the necessary Google APIs
google.load("language", "1", { "callback" : function() {googleLanguageLoaded = true}});
 
// Load Google Transliteration package
google.load("elements", "1", {packages: ["keyboard", "transliteration"], callback: function() {googleElementsLoaded = true}});
</script>

And as I was afraid, when I run the extension after upgrading the manifest to version 2, it throw the following error:

Refused to load the script ‘http://www.google.com/jsapi’ because it violates the following Content Security Policy directive: “script-src ‘self’”.

After doing some research, I found that it’s possible to load remote scripts too (phew!), but with two conditions:
- It must be served on the HTTPS.
- You need to explicitly add this relaxation in the manifest file.

Both of the steps were quite easy for me. For the first, I simply changed the script source from “http://www.google.com/jsapi” to “https://www.google.com/jsapi”, and then added the following line in the manifest file:

1
"content_security_policy": "script-src 'self' https://www.google.com; object-src 'self'",

Which simply means that I’m allowing it to load the scripts from extension local folder, and from www.google.com. Simply reload the extension after doing these changes and you are good to go.

JavaScript eval function and Content Security Policy

Thursday, August 23rd, 2012

I have been getting warnings for my two of the Basecampe Extensions for the manifest version 1, and need to upgrade those to version 2. However, when working on this upgrade, I found that upgrade was not as simple, as I thought at first.

The biggest problem for me was the new Content Security Policy of Chrome Extension, and to make my application compliant with this, I have to do a lot of code changes here and there in the extensions.

Most of them was simple, though tedious, to integrate. However, I was stuck on one issue and that’s new security policy doesn’t allow the javascript “eval” function. I have been using this in past for evaluating the JSON, checking dynamic global variables and executing dynamic code from the server.

While, I can understand that it’s pretty dangerous and vulnerable to attacks, I have to use it one way or the other. Fortunately, there are some workarounds available. For example, one of the most widely use of the eval by me is to evaluate if a particular event has occurred or something is loaded:

1
eval(" result = " + customJavascriptCode)

If you don’t want to use the eval (or are blocked by some security policy like I was), then one simple workaround for this is by help of javascript Anonymous functions like:

1
var result = ( new Function( 'return ' + customJavascriptCode) )();

Now, I think this is as unsecure as the eval function, and in fact, this gets blocked by Chrome Extension. So the better workaround is to instead of passing the string to evaluate or make anonymous functions, simply pass the anonymous functions and then let the evaluation script simply execute them. So here is another round of changes which actually work in Chrome extension too:

1
2
3
4
5
6
// Instead of passing the string to evaluate, pass anonymous function evaluate 
var result = getResult( function() { return javaScriptVariableToCheck };)
 
// The target function can then execute that function to generate, process and return the 
// results.
function getResult(func) {return func(); }

In worst case, if you only get the JavaScript as a string (may be from some third party) and still want to evaluate the results, the one (though bad in terms of security) is to pass create send this JavaScript as string to a HTTP server which simply echo it back, and then you can use that server file in the Script src tag. The following thread discuss this option in bit more detail:
http://stackoverflow.com/questions/7127652/alternatives-for-javascript-eval

One the side note, if you have been using the eval to evaluate JSON in past (like me), the I found that there is a better workaround for this, and that’s most of the latest browser, including Chrome 3.0+ support JSON object which helps you easily achieve this goal. Here is a sample of this which works fine in Chrome:

1
JSON.parse("{ \"firstName\": \"John\", \"lastName\": \"Smith\" }")

Google Website Translator and Skipping Translation Segments

Saturday, August 18th, 2012

I have been using the Google Website Translator widget on my website for few years, and I’m quite happy with that. The machine translation is not very accurate, but it does provide some help in case someone doesn’t know the target language at all.

Plus, I had also been using the Google Translate API for my Dynamic Subtitles Translator product for a year or so, and then Google decided to discontinue that service and made it Paid only. I tried going with Microsoft Bing Translator, and though it’s free, it has monthly traffic limit. So, at the end, I have to revert back to Google Website Translator widget which do the job, but then it translate all the page, and not just the subtitles I want to translate, and it looks quite bad in the end.

Today when inspecting the Google Translator header widget, I found something interesting and that’s the wrapper DIV and IFRAME elements of the Google Translate bar has the CSS class of “skiptranslate”. My hunch was that this is something which is preventing the translation of this block on the page. So, I quickly tested this and applied this class to few of my DIV elements, and sure enough, this did the job.

So, at the end, I just added the “skiptranslate” to all the elements other than subtitles which needs to be translated, and this works great. You can view this at:
http://www.syedgakbar.com/products/dst/

IP Address to Country Lookup using iPInfoDB

Saturday, July 7th, 2012

Recently, I have been working on a simple idea, and that’s to show the Google GeoMaps (similar to the maps in Google Analytic) to show the different user activity directly on the site e.g. total number of downloads of a product by country, total subtitles translation, etc. My first research was to find some API which can draw decent looking graphs, as in Google Analytic, without considerable effort. Fortunately, I found that there is API from the Google which does exactly this:

Google GeoMaps

The next research task was to find a free and easy to use API which can provide the user location (City, Country, etc) given an API Address. While there are dozens such available, after trying few, I decided to go with the iPInfoDB API:
http://ipinfodb.com/ip_location_api.php

They have simple to use API, and also have sample PHP code on how to best use their service on the above API page. However, I ,after doing some research, ended up using the following code to fetch the user info from the IP Address:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Find the Country Name, Code and City information from the IPInfoDB:
// http://www.ipinfodb.com/ip_location_api_json.php
private function getGeoLocation()
{
	// Make a special cookie name by adding the IP address (to make different cookie per IP address)
	$cookieName = 'geolocation_'. str_replace('.', '_', $_SERVER['REMOTE_ADDR']);
 
	//Check if geolocation cookie exists (to avoid repeated calls to their server)
	if(!isset($_COOKIE[$cookieName]))
	{
		// If no, create a new request;
		$APIKey='{YOU-API-KEY}';
		$JSONUrl='http://api.ipinfodb.com/v3/ip-city/?key='.$APIKey.'&ip='.$_SERVER['REMOTE_ADDR'].'&format=json';
 
		// Get the JSON content from the remote URL
		$response = file_get_contents($JSONUrl);
 
		// Parse JSON
		$visitorGeolocation  = json_decode($response, true);
 
		// Geo Location query was successfull
		if ($visitorGeolocation && $visitorGeolocation['statusCode'] == 'OK') {
			$data = base64_encode(serialize($visitorGeolocation));
			setcookie($cookieName, $data, time()+3600*24*7); //set cookie for 1 week
		}
	}
	else
	{
		// Load previously stored info from the cooki
		$visitorGeolocation = unserialize(base64_decode($_COOKIE[$cookieName]));
	}
 
	return $visitorGeolocation;
}

This simple script also makes use of cookies to avoid sending repeated hits to their server if you have already found out the location of the user once. The two little tweaks I done to the code available at their API page are:

1) Make sure to add the user API Address in the cookie name. This helps detect the correct location for the user, even when he switches to different network within seven days.

2) I decided to use JSON fetch to get the results instead of using their wrapper class. This makes the overall code simple and clean.

With all this, I also ended up creating a simple product in the PHP which can be used to log and show the nice statistics graph on any website. I may make it available for public download soon. So, stay tuned.