Wednesday, April 3, 2013

Taking a Break

So tonight I'm taking a break. No work. Nothing... So of course I ended up doing a little bit of programming... Something kind of small and relaxing that I've never done before.

I've decided that as part of gherkin, I should probably build a bunch of tools to do quite specific things to do with deployments. Google Chrome, for example, has information all over the place. Do not use this link - you'll waste A LOT of time. Firstly, it's near on impossible to get a crx file unless you manage to get it from your Downloads folder before Chrome moves it. Secondly, the method using master_preferences (which ironically doesn't use master_preferences) - simply doesn't work. There is no "extensions" folder any more. You could hack "default_apps" but it just feels ugly.

So once I figured that out, I found that I had to include something like this to the master_preferences (for this example, for all you education buff's out there, the extension described here is Hapara's Teacher Dashboard client extensions).

  "extensions": {  
   "settings": {  
    "iehakgpdecaomokcdicdigpbmipnllcg": {  
     "granted_permissions": {  
      "api": [  
       "tabs",   
       "webRequest",   
       "webRequestInternal"  
      ],   
      "explicit_host": [  
       "<all_urls>"  
      ]  
     },   
     "location": 1,   
     "manifest": {  
      "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmsCpYnhR25L1k9EgWUEKmxPUS5FfklZ4KbH+X2I4wcYCuQpjwVpHycGTgLcW4BOWXHDFJAeGZWvo7mdAb62kOeCoOehdbQnr5ChG69NAsWk+CFARyVcaEfcXgoulgGiQgg8DkIq7/wMoLALrzTubzX4ziFs+Ferc1PYp1jA7MBwIDAQAB",   
      "name": "Hapara Remote Control Teacher Dashboard Ext",   
      "permissions": [  
       "<all_urls>",   
       "tabs",   
       "webRequest"  
      ],   
      "update_url": "http://clients2.google.com/service/update2/crx",   
      "version": "0.9.27"  
     },   
     "path": "iehakgpdecaomokcdicdigpbmipnllcg\\0.9.27",   
     "state": 1  
    }  
   }  
  }  

Ugly huh? It turns out that the information you need to generate that isn't that hard to find. But it's SOOO easy to miss bits. Firstly, you have to install the extension you want to install, pull out the bits you need from the manifest file for that extension (visually it's easier to pull the bits that you want from here) and then go to your own preferences file and pull out bits from there.... Not TOO hard. But it takes up a lot of time - find the bits, put it into the file, make sure you have all the syntax right, remove your profile (Personally I used Chromium and Chrome - so 2 different profiles. One to test with, one to use to generate the profile). Open up Chrome, see if it's worked.

Just plain painful...

 #!/usr/bin/env python  
 #Change SOURCE_DIR to wherever your profile for Chrome or Chromium are.  
 SOURCE_DIR="/home/nevyn/.config/chromium/Default"  
 EXTENSIONS_DIR=SOURCE_DIR + "/Extensions"  
 import glob  
 import json  
 import sys  
 for manifest in glob.glob( EXTENSIONS_DIR + "/*/*/manifest.json" ):  
   f = open( manifest, 'r' )  
   manifest_file = f.read()  
   f.close()  
   manifest_file=json.loads( manifest_file )  
   if sys.argv[1].upper() in manifest_file[ "name" ].upper():  
     UID = manifest[ len( EXTENSIONS_DIR ) + 1: ]  
     UID = UID[ 0 : UID.find( '/' ) ]  
     output = {'extensions': { 'settings': { UID: { 'manifest':{} } } } }  
     output['extensions']['settings'][UID]['location'] = 1  
     if "content_scripts" in manifest_file:  
       output['extensions']['settings'][UID]['manifest']['content_scripts'] = manifest_file[ "content_scripts" ]  
     output['extensions']['settings'][UID]['manifest']['key'] = manifest_file[ "key" ]  
     output['extensions']['settings'][UID]['manifest']['name'] = manifest_file[ "name" ]  
     output['extensions']['settings'][UID]['manifest']['permissions'] = manifest_file[ "permissions" ]  
     output['extensions']['settings'][UID]['manifest']['update_url'] = manifest_file[ "update_url" ]  
     output['extensions']['settings'][UID]['manifest']['version'] = manifest_file[ "version" ]  
     output['extensions']['settings'][UID]['path'] = UID + '\\' + manifest_file[ "version" ]  
     output['extensions']['settings'][UID]['state'] = 1  
     #I'm an idiot.. I could have just grabbed it ALL out of Preferences..
     f = open( SOURCE_DIR + '/Preferences', 'r' )  
     preferences = f.read()  
     f.close()  
     preferences=json.loads( preferences )  
     if 'granted_permissions' in preferences['extensions']['settings'][UID]:  
       output['extensions']['settings'][UID]['granted_permissions']=preferences['extensions']['settings'][UID]['granted_permissions']  
     print json.dumps( output, indent=2 )  
     break  

So there you have it.. The start of what will hopefully become a much bigger solution (How great would it be to have a GUI to generate a master_preferences file? I'm wondering if this might be an appropriate use for Pajamas - so that it could be hosted on a website for others to use i.e. set up all of the extensions you want and then upload the preferences file and have it spit out a master_preferences file with the extensions already set up). At the moment this just spews out the appropriate settings to the screen for you to copy and paste.

[edit] I just realised that people are actually using this information. So I should probably say what's going on. So it turns out that if you describe the extension in master_preferences, Google Chrome will then go and download the extension. However, the description of that extension has to be just right or otherwise, it won't appear on the extensions list at all or will appear disabled. Anyway, when I get the time I'll start working on the tool.

[another edit] 8th April
At testing tonight none of the extensions downloaded and installed. While doing it on the machine I was developing on seemed to work a few days ago (eventually - it did take a little longer than I'd like). I've since found the error. It turns out the version should be set to 0. I think this tricks chrome into thinking it has to update the extensions (and so effectively installs it).

No comments:

Post a Comment