1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Utilities for FileOperationManager. 93240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch */ 103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvar fileOperationUtil = {}; 113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch/** 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Resolves a path to either a DirectoryEntry or a FileEntry, regardless of 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * whether the path is a directory or file. 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {DirectoryEntry} root The root of the filesystem to search. 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {string} path The path to be resolved. 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {Promise} Promise fulfilled with the resolved entry, or rejected with 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * FileError. 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)fileOperationUtil.resolvePath = function(root, path) { 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (path === '' || path === '/') 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.resolve(root); 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new Promise(root.getFile.bind(root, path, {create: false})). 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) catch(function(error) { 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error.name === util.FileError.TYPE_MISMATCH_ERR) { 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Bah. It's a directory, ask again. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new Promise( 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) root.getDirectory.bind(root, path, {create: false})); 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject(error); 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Checks if an entry exists at |relativePath| in |dirEntry|. 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * If exists, tries to deduplicate the path by inserting parenthesized number, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * such as " (1)", before the extension. If it still exists, tries the 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * deduplication again by increasing the number up to 10 times. 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * For example, suppose "file.txt" is given, "file.txt", "file (1).txt", 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * "file (2).txt", ..., "file (9).txt" will be tried. 433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * 443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {DirectoryEntry} dirEntry The target directory entry. 453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {string} relativePath The path to be deduplicated. 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {function(string)=} opt_successCallback Callback run with the 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * deduplicated path on success. 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {function(FileOperationManager.Error)=} opt_errorCallback Callback run 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * on error. 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {Promise} Promise fulfilled with available path. 513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch */ 523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochfileOperationUtil.deduplicatePath = function( 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dirEntry, relativePath, opt_successCallback, opt_errorCallback) { 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The trial is up to 10. 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var MAX_RETRY = 10; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Crack the path into three part. The parenthesized number (if exists) will 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // be replaced by incremented number for retry. For example, suppose 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |relativePath| is "file (10).txt", the second check path will be 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // "file (11).txt". 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var match = /^(.*?)(?: \((\d+)\))?(\.[^.]*?)?$/.exec(relativePath); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var prefix = match[1]; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var ext = match[3] || ''; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Check to see if the target exists. 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var resolvePath = function(trialPath, numRetry, copyNumber) { 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return fileOperationUtil.resolvePath(dirEntry, trialPath).then(function() { 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (numRetry <= 1) { 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Hit the limit of the number of retrial. 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Note that we cannot create FileError object directly, so here we 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // use Object.create instead. 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject( 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) util.createDOMError(util.FileError.PATH_EXISTS_ERR)); 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var newTrialPath = prefix + ' (' + copyNumber + ')' + ext; 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return resolvePath(newTrialPath, numRetry - 1, copyNumber + 1); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, function(error) { 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We expect to be unable to resolve the target file, since we're 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // going to create it during the copy. However, if the resolve fails 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // with anything other than NOT_FOUND, that's trouble. 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error.name === util.FileError.NOT_FOUND_ERR) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return trialPath; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject(error); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var promise = resolvePath(relativePath, MAX_RETRY, 1).catch(function(error) { 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var targetPromise; 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error.name === util.FileError.PATH_EXISTS_ERR) { 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Failed to uniquify the file path. There should be an existing 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // entry, so return the error with it. 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) targetPromise = fileOperationUtil.resolvePath(dirEntry, relativePath); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) targetPromise = Promise.reject(error); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return targetPromise.then(function(entry) { 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject(new FileOperationManager.Error( 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) util.FileOperationErrorType.TARGET_EXISTS, entry)); 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, function(inError) { 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (inError instanceof Error) 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject(inError); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Promise.reject(new FileOperationManager.Error( 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, inError)); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (opt_successCallback) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) promise.then(opt_successCallback, opt_errorCallback); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return promise; 1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}; 1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch/** 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Traverses files/subdirectories of the given entry, and returns them. 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * In addition, this method annotate the size of each entry. The result will 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * include the entry itself. 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {Entry} entry The root Entry for traversing. 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {function(Array.<Entry>)} successCallback Called when the traverse 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * is successfully done with the array of the entries. 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {function(FileError)} errorCallback Called on error with the first 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * occurred error (i.e. following errors will just be discarded). 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)fileOperationUtil.resolveRecursively = function( 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry, successCallback, errorCallback) { 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var result = []; 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var error = null; 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var numRunningTasks = 0; 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var maybeInvokeCallback = function() { 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If there still remain some running tasks, wait their finishing. 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (numRunningTasks > 0) 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (error) 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) errorCallback(error); 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) else 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) successCallback(result); 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }; 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // The error handling can be shared. 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var onError = function(fileError) { 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If this is the first error, remember it. 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!error) 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) error = fileError; 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) --numRunningTasks; 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) maybeInvokeCallback(); 14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }; 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var process = function(entry) { 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) numRunningTasks++; 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result.push(entry); 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (entry.isDirectory) { 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // The size of a directory is 1 bytes here, so that the progress bar 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // will work smoother. 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(hidehiko): Remove this hack. 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry.size = 1; 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Recursively traverse children. 15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var reader = entry.createReader(); 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) reader.readEntries( 16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) function processSubEntries(subEntries) { 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (error || subEntries.length == 0) { 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If an error is found already, or this is the completion 16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // callback, then finish the process. 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) --numRunningTasks; 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) maybeInvokeCallback(); 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var i = 0; i < subEntries.length; i++) 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) process(subEntries[i]); 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Continue to read remaining children. 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) reader.readEntries(processSubEntries, onError); 17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }, 17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) onError); 17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // For a file, annotate the file size. 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry.getMetadata(function(metadata) { 18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry.size = metadata.size; 18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) --numRunningTasks; 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) maybeInvokeCallback(); 18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }, onError); 18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }; 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) process(entry); 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * Copies source to parent with the name newName recursively. 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * This should work very similar to FileSystem API's copyTo. The difference is; 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * - The progress callback is supported. 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * - The cancellation is supported. 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {Entry} source The entry to be copied. 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {DirectoryEntry} parent The entry of the destination directory. 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {string} newName The name of copied file. 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {function(Entry, Entry)} entryChangedCallback 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Callback invoked when an entry is created with the source Entry and 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * the destination Entry. 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {function(Entry, number)} progressCallback Callback invoked 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * periodically during the copying. It takes the source Entry and the 20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * processed bytes of it. 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {function(Entry)} successCallback Callback invoked when the copy 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * is successfully done with the Entry of the created entry. 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {function(FileError)} errorCallback Callback invoked when an error 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * is found. 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @return {function()} Callback to cancel the current file copy operation. 21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * When the cancel is done, errorCallback will be called. The returned 21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * callback must not be called more than once. 21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */ 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)fileOperationUtil.copyTo = function( 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) source, parent, newName, entryChangedCallback, progressCallback, 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) successCallback, errorCallback) { 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) var copyId = null; 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) var pendingCallbacks = []; 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Makes the callback called in order they were invoked. 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var callbackQueue = new AsyncUtil.Queue(); 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var onCopyProgress = function(progressCopyId, status) { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callbackQueue.run(function(callback) { 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (copyId === null) { 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the copyId is not yet available, wait for it. 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pendingCallbacks.push( 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) onCopyProgress.bind(null, progressCopyId, status)); 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This is not what we're interested in. 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (progressCopyId != copyId) { 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (status.type) { 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case 'begin_copy_entry': 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case 'end_copy_entry': 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(mtomasz): Convert URL to Entry in custom bindings. 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (source.isFile ? parent.getFile : parent.getDirectory).call( 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) parent, 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) newName, 2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) null, 2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) function(entry) { 2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) entryChangedCallback(status.sourceUrl, entry); 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) callback(); 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }, 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) function() { 2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) entryChangedCallback(status.sourceUrl, null); 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback(); 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case 'progress': 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) progressCallback(status.sourceUrl, status.size); 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case 'success': 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.onCopyProgress.removeListener( 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) onCopyProgress); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(mtomasz): Convert URL to Entry in custom bindings. 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.URLsToEntries( 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) [status.destinationUrl], function(destinationEntries) { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) successCallback(destinationEntries[0] || null); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case 'error': 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.onCopyProgress.removeListener( 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) onCopyProgress); 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) errorCallback(util.createDOMError(status.error)); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default: 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Found unknown state. Cancel the task, and return an error. 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.error('Unknown progress type: ' + status.type); 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.onCopyProgress.removeListener( 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) onCopyProgress); 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.cancelCopy(copyId); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) errorCallback(util.createDOMError( 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.FileError.INVALID_STATE_ERR)); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Register the listener before calling startCopy. Otherwise some events 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // would be lost. 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.onCopyProgress.addListener(onCopyProgress); 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Then starts the copy. 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(mtomasz): Convert URL to Entry in custom bindings. 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.startCopy( 30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) source.toURL(), parent.toURL(), newName, function(startCopyId) { 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // last error contains the FileError code on error. 30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (chrome.runtime.lastError) { 30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Unsubscribe the progress listener. 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.onCopyProgress.removeListener( 30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) onCopyProgress); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) errorCallback(util.createDOMError(chrome.runtime.lastError)); 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) copyId = startCopyId; 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (var i = 0; i < pendingCallbacks.length; i++) { 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) pendingCallbacks[i](); 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }); 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return function() { 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If copyId is not yet available, wait for it. 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (copyId == null) { 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) pendingCallbacks.push(function() { 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.cancelCopy(copyId); 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }); 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.cancelCopy(copyId); 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) }; 32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}; 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/** 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Thin wrapper of chrome.fileManagerPrivate.zipSelection to adapt its 3333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * interface similar to copyTo(). 3343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * 3353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {Array.<Entry>} sources The array of entries to be archived. 3363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {DirectoryEntry} parent The entry of the destination directory. 3373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {string} newName The name of the archive to be created. 3383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {function(FileEntry)} successCallback Callback invoked when the 3393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * operation is successfully done with the entry of the created archive. 3403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @param {function(FileError)} errorCallback Callback invoked when an error 3413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * is found. 3423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch */ 3433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochfileOperationUtil.zipSelection = function( 3443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch sources, parent, newName, successCallback, errorCallback) { 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mtomasz): Move conversion from entry to url to custom bindings. 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // crbug.com/345527. 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.fileManagerPrivate.zipSelection( 3483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch parent.toURL(), 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) util.entriesToURLs(sources), 3503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch newName, function(success) { 3513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!success) { 3523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Failed to create a zip archive. 3533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch errorCallback( 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.createDOMError(util.FileError.INVALID_MODIFICATION_ERR)); 3553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 3563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 3573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Returns the created entry via callback. 3593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch parent.getFile( 3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch newName, {create: false}, successCallback, errorCallback); 3613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch }); 3623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}; 3633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch/** 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)function FileOperationManager() { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.copyTasks_ = []; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.deleteTasks_ = []; 3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.taskIdCounter_ = 0; 371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) this.eventRouter_ = new FileOperationManager.EventRouter(); 3728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Object.seal(this); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Manages Event dispatching. 378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Currently this can send three types of events: "copy-progress", 379d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * "copy-operation-completed" and "delete". 380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * 381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * TODO(hidehiko): Reorganize the event dispatching mechanism. 382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @constructor 383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @extends {cr.EventTarget} 384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch */ 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.EventRouter = function() { 3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingDeletedEntries_ = []; 3876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingCreatedEntries_ = []; 3886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.entryChangedEventRateLimiter_ = new AsyncUtil.RateLimiter( 3896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.dispatchEntryChangedEvent_.bind(this), 500); 390d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch/** 393d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Extends cr.EventTarget. 394d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch */ 395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.EventRouter.prototype.__proto__ = cr.EventTarget.prototype; 396d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch/** 398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Dispatches a simple "copy-progress" event with reason and current 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * FileOperationManager status. If it is an ERROR event, error should be set. 400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * 401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @param {string} reason Event type. One of "BEGIN", "PROGRESS", "SUCCESS", 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * "ERROR" or "CANCELLED". TODO(hidehiko): Use enum. 403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {Object} status Current FileOperationManager's status. See also 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * FileOperationManager.Task.getStatus(). 4058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * @param {string} taskId ID of task related with the event. 406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {FileOperationManager.Error=} opt_error The info for the error. This 407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * should be set iff the reason is "ERROR". 408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch */ 409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.EventRouter.prototype.sendProgressEvent = function( 4108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) reason, status, taskId, opt_error) { 4116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Before finishing operation, dispatch pending entries-changed events. 4126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (reason === 'SUCCESS' || reason === 'CANCELED') 4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.entryChangedEventRateLimiter_.runImmediately(); 4146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) var event = new Event('copy-progress'); 416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch event.reason = reason; 417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch event.status = status; 4188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) event.taskId = taskId; 419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (opt_error) 420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) event.error = opt_error; 421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch this.dispatchEvent(event); 422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch/** 4256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * Stores changed (created or deleted) entry temporarily, and maybe dispatch 4266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * entries-changed event with stored entries. 4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {util.EntryChangedKind} kind The enum to represent if the entry is 4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * created or deleted. 429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {Entry} entry The changed entry. 430d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch */ 431424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.EventRouter.prototype.sendEntryChangedEvent = function( 4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kind, entry) { 4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (kind === util.EntryChangedKind.DELETED) 4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingDeletedEntries_.push(entry); 4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (kind === util.EntryChangedKind.CREATED) 4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingCreatedEntries_.push(entry); 4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.entryChangedEventRateLimiter_.run(); 4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)/** 4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * Dispatches an event to notify that entries are changed (created or deleted). 4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @private 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) */ 4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)FileOperationManager.EventRouter.prototype.dispatchEntryChangedEvent_ = 4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) function() { 4476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (this.pendingDeletedEntries_.length > 0) { 4486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) var event = new Event('entries-changed'); 4496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.kind = util.EntryChangedKind.DELETED; 4506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.entries = this.pendingDeletedEntries_; 4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.dispatchEvent(event); 4526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingDeletedEntries_ = []; 4536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (this.pendingCreatedEntries_.length > 0) { 4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) var event = new Event('entries-changed'); 4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.kind = util.EntryChangedKind.CREATED; 4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.entries = this.pendingCreatedEntries_; 4586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.dispatchEvent(event); 4596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.pendingCreatedEntries_ = []; 4606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 461d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 462d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 463d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch/** 464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Dispatches an event to notify entries are changed for delete task. 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * 466d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @param {string} reason Event type. One of "BEGIN", "PROGRESS", "SUCCESS", 467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * or "ERROR". TODO(hidehiko): Use enum. 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {DeleteTask} task Delete task related with the event. 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch */ 470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.EventRouter.prototype.sendDeleteEvent = function( 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reason, task) { 4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) var event = new Event('delete'); 473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch event.reason = reason; 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) event.taskId = task.taskId; 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) event.entries = task.entries; 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) event.totalBytes = task.totalBytes; 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) event.processedBytes = task.processedBytes; 478d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch this.dispatchEvent(event); 479d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch/** 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A record of a queued copy operation. 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Multiple copy operations may be queued at any given time. Additional 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Tasks may be added while the queue is being serviced. Though a 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cancel operation cancels everything in the queue. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 48868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {util.FileOperationType} operationType The type of this operation. 4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Array of source entries. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {DirectoryEntry} targetDirEntry Target directory. 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FileOperationManager.Task = function( 49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) operationType, sourceEntries, targetDirEntry) { 49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.operationType = operationType; 4963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.sourceEntries = sourceEntries; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.targetDirEntry = targetDirEntry; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) /** 50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * An array of map from url to Entry being processed. 50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @type {Array.<Object<string, Entry>>} 50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries = null; 504bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 505bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /** 50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Total number of bytes to be processed. Filled in initialize(). 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Use 1 as an initial value to indicate that the task is not completed. 508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch * @type {number} 509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch */ 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.totalBytes = 1; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) /** 51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Total number of already processed bytes. Updated periodically. 51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @type {number} 5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processedBytes = 0; 5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /** 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Index of the progressing entry in sourceEntries. 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @type {number} 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @private 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.processingSourceIndex_ = 0; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) /** 5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Set to true when cancel is requested. 5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @private {boolean} 5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.cancelRequested_ = false; 5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) /** 5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback to cancel the running process. 5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @private {function()} 5343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.cancelCallback_ = null; 5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 537bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // TODO(hidehiko): After we support recursive copy, we don't need this. 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If directory already exists, we try to make a copy named 'dir (X)', 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // where X is a number. When we do this, all subsequent copies from 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inside the subtree should be mapped to the new directory name. 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For example, if 'dir' was copied as 'dir (1)', then 'dir/file.txt' should 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // become 'dir (1)/file.txt'. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.renamedDirectories_ = []; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 546558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch/** 547558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {function()} callback When entries resolved. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 549424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.Task.prototype.initialize = function(callback) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Requests cancellation of this task. 5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * When the cancellation is done, it is notified via callbacks of run(). 5553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.Task.prototype.requestCancel = function() { 5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.cancelRequested_ = true; 5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (this.cancelCallback_) { 5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.cancelCallback_(); 5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.cancelCallback_ = null; 5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Runs the task. Sub classes must implement this method. 5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback 5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback invoked when an entry is changed. 5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} progressCallback Callback invoked periodically during 5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * the operation. 5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback Callback run on success. 572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback Callback run on 573424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * error. 5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.Task.prototype.run = function( 5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback, progressCallback, successCallback, errorCallback) { 5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 5801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Get states of the task. 5811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * TOOD(hirono): Removes this method and sets a task to progress events. 5821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @return {object} Status object. 5831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) */ 5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)FileOperationManager.Task.prototype.getStatus = function() { 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var processingEntry = this.sourceEntries[this.processingSourceIndex_]; 5861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return { 5871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) operationType: this.operationType, 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) numRemainingItems: this.sourceEntries.length - this.processingSourceIndex_, 5891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) totalBytes: this.totalBytes, 5901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) processedBytes: this.processedBytes, 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) processingEntryName: processingEntry ? processingEntry.name : '' 5921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }; 5931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 5941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)/** 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Obtains the number of total processed bytes. 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {number} Number of total processed bytes. 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @private 5991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) */ 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileOperationManager.Task.prototype.calcProcessedBytes_ = function() { 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var bytes = 0; 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (var i = 0; i < this.processingSourceIndex_ + 1; i++) { 6031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var entryMap = this.processingEntries[i]; 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!entryMap) 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (var name in entryMap) { 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bytes += i < this.processingSourceIndex_ ? 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) entryMap[name].size : entryMap[name].processedBytes; 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return bytes; 6121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 6131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)/** 6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Task to copy entries. 6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Array of source entries. 6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} targetDirEntry Target directory. 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {boolean} deleteAfterCopy Whether the delete original files after 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * copy. 6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @constructor 622424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @extends {FileOperationManager.Task} 6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileOperationManager.CopyTask = function(sourceEntries, 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) targetDirEntry, 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleteAfterCopy) { 62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FileOperationManager.Task.call( 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleteAfterCopy ? 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.FileOperationType.MOVE : util.FileOperationType.COPY, 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sourceEntries, 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) targetDirEntry); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.deleteAfterCopy = deleteAfterCopy; 634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Rate limiter which is used to avoid sending update request for progress bar 637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * too frequently. 638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @type {AsyncUtil.RateLimiter} 639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 640f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.updateProgressRateLimiter_ = null; 6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 645424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Extends FileOperationManager.Task. 6463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 647424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.CopyTask.prototype.__proto__ = 648424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FileOperationManager.Task.prototype; 6493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 6503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Initializes the CopyTask. 65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {function()} callback Called when the initialize is completed. 65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FileOperationManager.CopyTask.prototype.initialize = function(callback) { 65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var group = new AsyncUtil.Group(); 65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Correct all entries to be copied for status update. 65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries = []; 65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var i = 0; i < this.sourceEntries.length; i++) { 65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) group.add(function(index, callback) { 66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fileOperationUtil.resolveRecursively( 66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.sourceEntries[index], 66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) function(resolvedEntries) { 66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var resolvedEntryMap = {}; 66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var j = 0; j < resolvedEntries.length; ++j) { 66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var entry = resolvedEntries[j]; 66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry.processedBytes = 0; 66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) resolvedEntryMap[entry.toURL()] = entry; 66868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 66968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries[index] = resolvedEntryMap; 67068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback(); 67168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }.bind(this), 67268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) function(error) { 67368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) console.error( 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'Failed to resolve for copy: %s', error.name); 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback(); 67668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }); 67768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }.bind(this, i)); 67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 67968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 68068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) group.run(function() { 68168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Fill totalBytes. 68268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.totalBytes = 0; 68368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var i = 0; i < this.processingEntries.length; i++) { 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (var entryURL in this.processingEntries[i]) 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.totalBytes += this.processingEntries[i][entryURL].size; 68668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 68868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback(); 68968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }.bind(this)); 69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 69268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** 6933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Copies all entries to the target directory. 6943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Note: this method contains also the operation of "Move" due to historical 6953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * reason. 6963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 6973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback 6983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback invoked when an entry is changed. 6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} progressCallback Callback invoked periodically during 7003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * the copying. 7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback On success. 702424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback On error. 7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @override 7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 705424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.CopyTask.prototype.run = function( 7063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback, progressCallback, successCallback, errorCallback) { 7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(hidehiko): We should be able to share the code to iterate on entries 7083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // with serviceMoveTask_(). 70968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (this.sourceEntries.length == 0) { 7103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(hidehiko): Delete after copy is the implementation of Move. 7153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Migrate the part into MoveTask.run(). 7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var deleteOriginals = function() { 7173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var count = this.sourceEntries.length; 7183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var onEntryDeleted = function(entry) { 7203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback(util.EntryChangedKind.DELETED, entry); 7213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) count--; 7223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!count) 7233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 7243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }; 7253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var onFilesystemError = function(err) { 727424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, err)); 7293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }; 7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (var i = 0; i < this.sourceEntries.length; i++) { 7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var entry = this.sourceEntries[i]; 7333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.removeFileOrDirectory( 7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry, onEntryDeleted.bind(null, entry), onFilesystemError); 7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }.bind(this); 7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /** 739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Accumulates processed bytes and call |progressCallback| if needed. 740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} index The index of processing source. 742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} sourceEntryUrl URL of the entry which has been processed. 743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number=} opt_size Processed bytes of the |sourceEntry|. If it is 744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * dropped, all bytes of the entry are considered to be processed. 745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var updateProgress = function(index, sourceEntryUrl, opt_size) { 747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!sourceEntryUrl) 748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var processedEntry = this.processingEntries[index][sourceEntryUrl]; 751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!processedEntry) 752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Accumulates newly processed bytes. 755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var size = opt_size !== undefined ? opt_size : processedEntry.size; 756f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.processedBytes += size - processedEntry.processedBytes; 757f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) processedEntry.processedBytes = size; 758f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 759f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Updates progress bar in limited frequency so that intervals between 760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // updates have at least 200ms. 761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateProgressRateLimiter_.run(); 762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }.bind(this); 763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateProgressRateLimiter_ = new AsyncUtil.RateLimiter(progressCallback); 765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AsyncUtil.forEach( 7673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.sourceEntries, 7683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(callback, entry, index) { 7693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (this.cancelRequested_) { 770424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 7713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.createDOMError(util.FileError.ABORT_ERR))); 7733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 7743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) progressCallback(); 7761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.processEntry_( 7773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry, this.targetDirEntry, 778f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function(sourceEntryUrl, destinationEntry) { 779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) updateProgress(index, sourceEntryUrl); 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The destination entry may be null, if the copied file got 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // deleted just after copying. 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (destinationEntry) { 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) entryChangedCallback( 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.EntryChangedKind.CREATED, destinationEntry); 78568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 786f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }, 787f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function(sourceEntryUrl, size) { 788f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) updateProgress(index, sourceEntryUrl, size); 789f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }, 790a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) function() { 791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Finishes off delayed updates if necessary. 792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateProgressRateLimiter_.runImmediately(); 793a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Update current source index and processing bytes. 794a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this.processingSourceIndex_ = index + 1; 795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this.processedBytes = this.calcProcessedBytes_(); 796a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback(); 797a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }.bind(this), 798f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function(error) { 799f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Finishes off delayed updates if necessary. 800f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateProgressRateLimiter_.runImmediately(); 801f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) errorCallback(error); 802f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }.bind(this)); 8033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 8043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function() { 8053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (this.deleteAfterCopy) { 8063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) deleteOriginals(); 8073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 8083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 8093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 8103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }.bind(this), 8113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this); 8123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 8133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 8143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 8153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Copies the source entry to the target directory. 8163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 8173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Entry} sourceEntry An entry to be copied. 8183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} destinationEntry The entry which will contain the 8193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * copied entry. 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {function(Entry, Entry} entryChangedCallback 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Callback invoked when an entry is created with the source Entry and 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * the destination Entry. 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {function(Entry, number)} progressCallback Callback invoked 8243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * periodically during the copying. 8253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback On success. 826424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback On error. 8273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @private 8283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 8291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)FileOperationManager.CopyTask.prototype.processEntry_ = function( 8303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntry, destinationEntry, entryChangedCallback, progressCallback, 8313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback, errorCallback) { 8323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fileOperationUtil.deduplicatePath( 8333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) destinationEntry, sourceEntry.name, 8343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(destinationName) { 8351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (this.cancelRequested_) { 836424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 8373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.createDOMError(util.FileError.ABORT_ERR))); 8393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 8403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 8411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.cancelCallback_ = fileOperationUtil.copyTo( 8423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntry, destinationEntry, destinationName, 8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback, progressCallback, 8443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(entry) { 8451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.cancelCallback_ = null; 8463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 8471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this), 8483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(error) { 8491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.cancelCallback_ = null; 850424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 8513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, error)); 8521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this)); 8531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this), 8543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errorCallback); 8553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 8563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 8573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 8583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Task to move entries. 8593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 8603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Array of source entries. 8613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} targetDirEntry Target directory. 8623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @constructor 863424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @extends {FileOperationManager.Task} 8643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 865424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.MoveTask = function(sourceEntries, targetDirEntry) { 86668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FileOperationManager.Task.call( 86768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, util.FileOperationType.MOVE, sourceEntries, targetDirEntry); 8683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 8693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 8703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 871424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Extends FileOperationManager.Task. 8723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 873424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.MoveTask.prototype.__proto__ = 874424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FileOperationManager.Task.prototype; 8753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 8763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 87768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Initializes the MoveTask. 87868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {function()} callback Called when the initialize is completed. 87968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 88068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FileOperationManager.MoveTask.prototype.initialize = function(callback) { 88168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // This may be moving from search results, where it fails if we 88268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // move parent entries earlier than child entries. We should 88368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // process the deepest entry first. Since move of each entry is 88468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // done by a single moveTo() call, we don't need to care about the 88568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // recursive traversal order. 88668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.sourceEntries.sort(function(entry1, entry2) { 8875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return entry2.toURL().length - entry1.toURL().length; 88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }); 88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries = []; 89168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var i = 0; i < this.sourceEntries.length; i++) { 89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var processingEntryMap = {}; 89368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var entry = this.sourceEntries[i]; 89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // The move should be done with updating the metadata. So here we assume 89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // all the file size is 1 byte. (Avoiding 0, so that progress bar can 89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // move smoothly). 89868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(hidehiko): Remove this hack. 89968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entry.size = 1; 90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) processingEntryMap[entry.toURL()] = entry; 90168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries[i] = processingEntryMap; 90268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 90368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 90468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback(); 90568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 90668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 90768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** 9083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Moves all entries in the task. 9093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 9103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback 9113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback invoked when an entry is changed. 9123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} progressCallback Callback invoked periodically during 9133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * the moving. 9143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback On success. 915424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback On error. 9163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @override 9173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 918424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.MoveTask.prototype.run = function( 9193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback, progressCallback, successCallback, errorCallback) { 92068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (this.sourceEntries.length == 0) { 9213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 9223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 9233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 9243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 9253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AsyncUtil.forEach( 92668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.sourceEntries, 9273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(callback, entry, index) { 9283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (this.cancelRequested_) { 929424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 9303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) util.createDOMError(util.FileError.ABORT_ERR))); 9323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 9333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 9343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) progressCallback(); 935424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FileOperationManager.MoveTask.processEntry_( 9363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry, this.targetDirEntry, entryChangedCallback, 9373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function() { 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Update current source index. 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.processingSourceIndex_ = index + 1; 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.processedBytes = this.calcProcessedBytes_(); 9413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback(); 9423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }.bind(this), 9433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errorCallback); 9443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 9453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function() { 9463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 9473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }.bind(this), 9483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this); 9493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 9503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 9513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 9523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Moves the sourceEntry to the targetDirEntry in this task. 9533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 9543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Entry} sourceEntry An entry to be moved. 9553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} destinationEntry The entry of the destination 9563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * directory. 9573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback 9583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback invoked when an entry is changed. 9593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback On success. 960424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback On error. 9613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @private 9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 963424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.MoveTask.processEntry_ = function( 9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntry, destinationEntry, entryChangedCallback, successCallback, 9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errorCallback) { 9663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fileOperationUtil.deduplicatePath( 9673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) destinationEntry, 9683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntry.name, 9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(destinationName) { 9703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntry.moveTo( 9713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) destinationEntry, destinationName, 9723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(movedEntry) { 9733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback(util.EntryChangedKind.CREATED, movedEntry); 9743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback(util.EntryChangedKind.DELETED, sourceEntry); 9753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 9763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 9773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(error) { 978424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, error)); 9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }); 9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errorCallback); 9833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Task to create a zip archive. 9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Array of source entries. 9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} targetDirEntry Target directory. 9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {DirectoryEntry} zipBaseDirEntry Base directory dealt as a root 9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * in ZIP archive. 9923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @constructor 993424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @extends {FileOperationManager.Task} 9943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 995424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.ZipTask = function( 9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sourceEntries, targetDirEntry, zipBaseDirEntry) { 99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FileOperationManager.Task.call( 99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, util.FileOperationType.ZIP, sourceEntries, targetDirEntry); 9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.zipBaseDirEntry = zipBaseDirEntry; 10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 1003424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Extends FileOperationManager.Task. 10043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 1005424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.ZipTask.prototype.__proto__ = 1006424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FileOperationManager.Task.prototype; 10073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 100868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 100968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** 101068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Initializes the ZipTask. 101168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * @param {function()} callback Called when the initialize is completed. 101268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 101368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)FileOperationManager.ZipTask.prototype.initialize = function(callback) { 101468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var resolvedEntryMap = {}; 101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var group = new AsyncUtil.Group(); 101668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var i = 0; i < this.sourceEntries.length; i++) { 101768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) group.add(function(index, callback) { 101868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fileOperationUtil.resolveRecursively( 101968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.sourceEntries[index], 102068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) function(entries) { 102168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var j = 0; j < entries.length; j++) 102268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) resolvedEntryMap[entries[j].toURL()] = entries[j]; 102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback(); 102468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }, 10255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 102668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }.bind(this, i)); 102768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 102868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) group.run(function() { 103068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // For zip archiving, all the entries are processed at once. 103168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.processingEntries = [resolvedEntryMap]; 103268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 103368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.totalBytes = 0; 103468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var url in resolvedEntryMap) 103568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this.totalBytes += resolvedEntryMap[url].size; 103668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 103768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) callback(); 103868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) }.bind(this)); 103968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 104068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 10423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Runs a zip file creation task. 10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function(util.EntryChangedKind, Entry)} entryChangedCallback 10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Callback invoked when an entry is changed. 10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} progressCallback Callback invoked periodically during 10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * the moving. 10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {function()} successCallback On complete. 1049424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param {function(FileOperationManager.Error)} errorCallback On error. 10503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @override 10513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 1052424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.ZipTask.prototype.run = function( 10533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entryChangedCallback, progressCallback, successCallback, errorCallback) { 10543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(hidehiko): we should localize the name. 10553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var destName = 'Archive'; 10563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (this.sourceEntries.length == 1) { 10575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var entryName = this.sourceEntries[0].name; 10585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var i = entryName.lastIndexOf('.'); 10595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) destName = ((i < 0) ? entryName : entryName.substr(0, i)); 10603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 10613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fileOperationUtil.deduplicatePath( 10633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.targetDirEntry, destName + '.zip', 10643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(destPath) { 10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO: per-entry zip progress update with accurate byte count. 1066116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // For now just set completedBytes to 0 so that it is not full until 1067116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the zip operatoin is done. 1068116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.processedBytes = 0; 10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) progressCallback(); 10703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 107168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // The number of elements in processingEntries is 1. See also 107268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // initialize(). 107368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) var entries = []; 107468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (var url in this.processingEntries[0]) 107568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entries.push(this.processingEntries[0][url]); 107668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fileOperationUtil.zipSelection( 107868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) entries, 10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this.zipBaseDirEntry, 10803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) destPath, 10813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(entry) { 10826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.processedBytes = this.totalBytes; 10835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu entryChangedCallback(util.EntryChangedKind.CREATED, entry); 10843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) successCallback(); 10856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }.bind(this), 10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(error) { 1087424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) errorCallback(new FileOperationManager.Error( 10883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) util.FileOperationErrorType.FILESYSTEM_ERROR, error)); 10893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }); 10903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }.bind(this), 10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errorCallback); 10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Error class used to report problems with a copy operation. 1096558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * If the code is UNEXPECTED_SOURCE_FILE, data should be a path of the file. 1097558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * If the code is TARGET_EXISTS, data should be the existing Entry. 1098558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * If the code is FILESYSTEM_ERROR, data should be the FileError. 10992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1100558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {util.FileOperationErrorType} code Error type. 1101558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {string|Entry|FileError} data Additional data. 11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.Error = function(code, data) { 1105558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch this.code = code; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.data = data; 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// FileOperationManager methods. 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Adds an event listener for the tasks. 1113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @param {string} type The name of the event. 11144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function(Event)} handler The handler for the event. 1115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * This is called when the event is dispatched. 1116a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch */ 1117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.addEventListener = function(type, handler) { 1118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch this.eventRouter_.addEventListener(type, handler); 1119a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}; 1120a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 1121a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch/** 1122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * Removes an event listener for the tasks. 1123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch * @param {string} type The name of the event. 11244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {function(Event)} handler The handler to be removed. 1125a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch */ 1126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.removeEventListener = function(type, handler) { 1127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch this.eventRouter_.removeEventListener(type, handler); 1128a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}; 1129a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 1130a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch/** 1131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Says if there are any tasks in the queue. 1132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return {boolean} True, if there are any tasks. 1133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 1134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.hasQueuedTasks = function() { 1135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return this.copyTasks_.length > 0 || this.deleteTasks_.length > 0; 1136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 1137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Completely clear out the copy queue, either because we encountered an error 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or completed successfully. 11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.resetQueue_ = function() { 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.copyTasks_ = []; 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 11491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Requests the specified task to be canceled. 11501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @param {string} taskId ID of task to be canceled. 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)FileOperationManager.prototype.requestTaskCancel = function(taskId) { 11531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var task = null; 11541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (var i = 0; i < this.copyTasks_.length; i++) { 11551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task = this.copyTasks_[i]; 11561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (task.taskId !== taskId) 11571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) continue; 11581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.requestCancel(); 11591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If the task is not on progress, remove it immediately. 11601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (i !== 0) { 11611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendProgressEvent('CANCELED', 11621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.getStatus(), 11631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.taskId); 11641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.copyTasks_.splice(i, 1); 11651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 11661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 11671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (var i = 0; i < this.deleteTasks_.length; i++) { 11681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task = this.deleteTasks_[i]; 11691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (task.taskId !== taskId) 11701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) continue; 1171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.cancelRequested = true; 11721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If the task is not on progress, remove it immediately. 1173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (i !== 0) { 1174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.eventRouter_.sendDeleteEvent('CANCELED', task); 11751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.deleteTasks_.splice(i, 1); 11761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 11772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 118134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * Filters the entry in the same directory 118234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * 118334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Entries of the source files. 118434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * @param {DirectoryEntry} targetEntry The destination entry of the target 118534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * directory. 118634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * @param {boolean} isMove True if the operation is "move", otherwise (i.e. 118734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * if the operation is "copy") false. 118834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * @return {Promise} Promise fulfilled with the filtered entry. This is not 118934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) * rejected. 119034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) */ 119134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)FileOperationManager.prototype.filterSameDirectoryEntry = function( 119234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) sourceEntries, targetEntry, isMove) { 119334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!isMove) 119434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return Promise.resolve(sourceEntries); 119534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // Utility function to concat arrays. 119634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) var compactArrays = function(arrays) { 119734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return arrays.filter(function(element) { return !!element; }); 119834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }; 119934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // Call processEntry for each item of entries. 120034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) var processEntries = function(entries) { 120134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) var promises = entries.map(processFileOrDirectoryEntries); 120234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return Promise.all(promises).then(compactArrays); 120334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }; 120434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // Check all file entries and keeps only those need sharing operation. 120534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) var processFileOrDirectoryEntries = function(entry) { 120634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return new Promise(function(resolve) { 120734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) entry.getParent(function(inParentEntry) { 120834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!util.isSameEntry(inParentEntry, targetEntry)) 120934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) resolve(entry); 121034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) else 121134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) resolve(null); 121234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }, function(error) { 121334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) console.error(error.stack || error); 121434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) resolve(null); 121534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }); 121634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }); 121734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }; 121834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return processEntries(sourceEntries); 121934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 122034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 122134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)/** 122290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Kick off pasting. 12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {Array.<Entry>} sourceEntries Entries of the source files. 12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {DirectoryEntry} targetEntry The destination entry of the target 12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * directory. 12273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {boolean} isMove True if the operation is "move", otherwise (i.e. 12283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * if the operation is "copy") false. 12291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {string=} opt_taskId If the corresponding item has already created 12301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * at another places, we need to specify the ID of the item. If the 12311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * item is not created, FileOperationManager generates new ID. 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.paste = function( 12341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sourceEntries, targetEntry, isMove, opt_taskId) { 12355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do nothing if sourceEntries is empty. 12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sourceEntries.length === 0) 12373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 12383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 123934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) this.filterSameDirectoryEntry(sourceEntries, targetEntry, isMove).then( 124034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) function(entries) { 124134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (entries.length === 0) 124234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 124334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) this.queueCopy_(targetEntry, entries, isMove, opt_taskId); 124434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }.bind(this)).catch(function(error) { 124534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) console.error(error.stack || error); 124634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) }); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Initiate a file copy. When copying files, null can be specified as source 12515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * directory. 12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {DirectoryEntry} targetDirEntry Target directory. 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<Entry>} entries Entries to copy. 12553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {boolean} isMove In case of move. 12561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {string=} opt_taskId If the corresponding item has already created 12571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * at another places, we need to specify the ID of the item. If the 12581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * item is not created, FileOperationManager generates new ID. 125990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @private 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.queueCopy_ = function( 12621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci targetDirEntry, entries, isMove, opt_taskId) { 12633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var task; 12643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (isMove) { 12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // When moving between different volumes, moving is implemented as a copy 12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and delete. This is because moving between volumes is slow, and moveTo() 12675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is not cancellable nor provides progress feedback. 12686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (util.isSameFileSystem(entries[0].filesystem, 12696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) targetDirEntry.filesystem)) { 12706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task = new FileOperationManager.MoveTask(entries, targetDirEntry); 12716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 12726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task = new FileOperationManager.CopyTask(entries, targetDirEntry, true); 12736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 12743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 12756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task = new FileOperationManager.CopyTask(entries, targetDirEntry, false); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 12781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task.taskId = opt_taskId || this.generateTaskId(); 12796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.eventRouter_.sendProgressEvent('BEGIN', task.getStatus(), task.taskId); 12806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task.initialize(function() { 12816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.copyTasks_.push(task); 12826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (this.copyTasks_.length === 1) 12836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this.serviceAllTasks_(); 12846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }.bind(this)); 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Service all pending tasks, as well as any that might appear during the 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy. 12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.serviceAllTasks_ = function() { 12941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!this.copyTasks_.length) { 12951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // All tasks have been serviced, clean up and exit. 1296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) chrome.power.releaseKeepAwake(); 12971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.resetQueue_(); 12981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 12991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Prevent the system from sleeping while copy is in progress. 1302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) chrome.power.requestKeepAwake('system'); 1303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) var onTaskProgress = function() { 13051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendProgressEvent('PROGRESS', 13061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.copyTasks_[0].getStatus(), 13071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.copyTasks_[0].taskId); 13081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this); 1309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 13103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var onEntryChanged = function(kind, entry) { 13111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendEntryChangedEvent(kind, entry); 13121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this); 1313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var onTaskError = function(err) { 13151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var task = this.copyTasks_.shift(); 13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var reason = err.data.name === util.FileError.ABORT_ERR ? 13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'CANCELED' : 'ERROR'; 13181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendProgressEvent(reason, 13191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.getStatus(), 13201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.taskId, 13218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) err); 13221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.serviceAllTasks_(); 13231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this); 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch var onTaskSuccess = function() { 1326a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // The task at the front of the queue is completed. Pop it from the queue. 13271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var task = this.copyTasks_.shift(); 13281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendProgressEvent('SUCCESS', 13291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.getStatus(), 13301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) task.taskId); 13311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.serviceAllTasks_(); 13321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var nextTask = this.copyTasks_[0]; 13351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.eventRouter_.sendProgressEvent('PROGRESS', 13361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) nextTask.getStatus(), 13371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) nextTask.taskId); 13381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) nextTask.run(onEntryChanged, onTaskProgress, onTaskSuccess, onTaskError); 13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Timeout before files are really deleted (to allow undo). 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.DELETE_TIMEOUT = 30 * 1000; 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schedules the files deletion. 13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<Entry>} entries The entries. 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.deleteEntries = function(entries) { 1352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(hirono): Make FileOperationManager.DeleteTask. 1353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var task = Object.seal({ 13548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) entries: entries, 13551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci taskId: this.generateTaskId(), 1356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entrySize: {}, 1357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) totalBytes: 0, 1358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) processedBytes: 0, 1359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cancelRequested: false 1360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }); 1361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Obtains entry size and sum them up. 1363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var group = new AsyncUtil.Group(); 1364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (var i = 0; i < task.entries.length; i++) { 1365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) group.add(function(entry, callback) { 1366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.getMetadata(function(metadata) { 1367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var index = task.entries.indexOf(entries); 1368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.entrySize[entry.toURL()] = metadata.size; 1369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.totalBytes += metadata.size; 1370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback(); 1371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }, function() { 1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Fail to obtain the metadata. Use fake value 1. 1373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.entrySize[entry.toURL()] = 1; 1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.totalBytes += 1; 1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback(); 1376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }); 1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this, task.entries[i])); 1378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Add a delete task. 1381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) group.run(function() { 1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.deleteTasks_.push(task); 1383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.eventRouter_.sendDeleteEvent('BEGIN', task); 1384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (this.deleteTasks_.length === 1) 1385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.serviceAllDeleteTasks_(); 1386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this)); 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Service all pending delete tasks, as well as any that might appear during the 13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * deletion. 13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1393424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Must not be called if there is an in-flight delete task. 1394424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.serviceAllDeleteTasks_ = function() { 1398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.serviceDeleteTask_( 1399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.deleteTasks_[0], 1400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) function() { 1401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.deleteTasks_.shift(); 1402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (this.deleteTasks_.length) 1403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.serviceAllDeleteTasks_(); 1404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this)); 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Performs the deletion. 14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} task The delete task (see deleteEntries function). 1411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {function()} callback Callback run on task end. 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)FileOperationManager.prototype.serviceDeleteTask_ = function(task, callback) { 1415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var queue = new AsyncUtil.Queue(); 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Delete each entry. 1418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var error = null; 1419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var deleteOneEntry = function(inCallback) { 1420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!task.entries.length || task.cancelRequested || error) { 1421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) inCallback(); 1422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 1423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.eventRouter_.sendDeleteEvent('PROGRESS', task); 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) util.removeFileOrDirectory( 1426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.entries[0], 1427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) function() { 1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) this.eventRouter_.sendEntryChangedEvent( 1429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) util.EntryChangedKind.DELETED, task.entries[0]); 1430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.processedBytes += task.entrySize[task.entries[0].toURL()]; 1431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) task.entries.shift(); 1432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) deleteOneEntry(inCallback); 1433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this), 1434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) function(inError) { 1435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) error = inError; 1436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) inCallback(); 1437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this)); 1438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this); 1439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) queue.run(deleteOneEntry); 1440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Send an event and finish the async steps. 1442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) queue.run(function(inCallback) { 1443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var reason; 1444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (error) 1445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reason = 'ERROR'; 1446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if (task.cancelRequested) 1447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reason = 'CANCELED'; 1448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 1449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reason = 'SUCCESS'; 1450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.eventRouter_.sendDeleteEvent(reason, task); 1451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) inCallback(); 1452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback(); 1453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }.bind(this)); 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Creates a zip file for the selection of files. 14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {Entry} dirEntry The directory containing the selection. 1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {Array.<Entry>} selectionEntries The selected entries. 14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileOperationManager.prototype.zipSelection = function( 1463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dirEntry, selectionEntries) { 1464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) var zipTask = new FileOperationManager.ZipTask( 14653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) selectionEntries, dirEntry, dirEntry); 14661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci zipTask.taskId = this.generateTaskId(this.copyTasks_); 14672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zipTask.zip = true; 1468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.eventRouter_.sendProgressEvent('BEGIN', 1469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) zipTask.getStatus(), 1470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) zipTask.taskId); 14713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) zipTask.initialize(function() { 14721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.copyTasks_.push(zipTask); 14731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (this.copyTasks_.length == 1) 14741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.serviceAllTasks_(); 14751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }.bind(this)); 14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 14778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 14788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)/** 14798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Generates new task ID. 14808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * 14818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * @return {string} New task ID. 14828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) */ 14831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciFileOperationManager.prototype.generateTaskId = function() { 14841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 'file-operation-' + this.taskIdCounter_++; 14858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}; 1486