Aug 30 2011

experimental work in progress : Kynetx KBX augmented

Category: kynetx kynetx,technology

These days I should have been working on polishing SuiteFramework API which I promised to release on june ( this will teach me to announce release dates… ) but my procrastinating mind always finds a good reason to believe there are other things that deserve all my attention, RIGHT NOW.

About a month ago I was dreaming out loudly about a crossbrowser javascript library that would make it possible to access browser’s internals  . Last time I dived into Firefox I didn’t enjoy the journey so much in XUL-manifesto-xml-XPCOM-land . Recently I was lucky to stumble on good Firefox Add-on SDK docs (previously calledJetpack SDK) which showed that there were reasons to be much more optimistic. I also found an online addon builder which acts as a code repository so developers can understand the architecture of FF addons through working examples and share their code through libraries and that made me feel that Mozilla had become a sweeter monster.  I was positively suprised that chrome and firefox shared similar terminology in their addon architecture like “content scripts” ( FF , Chrome) .

In order to make a proof of concept I focused on how to modify the behavior of the Firefox Location Bar / Chrome omnibox so a KRL ruleset could inject code to augment the browser itself instead of pages.   This meant finding an entry point in the KBX were native api functions could be injected and executed on the fly. The way KBX emulates the Greasemonkey API by exposing javascript functions in a content script and communicating with the “addon context” ( main.js on FF and background.html on Chrome) helped me to pass this first obstacle.

One problem that raised while trying to run the injected code is that both Firefox and Chrome expects an addon to explicitely declare which API packages it will run. Thoses permissions are declared in manifest.json for Chrome. On Firefox both the online add-on builder and the command line SDK ( which I recommend for working locally ; check “Get the SDK” at the bottom of this page ) create a harness-options.json manifest file automatically during xpi build time (the whole process is explained here). On Chrome you have to declare what you use manually in manifest.json.
So if we want developers to be able to inject any method available by the APIs then it is necessary to give permission to all of them inside KBX.

What do we have?

A fork of the original KBX  extension that allows a KRL webhook or an external js file to feed the KBX extension with javascript code that runs inside the extension ( as opposed to javascript code that runs inside a page and only has access to the DOM ).
A Kynetx browser app that adds  github search (inspired by “Github address bar search” ) in the Location Bar (Firefox) or  Omnibox ( Chrome) . As all Kynetx browser apps this app is cross-browser.

On Chrome the github search engine gets invoked by first pressing the ‘k’ letter when the cursor is in the omnibox. Then you can type : github mysearch_terms to search for “mysearch_terms” on github or  type github @someuser to get “someuser” profile page.

On Firefox you don’t need to press ‘k’ first .

Get the modified KBX for Chrome and KBX for Firefox .
Install Kynetx “Github Search Engine” app .

 

 

 

 

 

 

 

 

 

 

Why use it ?

For now this modified KBX extension is experimental. If the concept reaches maturity then we can expect richer Kynetx browser apps that go beyond the scope of webpages because they can interact with location bar/search bar, take screenshots , make desktop notifications, modify context menus, make cross-Origin XMLHttpRequest … and do all the things browser addons/extensions you find on Mozilla Addons and Chrome Web Store do.

For developers:

The extensions exposes the javascript function remote_url_eval_in_addon(urls_array) which takes an array of urls pointing to js files ( js files on the remote server should end with _chrome.js or _firefox.js but in remote_url_eval_in_addon you will call :

remote_url_eval_in_addon([“http://lolo.asia/kynetx_remote_eval/omnibox_lib.js”,”http://lolo.asia/kynetx_remote_eval/github_search.js”]) and the KBX extension will add the missing _chrome or _firefox part .

Another method you can use is webhook_eval_in_addon(webhook_array) that can be used inside an emit << js_code >> . It takes an array of objects as unique paramenter. Each object has the field ‘appid’ which targets a ruleset and ‘eventname’ which targets a webhook in that ruleset.

Ex: webhook_eval_in_addon([{appid:”a1135x118″,eventname:”omnibox_lib”},{appid:”a1135x116″,eventname:”omnibox_github”}]) will request two webhooks from inside KBX :

http://webhooks.kynetxapps.net/h/a1135x118/omnibox_lib?browser=Firefox ( or browser=Chrome)

http://webhooks.kynetxapps.net/h/a1135x116/omnibox_github?browser=Firefox ( or browser=Chrome)

Those webhooks should return javascript which gets evaluated inside KBX in main.js (FF) or background.html ( Chrome) in sequence.

The omnibox_lib webhook returns a browser specific library of plumbery code for adding search engines to the Location Bar/Omnibox with the add_search(options) function.

The omnibox_github webhook returns javascript code that calls add_search(github_options) where github_options is an object that specifies the behavior of the github search engine :



rule omnibox_github_webhook is active {
       select when webhook omnibox_github
       pre {
           browser=event:param("browser") ;
           
           js_FF = <<
           //add github search
           add_search({
           keyword: 'github',
           icon: "github_16.png",
           matches: /^github\s/i,
           getSuggestions: function(query) {
               var suggest;
             
             query = query.replace(/^github\s/i, "");
             
             if (/^@([\w\d_-]+)/.test(query)) {
                   var username = query.match(/^@([\w\d_-]+)/)[1];
                   suggest=[
                                {
                                      title: 'Github user: ' + username,
                                      label: "View user profile for @" + username,
                                      favicon: self.data.url("github_16.png"),
                                      url: 'https://github.com/' + username
                                  }
                              ];
                   
                 } else {
                   suggest=[{
                         title: 'Search Github for: ' + query,
                         favicon: self.data.url("github_16.png"),
                         url: 'https://github.com/search?q=' + encodeURIComponent(query)
                         }
                            ];
                 }
                 
              
             
             return suggest;
           }
           });
           >>;
           
           js_Chrome = <<
           add_search({
           keyword: 'github',
           icon: '',
           matches: /^github\s/i,
           getSuggestions: function(query) {
               var suggest;
             
             query = query.replace(/^github\s/i, "");
             
             if (/^@([\w\d_-]+)/.test(query)) {
                   var username = query.match(/^@([\w\d_-]+)/)[1];
                   suggest=[
                                {content: 'https://github.com/' + username, description: '<match>View github user profile</match> : https://github.com/<match>' + username+ '</match>'}
                              ];
                   
                 } else {
                   suggest=[{content: 'https://github.com/search?q=' + encodeURIComponent(query) , description: '<match>Search github</match> : https://github.com/search?q=<match>' + encodeURIComponent(query)+ '</match>'}
                            ];
                 }
                 
              
             
             return suggest;
           }
           });
           >>;
            js = browser eq 'Firefox' => js_FF  | js_Chrome;
       }
       {
           send_directive("text") with body = js;
       }
     }

 

You can create your own custom and more elaborated search engine with dynamic suggestions by writing a new webhook that returns js code that calls add_search(custom_options) .

Firefox 4 runs javascript 1.8.5 code so this is the opportunity to improve your javascript knowledge using the new available functions and syntax like forEach for arrays. On Chrome we can use at least javascript 1.5 ( http://stackoverflow.com/questions/300185/google-chrome-javascript-version )

What’s next ?

– evaluate impact on browser security ( what’s the worst that could happen and how to avoid it)

– specify a cross-browser API that aims to provide access to installed extensions/addons as if they were services using things like code modules on Firefox or cross-extension messaging on Chrome .  KRL rulesets could then mashup data/features provided by installed extensions/addons .

– create more cross-browser KRL modules that act like abstraction layers to common browser features available in Firefox Add-on SDK and Google Chrome Extensions API

 

 

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Google Bookmarks
  • BlinkList
  • Reddit
  • Suggest to Techmeme via Twitter
  • Technorati

Related Posts:

  • No Related Posts

One Response to “experimental work in progress : Kynetx KBX augmented”

  1. MikeGrace says:

    Nicely done! I do believe that the Chrome and Firefox universal Kynetx browser extension already support cross domain ajax calls since they run in the browser’s sandbox. 

Leave a Reply