npm Setup

Your distro might have old versions of npm, so you'd have to install it yourself.

Then install the npm modules that we require. Do this in the root of the unpacker repo.

$ npm install bower vulcanize crisper

Unpacker Build

Once done, install the libarchive-fork/ from third-party/ of the unpacker project. Note that you cannot use libarchive nor libarchive-dev packages from webports at this moment, as not all patches in the fork are upstreamed.

$ cd third-party
$ make libarchive-fork

Polymer is used for UI. In order to fetch it, in the same directory type:

$ make polymer

Build the PNaCl module.

$ cd unpacker
$ make [debug]

Use

The package can be found in the release or debug directory. You can run it directly from there using Chrome's “Load unpacked extension” feature, or you can zip it up for posting to the Chrome Web Store.

$ zip -r release.zip release/

Once it's loaded, you should be able to open ZIP archives in the Files app.

Source Layout

Paths that aren't linked below are dynamically created at build time.

node_modules/: All the locally installed npm modules used for building.

NaCl/JS Life Cycle

Some high level points to remember: the JS side reacts to user events and is the only part that has access to actual data on disk. It uses the NaCl module to do all the data parsing (e.g. gzip & tar), but it has to both send a request to the module (“parse this archive”), and respond to requests from the module when the module needs to read actual bytes on disk.

When the extension loads, background.js registers everything and goes idle.

When the Files app wants to mount an archive, callbacks in app.jsunpacker.app are called to initialize the NaCl runtime. Creates an unpacker.Volume object for each mounted archive.

Requests on the archive (directory listing, metadata lookups, reading files) are routed through app.jsunpacker.app and to volume.jsunpacker.Volume. Then they are sent to the low level decompressor.jsunpacker.Decompressor which talks to the NaCl module using the request.jsunpacker.request protocol. Responses are passed back up.

When the NaCl module is loaded, module.ccNaclArchiveModule is instantiated. That instantiates NaclArchiveInstance for initial JS message entry points. It instantiates JavaScriptMessageSender for sending requests back to JS.

When JS requests come in, module.ccNaclArchiveInstance will create volume.hVolume objects on the fly, and pass requests down to them (using the protocol defined in request.hrequest::*).

volume.hVolume objects in turn use the volume_archive.hVolumeArchive abstract interface to handle requests from the JS side (using the protocol defined in request.hrequest:**). This way the lower levels don't have to deal with JS directly.

But NaCl code doesn't have access to any files or data itself. So the volume_reader.hVolumeReader abstract interface is passed to it to provide the low level data read functions. The volume_reader_javascript_stream.ccVolumeReaderJavaScriptStream implements that by passing requests back up to the JS side via the javascript_requestor_interface.hJavaScriptRequestorInterface interface (which was passed down to it).

So requests (mount an archive, read a file, etc...) generally follow the path: