/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ //////////////////////////////////////////////////////////////////////// // var Montage = require("montage/core/core").Montage; //////////////////////////////////////////////////////////////////////// // exports.NinjaLibrary = Montage.create(Object.prototype, { //////////////////////////////////////////////////////////////////// // _chromeApi: { value: null }, //////////////////////////////////////////////////////////////////// // chromeApi: { get: function() {return this._chromeApi;}, set: function(value) {this._chromeApi = value;} }, //////////////////////////////////////////////////////////////////// // _coreApi: { value: null }, //////////////////////////////////////////////////////////////////// // coreApi: { get: function() {return this._coreApi;}, set: function(value) {this._coreApi = value;} }, //////////////////////////////////////////////////////////////////// // _libs: { value: null }, //////////////////////////////////////////////////////////////////// // libs: { get: function() {return this._libs;}, set: function(value) {this._libs = value;} }, //////////////////////////////////////////////////////////////////// // _libsToSync: { value: 0 }, //////////////////////////////////////////////////////////////////// // _syncedLibs: { value: 0 }, //////////////////////////////////////////////////////////////////// // copyLibToCloud: { value: function (path, libName, callback) { var libCheck = this.coreApi.directoryExists({uri: path+libName}); //Checking for library to exists if(libCheck.status === 404) { //Getting contents to begin copying this.chromeApi.directoryContents(this.chromeApi.fileSystem.root, function (contents) { for (var i in contents) { if (libName === contents[i].name) { //Getting contents of library to be copied this.chromeApi.directoryContents(contents[i], function (lib) { //Copying to cloud if (callback) { this.copyDirectoryToCloud(path, contents[i], path, {total: 0, copied: 0, callback: callback.bind(this)}); } else { this.copyDirectoryToCloud(path, contents[i], path, {total: 0, copied: 0}); } }.bind(this)); break; } } }.bind(this)); } else if (libCheck.status === 204){ //Already present, so sending success if (callback) callback(true); } else { if (callback) callback(false); } } }, //////////////////////////////////////////////////////////////////// // copyDirectoryToCloud: { value: function(root, folder, fileRoot, tracking) { //Setting up directory name if (folder.name) { var dir; if (root) { dir = root+'/'+folder.name; } else { dir = folder.name; } //Creating directory if (!this.coreApi.createDirectory({uri: dir.replace(/\/\//gi, '/')})) { //Error occured while creating folders return; //TODO: Add error handling } } //Checking for directory if (folder.isDirectory) { //Using Chrome API to get directory contents this.chromeApi.directoryContents(folder, function (contents) { //Looping through children of directory to copy for (var i in contents) { //Checking for file or directory if (contents[i].isDirectory) { //Recursive call if directory this.copyDirectoryToCloud(dir, contents[i], fileRoot, tracking); } else if (contents[i].isFile){ // tracking.total++; //Copying file this.chromeApi.fileContent(contents[i].fullPath, function (result) { //Using binary when copying files to allow images and such to work var file = this.coreApi.createFile({uri: (fileRoot+result.file.fullPath).replace(/\/\//gi, '/'), contents: result.content}); //Checking for file copy success if (file.status === 201) { tracking.copied++; } else { //Error tracking.callback(false); } //Checking for all files to be copied to make callback if (tracking.copied === tracking.total && tracking.callback) { tracking.callback(true); } }.bind(this)); } } }.bind(this)); } } }, //////////////////////////////////////////////////////////////////// // synchronize: { value: function(chromeLibs, chrome) { //TODO: Remove window.wipeLibrary = this.deleteLibraries.bind(this); //Getting instance of browser file API this.chromeApi = chrome; //Local variables var i, l, libs, libjson, xhr = new XMLHttpRequest(), tocopylibs = []; //Getting known json list of libraries to copy to chrome (will be on a CDN later) xhr.open("GET", '/js/io/system/ninjalibrary.json', false); xhr.send(); //Checkng for correct reponse if (xhr.readyState === 4) { //Parsing json libraries libs = JSON.parse(xhr.response); //Storing JSON data this.libs = libs.libraries; //Checking for preview libraries to avoid duplicates if (chromeLibs.length > 0) { //Looping through libraries on browser file system for (i=0; chromeLibs[i]; i++) { for (var j in libs.libraries) { //Checking for matching names (directories are libraries names) if (String(libs.libraries[j].name+libs.libraries[j].version).toLowerCase() !== chromeLibs[i]) { //Checking for library to be single file (special case) if (libs.libraries[j].file) { tocopylibs.push({name: String(libs.libraries[j].name+libs.libraries[j].version).toLowerCase(), path: libs.libraries[j].path, file: libs.libraries[j].file}); } else { tocopylibs.push({name: String(libs.libraries[j].name+libs.libraries[j].version).toLowerCase(), path: libs.libraries[j].path}); } } } } } else { //No library is present, must copy all for (var j in libs.libraries) { //name: used to folder container contents //path: url of descriptor json or single file to load (descriptor has list of files) //singular: indicates the path is the file to be loaded into folder if (libs.libraries[j].file) { tocopylibs.push({name: String(libs.libraries[j].name+libs.libraries[j].version).toLowerCase(), path: libs.libraries[j].path, file: libs.libraries[j].file}); } else { tocopylibs.push({name: String(libs.libraries[j].name+libs.libraries[j].version).toLowerCase(), path: libs.libraries[j].path}); } } } //Storing list of libraries to copy this._libsToSync = tocopylibs.length; //Check to see if libraries are needed to be copied if (tocopylibs.length > 0) { for (i=0; tocopylibs[i]; i++) { //Checking for library to be single file if (tocopylibs[i].file) { //Creating root folder this.chromeApi.directoryNew('/'+tocopylibs[i].name); //Getting file contents xhr = new XMLHttpRequest(); xhr.open("GET", tocopylibs[i].path, false); xhr.responseType = "arraybuffer"; xhr.send(); //Checking for status if (xhr.readyState === 4) { //Creating new file from loaded content this.chromeApi.fileNew('/'+tocopylibs[i].name+'/'+tocopylibs[i].file, xhr.response, function (status) {if(status) this.libraryCopied()}.bind(this)); } else { //TODO: Add error handling } } else { //Creating root folder this.chromeApi.directoryNew('/'+tocopylibs[i].name); //Getting file contents xhr = new XMLHttpRequest(); xhr.open("GET", tocopylibs[i].path, false); xhr.send(); //Checking for status if (xhr.readyState === 4) { //Parsing JSON data of files to copy libjson = JSON.parse(xhr.response); //Looping through list for (l=0; libjson.directories[l]; l++) { //Initializing defaults libjson.dirsToCreate = libjson.directories.length; libjson.dirsCreated = 0; libjson.filesToCreate = libjson.files.length; libjson.filesCreated = 0; libjson.local = tocopylibs[i].name; libjson.main = this; //Looping through list and creating directories first this.createDirectory(tocopylibs[i].name, libjson.directories[l], function (status) { //Checking for success on directories created if (status) { this.dirsCreated++; } //All directories created if (this.dirsCreated === this.dirsToCreate) { var xhr, i; //Looping through files to copy now that directories are ready for (i=0; this.files[i]; i++) { xhr = new XMLHttpRequest(); xhr.open("GET", this.root+this.files[i], false); xhr.responseType = "arraybuffer"; xhr.send(); //Checking for status if (xhr.readyState === 4) { this.main.chromeApi.fileNew(this.local+'/'+this.files[i], xhr.response, function (status) { if (status) { this.filesCreated++; } if (this.filesCreated === this.filesToCreate) { this.main.libraryCopied(); } }.bind(this)); } } } }.bind(libjson)); } } else { //TODO: Add error handling } } } } else { //Dispatching ready event since nothing to copy this._dispatchEvent(); } } else { //TODO: Add error handling } } }, //////////////////////////////////////////////////////////////////// //Creating a directory on the file system (and sub directories if nested) createDirectory: { value: function(root, folder, callback) { //Checking for name, establishing format if (folder.name) { if (root) { dir = root+'/'+folder.name; } else { dir = folder.name; } //Creating directory this.chromeApi.directoryNew(dir, function (status) {if (callback)callback(status)}); } //Checking for children and making recursive calls if needed if (folder.children) { for (var j in folder.children) { if (root) { this.createDirectory(root+'/'+folder.name, folder.children[j]); } else { this.createDirectory(folder.name, folder.children[j]); } } } } }, //////////////////////////////////////////////////////////////////// //Callback to keep track of copied libraries during sync libraryCopied: { value: function() { this._syncedLibs++; if (this._syncedLibs === this._libsToSync) { this._dispatchEvent(); } } }, //////////////////////////////////////////////////////////////////// //Method to remove libraries copied into browser file system (ALL) deleteLibraries: { value: function () { //Used by file system API to callback function parseLibrary (contents) { //Looping through contents to delete for(var i=0; contents[i]; i++) { //Deleting entire directies (no single files are copied outside) if (contents[i].isDirectory) { this.chromeApi.directoryDelete(contents[i].name); } else { //TODO: Handle single files } } }; //Making call to file system API to get all libraries (files) on file system this.chromeApi.directoryContents(this.chromeApi.fileSystem.root, parseLibrary.bind(this)); } }, //////////////////////////////////////////////////////////////////// // _dispatchEvent: { value: function () { var syncEvent = document.createEvent("CustomEvent"); syncEvent.initEvent('sync', true, true); this.dispatchEvent(syncEvent); } } //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// }); //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////