Abstracting the chrome packaged app filesystem for use with node-webkit - javascript

I currently have a chrome packaged app that we have also ported to iPad, but I want to make it install-able using node-webkit (nw.js) and I need to abstract the chrome packaged app API for use with chrome.fileSystem. The code I am currently using to save is as follows.
var downloadFile = function (readUrl, next) {
var xhr = new XMLHttpRequest();
xhr.open('GET', readUrl);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
if (this.status == 200) {
var response = this.response;
var params = {
type : 'saveFile',
suggestedName : fileNameNoExtension,
//my code will inject the extension but in this case i just put in txt
accepts : [{
extensions : ['.txt']
}
]
}
chrome.fileSystem.chooseEntry(params, function (writableFileEntry) {
debugger;
writableFileEntry.createWriter(function (writer) {
debugger;
writer.onwriteend = function (e) {
return next(null)
};
writer.onerror = function (e) {};
writer.write(new Blob([response], {
type : 'application/octet-stream'
}));
});
});
} else {
//alert
}
};
xhr.onprogress = function (evt) {
if (evt.lengthComputable) {
console.log('progress: ' + Math.round(evt.loaded * 100 / evt.total));
}
}
xhr.addEventListener("error", function () {
return next('error')
}, false);
xhr.addEventListener("abort", function () {
return next('abort')
}, false);
xhr.send();
}

I have created a file that I am calling interop.js I load this script into my index.html and it will handle all of the chrome packaged app API calls for fileStorage if it's a nw.js project. If it's a chrome packaged app, then chrome will handle it's own API.
//if process is undefined then it is not an nw.js project and we can ignore the rest of the code;
if (typeof process == 'undefined') {}
//this is a nw.js project, spoof the chrome packaged app API
else {
var fs = require('fs')
chrome = new function () {
var fileSystem = {
//callback return readableFileEntry, which has a
chooseEntry : function (params, callback) {
if (params.type == 'openFile') {
//open file choose
chooseFile(params, function (files) {
//this is technically an html5 "filelist" we need to turn it into an array if there is more
//than one, and just return the single file if there isn't
if (!files) {
return callback(null)
}
async.map(files, function (file, cb) {
//normally chrome provides a 'readablefileentry' that will only give you the file
//asynchronously using the file() function
file.file = function (next) {
return next(this);
}
cb(null, file)
}, function (err, files) {
if (files.length > 1) {
return callback(files);
} else {
return callback(files[0]);
}
})
})
} else if (params.type == 'saveFile') {
chooseFile(params, function (files) {
var file = files[0];
debugger;
file.createWriter = function (next) {
var writer = {
write : function (blob) {
debugger;
var reader = new FileReader()
reader.readAsArrayBuffer(blob)
reader.addEventListener('loadend', function (e) {
var binary = new Uint8Array(reader.result)
debugger;
fs.writeFile(file.path, new Buffer(binary), function (err) {
//if the on error and writeend has been defined then callback, otherwise throw the error and log success
if (err && writer.onerror) {
writer.onerror(err)
} else if (err) {
throw err
} else if (writer.onwriteend) {
writer.onwriteend()
} else {
console.log('file was written but no callback was defined')
}
})
});
}
}
return next(writer)
}
return callback(file)
})
}
function chooseFile(params, next) {
var fileHtml = '<input type="file"'
debugger;
if (params.acceptsMultiple)
fileHtml += ' multiple';
if (params.accepts && params.accepts.length > 0 && params.accepts[0].extensions) {
fileHtml += ' accept="'
for (var i = 0; i < params.accepts[0].extensions.length; i++) {
if (i != 0)
fileHtml += ','
fileHtml += '.' + params.accepts[0].extensions[i]
}
fileHtml += '"'
}
if (params.suggestedName) {
fileHtml += ' nwsaveas="' + params.suggestedName + '"'
}
fileHtml += '>'
var chooser = $(fileHtml);
chooser.change(function (evt) {
debugger;
return next(chooser[0].files)
});
chooser.click();
}
}
}
return {
fileSystem : fileSystem,
}
};
}

Related

Transforming in a function to call

Im consuming a JSON file and its working fine, but how can i make this a function that i can call to active?
var getDescriptionLotoFacil = function (url, callback) {
var ajax = new XMLHttpRequest();
ajax.open('GET', url, true);
ajax.responseType = 'json';
ajax.onreadystatechange = function () {
var status = ajax.status;
if (status === 200) {
callback(status, ajax.response);
} else {
callback(null, ajax.response);
}
};
ajax.send();
};
getDescriptionLotoFacil('games.json', function (err, data) {
if (err === null) {
console.log('Ocorreu um erro' + err);
} else {
var bets = document.getElementById('bets-description');
bets.innerHTML = '';
bets.innerHTML += data.types[0].description;
}
});
just "wrap" this in a higher level function:
const myFunction = function() {
getDescriptionLotoFacil('games.json', function (err, data) {
if (err === null) {
console.log('Ocorreu um erro' + err);
} else {
var bets = document.getElementById('bets-description');
bets.innerHTML = '';
bets.innerHTML += data.types[0].description;
}
});
}
You can also use a lambda syntax instead, replace first lines by:
const myFunction = () => getDescriptionLotoFacil('games.json', function (err, data) {
...
then you call myFunction() and that executed the whole call.

Chrome Extensions, scope the local variable in.in.inside a function (from backgound.js )and use it globally (or in popup.js).

Recently I want to start a project by piggyback someone's extension. I want to scope one of the image source (local variable, a base64 url) and then photo recognize it on the popup page. I keep getting error "imgb64.replace is not a function" or "imgb64" not defined.
like my title said, I want to scope the local variable in.in.inside a function (from backgound.js )and use it globally (or in popup.js). very new to this, please help guys.
// this is popup.js
chrome.runtime.getBackgroundPage(function(bg) {
bg.capture(window);
});
/// what I did
function img_find() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
return imgSrcs;
}
var imgb64 = img_find();
try {
const app = new Clarifai.App({
apiKey: 'mykey'
});
}
catch(err) {
alert("Need a valid API Key!");
throw "Invalid API Key";
}
// Checks for valid image type
function validFile(imageName) {
var lowerImageName = imageName.toLowerCase();
return lowerImageName.search(/jpg|png|bmp|tiff/gi) != -1;
}
var imageDetails = imgb64.replace(/^data:image\/(.*);base64,/, '');
console.log(imageDetails)
app.models.predict("e466caa0619f444ab97497640cefc4dc", {base64:
imageDetails}).then(
function(response) {
// do something with response
},
function(err) {
// there was an error
}
);
/// end what I did
below is background.js, I think what I need is the local var img.src, thats all.
function capture(popup) {
function callOnLoad(func) {
popup.addEventListener("load", func);
if (popup.document.readyState === "complete") {
func();
}
}
crxCS.insert(null, { file: "capture.js" }, function() {
crxCS.callA(null, "get", function(result) {
var scrShot, zm, bufCav, bufCavCtx;
function mkImgList() {
for (var i = 0; i < result.vidShots.length; i++) {
var img = new popup.Image();
img.onload = function() {
this.style.height = this.naturalHeight /
(this.naturalWidth / 400) + "px";
};
if (result.vidShots[i].constructor === String) {
img.src = result.vidShots[i];
} else {
bufCav.width = result.vidShots[i].width * zm;
bufCav.height = result.vidShots[i].height * zm;
bufCavCtx.drawImage(scrShot, -result.vidShots[i].left *
zm, -result.vidShots[i].top * zm);
img.src = bufCav.toDataURL('image/png');
////// maybe clarifai here ?
////end clarifai
}
popup.document.body.appendChild(img);
}
popup.onclick = function(mouseEvent) {
if (mouseEvent.target.tagName === "IMG") {
chrome.downloads.download({ url: mouseEvent.target.src,
saveAs: true, filename: "chrome_video_capture_" + (new Date()).getTime() +
".png" });
}
};
popup.onunload = function(mouseEvent) {
crxCS.callA(null, "rcy");
};
} /// end mkImgList
if (result.needScrShot) {
bufCav = popup.document.createElement("canvas");
bufCavCtx = bufCav.getContext("2d");
chrome.tabs.captureVisibleTab({ format: "png" },
function(dataUrl) {
scrShot = new Image();
scrShot.onload = function() {
chrome.tabs.getZoom(function(zoomFactor) {
zm = zoomFactor;
callOnLoad(function() {
mkImgList(zoomFactor);
});
});
};
scrShot.src = dataUrl;
});
} else if (result.vidShots.length) {
callOnLoad(mkImgList);
} else {
popup.document.body.appendChild(notFound);
}
}); // end crxCS.callA
}); // end crxCS.insert
} // end capture
Please help guys. :)

record wav file in cordova and upload to api

I have created an app where I am recording an audio in wav format and then replaying that audio and then posting it to api for further processing.
But after posting data to api it says "not a wave file -- no riff header".
I tried this link also as reference.
Here is my javascript code of app:
var mediaVar = null;
var recordFileName = "recording.wav";
var mediaVarSrc = "cdvfile://localhost/sdcard/recording.wav";
var status = null;
var target = "";
document.getElementById("start-btn").addEventListener("click", function () {
createMedia(function () {
status = "recording";
mediaVar.startRecord();
}, onStatusChange);
$("#recordingText").show();
});
document.getElementById("stop-btn").addEventListener("click", function () {
stop();
});
function createMedia(onMediaCreated, mediaStatusCallback) {
if (mediaVar != null) {
onMediaCreated();
return;
}
if (typeof mediaStatusCallback == 'undefined') {
mediaStatusCallback = null;
}
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, function (fileSystem) {
fileSystem.getFile(recordFileName, {
create: true,
exclusive: false
}, function (fileEntry) {
fileUrl = fileEntry.toURL();
mediaVar = new Media(fileUrl,
function () {}, onError, mediaStatusCallback);
onMediaCreated();
}, onError);
}, onError);
}
function stop() {
alert("Stop");
$("#recordingText").hide();
if (mediaVar == null) {
return;
}
if (status == 'recording') {
mediaVar.stopRecord();
mediaVar.release();
status = 'stopped';
play();
} else {
alert("Nothing stopped");
}
}
function play() {
if (mediaVar) {
status = "playing";
//playAudioFile(recordFileName);
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory + recordFileName, function (tempFile) {
alert(JSON.stringify(tempFile));
tempFile.file(function (tempWav) {
alert(JSON.stringify(tempWav));
var options = new FileUploadOptions();
options.chunkedMode = false;
options.fileKey = "file";
options.fileName = recordFileName;
options.mimeType = "audio/wav";
var ft = new FileTransfer();
ft.upload(tempFile.nativeURL, encodeURI(target), function () {
alert("Win");
}, function () {
alert("false");
}, options, true);
});
}, function (e) {
console.log("Could not resolveLocalFileSystemURL: " + e.message);
});
}
}
var myMedia = null;
function playAudioFile(src) {
myMedia = new Media(src,
function () { },
function (error) { },
function (status) { }
);
myMedia.play();
}
function stopplay(calledfrom) {
mediaVar.stop();
}
function recordAudio() {
if (myMedia == null) {
myMedia = new Media(srcurl,
function () {
console.log("recordAudio():Audio Success");
},
function (err) {
console.log("recordAudio():Audio Error: " + err.code);
});
}
myMedia.startRecord();
}
For recording I have used Media plugin. I am not able to figure out why this is happening.
Here is my api code
[HttpPost]
[Route("UploadFile")]
public string UploadFile()
{
string Result = String.Empty;
string path = HttpContext.Current.Server.MapPath("~\\App_Data");
string convertedFileName = "convert.wav";
try
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
else
{
MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider(path);
Task.Run(async () =>
{
await Request.Content.ReadAsMultipartAsync(streamProvider);
}).Wait();
var file = streamProvider.FileData[0];
FileInfo fileInfo = new FileInfo(file.LocalFileName);
string fileName = fileInfo.Name;
if (System.IO.File.Exists(path + "\\" + fileName))
{
using (WaveFileReader reader = new WaveFileReader(path + "\\" + fileName))
{
WaveFormat format = new WaveFormat(16000, 16, 1);
using (WaveFormatConversionStream convert = new WaveFormatConversionStream(format, reader))
{
WaveFileWriter.CreateWaveFile(path + "\\" + convertedFileName, convert);
convert.Close();
}
reader.Close();
}
System.IO.File.Delete(path + "\\" + fileName);
BingSpeechToText obj = new BingSpeechToText();
STTResponse _STTResponse = obj.ConvertAudio(path + "\\" + convertedFileName);
if (_STTResponse.Status && !String.IsNullOrEmpty(_STTResponse.Response))
{
Result = _STTResponse.Response;
}
else
{
Result = "No Result";
}
}
}
}
catch (Exception ex)
{
Result = ex.Message;
}
finally
{
if (System.IO.File.Exists(path + "\\" + convertedFileName))
System.IO.File.Delete(path + "\\" + convertedFileName);
}
return Result;
}
Try like below one,
static String API_KEY = "YOUR-KEY";
static String PROFILE_ID = "YOUR-PROFILE-ID";
static String LOCATION = "westus";
HttpClient httpclient = HttpClients.createDefault();
try {
URIBuilder builder = new URIBuilder(
String.format("https://%s.api.cognitive.microsoft.com/spid/v1.0/identificationProfiles/%s/enroll", LOCATION, PROFILE_ID));
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Ocp-Apim-Subscription-Key", API_KEY);
request.setEntity(new FileEntity(new File("test.wav"), ContentType.APPLICATION_OCTET_STREAM));
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
// Response is empty on success; the following will contain the URI where you can check the status
System.out.println(response.getHeaders("Operation-Location")[0].getValue());
} catch (Exception e) {
System.out.println(e.getMessage());
}

What is Promises script in each .php file head section?

So I have this really weird issue which I did not find any solution online.
No matter what page I create, either .html or .php I get this Promises javascript in the head section. Has anyone seen this before or what is this?
// Promises
var _eid_promises = {};
// Turn the incoming message from extension
// into pending Promise resolving
window.addEventListener("message", function(event) {
if(event.source !== window) return;
if(event.data.src && (event.data.src === "background.js")) {
console.log("Page received: ");
console.log(event.data);
// Get the promise
if(event.data.nonce) {
var p = _eid_promises[event.data.nonce];
// resolve
if(event.data.result === "ok") {
if(event.data.signature !== undefined) {
p.resolve({hex: event.data.signature});
} else if(event.data.version !== undefined) {
p.resolve(event.data.extension + "/" + event.data.version);
} else if(event.data.cert !== undefined) {
p.resolve({hex: event.data.cert});
} else {
console.log("No idea how to handle message");
console.log(event.data);
}
} else {
// reject
p.reject(new Error(event.data.result));
}
delete _eid_promises[event.data.nonce];
} else {
console.log("No nonce in event msg");
}
}
}, false);
function TokenSigning() {
function nonce() {
var val = "";
var hex = "abcdefghijklmnopqrstuvwxyz0123456789";
for(var i = 0; i < 16; i++) val += hex.charAt(Math.floor(Math.random() * hex.length));
return val;
}
function messagePromise(msg) {
return new Promise(function(resolve, reject) {
// amend with necessary metadata
msg["nonce"] = nonce();
msg["src"] = "page.js";
// send message
window.postMessage(msg, "*");
// and store promise callbacks
_eid_promises[msg.nonce] = {
resolve: resolve,
reject: reject
};
});
}
this.getCertificate = function(options) {
var msg = {type: "CERT", lang: options.lang};
console.log("getCertificate()");
return messagePromise(msg);
};
this.sign = function(cert, hash, options) {
var msg = {type: "SIGN", cert: cert.hex, hash: hash.hex, hashtype: hash.type, lang: options.lang};
console.log("sign()");
return messagePromise(msg);
};
this.getVersion = function() {
console.log("getVersion()");
return messagePromise({
type: "VERSION"
});
};
}
This is Selenium extension.
Selenium Record and Playback tool for ease of getting acquainted with Selenium WebDriver.
extension id: mooikfkahbdckldjjndioackbalpho...

Need to modify this onlinejs code (internet detection script) to fire manually, not on a timer

I am using the excellent onlinejs (https://github.com/PixelsCommander/OnlineJS) library for checking that my app has a live internet connection. However, I don't need it to fire regularly, but rather upon the manual calling of the main function.
I would like to modify this code so that it is not firing on a timer, and know the name of the function to call for manual firing, which assume is just getterSetter.
My previous attempts to modify the code below have broken the script as I'm no expert at JavaScript. I appreciate any help in adapting this very useful code.
function getterSetter(variableParent, variableName, getterFunction, setterFunction) {
if (Object.defineProperty) {
Object.defineProperty(variableParent, variableName, {
get: getterFunction,
set: setterFunction
});
}
else if (document.__defineGetter__) {
variableParent.__defineGetter__(variableName, getterFunction);
variableParent.__defineSetter__(variableName, setterFunction);
}
}
(function (w) {
w.onlinejs = w.onlinejs || {};
//Checks interval can be changed in runtime
w.onLineCheckTimeout = 5000;
//Use window.onLineURL incapsulated variable
w.onlinejs._onLineURL = "http://lascelles.us/wavestream/online.php";
w.onlinejs.setOnLineURL = function (newURL) {
w.onlinejs._onLineURL = newURL;
w.onlinejs.getStatusFromNavigatorOnLine();
}
w.onlinejs.getOnLineURL = function () {
return w.onlinejs._onLineURL;
}
getterSetter(w, 'onLineURL', w.onlinejs.getOnLineURL, w.onlinejs.setOnLineURL);
//Verification logic
w.onlinejs.setStatus = function (newStatus) {
w.onlinejs.fireHandlerDependOnStatus(newStatus);
w.onLine = newStatus;
}
w.onlinejs.fireHandlerDependOnStatus = function (newStatus) {
if (newStatus === true && w.onLineHandler !== undefined && (w.onLine !== true || w.onlinejs.handlerFired === false)) {
w.onLineHandler();
}
if (newStatus === false && w.offLineHandler !== undefined && (w.onLine !== false || w.onlinejs.handlerFired === false)) {
w.offLineHandler();
}
w.onlinejs.handlerFired = true;
};
w.onlinejs.startCheck = function () {
setInterval("window.onlinejs.logic.checkConnectionWithRequest(true)", w.onLineCheckTimeout);
}
w.onlinejs.stopCheck = function () {
clearInterval("window.onlinejs.logic.checkConnectionWithRequest(true)", w.onLineCheckTimeout);
}
w.checkOnLine = function () {
w.onlinejs.logic.checkConnectionWithRequest(false);
}
w.onlinejs.getOnLineCheckURL = function () {
return w.onlinejs._onLineURL + '?' + Date.now();
}
w.onlinejs.getStatusFromNavigatorOnLine = function () {
if (w.navigator.onLine !== undefined) {
w.onlinejs.setStatus(w.navigator.onLine);
} else {
w.onlinejs.setStatus(true);
}
}
//Network transport layer
var xmlhttp = new XMLHttpRequest();
w.onlinejs.isXMLHttp = function () {
return "withCredentials" in xmlhttp;
}
w.onlinejs.isXDomain = function () {
return typeof XDomainRequest != "undefined";
}
//For IE we use XDomainRequest and sometimes it uses a bit different logic, so adding decorator for this
w.onlinejs.XDomainLogic = {
init: function () {
xmlhttp = new XDomainRequest();
xmlhttp.onerror = function () {
xmlhttp.status = 404;
w.onlinejs.processXmlhttpStatus();
}
xmlhttp.ontimeout = function () {
xmlhttp.status = 404;
w.onlinejs.processXmlhttpStatus();
}
},
onInternetAsyncStatus: function () {
try {
xmlhttp.status = 200;
w.onlinejs.processXmlhttpStatus();
} catch (err) {
w.onlinejs.setStatus(false);
}
},
checkConnectionWithRequest: function (async) {
xmlhttp.onload = w.onlinejs.logic.onInternetAsyncStatus;
var url = w.onlinejs.getOnLineCheckURL();
xmlhttp.open("GET", url);
w.onlinejs.tryToSend(xmlhttp);
}
}
//Another case for decoration is XMLHttpRequest
w.onlinejs.XMLHttpLogic = {
init: function () {
},
onInternetAsyncStatus: function () {
if (xmlhttp.readyState === 4) {
try {
w.onlinejs.processXmlhttpStatus();
} catch (err) {
w.onlinejs.setStatus(false);
}
}
},
checkConnectionWithRequest: function (async) {
if (async) {
xmlhttp.onreadystatechange = w.onlinejs.logic.onInternetAsyncStatus;
} else {
xmlhttp.onreadystatechange = undefined;
}
var url = w.onlinejs.getOnLineCheckURL();
xmlhttp.open("HEAD", url, async);
w.onlinejs.tryToSend(xmlhttp);
if (async === false) {
w.onlinejs.processXmlhttpStatus();
return w.onLine;
}
}
}
if (w.onlinejs.isXDomain()) {
w.onlinejs.logic = w.onlinejs.XDomainLogic;
} else {
w.onlinejs.logic = w.onlinejs.XMLHttpLogic;
}
w.onlinejs.processXmlhttpStatus = function () {
var tempOnLine = w.onlinejs.verifyStatus(xmlhttp.status);
w.onlinejs.setStatus(tempOnLine);
}
w.onlinejs.verifyStatus = function (status) {
return status === 200;
}
w.onlinejs.tryToSend = function (xmlhttprequest) {
try {
xmlhttprequest.send();
} catch(e) {
w.onlinejs.setStatus(false);
}
}
//Events handling
w.onlinejs.addEvent = function (obj, type, callback) {
if (window.attachEvent) {
obj.attachEvent('on' + type, callback);
} else {
obj.addEventListener(type, callback);
}
}
w.onlinejs.addEvent(w, 'load', function () {
w.onlinejs.fireHandlerDependOnStatus(w.onLine);
});
w.onlinejs.addEvent(w, 'online', function () {
window.onlinejs.logic.checkConnectionWithRequest(true);
})
w.onlinejs.addEvent(w, 'offline', function () {
window.onlinejs.logic.checkConnectionWithRequest(true);
})
w.onlinejs.getStatusFromNavigatorOnLine();
w.onlinejs.logic.init();
w.checkOnLine();
w.onlinejs.startCheck();
w.onlinejs.handlerFired = false;
})(window);
Looking at the source, I believe you can simply call onlinejs.logic.checkConnectionWithRequest(false) to get the status synchronously. This function will return either true or false.
PS: I am sure there are better libraries for this task out there, I really do not like the way it's written and clearly, the author doesn't know JS very well. E.g., the following code taken from the library makes no sense at all.
w.onlinejs.stopCheck = function () {
clearInterval("window.onlinejs.logic.checkConnectionWithRequest(true)", w.onLineCheckTimeout);
}

Categories