| Index: ui/file_manager/zip_archiver/unpacker/js/compressor.js
|
| diff --git a/ui/file_manager/zip_archiver/unpacker/js/compressor.js b/ui/file_manager/zip_archiver/unpacker/js/compressor.js
|
| deleted file mode 100644
|
| index a96fd4db7375d809bcc81623df9cee62b5df2c68..0000000000000000000000000000000000000000
|
| --- a/ui/file_manager/zip_archiver/unpacker/js/compressor.js
|
| +++ /dev/null
|
| @@ -1,516 +0,0 @@
|
| -// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -'use strict';
|
| -
|
| -/**
|
| - * A class that takes care of communication with NaCL and creates an archive.
|
| - * One instance of this class is created for each pack request. Since multiple
|
| - * compression requests can be in progress at the same time, each instance has
|
| - * a unique compressor id of positive integer. Every communication with NaCL
|
| - * must be done with compressor id.
|
| - * @constructor
|
| - * @param {!Object} naclModule The nacl module.
|
| - * @param {!Array} items The items to be packed.
|
| - */
|
| -unpacker.Compressor = function(naclModule, items) {
|
| - /**
|
| - * @private {!Object}
|
| - * @const
|
| - */
|
| - this.naclModule_ = naclModule;
|
| -
|
| - /**
|
| - * @private {!Array}
|
| - * @const
|
| - */
|
| - this.items_ = items;
|
| -
|
| - /**
|
| - * @private {!unpacker.types.CompressorId}
|
| - * @const
|
| - */
|
| - this.compressorId_ = unpacker.Compressor.compressorIdCounter++;
|
| -
|
| - /**
|
| - * @private {string}
|
| - * @const
|
| - */
|
| - this.archiveName_ = this.getArchiveName_();
|
| -
|
| - /**
|
| - * The counter used to assign a unique id to each entry.
|
| - * @type {number}
|
| - */
|
| - this.entryIdCounter_ = 1;
|
| -
|
| - /**
|
| - * The set of entry ids waiting for metadata from FileSystem API.
|
| - * These requests needs to be tracked here to tell whether all pack process
|
| - * has finished or not.
|
| - * @type {!Set}
|
| - */
|
| - this.metadataRequestsInProgress_ = new Set();
|
| -
|
| - /**
|
| - * The queue containing entry ids that have already obtained metadata from
|
| - * FileSystem API and are waiting to be added into archive.
|
| - * @type {!Array}
|
| - */
|
| - this.pendingAddToArchiveRequests_ = [];
|
| -
|
| - /**
|
| - * The id of the entry that is being compressed and written into archive.
|
| - * Note that packing of each entry should be done one by one unlike
|
| - * unpacking. Thus, at most one entry is processed at once.
|
| - * @type {!unpacker.types.EntryId}
|
| - */
|
| - this.entryIdInProgress_ = 0;
|
| -
|
| - /**
|
| - * Map from entry ids to entries.
|
| - * @const {!Object<!unpacker.types.EntryId, !FileEntry|!DirectoryEntry>}
|
| - */
|
| - this.entries_ = {};
|
| -
|
| - /**
|
| - * Map from entry ids to its metadata.
|
| - * @const {!Object<!unpacker.types.EntryId, !Metadata>}
|
| - */
|
| - this.metadata_ = {};
|
| -
|
| - /**
|
| - * The offset from which the entry in progress should be read.
|
| - * @type {number}
|
| - */
|
| - this.offset_ = 0;
|
| -};
|
| -
|
| -/**
|
| - * The counter which is assigned and incremented every time a new compressor
|
| - * instance is created.
|
| - * @type {number}
|
| - */
|
| -unpacker.Compressor.compressorIdCounter = 1;
|
| -
|
| -/**
|
| - * The queue containing compressor ids that wait for foreground page to be
|
| - * loaded. Once this extension becomes a component extension, we don't need to
|
| - * create an archive file on the foreground page and this also gets unnecessary.
|
| - * @type {!Array}
|
| - */
|
| -unpacker.Compressor.CompressorIdQueue = [];
|
| -
|
| -/**
|
| - * The default archive name.
|
| - * @type {string}
|
| - */
|
| -unpacker.Compressor.DEFAULT_ARCHIVE_NAME = 'Archive.zip';
|
| -
|
| -/**
|
| - * The getter function for compressor id.
|
| - * @return {!unpacker.types.CompressorId}
|
| - */
|
| -unpacker.Compressor.prototype.getCompressorId = function() {
|
| - return this.compressorId_;
|
| -};
|
| -
|
| -/**
|
| - * Returns the archive file name.
|
| - * @private
|
| - * @return {string}
|
| - */
|
| -unpacker.Compressor.prototype.getArchiveName_ = function() {
|
| - // When multiple entries are selected.
|
| - if (this.items_.length !== 1)
|
| - return unpacker.Compressor.DEFAULT_ARCHIVE_NAME;
|
| -
|
| - var name = this.items_[0].entry.name
|
| - var idx = name.lastIndexOf('.');
|
| - // When the name does not have extension.
|
| - // TODO(takise): This converts file.tar.gz to file.tar.zip.
|
| - if (idx === -1)
|
| - return name + '.zip';
|
| - // When the name has extension.
|
| - return name.substring(0, idx) + '.zip';
|
| -};
|
| -
|
| -/**
|
| - * Starts actual compressing process.
|
| - * Creates an archive file and requests libarchive to create an archive object.
|
| - * @param {function(!unpacker.types.CompressorId)} onSuccess
|
| - * @param {function(!unpacker.types.CompressorId)} onError
|
| - */
|
| -unpacker.Compressor.prototype.compress = function(onSuccess, onError) {
|
| - this.onSuccess_ = onSuccess;
|
| - this.onError_ = onError;
|
| -
|
| - this.getArchiveFile_();
|
| -};
|
| -
|
| -/**
|
| - * Gets an archive file with write permission. Currently, this extension does
|
| - * not have permission to create files from the background page. Thus, this
|
| - * function first creates a foreground page and then creates an archive file in
|
| - * it. Once this extension becomes a component extension, this process will be
|
| - * simpler.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.getArchiveFile_ = function() {
|
| - // If the foreground page already exists, create an archive file.
|
| - if (this.createArchiveFileForeground_) {
|
| - this.createArchiveFileForeground_(this.compressorId_);
|
| - } else {
|
| - // If the foreground page does not exist, push the id of this compressor to
|
| - // the queue so that we can resume later and create the foreground page.
|
| - // We need this queue because multiple compressors can wait for the
|
| - // foreground page to be loaded.
|
| - var queue = unpacker.Compressor.CompressorIdQueue;
|
| - queue.push(this.compressorId_);
|
| - if (queue.length === 1) {
|
| - chrome.app.window.create('../html/compressor.html', {hidden: true});
|
| - }
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Sends an create archive request to NaCL.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.sendCreateArchiveRequest_ = function() {
|
| - var request = unpacker.request.createCreateArchiveRequest(
|
| - this.compressorId_);
|
| - this.naclModule_.postMessage(request);
|
| -}
|
| -
|
| -/**
|
| - * A handler of create archive done response.
|
| - * Enumerates entries and requests FileSystem API for their metadata.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.createArchiveDone_ = function() {
|
| - this.items_.forEach(function(item) {
|
| - this.getEntryMetadata_(item.entry);
|
| - }.bind(this));
|
| -}
|
| -
|
| -/**
|
| - * Gets metadata of a file or directory.
|
| - * @param {!FileEntry|!DirectoryEntry} entry FileEntry or DirectoryEntry.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.getEntryMetadata_ = function(entry) {
|
| - if (entry.isFile)
|
| - this.getSingleMetadata_(entry);
|
| - else
|
| - this.getDirectoryEntryMetadata_(/** @type {!DirectoryEntry} */ (entry));
|
| -}
|
| -
|
| -/**
|
| - * Requests metadata of an entry non-recursively.
|
| - * @param {!FileEntry|!DirectoryEntry} entry FileEntry or DirectoryEntry.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.getSingleMetadata_ = function(entry) {
|
| - var entryId = this.entryIdCounter_++;
|
| - this.metadataRequestsInProgress_.add(entryId);
|
| - this.entries_[entryId] = entry;
|
| -
|
| - entry.getMetadata(function(metadata) {
|
| - this.metadataRequestsInProgress_.delete(entryId);
|
| - this.pendingAddToArchiveRequests_.push(entryId);
|
| - this.metadata_[entryId] = metadata;
|
| - this.sendAddToArchiveRequest_();
|
| - }.bind(this), function(error) {
|
| - console.error('Failed to get metadata: ' +
|
| - error.message + '.');
|
| - this.onError_(this.compressorId_);
|
| - }.bind(this));
|
| -}
|
| -
|
| -/**
|
| - * Requests metadata of an entry recursively.
|
| - * @param {!DirectoryEntry} dir DirectoryEntry.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.getDirectoryEntryMetadata_ = function(dir) {
|
| -
|
| - // Read entries in dir and call getEntryMetadata_ for them recursively.
|
| - var dirReader = dir.createReader();
|
| -
|
| - // Recursive function
|
| - var getEntries = function() {
|
| - dirReader.readEntries(function(results) {
|
| - // ReadEntries must be called until it returns nothing, because
|
| - // it does not necessarily return all entries in the directory.
|
| - if (results.length) {
|
| - results.forEach(this.getEntryMetadata_.bind(this));
|
| - getEntries();
|
| - }
|
| - }.bind(this), function(error) {
|
| - console.error('Failed to get directory entries: ' +
|
| - error.message + '.');
|
| - this.onError_(this.compressorId_);
|
| - }.bind(this));
|
| - }.bind(this);
|
| -
|
| - getEntries();
|
| -
|
| - // Get the metadata of this dir itself.
|
| - this.getSingleMetadata_(dir);
|
| -}
|
| -
|
| -/**
|
| - * Pops an entry from the queue and adds it to the archive.
|
| - * If another entry is in progress, this function does nothing. If there is no
|
| - * entry in the queue, it shifts to close archive process. Otherwise, this sends
|
| - * an add to archive request for a popped entry with its metadata to libarchive.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.sendAddToArchiveRequest_ = function() {
|
| - // Another process is in progress.
|
| - if (this.entryIdInProgress_ != 0)
|
| - return;
|
| -
|
| - // All entries have already been archived.
|
| - if (this.pendingAddToArchiveRequests_.length === 0) {
|
| - if (this.metadataRequestsInProgress_.size === 0)
|
| - this.sendCloseArchiveRequest(false /* hasError */);
|
| - return;
|
| - }
|
| -
|
| - var entryId = this.pendingAddToArchiveRequests_.shift();
|
| - this.entryIdInProgress_ = entryId;
|
| -
|
| - // Convert the absolute path on the virtual filesystem to a relative path from
|
| - // the archive root by removing the leading '/' if exists.
|
| - var fullPath = this.entries_[entryId].fullPath;
|
| - if (fullPath.length && fullPath[0] == '/')
|
| - fullPath = fullPath.substring(1);
|
| -
|
| - // Modification time is sent as string in a format: 'mm/dd/yy hh:mm:ss'.
|
| - var mt = this.metadata_[entryId].modificationTime;
|
| - var formattedTime = (mt.getMonth() + 1) + '/' + mt.getDate() + '/' +
|
| - mt.getFullYear() + ' ' + mt.getHours() + ':' +
|
| - mt.getMinutes() + ':' + mt.getSeconds();
|
| -
|
| - var request = unpacker.request.createAddToArchiveRequest(
|
| - this.compressorId_, entryId, fullPath,
|
| - this.metadata_[entryId].size, formattedTime,
|
| - this.entries_[entryId].isDirectory);
|
| - this.naclModule_.postMessage(request);
|
| -}
|
| -
|
| -/**
|
| - * Sends a close archive request to libarchive. libarchive writes metadata of
|
| - * the archive itself on the archive and releases objects obtainted in the
|
| - * packing process.
|
| - */
|
| -unpacker.Compressor.prototype.sendCloseArchiveRequest = function(hasError) {
|
| - var request = unpacker.request.createCloseArchiveRequest(
|
| - this.compressorId_, hasError);
|
| - this.naclModule_.postMessage(request);
|
| -}
|
| -
|
| -/**
|
| - * Sends a read file chunk done response.
|
| - * @param {number} length The number of bytes read from the entry.
|
| - * @param {!ArrayBuffer} buffer A buffer containing the data that was read.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.sendReadFileChunkDone_ =
|
| - function(length, buffer) {
|
| - var request = unpacker.request.createReadFileChunkDoneResponse(
|
| - this.compressorId_, length, buffer);
|
| - this.naclModule_.postMessage(request);
|
| -}
|
| -
|
| -/**
|
| - * A handler of read file chunk messages.
|
| - * Reads 'length' bytes from the entry currently in process.
|
| - * @param {!Object} data
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.onReadFileChunk_ = function(data) {
|
| - var entryId = this.entryIdInProgress_;
|
| - var entry = this.entries_[entryId];
|
| - var length = Number(data[unpacker.request.Key.LENGTH]);
|
| -
|
| - // A function to create a reader and read bytes.
|
| - var readFileChunk = function() {
|
| - var file = this.file_.slice(this.offset_, this.offset_ + length);
|
| - var reader = new FileReader();
|
| -
|
| - reader.onloadend = function(event) {
|
| - var buffer = event.target.result;
|
| -
|
| - // The buffer must have 'length' bytes because the byte length which can
|
| - // be read from the file is already calculated on NaCL side.
|
| - if (buffer.byteLength !== length) {
|
| - console.error('Tried to read chunk with length ' + length +
|
| - ', but byte with length ' + buffer.byteLength + ' was returned.');
|
| -
|
| - // If the first argument(length) is negative, it means that an error
|
| - // occurred in reading a chunk.
|
| - this.sendReadFileChunkDone_(-1, buffer);
|
| - this.onError_(this.compressorId_);
|
| - return;
|
| - }
|
| -
|
| - this.offset_ += length;
|
| - this.sendReadFileChunkDone_(length, buffer);
|
| - }.bind(this);
|
| -
|
| - reader.onerror = function(event) {
|
| - console.error('Failed to read file chunk. Name: ' + file.name +
|
| - ', offset: ' + this.offset_ + ', length: ' + length + '.');
|
| -
|
| - // If the first argument(length) is negative, it means that an error
|
| - // occurred in reading a chunk.
|
| - this.sendReadFileChunkDone_(-1, new ArrayBuffer(0));
|
| - this.onError_(this.compressorId_);
|
| - }
|
| -
|
| - reader.readAsArrayBuffer(file);
|
| - }.bind(this);
|
| -
|
| - // When the entry is read for the first time.
|
| - if (!this.file_) {
|
| - entry.file(function(file) {
|
| - this.file_ = file;
|
| - readFileChunk();
|
| - }.bind(this));
|
| - return;
|
| - }
|
| -
|
| - // From the second time onward.
|
| - readFileChunk();
|
| -}
|
| -
|
| -/**
|
| - * A handler of write chunk requests.
|
| - * Writes the data in the given buffer onto the archive file.
|
| - * @param {!Object} data
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.onWriteChunk_ = function(data) {
|
| - var length = Number(data[unpacker.request.Key.LENGTH]);
|
| - var buffer = data[unpacker.request.Key.CHUNK_BUFFER];
|
| - this.writeChunk_(length, buffer, this.sendWriteChunkDone_.bind(this));
|
| -}
|
| -
|
| -/**
|
| - * Writes buffer into the archive file (window.archiveFileEntry).
|
| - * @param {number} length The number of bytes in the buffer to write.
|
| - * @param {!ArrayBuffer} buffer The buffer to write in the archive.
|
| - * @param {function(number)} callback Callback to execute at the end of the
|
| - * function. This function has one parameter: length, which represents the
|
| - * length of bytes written on to the archive. If writing a chunk fails,
|
| - * a negative value must be assigned to this argument.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.writeChunk_ = function(length, buffer,
|
| - callback) {
|
| - // TODO(takise): Use the same instance of FileWriter over multiple calls of
|
| - // this function instead of creating new ones.
|
| - this.archiveFileEntry_.createWriter(function(fileWriter) {
|
| - fileWriter.onwriteend = function(event) {
|
| - callback(length);
|
| - };
|
| -
|
| - fileWriter.onerror = function(event) {
|
| - console.error('Failed to write chunk to ' + this.archiveFileEntry_ + '.');
|
| -
|
| - // If the first argument(length) is negative, it means that an error
|
| - // occurred in writing a chunk.
|
| - callback(-1 /* length */);
|
| - this.onError_(this.compressorId_);
|
| - };
|
| -
|
| - // Create a new Blob and append it to the archive file.
|
| - var blob = new Blob([buffer], {});
|
| - fileWriter.seek(fileWriter.length);
|
| - fileWriter.write(blob);
|
| - }, function(event) {
|
| - console.error('Failed to create writer for ' + this.archiveFileEntry_ +
|
| - '.');
|
| - this.onError_(this.compressorId_);
|
| - });
|
| -};
|
| -
|
| -/**
|
| - * Sends a write chunk done response.
|
| - * @param {number} length The number of bytes written onto the entry.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.sendWriteChunkDone_ = function(length) {
|
| - var request = unpacker.request.createWriteChunkDoneResponse(
|
| - this.compressorId_, length);
|
| - this.naclModule_.postMessage(request);
|
| -}
|
| -
|
| -/**
|
| - * A handler of add to archive done responses.
|
| - * Resets information on the current entry and starts processing another entry.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.onAddToArchiveDone_ = function() {
|
| - // Reset information on the current entry.
|
| - this.entryIdInProgress_ = 0;
|
| - this.file_ = null;
|
| - this.offset_ = 0;
|
| -
|
| - // Start processing another entry.
|
| - this.sendAddToArchiveRequest_();
|
| -}
|
| -
|
| -/**
|
| - * A handler of close archive responses.
|
| - * Receiving this response means the entire packing process has finished.
|
| - * @private
|
| - */
|
| -unpacker.Compressor.prototype.onCloseArchiveDone_ = function() {
|
| - this.onSuccess_(this.compressorId_);
|
| -}
|
| -
|
| -/**
|
| - * Processes messages from NaCl module.
|
| - * @param {!Object} data The data contained in the message from NaCl. Its
|
| - * types depend on the operation of the request.
|
| - * @param {!unpacker.request.Operation} operation An operation from request.js.
|
| - */
|
| -unpacker.Compressor.prototype.processMessage = function(data, operation) {
|
| - switch (operation) {
|
| - case unpacker.request.Operation.CREATE_ARCHIVE_DONE:
|
| - this.createArchiveDone_();
|
| - break;
|
| -
|
| - case unpacker.request.Operation.READ_FILE_CHUNK:
|
| - this.onReadFileChunk_(data);
|
| - break;
|
| -
|
| - case unpacker.request.Operation.WRITE_CHUNK:
|
| - this.onWriteChunk_(data);
|
| - break;
|
| -
|
| - case unpacker.request.Operation.ADD_TO_ARCHIVE_DONE:
|
| - this.onAddToArchiveDone_();
|
| - break;
|
| -
|
| - case unpacker.request.Operation.CLOSE_ARCHIVE_DONE:
|
| - this.onCloseArchiveDone_();
|
| - break;
|
| -
|
| - case unpacker.request.Operation.COMPRESSOR_ERROR:
|
| - console.error('Compressor error for compressor id ' + this.compressorId_ +
|
| - ': ' + data[unpacker.request.Key.ERROR]); // The error contains
|
| - // the '.' at the end.
|
| - this.onError_(this.compressorId_);
|
| - break;
|
| -
|
| - default:
|
| - console.error('Invalid NaCl operation: ' + operation + '.');
|
| - this.onError_(this.compressorId_);
|
| - }
|
| -};
|
|
|