mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
1b8bb1df3d
* feat: add Chromium Browser implementation with new architecture * refactor: replace Walk with ReadDir+Stat for profile discovery * refactor: remove queries override, use extractors for Yandex passwords * refactor: remove dataSource wrapper, use []sourcePath directly * fix: address Copilot review feedback on chromium_new.go * fix: always call key retriever regardless of Local State existence
77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
package chromium
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
"github.com/moond4rk/hackbrowserdata/types"
|
|
)
|
|
|
|
// defaultExtensionKeys are the JSON paths tried for standard Chromium browsers.
|
|
var defaultExtensionKeys = []string{
|
|
"extensions.settings",
|
|
"settings.extensions",
|
|
"settings.settings",
|
|
}
|
|
|
|
func extractExtensions(path string) ([]types.ExtensionEntry, error) {
|
|
return extractExtensionsWithKeys(path, defaultExtensionKeys)
|
|
}
|
|
|
|
// extractExtensionsWithKeys reads Secure Preferences and looks for extension
|
|
// settings under the given JSON key paths. This allows browser variants
|
|
// (e.g. Opera with "extensions.opsettings") to reuse the same parsing logic.
|
|
func extractExtensionsWithKeys(path string, keys []string) ([]types.ExtensionEntry, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var settings gjson.Result
|
|
for _, key := range keys {
|
|
settings = gjson.GetBytes(data, key)
|
|
if settings.Exists() {
|
|
break
|
|
}
|
|
}
|
|
if !settings.Exists() {
|
|
return nil, fmt.Errorf("cannot find extensions in settings")
|
|
}
|
|
|
|
var extensions []types.ExtensionEntry
|
|
settings.ForEach(func(id, ext gjson.Result) bool {
|
|
// Skip system/component extensions
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:extensions/common/mojom/manifest.mojom
|
|
location := ext.Get("location").Int()
|
|
if location == 5 || location == 10 {
|
|
return true
|
|
}
|
|
|
|
manifest := ext.Get("manifest")
|
|
if !manifest.Exists() {
|
|
return true
|
|
}
|
|
|
|
extensions = append(extensions, types.ExtensionEntry{
|
|
Name: manifest.Get("name").String(),
|
|
ID: id.String(),
|
|
Description: manifest.Get("description").String(),
|
|
Version: manifest.Get("version").String(),
|
|
HomepageURL: manifest.Get("homepage_url").String(),
|
|
Enabled: ext.Get("state").Int() == 1,
|
|
})
|
|
return true
|
|
})
|
|
|
|
return extensions, nil
|
|
}
|
|
|
|
// extractOperaExtensions extracts extensions from Opera's Secure Preferences,
|
|
// which stores extension data under "extensions.opsettings" instead of the
|
|
// standard "extensions.settings".
|
|
func extractOperaExtensions(path string) ([]types.ExtensionEntry, error) {
|
|
return extractExtensionsWithKeys(path, []string{"extensions.opsettings"})
|
|
}
|