blob: f1d16c92fdba1ff733750cb0c778c298c7dd1a74 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var harness = {
/**
* Kick off the test harness.
*
* Called by harness.html after the dom has been parsed.
*/
init: function() {
console.log('Initializing harness...');
util.installFileErrorToString();
function onFilesystem(filesystem) {
console.log('Filesystem found.');
harness.filesystem = filesystem;
chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
var roots = ['/Downloads', '/removable', '/archives'];
for (var i = 0; i != mountPoints.length; i++) {
roots.push(mountPoints[i].mountPath);
}
createRoots(roots);
});
}
function createRoots(roots) {
if (roots.length == 0) {
loadUI();
return;
}
var root = roots.shift();
util.getOrCreateDirectory(harness.filesystem.root, root,
function(dir) {
console.log('Created/found', dir.fullPath);
createRoots(roots);
},
function(err) {
console.log('Error creating ' + root + ':' + err.toString());
createRoots(roots);
});
}
function loadUI() {
harness.iframe.src = 'main.html' + document.location.search;
}
window.webkitStorageInfo.requestQuota(
window.PERSISTENT,
1024 * 1024 * 1024, // 1 Gig should be enough for everybody:)
function(grantedBytes) {
window.webkitRequestFileSystem(
window.PERSISTENT,
grantedBytes,
onFilesystem,
util.flog('Error initializing filesystem'));
},
util.flog('Error requesting filesystem quota'));
var paramstr = decodeURIComponent(document.location.search.substr(1));
this.params = paramstr ? JSON.parse(paramstr) : {};
var input = document.querySelector('#default-path');
input.value = this.params.defaultPath || '';
input.addEventListener('keyup', this.onInputKeyUp.bind(this));
},
onInputKeyUp: function(event) {
if (event.keyCode != 13)
return;
this.changePath();
},
changePath: function() {
var input = document.querySelector('#default-path');
this.changeParam('defaultPath', input.value);
},
changeParam: function(name, value) {
this.params[name] = value;
document.location.href = '?' + JSON.stringify(this.params);
},
/**
* 'Reset Filesystem' button click handler.
*/
onClearClick: function() {
harness.resetFilesystem(this.filesystem, harness.init);
},
resetFilesystem: function(filesystem, opt_callback) {
util.forEachDirEntry(filesystem.root, function(dirEntry) {
if (!dirEntry) {
console.log('Filesystem reset.');
if (opt_callback) opt_callback();
return;
}
util.removeFileOrDirectory(
dirEntry,
util.flog('Removed ' + dirEntry.name),
util.flog('Error deleting ' + dirEntry.name));
});
},
/**
* 'Auto-populate' button click handler.
*/
onPopulateClick: function() {
harness.importWebDirectory(this.filesystem,
'Downloads', 'harness_files', function() {}, harness.init);
},
/**
* Change handler for the 'input type=file' element.
*/
onFilesChange: function(event) {
this.importFiles(harness.filesystem,
harness.fileManager.getCurrentDirectory(),
[].slice.call(event.target.files),
function() {
harness.chrome.fileBrowserPrivate.onFileChanged.notify({
fileUrl: harness.fileManager.getCurrentDirectoryURL()
});
});
},
/**
* The fileManager object under test.
*
* This is a getter rather than a normal property because the fileManager
* is initialized asynchronously, and we won't be sure when it'll be
* done. Since harness.fileManager is intended to be used for debugging
* from the JS console, we don't really need to be sure it's ready at any
* particular time.
*/
get iframe() { return document.querySelector('#dialog') },
get fileManager() { return harness.iframe.contentWindow.fileManager },
get pyautoAPI() { return harness.iframe.contentWindow.pyautoAPI },
get chrome() { return harness.iframe.contentWindow.chrome; },
/**
* Copy a blob into the filesystem.
*
* @param {DOMFileSystem} filesystem Destination file system.
* @param {string} dstPath Destination file path.
* @param {Blob} srcBlob Source blob.
* @param {function} callback Completion callback.
*/
copyBlob: function(filesystem, dstPath, srcBlob, callback) {
function onWriterCreated(entry, writer) {
writer.onerror =
util.flog('Error writing: ' + entry.fullPath, callback);
writer.onwriteend = function() {
console.log('Wrote ' + srcBlob.size + ' bytes to ' + entry.fullPath);
callback();
};
writer.write(srcBlob);
}
function onFileFound(fileEntry) {
fileEntry.createWriter(onWriterCreated.bind(null, fileEntry), util.flog(
'Error creating writer for: ' + fileEntry.fullPath, callback));
}
util.getOrCreateFile(filesystem.root, dstPath, onFileFound,
util.flog('Error finding path: ' + dstPath, callback));
},
/**
* Import a list of File objects into harness.filesystem.
*
* @param {DOMFileSystem} filesystem File system.
* @param {string} dstDir Destination path.
* @param {Array.<File>} files Array of files.
* @param {function} callback Completion callback.
*/
importFiles: function(filesystem, dstDir, files, callback) {
function processNextFile() {
if (files.length == 0) {
console.log('Import complete');
callback();
return;
}
var file = files.shift();
harness.copyBlob(
filesystem, dstDir + '/' + file.name, file, processNextFile);
}
console.log('Start import: ' + files.length + ' file(s)');
processNextFile();
},
/**
* Copy all files recursively linked from a web page.
*
* Assumes the directory listing format produced by Python's SimpleHTTPServer:
* Child names are in |href| attributes, subdirectory names end with '/'.
*
* @param {DOMFileSystem} filesystem File system.
* @param {string} dstDir Destination path.
* @param {string} srcDirUrl Directory page url.
* @param {function(string, Blob)} onProgress Progress callback.
* @param {function} onComplete Completion callback.
*/
importWebDirectory: function(
filesystem, dstDirPath, srcDirUrl, onProgress, onComplete) {
var childNames = [];
function readFromUrl(url, type, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = type;
xhr.onload = function() {
if (xhr.status == 200)
callback(
xhr.responseType == 'text' ? xhr.responseText : xhr.response);
else
callback(null);
};
xhr.send();
}
function processNextChild() {
if (childNames.length == 0) {
onComplete();
return;
}
var name = childNames.shift();
var isDirectory = name.match(/\/$/); // Ends with '/'.
if (isDirectory) name = name.substring(0, name.length - 1);
var srcChildUrl = srcDirUrl + '/' + name;
var dstChildPath = dstDirPath + '/' + name;
if (isDirectory) {
harness.importWebDirectory(filesystem,
dstChildPath, srcChildUrl, onProgress, processNextChild);
} else {
readFromUrl(srcChildUrl, 'blob', function(blob) {
onProgress(blob);
harness.copyBlob(filesystem, dstChildPath, blob, processNextChild);
});
}
}
readFromUrl(srcDirUrl, 'text', function(text) {
if (!text) {
console.log('Cannot read ' + srcDirUrl);
onComplete();
return;
}
var links = text.match(/href=".*"/g); // Extract all links from the page.
if (links) {
for (var i = 0; i != links.length; i++)
childNames.push(links[i].match(/href="(.*)"/)[1]);
}
console.log(
'Importing ' + childNames.length + ' entries from ' + srcDirUrl);
processNextChild();
});
}
};