I am making a native messaging application, with the web API, from firefox. The extension is supposed to call an application that parses stdin and then calls my other rust app, based on some of the data it parsed, but for no apparent reason, the rust app doesn't accept input from firefox (it works when I do it manually). This is the code of the extension:
/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
console.log("Sending: ping");
var sending = browser.runtime.sendNativeMessage(
"themefox_manager",
"ping");
sending.then(onResponse, onError);
});
function onResponse(response) {
console.log("Received " + response);
}
function onError(error) {
console.log(`Error: ${error}`);
}
and this the code of the rust app:
use std::fs;
use std::io;
use std::io::prelude::*;
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let mut file = fs::File::create("/home/user/filename.txt").unwrap();
//
if line.unwrap() == "ping" {
file.write_all(b"TEST").expect("Error");
}
}
}
The weird thing is, that the text file in my home dir first appears, when I close firefox, not when the app gets started. And it also doen't have the text TEST.
Thanks for any help!
Cheers
I managed to make my own solution, taking a bit from this crate.
Quick note: "If you want to skip all of the code and immeditly want to start coding from a template repo, scoll to the bottom of this solution, and you should be able to find more info there."
The code, which reads the input, and then returns it, is the following:
pub fn read_input<R: Read>(mut input: R) -> io::Result<serde_json::Value> {
let length = input.read_u32::<NativeEndian>().unwrap();
let mut buffer = vec![0; length as usize];
input.read_exact(&mut buffer)?;
let json_val: serde_json::Value = serde_json::from_slice(&buffer).unwrap();
Ok(json_val)
}
What the code does, is read the input, which is being passed as a parameter to the function, and then it reads it parses it in a json var and returns the sucess/err value of it.
That code is being used in the main.rs file like this:
let json_val = match lib::read_input(io::stdin()) {
Err(why) => panic!("{}", why.to_string()),
Ok(json_val) => json_val,
};
Here the input is being passed as a parameter to the read_input function.
And to send the code i used the following function:
pub fn write_output<W: Write>(mut output: W, value: &serde_json::Value) -> io::Result<()> {
let msg = serde_json::to_string(value)?;
let len = msg.len();
// Chrome won't accept a message larger than 1MB
if len > 1024 * 1024 {
panic!("Message was too large", length: {}, len)
}
output.write_u32::<NativeEndian>(len as u32)?;
output.write_all(msg.as_bytes())?;
output.flush()?;
Ok(())
}
Which gets the stdout and the message passed as parameters. The function then writes the message to the output (normally stdout, could also be a file for debugging purposes).
The code which calls the function write_output is the following:
let response = serde_json::json!({ "msg": "pong" });
match lib::write_output(io::stdout(), &response) {
Err(why) => panic!("{}", why.to_string()),
Ok(_) => (),
};
The project uses these dependencies, so make sure to add them to Cargo.toml
"byteorder" = "*"
"serde_json" = "*"
The imports for the main.rs file are:
mod lib;
use std::io;
and for the lib.rs file, in which both functions reside:
extern crate serde_json;
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
use std::error::Error;
use std::fs;
use std::io;
use std::io::{Read, Write};
I also created a git template repo, so that you can start really quick, you can find it here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With