⬆️ ⬇️

We write the Firefox extension for integration with the Unity panel

Narwhals, Narwhals, swimming in the ocean, causing a commotion coz they are so awesome! With the release of Ubuntu 11.04, the Unity shell rather unexpectedly took the place of the default shell. The appearance of Unity in Ubuntu Netbook Edition, despite the slow speed of work, was quite reasonable: it allowed the effective use of small screens of netbooks, thanks to, for example, a vertical panel for switching between running programs. Why did it become necessary to transfer Unity to desktops? It would be possible to answer this question now. However, such an incomplete, without ready-made examples, a subjective response would hardly satisfy the user, who at the moment had to face the inconvenience of the transition. Therefore, we will talk about how to improve, and not about how and why to survive.



The article is aimed at software developers for Linux, as well as for those who want to start developing extensions for Firefox. Users are invited to follow the link for a ready extension.



So, what we need:
  1. Extension Restartless Restart . During the development process, you will need to frequently restart the browser to test the extension
  2. Archiver that allows you to edit files directly in the archive, without manual repacking. The standard archiver in Ubuntu File-Roller does it.
  3. Text editor


Actually, for such a simple extension is enough. You may also need the Extension Developer Extension .

')

Now we need to create the structure of our extension:

 unityfox
 - chrome  
 ---- content
 ------ main.xul
 - chrome.manifest 
 - install.rdf




Our extension does not use localization or settings, so the standard locale and preferences directories will not be useful to us.



It all starts with the file install.rdf . It is customary to describe brief information about the extension: name, description, version, authors, unique identifier of the extension and a set of supported applications (the same extension can work, for example, in Seamonkey and Firefox):

<? xml version = "1.0" ?>



<RDF xmlns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"

xmlns: em = "http://www.mozilla.org/2004/em-rdf#" >



<Description about = "urn: mozilla: install-manifest" >

<em: id > unityfox@mozilla.org </ em: id >

<em: version > 0.1.3 </ em: version >

<em: type > 2 </ em: type >



<em: targetApplication >

<Description >

<em: id > {ec8030f7-c20a-464f-9b0e-13a3a9e97384} </ em: id >

<em: minVersion > 4.0 </ em: minVersion >

<em: maxVersion > 6.0a1 </ em: maxVersion >

</ Description >

</ em: targetApplication >



<em: name > unityfox </ em: name >

<em: description > Integration with the Ubuntu Unity panel </ em: description >

<em: creator > Lockal </ em: creator >

</ Description >

</ Rdf >




The file structure should be clear without explanation. A small clarification: <em: type> 2 </ em: type> indicates that this file is an extension, not a theme, for example. {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - code of the Firefox browser. The lower limit of version 4.0 is due to the fact that we will use js-ctypes functions to exchange messages with the Unity library.



Having finished writing install.rdf , you can proceed directly to creating working code. To create our javascript code from the main.xul file when creating the window, you need to describe the overlay procedure in the chrome.manifest file:

 content unityfox chrome / content /
 overlay chrome: //browser/content/browser.xul chrome: //unityfox/content/main.xul
This tells the browser to download our main.xul file along with the browser.xul browser interface.



Here it is worth stopping and remembering the problem we are solving. Our goal is to display the download bar and the number of active downloads in the Unity panel. Fortunately, Unity provides a special API for this. From this API, we need functions:gint64 is an analog of long in C, and gboolean is an analog of int. A pointer to UnityLauncherEntry can be considered a pointer to an anonymous structure and easily lead to a pointer to void. Further comments will go straight to the main.xul code.

<? xml version = "1.0"?>

<overlay id = "unityfox"

xmlns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">



<script type = "text / javascript" >



// In Firefox extensions, it is customary to be careful about the global area in xul

if ( "undefined" == typeof ( unityProgress ) ) {



var unityProgress = {



setup : function ( ) {

// Load the ctypes module to access the system libraries

Components. utils . import ( "resource: //gre/modules/ctypes.jsm" ) ;



// Execute libunity.so.4 loading

// We do not need the extension to generate errors in the absence of libunity

try {

this . libunity = ctypes. open ( "libunity.so.4" ) ;

} catch ( err ) { return ; }



// Describe the necessary functions libunity

this . getEntry = this . libunity . declare ( "unity_launcher_entry_get_for_desktop_id" ,

ctypes. default_abi ,

ctypes. voidptr_t ,

ctypes. char . ptr ) ;





this . setProgress = this . libunity . declare ( "unity_launcher_entry_set_progress" ,

ctypes. default_abi ,

ctypes. void_t ,

ctypes. voidptr_t ,

ctypes. double ) ;



this . setVisibilityP = this . libunity . declare ( "unity_launcher_entry_set_progress_visible" ,

ctypes. default_abi ,

ctypes. void_t ,

ctypes. voidptr_t ,

ctypes. int ) ;



this . setVisibilityN = this . libunity . declare ( "unity_launcher_entry_set_count_visible" ,

ctypes. default_abi ,

ctypes. void_t ,

ctypes. voidptr_t ,

ctypes. int ) ;



this . setCount = this . libunity . declare ( "unity_launcher_entry_set_count" ,

ctypes. default_abi ,

ctypes. void_t ,

ctypes. voidptr_t ,

ctypes. long ) ;



// all main functions of libunity library work with UnityLauncherEntry *

this . entry = this . getEntry ( "firefox.desktop" ) ;



this . Cc = Components. classes ;

this . Ci = Components. interfaces ;

this . IDLM = this . Ci . nsIDownloadManager ;



// The panel will be updated using the download-manager service

// Interfaces of all embedded services are described at https://developer.mozilla.org

this . dlMgr = this . Cc [ "@ mozilla.org / download-manager; 1" ] . getService ( this . IDLM ) ;

this . dlMgr . addListener ( this ) ;

} ,



// The update function is called on each event from download-manager

update : function ( ) {

var total = 0 , cur = 0 , count = 0 ;

var dls = this . dlMgr . activeDownloads ;

while ( dls. hasMoreElements ( ) ) {

var dl = dls. getNext ( ) . QueryInterface ( this . Ci . NsIDownload ) ;

// Skip inactive downloads and downloads, the end time of which is unknown

if ( dl. state ! = this . IDLM . DOWNLOAD_DOWNLOADING || dl. percentComplete == - 1 )

continue ;



// Consider the total size, the loaded size and the number of downloads

total + = dl. size ;

cur + = dl. amountTransferred ;

count ++;

}



if ( total == 0 ) {

// If there are no downloads, hide the counter and the bar on the panel

this . setVisibilityP ( this . entry , 0 ) ;

this . setVisibilityN ( this . entry , 0 ) ;

} else {

// Show the download progress (from 0 to 1) and the number of downloads

this . setProgress ( this . entry , cur / total ) ;

this . setCount ( this . entry , count ) ;

this . setVisibilityP ( this . entry , 1 ) ;

this . setVisibilityN ( this . entry , 1 ) ;

}

} ,



// This object is nsIDownloadProgressListener in combination.

// nsIDownloadManager will send messages to the functions described below.

onDownloadStateChange : function ( ) { this . update ( ) } ,

onStateChange : function ( ) { this . update ( ) } ,

onProgressChange : function ( ) { this . update ( ) } ,

onSecurityChange : function ( ) { this . update ( ) }

} ;

}



// Finally, initialize unityProgress via the so-called. anonymous namespace

( function ( ) { this . setup ( ) ; } ) . apply ( unityProgress ) ;

</ script>

</ overlay>




Expansion is ready. Now files from the unityfox directory can be packed into a zip-archive, change the file extension to .xpi and set by dragging on the browser window.



The finished extension and list of ingredients can be found at addons.mozilla.org/ru/firefox/addon/unityfox . Enjoy your meal!



The text of this article is distributed under the terms of the license CC BY-SA 3.0

Source: https://habr.com/ru/post/118678/



All Articles