
I couldn’t have asked for a better departmental senior seminar (CSCI 481 at Hope College) this semester. On the first day of class, the professor shared his “vision” with us of a Dropbox(TM) client for the Nokia N900 mobile device and those like it — the N900 is a smartphone which runs a Debian-based Linux variant — whereupon he essentially allowed us to devote nearly all of our in- and out-of-class time to the project for the entire semester! The result is a working implementation for the Linux desktop (not yet ported to the N900), that I am excited to describe in brief here.
Project Goals
So why another Dropbox client for Linux? The following goals set DBoxTop apart from the crowd:
- Tight integration with the operating system.
Existing projects that aim to bring Dropbox to Maemo/MeeGo-based devices tend to act as file viewers from a client program of some sort. This was deemed to restrictive for our purposes, so we set out with the intention to implement our client as a Virtual File System (VFS) using the Linux GVFS/GIO libraries.
- Storage-sensitive caching. Since our primary targeted platform is a mobile device with limited storage, we want to allow the user to limit the size of locally cached files, and the program to smartly maintain this cache by replacing files that are used least often with incoming files that need to utilize the limited cache space.
- Local/remote transparency. The user should be able to interact with (e.g., move, copy, delete, rename, etc.) all files on his or her Dropbox account in exactly the same manner whether the files are cached locally or remotely. A natural corollary (don’t you love it when your textbooks use that phrase?) is that files should only be downloaded for operations that truly need them to be local, such as opening a file to read or write.
Finally, we the source code developed in this process is and will remain a part of the open-source domain.
Architecture
Writing a virtual filesystem for DBoxTop requires a daemon in C that implements a common interface by which the operating system interacts with the filesystem. The way that this works in GVFS is that the first time a file is requested, a master daemon determines which implementation-specific daemon to launch by extracting the protocol out of the URI (smb://, ftp://, trash://, dboxtop://, etc.). The master daemon spawns the appropriate child daemon, whereupon the file viewer (Nautilus, a command window, or any other program accessing the file using the GIO API) communicates with the child daemon to present the files for user interaction.
Essentially, the role of the child daemon is to present the filesystem in a unified format, so that the view does not have to care about its specifics. The inherent beauty in this system is that a program needs only to know the URI for the file or folder to access and manipulate it. The diagram below illustrates the GVFS daemon system.

As an example, suppose that some application wishes to display the directory at dboxtop://Public/fun. Assuming that this is the first time in the user’s logon session that a file on this protocol has been accessed, the process looks something like this:
- The master GVFS daemon launches the appropriate (dboxtop) daemon and calls do_mount on it so that the child daemon can perform appropriate setup. At this point, the dboxtop daemon performs initialization tasks.
- The master calls do_enumerate on the daemon to request the list of files, passing the path /Public/fun.
- The child daemon requests a file listing from Dropbox (more on how this is done later), and returns the list of file and directory names (e.g., “image1.png,” “text_file.txt,” and “another_folder”).
- For each of these names, the master daemon calls do_query_info on the child (dboxtop) daemon, requesting metadata such as the mime type, icon, creation date, and the size of the file.
- The user now sees the file listing, complete with metadata, as if the files were part of the local filesystem (indeed, this is the whole point of a “virtual” filesystem). The communication flow for file operations is very similar to listing files.
At the time of this writing,
an SDK for the Dropbox API has not been implemented in C, so rather than spend the entire semester writing such as SDK, we chose to use the pre-existing Dropbox library written in Python. However, this meant that we either had to interop the Python and C code, or run the two components in isolation and set up Inter-Process Communication (IPC) between them. After some experimentation, we chose the latter route, using DBus for the IPC.
Although this was likely the easier route and leads to a nice separation of work into a “frontend” (the gateway for accessing the Dropbox SDK and displaying a simple widget-like UI) and a “backend” (the GVFS daemon supporting the dboxtop:// protocol), it somewhat muddles the distinction a bit. For while the frontend does provide the user interface as would be expected, it also acts somewhat like a backend by providing a service for the daemon. The interaction between the two can be seen from the illustration below.

The internal circular components represent modules which have specific responsibilities. For example, on the backend side, each operation can be separated into a local and a remote part: first, if the file is local, perform the operation on it in the cache; then, request that the frontend tell Dropbox to perform the same operation remotely. Needless to say, if a file is not local, then the first part is skipped and only the remote operation is performed.
The frontend also contains a few internal components with distinct purpose. The most prominent of these are a multi-threaded upload and download manager, and a “cache trimmer” which manages the free space in the local cache. The latter is used whenever a file operation needs to add one or more files to the cache, from the user either copying a file into the Dropbox folder from an external location (some other location on their hard disk), or requesting that a file be opened (in which case it needs to be downloaded first). What the user sees of the frontend looks like this:

The icon on the left launches user preferences, and the graphic on the right “connects” or “disconnects” from Dropbox (in actuality, this means mounting/dismounting the DBoxTop filesystem daemon).
The frontend is responsible for all authorization/authentication dialogs which grant the application access to the user’s Dropbox account, a preference dialog, and a multi-task progress indicator for downloads (although this workflow is currently impeded; see the end of this post for details). Its primary purpose however, as mentioned before, is to provide a bridge from the backend to the Dropbox API.
While the backend does not provide a graphical user interface, the user initiates interaction with it whenever he or she performs an operation on files. The avenue by which this is typically done is either via Nautilus or the command window, as shown.

The screenshot above also hints at our goal of local/remote transparency, or that all of the user’s files are visible regardless of whether or not they are cached locally.
Development Process
Despite its drawbacks, separating the project in this way led to a rather intuitive way to organize teams. Since we had a small class of 7 people, it was decided that three persons (Ryan Alfuth, Benjamin Bockstege, and myself) would work on the backend, while the remaining students (Elijah English, Jeff Largent, Nathaniel Martin, and Ryan Veneklase) would implement the frontend and its components.
We practiced a loose form of the scrum agile development process, meeting once or twice a week for 10-15 minutes with our advisor, who kept track of progress for grading purposes and played a large role in sprint planning.
An Incredible Experience
This is the kind of class that I can’t get enough of. Furthermore, the fact that it is not only a class that I dig but that it also counts as academic credit tickles me all shades of neon colors.
I learned a great deal about working with a team this semester. Perhaps the highlight of my experience was successful paired programming, which taught me a great deal about the value of patience and being willing to teach others to “fish” rather than “fishing” for them. It also brought the backend team very close together as a unit, with each contributing significant personal investment in time, code, and brain cycles. I also witnessed a transformation in at least one member who, as we encouraged his contribution and kept him looped in on decisions, rapidly took ownership of his involvement and could scarcely contain his enthusiasm for the project.
Of course, managing a project also comes with a great deal of frustration, especially when there is a large lack of communication intra- as well as inter-team. While functioning as the informal project lead — which occurred mostly because my zeal for the project, combined with a lack of leadership initiative at the onset of the project, positioned me for the role — myself in addition to a few other of the more involved folks were constantly faced with the problem of giving the remaining members of the group opportunities to be actively invested in the process, yet under the constraint of looming deadlines. More often than not an empty-handed team-mate forced one or two people on the team to pick up the slack for the other, just to be able to meet the sprint deadlines.
In summary, while I feel that overall we were successful, we certainly could have improved our communication and fostered greater contribution as a whole. For one thing, we should have agreed on a weekly, set schedule by which we could have met as an entire team to hash out the latest problems and solution proposals, argue over intelligently discuss important architecture decisions, and so on. This would have kept us much more responsible to each other. As it were, our meetings did take place fairly frequently, but they were ad-hoc, somewhat unstructured, and often lacked key developers.
Current State & Future Goals
As of December 2010, DBoxTop is fully functional as a Dropbox client for the Linux desktop. There are, however, a few major tasks which we were not able to complete in the course of a single semester. What follows is a shortened version of DBoxTop’s to-do list:
Continue remedying the asynchronous downloading
“Whoa, wait,” you say, “you mean to tell us you didn’t plan for asynchronous downloading of files!?” Not to worry: the system was indeed designed for this from the onset of the project, but a few technical complications got in the way of achieving fully-asynchronous file downloads that can happen concurrently and without blocking the user interface. We do have a functioning multi-threaded download manager on the frontend and requests to download a file from the backend are also performed on separate threads. Without delving into too much detail here, the problem currently lies in the way that the DBus message pump ties into the Glib UI loop, which has the consequence that while a service call (from backend to frontend) is waiting to return, the UI thread is effectively frozen.
The solution to this dilemma is to implement two-way IPC so that the frontend can asynchronously notify the backend when a download has been completed; however, this requires that the backend also provide a DBus “server” and have the threading backbone to manage download requests and their state. We made a significant amount of progress toward this end, but we ended up running out of time and had to revert the code back to its synchronous state for the product demo.
Port to the N900
This is, of course, a major goal of the project. It should not be too difficult, however, since the N900 runs a 2.6.x Linux kernel, sports a Gnome-based desktop with GVFS/GIO support, and can run a Python interpreter. We’ll need to cross-compile the binaries and tweak a few things here and there, including using Maemo’s or MeeGo’s adaptation of Qt for our user interface.
Authorize the application with Dropbox
In order for normal accounts (those other than our developer accounts) to be linked to our application, we must submit our source code to Dropbox for its “blessing.” The next goal naturally follows…
Provide installation packages
This is especially wanted since what we have now is nearly ready for installation and beta preview by end-users, at least on Ubuntu systems.
Since the backend is already setup to build with automake/autoconf, this shouldn’t be tremendously difficult. We intend to package the backend and frontend separately, but have them inter-dependent and/or create a metapackage called “dboxtop” which depends on both “dboxtop-backend” and “dboxtop-frontend.”
Although it is obvious that we have a long way to go on the project, my colleagues and I are extraordinarily excited to have been a part of the inception of the project, and satisfied with the progress that we have been able to make towards the end result. I look forward to see it evolve into a fully-featured client.
Resources
- Technology information
- DBoxTop information
Credits
Out of all who contributed to the DBoxTop project this semester, special thanks go to teammates Ryan Alfuth and Benjamin Bockstege for their stellar work. In addition to his technical contributions, we also owe Jeff Largent for the DBoxTop logo. Nate is officially the Qt guru for the project, Eli wins the award for most on-topic late-night phone-calls placed, and the prize for the best humor and team spirit goes, as always, to Jeff. Thanks guys!
Want to Help?
If you are interested in being a part of the DBoxTop project moving forward, feel free to contact our adviser.