fix ext fetch
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
@@ -14,7 +13,7 @@ use crate::{
|
||||
BrowserConfigEntry, BrowserStats, BrowserView, ExtensionSummary, ProfileSummary,
|
||||
ScanResponse, TempBookmark, TempExtension,
|
||||
},
|
||||
utils::{first_non_empty, load_image_as_data_url, pick_latest_subdirectory, read_json_file},
|
||||
utils::{first_non_empty, load_image_as_data_url, read_json_file},
|
||||
};
|
||||
|
||||
pub fn scan_browsers(app: &AppHandle) -> Result<ScanResponse, String> {
|
||||
@@ -192,37 +191,38 @@ fn scan_extensions_for_profile(
|
||||
profile: &ProfileSummary,
|
||||
extensions: &mut BTreeMap<String, TempExtension>,
|
||||
) {
|
||||
let extensions_root = profile_path.join("Extensions");
|
||||
let Ok(entries) = fs::read_dir(&extensions_root) else {
|
||||
let secure_preferences_path = profile_path.join("Secure Preferences");
|
||||
let Some(secure_preferences) = read_json_file(&secure_preferences_path) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for entry in entries.flatten() {
|
||||
let Ok(file_type) = entry.file_type() else {
|
||||
continue;
|
||||
let Some(extension_settings) = secure_preferences
|
||||
.get("extensions")
|
||||
.and_then(|value| value.get("settings"))
|
||||
.and_then(Value::as_object)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !file_type.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let extension_id = entry.file_name().to_string_lossy().to_string();
|
||||
let Some(version_path) = pick_latest_subdirectory(&entry.path()) else {
|
||||
for (extension_id, extension_value) in extension_settings {
|
||||
let Some(manifest) = extension_value.get("manifest") else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let manifest_path = version_path.join("manifest.json");
|
||||
let Some(manifest) = read_json_file(&manifest_path) else {
|
||||
let Some(install_dir) =
|
||||
resolve_extension_install_dir(profile_path, extension_id, extension_value)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let name = resolve_extension_name(&manifest, &version_path)
|
||||
let name = resolve_extension_name(manifest, &install_dir)
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| extension_id.clone());
|
||||
let version = manifest
|
||||
.get("version")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::to_string);
|
||||
let icon_data_url = resolve_extension_icon(&manifest, &version_path);
|
||||
let icon_data_url = resolve_extension_icon(manifest, &install_dir);
|
||||
|
||||
let entry = extensions
|
||||
.entry(extension_id.clone())
|
||||
@@ -235,7 +235,7 @@ fn scan_extensions_for_profile(
|
||||
profiles: BTreeMap::new(),
|
||||
});
|
||||
|
||||
if entry.name == entry.id && name != extension_id {
|
||||
if entry.name == entry.id && name != *extension_id {
|
||||
entry.name = name.clone();
|
||||
}
|
||||
if entry.version.is_none() {
|
||||
@@ -260,6 +260,30 @@ fn scan_extensions_for_profile(
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_extension_install_dir(
|
||||
profile_path: &Path,
|
||||
extension_id: &str,
|
||||
extension_value: &Value,
|
||||
) -> Option<PathBuf> {
|
||||
let raw_path = extension_value
|
||||
.get("path")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())?;
|
||||
|
||||
let normalized_path = raw_path.trim_start_matches('/');
|
||||
let candidate = PathBuf::from(normalized_path);
|
||||
let resolved = if normalized_path.starts_with(extension_id) {
|
||||
profile_path.join("Extensions").join(candidate)
|
||||
} else if candidate.is_absolute() {
|
||||
candidate
|
||||
} else {
|
||||
PathBuf::from(raw_path)
|
||||
};
|
||||
|
||||
resolved.is_dir().then_some(resolved)
|
||||
}
|
||||
|
||||
fn resolve_extension_name(manifest: &Value, version_path: &Path) -> Option<String> {
|
||||
let raw_name = manifest.get("name").and_then(Value::as_str)?;
|
||||
if let Some(localized_name) = resolve_localized_manifest_value(raw_name, manifest, version_path)
|
||||
@@ -333,9 +357,10 @@ fn resolve_extension_icon(manifest: &Value, version_path: &Path) -> Option<Strin
|
||||
}
|
||||
|
||||
candidates.sort_by(|left, right| right.0.cmp(&left.0));
|
||||
candidates
|
||||
.into_iter()
|
||||
.find_map(|(_, relative_path)| load_image_as_data_url(&version_path.join(relative_path)))
|
||||
candidates.into_iter().find_map(|(_, relative_path)| {
|
||||
let normalized_path = relative_path.trim_start_matches('/');
|
||||
load_image_as_data_url(&version_path.join(normalized_path))
|
||||
})
|
||||
}
|
||||
|
||||
fn icon_candidates_from_object(map: &serde_json::Map<String, Value>) -> Vec<(u32, String)> {
|
||||
|
||||
@@ -14,29 +14,6 @@ pub fn local_app_data_dir() -> Option<PathBuf> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pick_latest_subdirectory(root: &Path) -> Option<PathBuf> {
|
||||
let entries = fs::read_dir(root).ok()?;
|
||||
let mut candidates = entries
|
||||
.flatten()
|
||||
.filter_map(|entry| {
|
||||
let file_type = entry.file_type().ok()?;
|
||||
if !file_type.is_dir() {
|
||||
return None;
|
||||
}
|
||||
let metadata = entry.metadata().ok()?;
|
||||
let modified = metadata.modified().ok();
|
||||
Some((
|
||||
modified,
|
||||
entry.file_name().to_string_lossy().to_string(),
|
||||
entry.path(),
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
candidates.sort_by(|left, right| right.0.cmp(&left.0).then_with(|| right.1.cmp(&left.1)));
|
||||
candidates.into_iter().next().map(|(_, _, path)| path)
|
||||
}
|
||||
|
||||
pub fn load_image_as_data_url(path: &Path) -> Option<String> {
|
||||
let bytes = fs::read(path).ok()?;
|
||||
let extension = path
|
||||
|
||||
Reference in New Issue
Block a user