Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(743)

Unified Diff: ui/file_manager/zip_archiver/unpacker/js/compressor.js

Issue 2804453002: Move files from zip_archiver/unpacker/ to zip_archiver/. (Closed)
Patch Set: Move files from zip_archiver/unpacker/ to zip_archiver/. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_);
- }
-};

Powered by Google App Engine
This is Rietveld 408576698