function uploadFile(file) {
  var parentDirPath = document.getElementById('file_input_parent_dir').value;
  var parentDir = getService('File').getEntry(parentDirPath);
  if (!parentDir) {
    return;
  }
  if (parentDir.children[file.name])
    delete parentDir.children[file.name];
  var obj = {
    name: file.name, 
    blob: file
  };
  parentDir.children[file.name] = obj;
  //saveFileBinaryString(obj, file);
  getService('File').refreshTree();
}

function uploadDirectory() {
  // Get the path to a file. I.E. getParentPath("a/b/c") returns "a/b"
  function getParentPath(filePath) {
    var lastSlashIndex = filePath.lastIndexOf("/");
    if (lastSlashIndex > -1)
        return filePath.substring(0, lastSlashIndex);
    return "";
  }
  
  function createDirectory(directory) {
    var pathComponents = directory.split("/");
    var currentPath;
    var parentPath;

    for (var i = 0; i < pathComponents.length; i++) {
      currentFolder = pathComponents[i];
      currentPath = pathComponents.slice(0, i + 1).join('/');
      if (dirs[currentPath]) continue;
      // Create current path only if it doesn't already exist
      dirs[currentPath] = { name: pathComponents[i], children: {}};
      parentPath = pathComponents.slice(0, i).join('/');
      if (parentPath) // Add newly created path to parent
        dirs[parentPath].children[currentFolder] = dirs[currentPath];
    }
  }
  getService('File').files = event.target.files;

  var dirs = {};
  var file;
  var obj;
  var parentPath;
	for (var i = 0; i < event.target.files.length; i++) {
		file = event.target.files[i];
    var obj = {
      name: file.name, 
      blob: file
    };

		parentPath = getParentPath(file.webkitRelativePath);
    // Create all directories in parent path in dirs if they don't exist
    if (!dirs[parentPath]) {
      createDirectory(parentPath);
    }
		dirs[parentPath].children[file.name] = obj;
	}

  var rootDir;
  for (var dir in dirs) {
    if (dir.indexOf('/') === -1) {
      rootDir = dir;
      break;
    }
  }
  getService('File').fileSystem = dirs[rootDir];
  getService('File').refreshTree();
}

require([
        "dojo/dom",
        "dojo/dom-construct",
        "dojo/has",
        "dojo/_base/sniff"], function(dom, domConstruct, has){
	addService("File", function() {

    this.STATUS_CODES = {
      NO_RESULT: 0,
		  OK: 1,
		  CLASS_NOT_FOUND_EXCEPTION: 2,
		  ILLEGAL_ACCESS_EXCEPTION: 3,
		  INSTANTIATION_EXCEPTION: 4,
		  MALFORMED_URL_EXCEPTION: 5,
		  IO_EXCEPTION: 6,
		  INVALID_ACTION: 7,
		  JSON_EXCEPTION: 8,
		  ERROR: 9
    };
    this.ERROR_CODES = {
      NOT_FOUND_ERR: 1,
      SECURITY_ERR: 2,
      ABORT_ERR: 3,

      NOT_READABLE_ERR: 4,
      ENCODING_ERR: 5,
      NO_MODIFICATION_ALLOWED_ERR: 6,
      INVALID_STATE_ERR: 7,
      SYNTAX_ERR: 8,
      INVALID_MODIFICATION_ERR: 9,
      QUOTA_EXCEEDED_ERR: 10,
      TYPE_MISMATCH_ERR: 11,
      PATH_EXISTS_ERR: 12
    };

    // IF WE CAN'T use the File constructor, this is a browser that doesn't 
    // support the File API. In this case, set the html of the File section
    // and return
    var canUseFileAPI = true;
    try {
      new File(['Contents of readme.txt'], 'readme.txt', {type: 'text/plain'});
    } catch (err) {
      canUseFileAPI = false;
    }
    if (!canUseFileAPI) {
      document.getElementById('fileSection').innerHTML = 'You cannot use the File API in this browser. Use Chrome or FireFox.';
      return;
    }

    // Default file system
    this.fileSystem = {
      "name": "MyFileSystem",
      "children": {
        "readme.txt": {
          'blob': new File(['Contents of readme.txt'], 'readme.txt', 
                           {type: 'text/plain'}),
          "name": "readme.txt"
        }
      }
    }
		// Associative array of source windows to uuids (key is the uuid)
		var sources = new Array();
		var fileSystemDirectory = null;
    var result;
    var system;
		
		// Public
    this.freeDiskSpace = function() {
      return document.getElementById('file_diskspace').text;
    }
		// Handle requests
		this.exec = function(action, args, callbackId, source, uuid) {
			try {
				_consoleLog("cordovaFileApplet.exec( " + action + " " + JSON.stringify(args) + " " + callbackId + " " + uuid );
				sources[uuid]=source;
        if (action === 'testSaveLocationExists') {
          this.testSaveLocationExists(callbackId, uuid);
        } else if (action === 'getFreeDiskSpace') {
          this.getFreeDiskSpace(callbackId, uuid);
        } else if (action === 'testFileExists' || action === 'testDirectoryExists') {
          // In the Java Applet code, these methods are the same
          this.testFileExists(callbackId, uuid, args);
        } else if (action == 'readAsText') {
          // TODO encoding
          this.readAsText(callbackId, uuid, args);
        } else if (action === 'readAsDataURL') {
          this.readAsDataURL(callbackId, uuid, args);
        } else if (action == 'write') {
          this.write(callbackId, uuid, args);
        } else if (action == 'truncate') {
          this.truncate(callbackId, uuid, args);
        } else if (action === 'requestFileSystem') {
          this.requestFileSystem(callbackId, uuid, args);
        } else if (action === 'resolveLocalFileSystemURI') {
          this.resolveLocalFileSystemURI(callbackId, uuid, args);
        } else if (action === 'getMetadata') {
          this.getMetadata(callbackId, uuid, args);
        } else if (action === 'getFileMetadata') {
          this.getFileMetadata(callbackId, uuid, args);
        } else if (action === 'getParent') {
          this.getParent(callbackId, uuid, args);
        } else if (action === 'getDirectory') {
          this.getDirectory(callbackId, uuid, args);
        } else if (action === 'getFile') {
          this.getFile(callbackId, uuid, args);
        } else if (action === 'remove') {
          this.remove(callbackId, uuid, args, false);
        } else if (action === 'removeRecursively') {
          this.remove(callbackId, uuid, args, true);
        } else if (action === 'moveTo') {
          this.transferTo(callbackId, uuid, args, false);
        } else if (action === 'copyTo') {
          this.transferTo(callbackId, uuid, args, true);
        } else if (action === 'readEntries') {
          this.readEntries(callbackId, uuid, args[0]);
        } else {
          this.postResult(JSON.stringify({
            id: callbackId,
            status: this.STATUS_CODES.INVALID_ACTION,
            message: '',
            keepCallback: false
          }), uuid);
        }

				document.cordovaFileApplet.exec(action, JSON.stringify(args), callbackId, uuid);
				return; // Nothing is returned as Plugin Results are sent from Java code invoking the Javascript postResult method.
			} catch (e) {
				_consoleLog("ERROR: " + e);
			}
		};

    this.resolveLocalFileSystemURI = function(callbackId, uuid, args) {
      var uuri = args[0];
      var filePath = decodeURIComponent(uri);
      var questionMarkIndex;
      var file;
      if (filePath.startsWith('file://')) {
        questionMark = filePath.indexOf('?');
        if (questionMark < 0) {
          filePath = filePath.substring('file://'.length, filePath.length);
        } else {
          filePath = filePath.substring('file://'.length, questionMarkIndex);
        }
      }
      file = this.getEntry(filePath);
      if (file) {
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
      } else {
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.OK,
          message: {
            fullPath: filePath,
            isFile: !this.isDirectory(file),
            isDirectory: this.isDirectory(file),
            name: file.name
          },
          keepCallback: false
        }), uuid);
      }
    }
    
    this.requestFileSystem = function(callbackId, uuid, args) {
      var type = args[0];
      var size = args[1];
      if (!this.fileSystem) {
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.IO_EXCEPTION,
          message: "SD Card not mounted",
          keepCallback: false
        }), uuid);
        return;
      }
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: {
          root: {
            fullPath: this.fileSystem.name,
            isFile: false,
            isDirectory: true
          },
          name: this.fileSystem.name
        },
        keepCallback: false
      }), uuid);
    }

    this.readEntries = function(callbackId, uuid, path) {
      var entry = this.getEntry(path);
      if (!entry) { // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      }
      
      if (!this.isDirectory(entry)) { // not a directory
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
        return;
      }
      var entries = [];
      for (var childEntryName in entry.children) {
        var child = entry.children[childEntryName]; 
        files.push({
          fullPath: args[0] + '/' + child.name,
          isFile: typeof child.children === 'undefined',
          isDirectory: 'children' in child,
          name: child.name
        });
      }
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: files,
        keepCallback: false
      }), uuid);
    }

    this.remove = function(callbackId, uuid, args, recursively) {
      var path = args[0];
      var parentPath = path.lastIndexOf('/') > -1 ? 
                       path.substr(0, path.lastIndexOf('/')) : 
                       null;
      var entry = this.getEntry(args[0]);
      var parentEntry = this.getEntry(args[0]);
      if (path.equals(this.fileSystem.name)) {
        // is root dir
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.OK,
          message: false,
          keepCallback: false
        }), uuid);
        return;
      }
      if (!entry) { 
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      }
      if (!recursively && this.isDirectory(entry) &&
          Object.keys(entry.children).length > 0) {
        // Directory that isn't empty
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
        return;
      }
      parentFile.children[entry.name] = null;
      result = {
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: true,
        keepCallback: false
      };
      this.postResult(JSON.stringify(result), uuid);
    }

    this.getParent = function(callbackId, uuid, args) {
      var path = args[0];
      var entry = this.getEntry(path);
      var parentPath = args[0].lastIndexOf('/') > -1 ? 
                       args[0].substr(0, args[0].lastIndexOf('/')) : 
                       null;
      var parentEntry = this.getEntry(parentPath);
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
      } else if (path.equals(this.fileSystem.name)) {
        // file is root dir, return root dir
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.ERR,
          message: {
            fullPath: path,
            isFile: !this.sDirectory(file),
            isDirectory: this.isDirectory(file),
            name: file.name
          },
          keepCallback: false
        }), uuid);
      } else {
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.OK,
          message: {
            fullPath: parentPath,
            isFile: !this.isDirectory(parentEntry),
            isDirectory: this.isDirectory(parentEntry),
            name: parentEntry.name
          },
          keepCallback: false
        }), uuid);
      }
    }

    this.getFileMetadata = function(callbackId, uuid, args) {
      var path = args[0];
      var entry = this.getEntry(path);
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
      } else if (this.isDirectory(entry)) {
        // not a file
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
      } else {
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.OK,
          message: {
            name: entry.name,
            fullPath: path,
            type: entry.blob.type,
            lastModifiedDate: entry.blob.lastModifiedDate,
            size: entry.blob.size
          },
          keepCallback: false
        }), uuid);
      }
    }

    this.getMetadata = function(callbackId, uuid, args) {
      var path = args[0];
      var entry = this.getEntry(path);
      if (this.isDirectory(entry)) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
      } else {
        this.postResult({
          id: callbackId,
          status: this.STATUS_CODES.OK,
          message: {
            name: entry.name,
            fullPath: path,
            type: entry.blob.type,
            lastModifiedDate: entry.blob.lastModifiedDate,
            size: entry.blob.size
          },
          keepCallback: false
        }, uuid);
      }
    }
    this.readAsText = function(callbackId, uuid, args) {
      var path = args[0];
      var encoding = args[1];
      var entry = this.getEntry(path);
      var data;
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      } else if (this.isDirectory(entry)) {
        // not a file
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
        return;
      }
      var reader = new window.FileReader();
      var that = this;
      reader.onloadend = function() {
        that.postResult(JSON.stringify({
          id: callbackId,
          status: that.STATUS_CODES.OK,
          message: reader.result,
          keepCallback: false
        }), uuid);
      }
      reader.readAsText(entry.blob, encoding);
    }
    this.readAsDataURL = function(callbackId, uuid, args) {
      var path = args[0];
      var entry = this.getEntry(path);
      var data;
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      } else if (this.isDirectory(entry)) {
        // not a file
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
        return;
      }
      var reader = new window.FileReader();
      var that = this;
      reader.onloadend = function() {
        that.postResult(JSON.stringify({
          id: callbackId,
          status: that.STATUS_CODES.OK,
          message: reader.result,
          keepCallback: false
        }), uuid);
      }
      reader.readAsDataURL(entry.blob);
    }
    
    this.truncate = function(callbackId, uuid, args) {
      var name = args[0];
      var size = args[1];
      var entry = this.getEntry(name);
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      } else if (this.isDirectory(entry)) {
        // not a file
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
        return;
      }
      var reader = new window.FileReader();
      var that = this;
      reader.onloadend = function() {
        var newText = reader.result.substring(0, size);
        entry.blob = new File([newText], entry.blob.name, 
                              {type: entry.blob.type});
        //entry.blob = new Blob();
        that.postResult(JSON.stringify({
          id: callbackId,
          status: that.STATUS_CODES.OK,
          message: newText,
          keepCallback: false
        }), uuid);
      }
      reader.readAsText(entry.blob);
    }

    this.write = function(callbackId, uuid, args) {
      var name = args[0], 
          text = args[1], 
          position = args[2];
      var entry = this.getEntry(name);
      if (!entry) {
        // non-existent
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
      } else if (this.isDirectory(entry)) {
        // not a file
        this.postError(callbackId, uuid, this.ERROR_CODES.INVALID_MODIFICATION_ERR);
      }

      var reader = new window.FileReader();
      var that = this;
      reader.onloadend = function() {
        var newText = reader.result.substring(0, position);
        newText += text;
        if (reader.result.length > position + text.length) {
          newText += reader.result.substring(position + text.length, 
                                             reader.result.length);
        }
        entry.blob = new File([newText], entry.blob.name,
                              {type: entry.blob.type});
        that.postResult(JSON.stringify({
          id: callbackId,
          status: that.STATUS_CODES.OK,
          message: newText,
          keepCallback: false
        }), uuid);
      }
      reader.readAsText(entry.blob);
    }

    this.testFileExists = function(callbackId, uuid){
      var path = args[0];
      var entry = this.getEntry(path);
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: entry ? true : false,
        keepCallback: false
      }), uuid);
    }

    this.getFreeDiskSpace = function(callbackId, uuid){
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK, 
        message: this.freeDiskSpace(),
        keepCallback: false
      }), uuid);
    }

    this.testSaveLocationExists = function(callbackId, uuid){
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: this.fileSystem ? true : false,
        keepCallback: false
      }), uuid);
    }

    this.transferTo = function(callbackId, uuid, args, copy){
      var srcPath = args[0];
      var destPath = args[1];
      var namePath = args[2];
      var srcFile = this.getEntry(srcPath);
      var srcParentPath = srcPath.lastIndexOf('/') > -1 ? 
                          srcPath.substr(srcPath.lastIndexOf('/')) : null;
      var srcParentFile = this.getEntry();
      var destFile = this.getEntry(destPath);

      if (!srcFile) {
        // Non-existent source
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.ERR,
          message: this.ERROR_CODES.NOT_FOUND_ERR,
          keepCallback: false
        }), uuid);
      }
      if (!destFile) {
        // Non-existent dest
        this.postResult(JSON.stringify({
          id: callbackId,
          message: this.ERROR_CODES.NOT_FOUND_ERR,
          keepCallback: false
        }), uuid);
      }
      if (!destParentFile) {
        // dest isn't directory
        this.postResult(JSON.stringify({
          id: callbackId,
          message: this.ERROR_CODES.NOT_FOUND_ERR,
          keepCallback: false
        }), uuid);
      }

      if (destPath.startsWith(srcPath)) {
      // dest can't be same as source, dest can't be under source
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.ERROR_CODES.INVALID_MODIFICATION_ERR, 
          keepCallback: false
        }), uuid);
      }
      if (copy) {
        // copying the file to destination
        var srcFileCopy = this.clone(srcFile);
        destFile.children[name] = srcFileCopy;
        srcFileCopy.name = name;
      } else {
        // moving the file to destination, not copying it
        delete srcParentFile.children[srcFile.name];
        destFile.children[name] = srcFile;
        srcFile.name = name;
      }
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        keepCallback: false
      }), uuid);
    }

    this.clone = function(obj) {
      var copy;
    
      // Handle the 3 simple types, and null or undefined
      if (null == obj || "object" != typeof obj) return obj;
    
      // Handle Date
      if (obj instanceof Date) {
          copy = new Date();
          copy.setTime(obj.getTime());
          return copy;
      }
    
      // Handle Array
      if (obj instanceof Array) {
          copy = [];
          for (var i = 0, len = obj.length; i < len; i++) {
              copy[i] = clone(obj[i]);
          }
          return copy;
      }
    
      // Handle Object
      if (obj instanceof Object) {
          copy = {};
          for (var attr in obj) {
              if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
          }
          return copy;
      }
    
      throw new Error("Unable to copy obj! Its type isn't supported.");
    }

    this.postError = function(callbackId, uuid, error) {
        this.postResult(JSON.stringify({
          id: callbackId,
          status: this.STATUS_CODES.ERR,
          message: error,
          keepCallback: false
        }), uuid);
    }

    this.isDirectory = function(file) {
      return file && 'children' in file;
    }

    this.getEntry = function(path, isDir) {
      // Remove leading "/"?
      entryPath = path.startsWith('/') ? path.substring(1, path.length) : path;
      if (!this.fileSystem) return null;
      var pathComponents = entryPath.split("/");
      if (!pathComponents || pathComponents[0] !== this.fileSystem.name) {
        return null;
      }
      var currentFile = getService('File').fileSystem;
      for (var i = 1; i < pathComponents.length; i++) {
        if (!currentFile) break;
        currentFile = currentFile.children ? 
                      currentFile.children[pathComponents[i]] : null;
      }
      if (!currentFile) return null;
      if (typeof isDir === 'undefined')
        return currentFile;
      // Check if entry is file/directory when we expect a file/directory
      return  isDir ^ this.isDirectory(currentFile) ? currentFile : null;
    }
    this.getFileOrDirectory = function(callbackId, uuid, args, isDir) {
      var dirPath = args[0];
      var entryName = args[1];
      var options = args[2];
      var create = false;
      var exclusive = false;
      var newFile;
      var parentPath = dirPath.startsWith('/') ?
                       dirPath.substring(1, dirPath.length) : dirPath;
      if (options) {
        create = options['create'];
        if (create) {
          exclusive = options['exclusive'];
        }
      }
      var parentDir = this.getEntry(parentPath);
      if (!parentDir || !this.isDirectory(parentDir)) {
        // parent directory doesn't exist or isn't a directory
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      }
      var entry = parentDir.children[entryName];
      if (create) {
        // create entry if it doesn't exist
        if (exclusive && entry) {
          // entry already exists when it shouldn't
          this.postError(callbackId, uuid, this.ERROR_CODES.PATH_EXISTS_ERR);
          return;
        }
        if (!entry && isDir) {
          // create directory if it doesn't exist
          parentDir.children[entryName] = {
            name: entryName,
            children: {}
          };
          entry = parentDir.children[entryName];
        } else if (!entry && !isDir) {
          // create entry if it doesn't exist
          parentDir.children[entryName] = {
            name: entryName,
            blob: new File([''], entryName)
          };
          entry = parentDir.children[entryName];
        }
      }
      if (!entry) {
        // entry doesn't exist
        this.postError(callbackId, uuid, this.ERROR_CODES.NOT_FOUND_ERR);
        return;
      }
      if (this.isDirectory(entry) ^ isDir) {
        // Entry is a directory when a file is expected, or vice-versa
        this.postError(callbackId, uuid, this.ERROR_CODES.TYPE_MISMATCH_ERR);
        return;
      }
      this.postResult(JSON.stringify({
        id: callbackId,
        status: this.STATUS_CODES.OK,
        message: {
          fullPath: parentPath + '/' + entry.name,
          isFile: !this.isDirectory(entry),
          isDirectory: this.isDirectory(entry),
          name: entry.name
        },
        keepCallback: false
      }), uuid);
    }

    this.getFile = function(callbackId, uuid, args) {
      this.getFileOrDirectory(callbackId, uuid, args, false);
    }

    this.getDirectory = function(callbackId, uuid, args) {
      this.getFileOrDirectory(callbackId, uuid, args, true);
    }
		
		this.postResult = function(resultString, uuid) {
			_consoleLog("Message recieved from File applet" + resultString);
			var source = sources[uuid];
			if ((source != null) && (typeof source !== "undefined")) {
				var result = null;
				try {
					result = JSON.parse(resultString);
				} catch (err) {
					_consoleLog(err.message);
					_consoleLog("Error occured while interpreting: " + resultString);
				}
				if (typeof result === 'object') {
					_consoleLog("posting...");
					try {
						source.postMessage(JSON.stringify(result), "*");
					} catch (err) {
						_consoleLog(err.message);
						_consoleLog("Error occured while stringifying: " + resultString);
					}
					_consoleLog("posted...");
				} else {
					source.postMessage(resultString, "*");
				}
			} else {
				_consoleLog("Error in postResult");
			}
		};

		this.refreshTree = function() {
      populateTree([this.treeDataFromFile(this.fileSystem)]);
    }
		

		this.treeDataFromFile = function(file, currentPath) {
      if (!file) return;
      currentPath = currentPath ? currentPath : '';
      var obj = {};
      obj.label = file.name;
      obj.id = currentPath + '/' + file.name;
      if (typeof file.children === 'undefined') {
        return obj;
      }
      obj.children = [];
      for (var childName in file.children) {
        var child = file.children[childName];
        if (child) {
          obj.children.push(this.treeDataFromFile(child, obj.id));
        }
      }
      return obj;
    }
		
	
		// Initialization
		{
			_consoleLog("File initialization");
	
			var n = _pg_sim_nls;
			sim_file_refresh_button.set("label", n.sim_file_refresh_button);
      var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
      var isChrome = !!window.chrome && !isOpera;
      if (!isChrome) { // hide directory upload folder if we're not in Chrome
         document.getElementById('file_upload_directory').style.display = 'none';
      }

      this.refreshTree();
		}
	});
	
	// -----------------------------------------------------------------------------
	// Javascript for File UI
	// -----------------------------------------------------------------------------
	
	/**
	 * Retrieve all files and populate tree control
	 */
	function populateTree(treeData) {
		// Delete existing tree widget
		if (dijit.byId("fileTree")) {
			dijit.byId("fileTree").destroyRecursive();
		}
	
		// Create tree widget
		var store = new dojo.data.ItemFileReadStore({
			data : {
			    identifier : 'id',
			    label : 'label',
			    items : treeData
			}
		});
		var treeModel = new dijit.tree.ForestStoreModel({
			store : store
		});
		var treeControl = new dijit.Tree({
		    model : treeModel,
		    showRoot : false,
		    autoExpand : true
		}, "fileTree");
	
		// Add tree widget to DOM
		var block = document.getElementById('fileTreeContainer');
		if (block) {
			block.innerHTML = "";
			block.appendChild(treeControl.domNode);
		}

    // Clicking on an element in the tree sets the directory to upload to
    // in the 'file_input_parent_dir' element
    var dojoTreeRows = document.getElementById('fileTreeContainer')
                               .getElementsByClassName('dijitTreeRow');
    for (var i = 0; i < dojoTreeRows.length; i++) {
      dojoTreeRows[i].onclick = function() {
        // Build directory path leading up to tree label
        var parent_ = this.parentElement;
        var directoryPath = '';
        while (parent_ && parent_.id !== 'fileTreeContainer') {
          if (parent_.classList.contains('dijitTreeNode')) {
            directoryPath = '/' + parent_.getElementsByClassName('dijitTreeLabel')[0].innerHTML + directoryPath;
          }
          parent_ = parent_.parentElement;
        }
        // Remove leading "/undefined". This is an empty tree node
        directoryPath = directoryPath.substr('/undefined'.length, directoryPath.length);

        // Only set the input directory if it is a directory
        var clickedEntry = getService('File').getEntry(directoryPath);
        if (getService('File').isDirectory(clickedEntry)) {
          document.getElementById('file_input_parent_dir').value = directoryPath;
        }
      };
    }
		var nls = _pg_sim_nls;
		new dijit.Tooltip({
	        connectId: ["fileTreeContainer"],
	        label: nls.sim_file_tooltip 	   
	    });

		treeControl.startup();
  }

  var filedata= null;
	
});

