Install native host

This commit is contained in:
darktohka
2026-03-17 03:10:48 +02:00
parent 202e2c160f
commit 50409fdd83
9 changed files with 626 additions and 31 deletions
@@ -9,8 +9,9 @@ pub const PLAYER_START_MENU: u32 = 1 << 4;
pub const PLAYER_DESKTOP: u32 = 1 << 5;
pub const X64: u32 = 1 << 6;
pub const DEBUG: u32 = 1 << 7;
pub const NATIVE_HOST: u32 = 1 << 8;
const UNINSTALL_TICKS: u32 = 9;
const UNINSTALL_TICKS: u32 = 10;
const INSTALL_GENERAL_TICKS: u32 = 5;
#[derive(Clone, Copy)]
@@ -65,6 +66,10 @@ impl InstallFlags {
ticks += 1;
}
if self.is_set(NATIVE_HOST) {
ticks += 1;
}
ticks += UNINSTALL_TICKS;
ticks += INSTALL_GENERAL_TICKS;
ticks
@@ -26,6 +26,10 @@ const COMPLETE_INSTALL_TEXT: &str = "Clean Flash Player has been successfully in
Don't forget, Flash Player is no longer compatible with new browsers.\n\n\
For browser recommendations and Flash Player updates, check out Clean Flash Player's website!";
const COMPLETE_INSTALL_WITH_EXTENSION_TEXT: &str = "Clean Flash Player has been successfully installed!\n\n\
To use Flash in modern browsers, install the Clean Flash Player extension into your browser.\n\n\
For Flash Player updates, check out Clean Flash Player's website!";
const COMPLETE_UNINSTALL_TEXT: &str = "\nAll versions of Flash Player have been successfully uninstalled.\n\n\
If you ever change your mind, check out Clean Flash Player's website!";
@@ -66,6 +70,8 @@ pub struct InstallForm {
pub disclaimer_box: ImageCheckBox,
// Choice panel (browser plugins)
pub browser_ask_label: Label,
pub native_host_box: ImageCheckBox,
pub native_host_label: Label,
pub pepper_box: ImageCheckBox,
pub pepper_label: Label,
pub netscape_box: ImageCheckBox,
@@ -130,7 +136,7 @@ impl InstallForm {
let fonts = FontManager::new();
Self {
let mut form = Self {
scale,
panel: Panel::Disclaimer,
title_text,
@@ -143,12 +149,14 @@ impl InstallForm {
disclaimer_box: chk(PANEL_X, PANEL_Y),
// Choice panel
browser_ask_label: lbl(PANEL_X - 2, PANEL_Y + 2, "Which browser plugins would you like to install?", 15.0),
pepper_box: chk(PANEL_X, PANEL_Y + 47),
pepper_label: lbl(PANEL_X + 24, PANEL_Y + 47, "Pepper API (PPAPI)\n(Chrome/Opera/Brave)", 15.0),
netscape_box: chk(PANEL_X + 186, PANEL_Y + 47),
netscape_label: lbl(PANEL_X + 210, PANEL_Y + 47, "Netscape API (NPAPI)\n(Firefox/ESR/Waterfox)", 15.0),
activex_box: chk(PANEL_X + 365, PANEL_Y + 47),
activex_label: lbl(PANEL_X + 389, PANEL_Y + 47, "ActiveX (OCX)\n(IE/Embedded/Desktop)", 15.0),
native_host_box: chk(PANEL_X, PANEL_Y + 27),
native_host_label: lbl(PANEL_X + 24, PANEL_Y + 27, "Modern Browsers (MV3)\n(Chrome/Firefox/Edge)", 15.0),
pepper_box: chk(PANEL_X, PANEL_Y + 73),
pepper_label: lbl(PANEL_X + 24, PANEL_Y + 73, "Pepper API (PPAPI)\n(Chrome/Opera/Brave)", 15.0),
netscape_box: chk(PANEL_X + 186, PANEL_Y + 73),
netscape_label: lbl(PANEL_X + 210, PANEL_Y + 73, "Netscape API (NPAPI)\n(Firefox/ESR/Waterfox)", 15.0),
activex_box: chk(PANEL_X + 365, PANEL_Y + 73),
activex_label: lbl(PANEL_X + 389, PANEL_Y + 73, "ActiveX (OCX)\n(IE/Embedded/Desktop)", 15.0),
// Player choice panel
player_ask_label: lbl(PANEL_X - 2, PANEL_Y + 2, "Would you like to install the standalone Flash Player?", 15.0),
player_box: chk(PANEL_X, PANEL_Y + 47),
@@ -194,7 +202,29 @@ The following details could be useful. Press the Retry button to try again.",
})),
fonts,
prev_mouse_down: false,
};
// Modern browser support should be the default choice.
form.native_host_box.checked = true;
// On non-Windows platforms, disable legacy browser plugins and player options.
#[cfg(not(target_os = "windows"))]
{
form.pepper_box.checked = false;
form.pepper_box.enabled = false;
form.netscape_box.checked = false;
form.netscape_box.enabled = false;
form.activex_box.checked = false;
form.activex_box.enabled = false;
form.player_box.checked = false;
form.player_box.enabled = false;
form.player_desktop_box.checked = false;
form.player_desktop_box.enabled = false;
form.player_start_menu_box.checked = false;
form.player_start_menu_box.enabled = false;
}
form
}
/// Scale a logical integer coordinate to physical pixels.
@@ -296,16 +326,30 @@ The following details could be useful. Press the Retry button to try again.",
}
}
Panel::Choice => {
self.native_host_box.toggle_if_clicked(mx, my, mouse_released);
self.pepper_box.toggle_if_clicked(mx, my, mouse_released);
self.netscape_box.toggle_if_clicked(mx, my, mouse_released);
self.activex_box.toggle_if_clicked(mx, my, mouse_released);
if self.pepper_label.clicked(mx, my, mouse_released, &self.fonts) {
if self.native_host_box.enabled
&& self
.native_host_label
.clicked(mx, my, mouse_released, &self.fonts)
{
self.native_host_box.checked = !self.native_host_box.checked;
}
if self.pepper_box.enabled
&& self.pepper_label.clicked(mx, my, mouse_released, &self.fonts)
{
self.pepper_box.checked = !self.pepper_box.checked;
}
if self.netscape_label.clicked(mx, my, mouse_released, &self.fonts) {
if self.netscape_box.enabled
&& self.netscape_label.clicked(mx, my, mouse_released, &self.fonts)
{
self.netscape_box.checked = !self.netscape_box.checked;
}
if self.activex_label.clicked(mx, my, mouse_released, &self.fonts) {
if self.activex_box.enabled
&& self.activex_label.clicked(mx, my, mouse_released, &self.fonts)
{
self.activex_box.checked = !self.activex_box.checked;
}
}
@@ -313,13 +357,25 @@ The following details could be useful. Press the Retry button to try again.",
self.player_box.toggle_if_clicked(mx, my, mouse_released);
self.player_desktop_box.toggle_if_clicked(mx, my, mouse_released);
self.player_start_menu_box.toggle_if_clicked(mx, my, mouse_released);
if self.player_label.clicked(mx, my, mouse_released, &self.fonts) {
if self.player_box.enabled
&& self.player_label.clicked(mx, my, mouse_released, &self.fonts)
{
self.player_box.checked = !self.player_box.checked;
}
if self.player_desktop_label.clicked(mx, my, mouse_released, &self.fonts) && self.player_box.checked {
if self.player_desktop_box.enabled
&& self
.player_desktop_label
.clicked(mx, my, mouse_released, &self.fonts)
&& self.player_box.checked
{
self.player_desktop_box.checked = !self.player_desktop_box.checked;
}
if self.player_start_menu_label.clicked(mx, my, mouse_released, &self.fonts) && self.player_box.checked {
if self.player_start_menu_box.enabled
&& self
.player_start_menu_label
.clicked(mx, my, mouse_released, &self.fonts)
&& self.player_box.checked
{
self.player_start_menu_box.checked = !self.player_start_menu_box.checked;
}
// Disable sub-options when player unchecked.
@@ -359,7 +415,13 @@ The following details could be useful. Press the Retry button to try again.",
Panel::Choice => self.open_disclaimer(),
Panel::PlayerChoice => self.open_choice(),
Panel::DebugChoice => self.open_player_choice(),
Panel::BeforeInstall => self.open_debug_choice(),
Panel::BeforeInstall => {
if cfg!(target_os = "windows") {
self.open_debug_choice();
} else {
self.open_choice();
}
}
_ => {}
}
}
@@ -367,7 +429,13 @@ The following details could be useful. Press the Retry button to try again.",
fn on_next_clicked(&mut self) {
match self.panel {
Panel::Disclaimer => self.open_choice(),
Panel::Choice => self.open_player_choice(),
Panel::Choice => {
if cfg!(target_os = "windows") {
self.open_player_choice();
} else {
self.open_before_install();
}
}
Panel::PlayerChoice => self.open_debug_choice(),
Panel::DebugChoice => self.open_before_install(),
Panel::BeforeInstall | Panel::Failure => self.open_install(),
@@ -418,10 +486,13 @@ The following details could be useful. Press the Retry button to try again.",
self.prev_button.enabled = true;
let has_plugins =
self.pepper_box.checked || self.netscape_box.checked || self.activex_box.checked || self.player_box.checked;
self.native_host_box.checked || self.pepper_box.checked || self.netscape_box.checked || self.activex_box.checked || self.player_box.checked;
if has_plugins {
let mut browsers = Vec::new();
if self.native_host_box.checked {
browsers.push("Modern Browsers (via extension)");
}
if self.pepper_box.checked {
browsers.push("Google Chrome");
}
@@ -458,6 +529,7 @@ The installer will completely remove all versions of Flash Player from this comp
self.next_button.visible = false;
let mut flags = InstallFlags::new();
flags.set_conditionally(self.native_host_box.checked, install_flags::NATIVE_HOST);
flags.set_conditionally(self.pepper_box.checked, install_flags::PEPPER);
flags.set_conditionally(self.netscape_box.checked, install_flags::NETSCAPE);
flags.set_conditionally(self.activex_box.checked, install_flags::ACTIVEX);
@@ -529,7 +601,9 @@ The installer will completely remove all versions of Flash Player from this comp
self.prev_button.enabled = true;
self.next_button.visible = false;
if self.pepper_box.checked || self.netscape_box.checked || self.activex_box.checked {
if self.native_host_box.checked {
self.complete_label.text = COMPLETE_INSTALL_WITH_EXTENSION_TEXT.to_string();
} else if self.pepper_box.checked || self.netscape_box.checked || self.activex_box.checked {
self.complete_label.text = COMPLETE_INSTALL_TEXT.to_string();
} else {
self.complete_label.text = COMPLETE_UNINSTALL_TEXT.to_string();
@@ -553,6 +627,8 @@ The installer will completely remove all versions of Flash Player from this comp
fn draw_choice(&self, r: &mut Renderer) {
self.browser_ask_label.draw(r, &self.fonts);
self.native_host_box.draw(r);
self.native_host_label.draw(r, &self.fonts);
self.pepper_box.draw(r);
self.pepper_label.draw(r, &self.fonts);
self.netscape_box.draw(r);
@@ -1,6 +1,6 @@
use crate::install_flags::{self, InstallFlags};
use clean_flash_common::{
process_utils, registry, resources, system_info, InstallError, ProgressCallback,
native_host, process_utils, registry, resources, system_info, InstallError, ProgressCallback,
};
use std::env;
use std::fs;
@@ -89,6 +89,7 @@ fn install_from_archive(
let flash64_path = si.flash64_path.clone();
let system32_path = si.system32_path.clone();
let flash_program32_path = si.flash_program32_path.clone();
let native_host_dir = native_host::get_native_host_install_dir();
let mut registry_to_apply: Vec<&str> = vec![resources::INSTALL_GENERAL];
@@ -179,6 +180,24 @@ fn install_from_archive(
registry_instructions: Some(resources::INSTALL_PP_64),
},
),
(
"native-host-64",
InstallEntry {
install_text: "Installing native messaging host (64-bit)...",
required_flags: install_flags::NATIVE_HOST | install_flags::X64,
target_directory: native_host_dir.clone(),
registry_instructions: None,
},
),
(
"native-host-32",
InstallEntry {
install_text: "Installing native messaging host (32-bit)...",
required_flags: install_flags::NATIVE_HOST,
target_directory: native_host_dir.clone(),
registry_instructions: None,
},
),
];
let legacy = si.is_legacy_windows();
@@ -202,24 +221,48 @@ fn install_from_archive(
let filename = parts[0];
let install_key = filename.split('-').next().unwrap_or(filename);
let is_pp32 = install_key == "pp32";
let is_pp64 = install_key == "pp64";
let should_extract_pepper_for_native_host =
flags.is_set(install_flags::NATIVE_HOST)
&& ((si.is_64bit && is_pp64) || (!si.is_64bit && is_pp32));
// Find the matching entry.
let Some((_key, install_entry)) = entries.iter().find(|(k, _)| *k == install_key)
// Find the matching entry: try exact match on full dirname first,
// then fall back to first segment before '-'.
let Some((_key, install_entry)) = entries
.iter()
.find(|(k, _)| *k == filename)
.or_else(|| entries.iter().find(|(k, _)| *k == install_key))
else {
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
return Ok(true);
};
// Check required flags.
let should_install_by_flags = install_entry.required_flags == install_flags::NONE
|| flags.is_set(install_entry.required_flags);
if install_entry.required_flags != install_flags::NONE
&& !flags.is_set(install_entry.required_flags)
&& !(should_extract_pepper_for_native_host && (is_pp32 || is_pp64))
{
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
return Ok(true);
}
// Check debug flag match.
if install_entry.required_flags != install_flags::NONE {
// For native-host: on 64-bit use only native-host-64, on 32-bit use only native-host-32.
if filename == "native-host-32" && si.is_64bit {
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
return Ok(true);
}
if filename == "native-host-64" && !si.is_64bit {
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
return Ok(true);
}
// Check debug flag match (skip native-host entries from this check).
if install_entry.required_flags != install_flags::NONE
&& (install_entry.required_flags & install_flags::NATIVE_HOST) == 0
{
let is_debug_file = filename.contains("-debug");
if flags.is_set(install_flags::DEBUG) != is_debug_file {
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
@@ -236,14 +279,31 @@ fn install_from_archive(
}
}
form.update_progress_label(install_entry.install_text, true);
let extract_for_native_host_only = !should_install_by_flags
&& should_extract_pepper_for_native_host
&& (is_pp32 || is_pp64);
if extract_for_native_host_only {
form.update_progress_label(
"Extracting Pepper files required by modern browser support...",
true,
);
} else {
form.update_progress_label(install_entry.install_text, true);
}
let target_directory = if extract_for_native_host_only {
native_host_dir.clone()
} else {
install_entry.target_directory.clone()
};
// Ensure target directory exists.
let _ = fs::create_dir_all(&install_entry.target_directory);
let _ = fs::create_dir_all(&target_directory);
// Extract file: use just the file name (strip any path prefix).
let out_name = parts.last().unwrap_or(&filename);
let out_path = install_entry.target_directory.join(out_name);
let out_path = target_directory.join(out_name);
let mut buf = Vec::new();
reader.read_to_end(&mut buf).map_err(sevenz_rust2::Error::from)?;
@@ -319,6 +379,11 @@ fn install_from_archive(
}
}
// Install native messaging host manifests for detected browsers.
if flags.is_set(install_flags::NATIVE_HOST) {
native_host::install_native_host(form)?;
}
Ok(())
}
@@ -1,4 +1,4 @@
//#![windows_subsystem = "windows"]
#![windows_subsystem = "windows"]
mod install_flags;
mod install_form;
@@ -34,8 +34,8 @@ fn main() {
// Set window icon from the resource embedded by build.rs.
clean_flash_ui::set_window_icon(&window);
// Cap at ~60 fps.
window.set_target_fps(60);
// Cap at ~24 fps.
window.set_target_fps(24);
// Renderer operates at physical resolution; the form layout is scaled accordingly.
let mut renderer = Renderer::new(phys_w, phys_h);