Skip to content

Commit

Permalink
Preparations for "always open this site in profile X" feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
null-dev committed May 31, 2021
1 parent 675c7b5 commit 543eace
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 60 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ bench = false
rust-ini = "0.16"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_cbor = "0.11.1"
byteorder = "1.4.2"
directories = "3.0"
fs2 = "0.4"
Expand Down
8 changes: 2 additions & 6 deletions src/cmd/close_manager.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
use crate::state::AppState;
use crate::profiles::ProfilesIniState;
use crate::native_resp::{NativeResponse, NativeResponseData};
use crate::ipc::{IPC_CMD_CLOSE_MANAGER, send_ipc_cmd};
use crate::ipc::notify_close_manager;

pub fn process_cmd_close_manager(app_state: &AppState, profiles: &ProfilesIniState) -> NativeResponse {
for profile in &profiles.profile_entries {
if Some(&profile.id) != app_state.cur_profile_id.as_ref() {
send_ipc_cmd(app_state, &profile.id, IPC_CMD_CLOSE_MANAGER);
}
}
notify_close_manager(app_state, profiles);

return NativeResponse::success(NativeResponseData::ManagerClosed)
}
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/create_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn process_cmd_create_profile(app_state: &AppState, profiles: &mut ProfilesI
path: new_profile_path,
default: false,
avatar: Some(msg.avatar),
options: HashMap::new()
options: msg.options
};

// Firefox will refuse to launch if we do not mkdirs the new profile folder
Expand Down
20 changes: 13 additions & 7 deletions src/cmd/launch_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::state::AppState;
use crate::profiles::ProfilesIniState;
use crate::native_req::NativeMessageLaunchProfile;
use crate::native_resp::{NativeResponse, NativeResponseData};
use crate::ipc::{IPC_CMD_FOCUS_WINDOW, send_ipc_cmd};
use std::path::PathBuf;
use std::{io, env};
use std::process::{exit, Child, Command, Stdio};
use std::env::VarError;
use cfg_if::cfg_if;
use crate::cmd::launch_profile::GetParentProcError::NoCrashReporterEnvVar;
use crate::ipc::notify_focus_window;

cfg_if! {
if #[cfg(target_family = "unix")] {
Expand Down Expand Up @@ -37,7 +37,7 @@ pub fn process_cmd_launch_profile(app_state: &AppState,

log::trace!("Launching profile: {}", profile.id);

match send_ipc_cmd(app_state, &msg.profile_id, IPC_CMD_FOCUS_WINDOW) {
match notify_focus_window(app_state, &msg.profile_id, msg.url.clone()) {
Ok(_) => { return NativeResponse::success(NativeResponseData::ProfileLaunched); }
Err(e) => { log::info!("Failed to focus current browser window, launching new window: {:?}", e); }
}
Expand Down Expand Up @@ -74,7 +74,7 @@ pub fn process_cmd_launch_profile(app_state: &AppState,
libc::close(1);
libc::close(2);
}*/
match spawn_browser_proc(&parent_proc, &profile.name) {
match spawn_browser_proc(&parent_proc, &profile.name, msg.url) {
Ok(_) => 0,
Err(e) => 1
}
Expand All @@ -85,7 +85,7 @@ pub fn process_cmd_launch_profile(app_state: &AppState,
}
} else if #[cfg(target_family = "windows")] {
// TODO Change app ID to separate on taskbar?
match spawn_browser_proc(&parent_proc, &profile.name) {
match spawn_browser_proc(&parent_proc, &profile.name, msg.url) {
Ok(_) => NativeResponse::success(NativeResponseData::ProfileLaunched),
Err(e) => NativeResponse::error_with_dbg_msg("Failed to launch browser with new profile!", e)
}
Expand All @@ -97,16 +97,22 @@ pub fn process_cmd_launch_profile(app_state: &AppState,

// === PROCESS UTILS ===

fn spawn_browser_proc(bin_path: &PathBuf, profile_name: &str) -> io::Result<Child> {
fn spawn_browser_proc(bin_path: &PathBuf, profile_name: &str, url: Option<String>) -> io::Result<Child> {
let mut command = Command::new(bin_path);
cfg_if! {
if #[cfg(target_family = "windows")] {
command.creation_flags((winapi::um::winbase::DETACHED_PROCESS | winapi::um::winbase::CREATE_BREAKAWAY_FROM_JOB) as u32);
}
}
return command
command
.arg("-P")
.arg(profile_name)
.arg(profile_name);
if let Some(url) = url {
command
.arg("--new-tab")
.arg(url);
}
return command
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
Expand Down
99 changes: 56 additions & 43 deletions src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@ use interprocess::local_socket::{ToLocalSocketName, LocalSocketStream, LocalSock
use std::{io, fs, thread};
use crate::state::AppState;
use byteorder::{WriteBytesExt, NetworkEndian, ReadBytesExt};
use std::io::Write;
use std::io::{Write, Read, BufReader, BufWriter};
use std::path::PathBuf;
use crate::native_resp::{write_native_response, NativeResponseWrapper, NATIVE_RESP_ID_EVENT, NativeResponse, NativeResponseEvent, NativeResponseProfileListProfileEntry};
use crate::profiles::{read_profiles, ProfilesIniState};
use crate::options::read_global_options;
use crate::storage::options_data_path;
use cfg_if::cfg_if;
use serde::{Serialize, Deserialize};
use serde_json::value::Serializer;

// === IPC ===
pub const IPC_CMD_FOCUS_WINDOW: u32 = 1;
const IPC_CMD_UPDATE_PROFILE_LIST: u32 = 2;
pub const IPC_CMD_CLOSE_MANAGER: u32 = 3;
const IPC_CMD_UPDATE_OPTIONS: u32 = 4;
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "t", content = "c")]
enum IPCCommand {
FocusWindow(FocusWindowCommand),
UpdateProfileList,
CloseManager,
UpdateOptions
}
#[derive(Serialize, Deserialize, Debug)]
struct FocusWindowCommand {
url: Option<String>
}
fn get_ipc_socket_name(profile_id: &str, reset: bool) -> io::Result<impl ToLocalSocketName<'static>> {
cfg_if! {
if #[cfg(target_family = "unix")] {
Expand Down Expand Up @@ -43,31 +53,14 @@ fn handle_conn(app_state: &AppState, mut conn: LocalSocketStream) {

loop {
// Read command
let command = match conn.read_u32::<NetworkEndian>() {
Ok(c) => c,
Err(e) => {
match e.kind() {
io::ErrorKind::UnexpectedEof => {}
io::ErrorKind::ConnectionAborted => {}
_ => log::error!("IPC error while reading command: {:?}", e)
}
return
}
};

// Read command length
/*let len = match conn.read_u64() {
Ok(c) => c,
let mut deserializer = serde_cbor::Deserializer::from_reader(&mut conn);
match IPCCommand::deserialize(&mut deserializer) {
Ok(command) => handle_ipc_cmd(app_state, command),
Err(e) => {
match e.kind() {
io::ErrorKind::UnexpectedEof => {}
_ => log::error!("IPC error while reading command length: {:?}", e)
}
log::error!("Failed to read command from IPC: {:?}", e);
return
}
};*/

handle_ipc_cmd(app_state, command);
}

// TODO Write different status if command failed
// Write command status
Expand Down Expand Up @@ -109,17 +102,20 @@ pub fn setup_ipc(cur_profile_id: &str, app_state: &AppState) -> std::result::Res
return Ok(());
}

fn handle_ipc_cmd(app_state: &AppState, cmd: u32) {
log::trace!("Executing IPC command: {}", cmd);
fn handle_ipc_cmd(app_state: &AppState, cmd: IPCCommand) {
log::trace!("Executing IPC command: {:?}", cmd);

match cmd {
IPC_CMD_FOCUS_WINDOW => {
IPCCommand::FocusWindow(options) => {
// Focus window
write_native_response(NativeResponseWrapper {
id: NATIVE_RESP_ID_EVENT,
resp: NativeResponse::event(NativeResponseEvent::FocusWindow)
resp: NativeResponse::event(NativeResponseEvent::FocusWindow {
url: options.url
})
});
}
IPC_CMD_UPDATE_PROFILE_LIST => {
IPCCommand::UpdateProfileList => {
match read_profiles(&app_state.config, &app_state.config_dir) {
Ok(profiles) => {
if let Some(pid) = &app_state.cur_profile_id
Expand All @@ -140,13 +136,13 @@ fn handle_ipc_cmd(app_state: &AppState, cmd: u32) {
}
};
}
IPC_CMD_CLOSE_MANAGER => {
IPCCommand::CloseManager => {
write_native_response(NativeResponseWrapper {
id: NATIVE_RESP_ID_EVENT,
resp: NativeResponse::event(NativeResponseEvent::CloseManager)
});
}
IPC_CMD_UPDATE_OPTIONS => {
IPCCommand::UpdateOptions => {
let new_options = read_global_options(
&options_data_path(&app_state.config_dir));

Expand All @@ -157,21 +153,19 @@ fn handle_ipc_cmd(app_state: &AppState, cmd: u32) {
})
})
}
_ => {
log::error!("Unknown IPC command: {}", cmd);
}
}
}

#[derive(Debug)]
pub enum IpcError {
NotRunning,
BadStatus,
SerializationError(serde_cbor::Error),
IoError(io::Error)
}

pub fn send_ipc_cmd(app_state: &AppState, target_profile_id: &str, cmd: u32) -> std::result::Result<(), IpcError> {
log::trace!("Sending IPC command {} to profile: {}", cmd, target_profile_id);
fn send_ipc_cmd(app_state: &AppState, target_profile_id: &str, cmd: IPCCommand) -> std::result::Result<(), IpcError> {
log::trace!("Sending IPC command {:?} to profile: {}", cmd, target_profile_id);
let cur_profile_id = &app_state.cur_profile_id;
if cur_profile_id.is_some() && cur_profile_id.as_ref().unwrap() == target_profile_id {
log::trace!("Fast-pathing IPC command...");
Expand All @@ -185,7 +179,10 @@ pub fn send_ipc_cmd(app_state: &AppState, target_profile_id: &str, cmd: u32) ->
log::trace!("Connected to IPC target, reading remote version...");
let remote_version = conn.read_u8().map_err(|e| {IpcError::IoError(e)})?;
log::trace!("Remote version is: {}, Writing IPC command...", remote_version);
conn.write_u32::<NetworkEndian>(cmd).and_then(|_| conn.flush()).map_err(|e| {IpcError::IoError(e)})?;
serde_cbor::to_writer(&mut conn, &cmd)
.map_err(IpcError::SerializationError)
.and_then(|_| conn.flush()
.map_err(IpcError::IoError))?;
log::trace!("IPC command written, reading status...");
let status = conn.read_i32::<NetworkEndian>().map_err(|e| {IpcError::IoError(e)})?;
log::trace!("IPC command status is: {}", status);
Expand All @@ -197,16 +194,32 @@ pub fn send_ipc_cmd(app_state: &AppState, target_profile_id: &str, cmd: u32) ->
}
}

// Notify another instance to focus it's window
pub fn notify_focus_window(app_state: &AppState, target_profile_id: &String, url: Option<String>) -> Result<(), IpcError> {
send_ipc_cmd(app_state, target_profile_id, IPCCommand::FocusWindow(FocusWindowCommand {
url
}))
}

// Notify all other running instances to update their profile list
pub fn notify_profile_changed(app_state: &AppState, profiles: &ProfilesIniState) {
for profile in &profiles.profile_entries {
send_ipc_cmd(app_state, &profile.id, IPC_CMD_UPDATE_PROFILE_LIST);
send_ipc_cmd(app_state, &profile.id, IPCCommand::UpdateProfileList);
}
}

// Notify all other running instances to update their options list
// Notify all other running instances to update their options
pub fn notify_options_changed(app_state: &AppState, profiles: &ProfilesIniState) {
for profile in &profiles.profile_entries {
send_ipc_cmd(app_state, &profile.id, IPC_CMD_UPDATE_OPTIONS);
send_ipc_cmd(app_state, &profile.id, IPCCommand::UpdateOptions);
}
}

// Notify all other running instances to close their managers
pub fn notify_close_manager(app_state: &AppState, profiles: &ProfilesIniState) {
for profile in &profiles.profile_entries {
if Some(&profile.id) != app_state.cur_profile_id.as_ref() {
send_ipc_cmd(app_state, &profile.id, IPCCommand::CloseManager);
}
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern crate log;
extern crate url;
extern crate chrono;
extern crate rand;
extern crate serde_cbor;

use std::{io, env};
use std::fs;
Expand Down
6 changes: 4 additions & 2 deletions src/native_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ pub struct NativeMessageInitialize {

#[derive(Serialize, Deserialize, Debug)]
pub struct NativeMessageLaunchProfile {
pub profile_id: String
pub profile_id: String,
pub url: Option<String>
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NativeMessageCreateProfile {
pub name: String,
pub avatar: String
pub avatar: String,
pub options: HashMap<String, Value>
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/native_resp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub enum NativeResponseData {
#[serde(tag = "event")]
pub enum NativeResponseEvent {
ProfileList { current_profile_id: String, profiles: Vec<NativeResponseProfileListProfileEntry> },
FocusWindow,
FocusWindow { url: Option<String> },
CloseManager,
ConnectorInformation { version: String },
OptionsUpdated { options: HashMap<String, Value> }
Expand Down

0 comments on commit 543eace

Please sign in to comment.